diff options
Diffstat (limited to 'src/mesa/drivers/dri/i915/i915_metaops.c')
-rw-r--r-- | src/mesa/drivers/dri/i915/i915_metaops.c | 208 |
1 files changed, 196 insertions, 12 deletions
diff --git a/src/mesa/drivers/dri/i915/i915_metaops.c b/src/mesa/drivers/dri/i915/i915_metaops.c index a3d22b7bd0..f7b8e5415e 100644 --- a/src/mesa/drivers/dri/i915/i915_metaops.c +++ b/src/mesa/drivers/dri/i915/i915_metaops.c @@ -34,6 +34,7 @@ #include "intel_screen.h" #include "intel_batchbuffer.h" #include "intel_ioctl.h" +#include "intel_rotate.h" #include "i915_context.h" #include "i915_reg.h" @@ -240,7 +241,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 +290,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 +311,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 +325,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 +450,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 +508,7 @@ i915ClearWithTris(intelContextPtr intel, GLbitfield mask, LOCK_HARDWARE(intel); - if(!all) { + if (!all) { x0 = cx; y0 = cy; x1 = x0 + cw; @@ -478,7 +527,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->front.offset ); + set_draw_region( i915, &screen->front ); draw_quad(i915, x0, x1, y0, y1, intel->clear_red, intel->clear_green, @@ -489,7 +538,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->back.offset ); + set_draw_region( i915, &screen->back ); draw_quad(i915, x0, x1, y0, y1, intel->clear_red, intel->clear_green, @@ -503,7 +552,7 @@ i915ClearWithTris(intelContextPtr intel, GLbitfield mask, intel->ctx.Stencil.Clear); set_color_mask( i915, GL_FALSE ); - set_draw_offset( i915, screen->front.offset ); /* 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 +563,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 ); +} + |