summaryrefslogtreecommitdiff
path: root/src/i915_trapezoids.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/i915_trapezoids.c')
-rw-r--r--src/i915_trapezoids.c257
1 files changed, 257 insertions, 0 deletions
diff --git a/src/i915_trapezoids.c b/src/i915_trapezoids.c
new file mode 100644
index 00000000..53c781fb
--- /dev/null
+++ b/src/i915_trapezoids.c
@@ -0,0 +1,257 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Chris Wilson <chris@chris-wilson.co.uk>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "xaarop.h"
+#include "i830.h"
+#include "i915_reg.h"
+#include "i915_3d.h"
+
+#define FLOATS_PER_VERTEX 6
+
+Bool
+i915_check_trapezoids(int width, int height, int depth)
+{
+ return width <= 2048 && height <= 2048 && depth == 8;
+}
+
+static inline float
+line_x_for_y(xLineFixed *l, xFixed y)
+{
+ if (y == l->p1.y)
+ return l->p1.x;
+ if (y == l->p2.y)
+ return l->p2.x;
+ if (l->p2.x == l->p1.x)
+ return l->p1.x;
+
+ return l->p1.x + (y - l->p1.y) * (float) (l->p2.x - l->p1.x) / (l->p2.y - l->p1.y);
+}
+
+#define OUT_TRAP_VERTEX(x, y) do { \
+ xFixed fy = IntToxFixed(y); \
+ float sf = 1. / xFixed1; \
+ OUT_VERTEX(x + dst_x); \
+ OUT_VERTEX(y + dst_y); \
+ OUT_VERTEX(y - trap->top*sf); \
+ OUT_VERTEX(trap->bottom*sf - y); \
+ OUT_VERTEX(x - sf*line_x_for_y(&trap->left, fy)); \
+ OUT_VERTEX(sf*line_x_for_y(&trap->right, fy) - x); \
+} while (0)
+
+static void
+i915_trapezoids_set_target(intel_screen_private *intel, PixmapPtr pixmap)
+{
+ if (intel->last_3d == LAST_3D_OTHER)
+ I915EmitInvarientState(intel);
+ intel->last_3d = LAST_3D_RENDER;
+
+ if (intel->render_current_dest != pixmap) {
+ uint32_t tiling_bits;
+
+ tiling_bits = 0;
+ switch(i830_get_pixmap_intel(pixmap)->tiling) {
+ case I915_TILING_NONE: break;
+ case I915_TILING_Y: tiling_bits |= BUF_3D_TILE_WALK_Y;
+ case I915_TILING_X: tiling_bits |= BUF_3D_TILED_SURFACE; break;
+ }
+
+ OUT_BATCH(_3DSTATE_BUF_INFO_CMD);
+ OUT_BATCH(BUF_3D_ID_COLOR_BACK | tiling_bits |
+ BUF_3D_PITCH(intel_get_pixmap_pitch(pixmap)));
+ OUT_RELOC_PIXMAP(pixmap, I915_GEM_DOMAIN_RENDER,
+ I915_GEM_DOMAIN_RENDER, 0);
+
+ OUT_BATCH(_3DSTATE_DST_BUF_VARS_CMD);
+ OUT_BATCH(COLR_BUF_8BIT);
+
+ /* draw rect is unconditional */
+ OUT_BATCH(_3DSTATE_DRAW_RECT_CMD);
+ OUT_BATCH(0x00000000);
+ OUT_BATCH(0x00000000); /* ymin, xmin */
+ OUT_BATCH(DRAW_YMAX(pixmap->drawable.height - 1) |
+ DRAW_XMAX(pixmap->drawable.width - 1));
+ /* yorig, xorig (relate to color buffer?) */
+ OUT_BATCH(0x00000000);
+
+ intel->render_current_dest = pixmap;
+ }
+}
+
+static void
+i915_trapezoids_set_shader(intel_screen_private *intel)
+{
+ FS_LOCALS();
+
+ OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(2) | I1_LOAD_S(6) | 1);
+ OUT_BATCH(~S2_TEXCOORD_FMT(0, TEXCOORDFMT_NOT_PRESENT) | S2_TEXCOORD_FMT(0, TEXCOORDFMT_4D));
+ OUT_BATCH(S6_CBUF_BLEND_ENABLE | S6_COLOR_WRITE_ENABLE |
+ (BLENDFUNC_ADD << S6_CBUF_BLEND_FUNC_SHIFT) |
+ (BLENDFACT_ONE << S6_CBUF_SRC_BLEND_FACT_SHIFT) |
+ (BLENDFACT_ONE << S6_CBUF_DST_BLEND_FACT_SHIFT));
+
+ FS_BEGIN();
+ i915_fs_dcl(FS_T0);
+ i915_fs_min(FS_U0,
+ i915_fs_operand(FS_R0, ZERO, ONE, ZERO, ONE),
+ i915_fs_operand_reg(FS_T0));
+ i915_fs_add(FS_U0,
+ i915_fs_operand(FS_U0, X, Z, ZERO, ZERO),
+ i915_fs_operand(FS_U0, Y, W, ZERO, ZERO));
+ i915_fs_mul(FS_OC,
+ i915_fs_operand(FS_U0, X, X, X, X),
+ i915_fs_operand(FS_U0, Y, Y, Y, Y));
+ FS_END();
+}
+
+static void
+i915_trapezoids_set_vertices(intel_screen_private *intel)
+{
+ intel->floats_per_vertex = FLOATS_PER_VERTEX;
+ if (intel_vertex_space(intel) < 3*4*FLOATS_PER_VERTEX) {
+ intel_next_vertex(intel);
+
+ OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
+ I1_LOAD_S(0) | I1_LOAD_S(1) | 1);
+ OUT_RELOC(intel->vertex_bo, I915_GEM_DOMAIN_VERTEX, 0, 0);
+ OUT_BATCH((FLOATS_PER_VERTEX << S1_VERTEX_WIDTH_SHIFT) |
+ (FLOATS_PER_VERTEX << S1_VERTEX_PITCH_SHIFT));
+ } else if (FLOATS_PER_VERTEX != intel->last_floats_per_vertex){
+ OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
+ I1_LOAD_S(1) | 0);
+ OUT_BATCH((FLOATS_PER_VERTEX << S1_VERTEX_WIDTH_SHIFT) |
+ (FLOATS_PER_VERTEX << S1_VERTEX_PITCH_SHIFT));
+
+ intel->vertex_index =
+ (intel->vertex_used + FLOATS_PER_VERTEX - 1) / FLOATS_PER_VERTEX;
+ intel->vertex_used = intel->vertex_index * FLOATS_PER_VERTEX;
+ }
+ intel->last_floats_per_vertex = FLOATS_PER_VERTEX;
+}
+
+Bool
+i915_rasterize_trapezoids(PixmapPtr pixmap, Bool clear,
+ int ntrap, xTrapezoid *trap,
+ int dst_x, int dst_y)
+{
+ ScrnInfoPtr scrn = xf86Screens[pixmap->drawable.pScreen->myNum];
+ intel_screen_private *intel = intel_get_screen_private(scrn);
+
+ if (pixmap->drawable.width > 2048 || pixmap->drawable.height > 2048)
+ return FALSE;
+
+ if(!intel_check_pitch_3d(pixmap))
+ return FALSE;
+
+ intel_batch_require_space(scrn, intel, 150);
+ i915_trapezoids_set_target(intel, pixmap);
+
+ if (clear) {
+#if 1
+ FS_LOCALS();
+
+ OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(2) | I1_LOAD_S(6) | 1);
+ OUT_BATCH(~0);
+ OUT_BATCH(S6_COLOR_WRITE_ENABLE);
+
+ FS_BEGIN();
+ i915_fs_mov(FS_OC, i915_fs_operand_zero());
+ FS_END();
+
+ OUT_BATCH(PRIM3D_RECTLIST | 5);
+ OUT_BATCH_F(pixmap->drawable.width);
+ OUT_BATCH_F(pixmap->drawable.height);
+ OUT_BATCH_F(0);
+ OUT_BATCH_F(pixmap->drawable.height);
+ OUT_BATCH_F(0);
+ OUT_BATCH_F(0);
+#else
+ OUT_BATCH(XY_COLOR_BLT_CMD);
+ OUT_BATCH(ROP_0 | intel_get_pixmap_pitch(pixmap));
+ OUT_BATCH(0);
+ OUT_BATCH((pixmap->drawable.height << 16) | pixmap->drawable.width);
+ OUT_RELOC_PIXMAP_FENCED(pixmap, I915_GEM_DOMAIN_RENDER,
+ I915_GEM_DOMAIN_RENDER, 0);
+ OUT_BATCH(0);
+#endif
+ }
+
+ i915_trapezoids_set_shader(intel);
+ i915_trapezoids_set_vertices(intel);
+
+ for (; ntrap--; trap++) {
+ int x1, x2, y1, y2;
+
+ if (!xTrapezoidValid(trap))
+ continue;
+
+ x1 = xFixedToInt(min(trap->left.p1.x, trap->left.p2.x));
+ x2 = xFixedToInt(xFixedCeil(max(trap->right.p1.x, trap->right.p2.x)));
+ y1 = xFixedToInt(trap->top);
+ y2 = xFixedToInt(xFixedCeil(trap->bottom));
+
+ if (x2 + dst_x <= 0 || x1 + dst_x >= pixmap->drawable.width ||
+ y2 + dst_y <= 0 || y1 + dst_y >= pixmap->drawable.height)
+ continue;
+
+ if (intel_vertex_space(intel) < 3*4*FLOATS_PER_VERTEX) {
+ i915_vertex_flush(intel);
+
+ if (intel_batch_require_space(scrn, intel, 16)) {
+ i915_trapezoids_set_target(intel, pixmap);
+ i915_trapezoids_set_shader(intel);
+
+ intel_next_vertex(intel);
+ OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
+ I1_LOAD_S(0) | I1_LOAD_S(1) | 1);
+ OUT_RELOC(intel->vertex_bo, I915_GEM_DOMAIN_VERTEX, 0, 0);
+ OUT_BATCH((FLOATS_PER_VERTEX << S1_VERTEX_WIDTH_SHIFT) |
+ (FLOATS_PER_VERTEX << S1_VERTEX_PITCH_SHIFT));
+
+ intel->last_floats_per_vertex = FLOATS_PER_VERTEX;
+ intel->floats_per_vertex = FLOATS_PER_VERTEX;
+ } else {
+ intel_next_vertex(intel);
+ OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
+ I1_LOAD_S(0) | 0);
+ OUT_RELOC(intel->vertex_bo, I915_GEM_DOMAIN_VERTEX, 0, 0);
+ }
+ }
+
+ OUT_TRAP_VERTEX(x2, y2);
+ OUT_TRAP_VERTEX(x1, y2);
+ OUT_TRAP_VERTEX(x1, y1);
+ intel->vertex_count += 3;
+ }
+
+ i915_vertex_flush(intel);
+ return TRUE;
+}