Fix writemasks on texture arb fp instructions.
[mesa.git] / src / mesa / drivers / dri / i915 / i915_metaops.c
index 2e9063edf0b3aaf656eabb785126739375fe2f04..3ab5dbfd68531b91326fb48f7d971c54a5eed69f 100644 (file)
 #include "intel_screen.h"
 #include "intel_batchbuffer.h"
 #include "intel_ioctl.h"
+#include "intel_rotate.h"
 
 #include "i915_context.h"
 #include "i915_reg.h"
 
 /* A large amount of state doesn't need to be uploaded.
  */
-#define ACTIVE (I915_UPLOAD_PROGRAM |          \
+#define ACTIVE (I915_UPLOAD_INVARIENT |         \
+               I915_UPLOAD_PROGRAM |           \
                I915_UPLOAD_STIPPLE |           \
                I915_UPLOAD_CTX |               \
                I915_UPLOAD_BUFFERS |           \
@@ -240,7 +242,7 @@ static void set_no_texture( i915ContextPtr i915 )
    i915->meta.emitted &= ~I915_UPLOAD_PROGRAM;
 }
 
-#if 0
+
 static void enable_texture_blend_replace( i915ContextPtr i915 )
 {
    static const GLuint prog[] = {
@@ -289,14 +291,16 @@ static void set_tex_rect_source( i915ContextPtr i915,
                                 GLuint offset,
                                 GLuint width, 
                                 GLuint height,
-                                GLuint pitch,
+                                GLuint pitch, /* in bytes! */
                                 GLuint textureFormat )
 {
    GLuint unit = 0;
    GLint numLevels = 1;
    GLuint *state = i915->meta.Tex[0];
 
-   pitch *= i915->intel.intelScreen->cpp;
+#if 0
+   printf("TexRect source offset 0x%x  pitch %d\n", offset, pitch);
+#endif
 
 /*    fprintf(stderr, "%s: offset: %x w: %d h: %d pitch %d format %x\n", */
 /*        __FUNCTION__, offset, width, height, pitch, textureFormat ); */
@@ -308,7 +312,6 @@ static void set_tex_rect_source( i915ContextPtr i915,
                            MS3_USE_FENCE_REGS);
 
    state[I915_TEXREG_MS4] = ((((pitch / 4) - 1) << MS4_PITCH_SHIFT) | 
-                           MS4_CUBE_FACE_ENA_MASK |
                            ((((numLevels-1) * 4)) << MS4_MAX_LOD_SHIFT));
 
    state[I915_TEXREG_SS2] = ((FILTER_NEAREST << SS2_MIN_FILTER_SHIFT) |
@@ -323,17 +326,23 @@ static void set_tex_rect_source( i915ContextPtr i915,
 
    i915->meta.emitted &= ~I915_UPLOAD_TEX(0);
 }
-#endif
+
 
 /* Select between front and back draw buffers.
  */
-static void set_draw_offset( i915ContextPtr i915,
-                            GLuint offset )
+static void set_draw_region( i915ContextPtr i915, const intelRegion *region )
 {
-   i915->meta.Buffer[I915_DESTREG_CBUFADDR2] = offset;
+#if 0
+   printf("Rotate into region: offset 0x%x  pitch %d\n",
+          region->offset, region->pitch);
+#endif
+   i915->meta.Buffer[I915_DESTREG_CBUFADDR1] =
+      (BUF_3D_ID_COLOR_BACK | BUF_3D_PITCH(region->pitch) | BUF_3D_USE_FENCE);
+   i915->meta.Buffer[I915_DESTREG_CBUFADDR2] = region->offset;
    i915->meta.emitted &= ~I915_UPLOAD_BUFFERS;
 }
 
+
 #if 0
 /* Setup an arbitary draw format, useful for targeting texture or agp
  * memory.
@@ -442,6 +451,47 @@ static void draw_quad(i915ContextPtr i915,
       vb[i] = tmp.ui[i];
 }
 
+
+static void draw_poly(i915ContextPtr i915, 
+                     GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha,
+                      GLuint numVerts,
+                      /*const*/ GLfloat verts[][2],
+                      /*const*/ GLfloat texcoords[][2])
+{
+   GLuint vertex_size = 8;
+   GLuint *vb = intelEmitInlinePrimitiveLocked( &i915->intel, 
+                                               PRIM3D_TRIFAN, 
+                                               numVerts * vertex_size,
+                                               vertex_size );
+   intelVertex tmp;
+   int i, k;
+
+   /* initial constant vertex fields */
+   tmp.v.z = 1.0;
+   tmp.v.w = 1.0; 
+   tmp.v.color.red = red;
+   tmp.v.color.green = green;
+   tmp.v.color.blue = blue;
+   tmp.v.color.alpha = alpha;
+   tmp.v.specular.red = 0;
+   tmp.v.specular.green = 0;
+   tmp.v.specular.blue = 0;
+   tmp.v.specular.alpha = 0;
+
+   for (k = 0; k < numVerts; k++) {
+      tmp.v.x = verts[k][0];
+      tmp.v.y = verts[k][1];
+      tmp.v.u0 = texcoords[k][0];
+      tmp.v.v0 = texcoords[k][1];
+
+      for (i = 0 ; i < vertex_size ; i++)
+         vb[i] = tmp.ui[i];
+
+      vb += vertex_size;
+   }
+}
+
+
 void 
 i915ClearWithTris(intelContextPtr intel, GLbitfield mask,
                  GLboolean all,
@@ -459,7 +509,7 @@ i915ClearWithTris(intelContextPtr intel, GLbitfield mask,
 
    LOCK_HARDWARE(intel);
 
-   if(!all) {
+   if (!all) {
       x0 = cx;
       y0 = cy;
       x1 = x0 + cw;
@@ -478,7 +528,7 @@ i915ClearWithTris(intelContextPtr intel, GLbitfield mask,
    if (mask & BUFFER_BIT_FRONT_LEFT) { 
       set_no_depth_stencil_write( i915 );
       set_color_mask( i915, GL_TRUE );
-      set_draw_offset( i915, screen->frontOffset );
+      set_draw_region( i915, &screen->front );
 
       draw_quad(i915, x0, x1, y0, y1,
                intel->clear_red, intel->clear_green, 
@@ -489,7 +539,7 @@ i915ClearWithTris(intelContextPtr intel, GLbitfield mask,
    if (mask & BUFFER_BIT_BACK_LEFT) {
       set_no_depth_stencil_write( i915 );
       set_color_mask( i915, GL_TRUE );
-      set_draw_offset( i915, screen->backOffset );
+      set_draw_region( i915, &screen->back );
 
       draw_quad(i915, x0, x1, y0, y1,
                intel->clear_red, intel->clear_green,
@@ -503,7 +553,7 @@ i915ClearWithTris(intelContextPtr intel, GLbitfield mask,
                           intel->ctx.Stencil.Clear);
       
       set_color_mask( i915, GL_FALSE );
-      set_draw_offset( i915, screen->frontOffset ); /* could be either? */
+      set_draw_region( i915, &screen->front ); /* could be either? */
 
       draw_quad( i915, x0, x1, y0, y1, 0, 0, 0, 0, 0, 0, 0, 0 );
    }
@@ -514,3 +564,138 @@ i915ClearWithTris(intelContextPtr intel, GLbitfield mask,
 }
 
 
+/**
+ * Copy the window contents named by dPriv to the rotated (or reflected)
+ * color buffer.
+ * srcBuf is BUFFER_BIT_FRONT_LEFT or BUFFER_BIT_BACK_LEFT to indicate the source.
+ */
+void
+i915RotateWindow(intelContextPtr intel, __DRIdrawablePrivate *dPriv,
+                 GLuint srcBuf)
+{
+   i915ContextPtr i915 = I915_CONTEXT( intel );
+   intelScreenPrivate *screen = intel->intelScreen;
+   const GLuint cpp = screen->cpp;
+   drm_clip_rect_t fullRect;
+   GLuint textureFormat, srcOffset, srcPitch;
+   const drm_clip_rect_t *clipRects;
+   int numClipRects;
+   int i;
+
+   int xOrig, yOrig;
+   int origNumClipRects;
+   drm_clip_rect_t *origRects;
+
+   /*
+    * set up hardware state
+    */
+   intelFlush( &intel->ctx );
+
+   SET_STATE( i915, meta ); 
+   set_initial_state( i915 ); 
+   set_no_texture( i915 ); 
+   set_vertex_format( i915 ); 
+   set_no_depth_stencil_write( i915 );
+   set_color_mask( i915, GL_TRUE );
+
+   LOCK_HARDWARE(intel);
+
+   /* save current drawing origin and cliprects (restored at end) */
+   xOrig = intel->drawX;
+   yOrig = intel->drawY;
+   origNumClipRects = intel->numClipRects;
+   origRects = intel->pClipRects;
+
+   if (!intel->numClipRects)
+      goto done;
+
+   /*
+    * set drawing origin, cliprects for full-screen access to rotated screen
+    */
+   fullRect.x1 = 0;
+   fullRect.y1 = 0;
+   fullRect.x2 = screen->rotatedWidth;
+   fullRect.y2 = screen->rotatedHeight;
+   intel->drawX = 0;
+   intel->drawY = 0;
+   intel->numClipRects = 1;
+   intel->pClipRects = &fullRect;
+
+   set_draw_region( i915, &screen->rotated );
+
+   if (cpp == 4)
+      textureFormat = MAPSURF_32BIT | MT_32BIT_ARGB8888;
+   else
+      textureFormat = MAPSURF_16BIT | MT_16BIT_RGB565;
+
+   if (srcBuf == BUFFER_BIT_FRONT_LEFT) {
+      srcPitch = screen->front.pitch;   /* in bytes */
+      srcOffset = screen->front.offset; /* bytes */
+      clipRects = dPriv->pClipRects;
+      numClipRects = dPriv->numClipRects;
+   }
+   else {
+      srcPitch = screen->back.pitch;   /* in bytes */
+      srcOffset = screen->back.offset; /* bytes */
+      clipRects = dPriv->pBackClipRects;
+      numClipRects = dPriv->numBackClipRects;
+   }
+
+   /* set the whole screen up as a texture to avoid alignment issues */
+   set_tex_rect_source(i915,
+                       srcOffset,
+                       screen->width,
+                      screen->height,
+                       srcPitch,
+                       textureFormat);
+
+   enable_texture_blend_replace(i915);
+
+   /*
+    * loop over the source window's cliprects
+    */
+   for (i = 0; i < numClipRects; i++) {
+      int srcX0 = clipRects[i].x1;
+      int srcY0 = clipRects[i].y1;
+      int srcX1 = clipRects[i].x2;
+      int srcY1 = clipRects[i].y2;
+      GLfloat verts[4][2], tex[4][2];
+      int j;
+
+      /* build vertices for four corners of clip rect */
+      verts[0][0] = srcX0;  verts[0][1] = srcY0;
+      verts[1][0] = srcX1;  verts[1][1] = srcY0;
+      verts[2][0] = srcX1;  verts[2][1] = srcY1;
+      verts[3][0] = srcX0;  verts[3][1] = srcY1;
+
+      /* .. and texcoords */
+      tex[0][0] = srcX0;  tex[0][1] = srcY0;
+      tex[1][0] = srcX1;  tex[1][1] = srcY0;
+      tex[2][0] = srcX1;  tex[2][1] = srcY1;
+      tex[3][0] = srcX0;  tex[3][1] = srcY1;
+
+      /* transform coords to rotated screen coords */
+      for (j = 0; j < 4; j++) {
+         matrix23TransformCoordf(&screen->rotMatrix,
+                                 &verts[j][0], &verts[j][1]);
+      }
+
+      /* draw polygon to map source image to dest region */
+      draw_poly(i915, 255, 255, 255, 255, 4, verts, tex);
+
+   } /* cliprect loop */
+
+   intelFlushBatchLocked( intel, GL_FALSE, GL_FALSE, GL_FALSE );
+
+ done:
+   /* restore original drawing origin and cliprects */
+   intel->drawX = xOrig;
+   intel->drawY = yOrig;
+   intel->numClipRects = origNumClipRects;
+   intel->pClipRects = origRects;
+
+   UNLOCK_HARDWARE(intel);
+
+   SET_STATE( i915, state );
+}
+