diff options
author | Alan Hourihane <alanh@tungstengraphics.com> | 2006-01-23 10:10:48 +0000 |
---|---|---|
committer | Alan Hourihane <alanh@tungstengraphics.com> | 2006-01-23 10:10:48 +0000 |
commit | 39c492bb14d706ffa8bf04f78048c05de735492b (patch) | |
tree | f29a5df4f7dc8013fb38b7b92b48b5f24a9cb8d2 | |
parent | acd1f16b356ee21d40c706eda14b7105a84c8001 (diff) |
Add Intel 945GM support
Add rotation support
(Tungsten Graphics)
30 files changed, 1612 insertions, 305 deletions
diff --git a/src/mesa/drivers/dri/i915/Makefile b/src/mesa/drivers/dri/i915/Makefile index c269fb1290..53349364d0 100644 --- a/src/mesa/drivers/dri/i915/Makefile +++ b/src/mesa/drivers/dri/i915/Makefile @@ -27,10 +27,12 @@ DRIVER_SOURCES = \ intel_ioctl.c \ intel_pixel.c \ intel_render.c \ + intel_rotate.c \ intel_screen.c \ intel_span.c \ intel_state.c \ intel_tex.c \ + intel_texmem.c \ intel_tris.c C_SOURCES = \ diff --git a/src/mesa/drivers/dri/i915/i830_context.h b/src/mesa/drivers/dri/i915/i830_context.h index 62e20d0a02..5bdcc21c5a 100644 --- a/src/mesa/drivers/dri/i915/i830_context.h +++ b/src/mesa/drivers/dri/i915/i830_context.h @@ -209,7 +209,9 @@ extern void i830ClearWithTris( intelContextPtr intel, GLbitfield mask, GLboolean all, GLint cx, GLint cy, GLint cw, GLint ch); +extern void +i830RotateWindow(intelContextPtr intel, __DRIdrawablePrivate *dPriv, + GLuint srcBuf); - #endif diff --git a/src/mesa/drivers/dri/i915/i830_metaops.c b/src/mesa/drivers/dri/i915/i830_metaops.c index 53997f8336..e7215dfaf0 100644 --- a/src/mesa/drivers/dri/i915/i830_metaops.c +++ b/src/mesa/drivers/dri/i915/i830_metaops.c @@ -49,9 +49,10 @@ #define SET_STATE( i830, STATE ) \ do { \ - i830->current->emitted &= ~ACTIVE; \ + assert(!i830->intel.prim.flush); \ + i830->current->emitted = 0; \ i830->current = &i830->STATE; \ - i830->current->emitted &= ~ACTIVE; \ + i830->current->emitted = 0; \ } while (0) /* Operations where the 3D engine is decoupled temporarily from the @@ -147,13 +148,12 @@ static void set_color_mask( i830ContextPtr i830, GLboolean state ) (1 << WRITEMASK_BLUE_SHIFT) | (1 << WRITEMASK_ALPHA_SHIFT)); + i830->meta.Ctx[I830_CTXREG_ENABLES_2] &= ~mask; + if (state) { - i830->meta.Ctx[I830_CTXREG_ENABLES_2] &= ~mask; i830->meta.Ctx[I830_CTXREG_ENABLES_2] |= (i830->state.Ctx[I830_CTXREG_ENABLES_2] & mask); } - else - i830->meta.Ctx[I830_CTXREG_ENABLES_2] |= mask; i830->meta.emitted &= ~I830_UPLOAD_CTX; } @@ -181,13 +181,12 @@ static void set_no_texture( i830ContextPtr i830 ) /* Set up a single element blend stage for 'replace' texturing with no * funny ops. */ -static void enable_texture_blend_replace( i830ContextPtr i830, - GLenum format ) +static void enable_texture_blend_replace( i830ContextPtr i830 ) { static const struct gl_tex_env_combine_state comb = { GL_REPLACE, GL_REPLACE, - { GL_TEXTURE, 0, 0, }, { GL_TEXTURE, 0, 0, }, - { GL_SRC_COLOR, 0, 0 }, { GL_SRC_ALPHA, 0, 0 }, + { GL_TEXTURE, GL_TEXTURE, GL_TEXTURE }, { GL_TEXTURE, GL_TEXTURE, GL_TEXTURE, }, + { GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR }, { GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA }, 0, 0, 1, 1 }; @@ -211,14 +210,12 @@ static void set_tex_rect_source( i830ContextPtr i830, GLuint offset, GLuint width, GLuint height, - GLuint pitch, + GLuint pitch, /* in bytes */ GLuint textureFormat ) { GLint numLevels = 1; GLuint *setup = i830->meta.Tex[0]; - pitch *= i830->intel.intelScreen->cpp; - /* fprintf(stderr, "%s: offset: %x w: %d h: %d pitch %d format %x\n", */ /* __FUNCTION__, offset, width, height, pitch, textureFormat ); */ @@ -249,16 +246,19 @@ static void set_tex_rect_source( i830ContextPtr i830, /* Select between front and back draw buffers. */ -static void set_draw_offset( i830ContextPtr i830, - GLuint offset ) +static void set_draw_region( i830ContextPtr i830, + const intelRegion *region ) { - i830->meta.Buffer[I830_DESTREG_CBUFADDR2] = offset; + i830->meta.Buffer[I830_DESTREG_CBUFADDR1] = + (BUF_3D_ID_COLOR_BACK | BUF_3D_PITCH(region->pitch) | BUF_3D_USE_FENCE); + i830->meta.Buffer[I830_DESTREG_CBUFADDR2] = region->offset; i830->meta.emitted &= ~I830_UPLOAD_BUFFERS; } /* Setup an arbitary draw format, useful for targeting * texture or agp memory. */ +#if 0 static void set_draw_format( i830ContextPtr i830, GLuint format, GLuint depth_format) @@ -269,6 +269,7 @@ static void set_draw_format( i830ContextPtr i830, DEPTH_IS_Z | depth_format); } +#endif static void set_vertex_format( i830ContextPtr i830 ) @@ -352,6 +353,45 @@ static void draw_quad(i830ContextPtr i830, /* __FUNCTION__, i830->meta.Buffer[I830_DESTREG_DV1]); */ } +static void draw_poly(i830ContextPtr i830, + GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha, + GLuint numVerts, + GLfloat verts[][2], + GLfloat texcoords[][2]) +{ + GLuint vertex_size = 8; + GLuint *vb = intelEmitInlinePrimitiveLocked( &i830->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 i830ClearWithTris(intelContextPtr intel, GLbitfield mask, GLboolean all, @@ -362,10 +402,10 @@ i830ClearWithTris(intelContextPtr intel, GLbitfield mask, intelScreenPrivate *screen = intel->intelScreen; int x0, y0, x1, y1; - + INTEL_FIREVERTICES(intel); SET_STATE( i830, meta ); set_initial_state( i830 ); - set_no_texture( i830 ); +/* set_no_texture( i830 ); */ set_vertex_format( i830 ); LOCK_HARDWARE(intel); @@ -389,7 +429,7 @@ i830ClearWithTris(intelContextPtr intel, GLbitfield mask, if(mask & BUFFER_BIT_FRONT_LEFT) { set_no_depth_stencil_write( i830 ); set_color_mask( i830, GL_TRUE ); - set_draw_offset( i830, screen->front.offset ); + set_draw_region( i830, &screen->front ); draw_quad(i830, x0, x1, y0, y1, intel->clear_red, intel->clear_green, intel->clear_blue, intel->clear_alpha, @@ -399,7 +439,7 @@ i830ClearWithTris(intelContextPtr intel, GLbitfield mask, if(mask & BUFFER_BIT_BACK_LEFT) { set_no_depth_stencil_write( i830 ); set_color_mask( i830, GL_TRUE ); - set_draw_offset( i830, screen->back.offset ); + set_draw_region( i830, &screen->back ); draw_quad(i830, x0, x1, y0, y1, intel->clear_red, intel->clear_green, @@ -413,17 +453,18 @@ i830ClearWithTris(intelContextPtr intel, GLbitfield mask, intel->ctx.Stencil.Clear); set_color_mask( i830, GL_FALSE ); - set_draw_offset( i830, screen->front.offset ); + set_draw_region( i830, &screen->front ); draw_quad( i830, x0, x1, y0, y1, 0, 0, 0, 0, 0, 0, 0, 0 ); } UNLOCK_HARDWARE(intel); + INTEL_FIREVERTICES(intel); SET_STATE( i830, state ); } - +#if 0 GLboolean i830TryTextureReadPixels( GLcontext *ctx, @@ -546,13 +587,13 @@ i830TryTextureReadPixels( GLcontext *ctx, textureFormat ); - enable_texture_blend_replace( i830, glTextureFormat ); + enable_texture_blend_replace( i830 ); /* Set the 3d engine to draw into the agp memory */ - set_draw_offset( i830, destOffset ); + set_draw_region( i830, destOffset ); set_draw_format( i830, destFormat, depthFormat ); @@ -624,7 +665,8 @@ i830TryTextureDrawPixels( GLcontext *ctx, !ctx->Color.ColorMask[2] || !ctx->Color.ColorMask[3] || ctx->Color.ColorLogicOpEnabled || - ctx->Texture._EnabledUnits) { + ctx->Texture._EnabledUnits || + ctx->Depth.OcclusionTest) { fprintf(stderr, "%s: other tests failed\n", __FUNCTION__); return GL_FALSE; } @@ -704,7 +746,7 @@ i830TryTextureDrawPixels( GLcontext *ctx, textureFormat ); - enable_texture_blend_replace( i830, glTextureFormat ); + enable_texture_blend_replace( i830 ); /* Draw to the current draw buffer: @@ -730,3 +772,142 @@ i830TryTextureDrawPixels( GLcontext *ctx, return GL_TRUE; } +#endif + +/** + * 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 +i830RotateWindow(intelContextPtr intel, __DRIdrawablePrivate *dPriv, + GLuint srcBuf) +{ + i830ContextPtr i830 = I830_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( i830, meta ); + set_initial_state( i830 ); + set_no_texture( i830 ); + set_vertex_format( i830 ); + set_no_depth_stencil_write( i830 ); + set_color_mask( i830, GL_FALSE ); + + 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( i830, &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(i830, + srcOffset, + screen->width, + screen->height, + srcPitch, + textureFormat); + + enable_texture_blend_replace(i830); + + /* + * 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(i830, 255, 255, 255, 255, 4, verts, tex); + + } /* cliprect loop */ + + assert(!intel->prim.flush); + 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( i830, state ); +} + diff --git a/src/mesa/drivers/dri/i915/i830_state.c b/src/mesa/drivers/dri/i915/i830_state.c index 605f400c06..ec9dca6231 100644 --- a/src/mesa/drivers/dri/i915/i830_state.c +++ b/src/mesa/drivers/dri/i915/i830_state.c @@ -1003,14 +1003,14 @@ static void i830_init_packets( i830ContextPtr i830 ) i830->state.Buffer[I830_DESTREG_CBUFADDR0] = _3DSTATE_BUF_INFO_CMD; i830->state.Buffer[I830_DESTREG_CBUFADDR1] = (BUF_3D_ID_COLOR_BACK | - BUF_3D_PITCH(screen->front.pitch * screen->cpp) | + BUF_3D_PITCH(screen->front.pitch) | /* pitch in bytes */ BUF_3D_USE_FENCE); i830->state.Buffer[I830_DESTREG_DBUFADDR0] = _3DSTATE_BUF_INFO_CMD; i830->state.Buffer[I830_DESTREG_DBUFADDR1] = (BUF_3D_ID_DEPTH | - BUF_3D_PITCH(screen->depth.pitch * screen->cpp) | + BUF_3D_PITCH(screen->depth.pitch) | /* pitch in bytes */ BUF_3D_USE_FENCE); i830->state.Buffer[I830_DESTREG_DBUFADDR2] = screen->depth.offset; diff --git a/src/mesa/drivers/dri/i915/i830_tex.c b/src/mesa/drivers/dri/i915/i830_tex.c index d56a4df8bb..3c4aedb35c 100644 --- a/src/mesa/drivers/dri/i915/i830_tex.c +++ b/src/mesa/drivers/dri/i915/i830_tex.c @@ -335,11 +335,22 @@ static void i830TexEnv( GLcontext *ctx, GLenum target, } } +static void i830BindTexture( GLcontext *ctx, GLenum target, + struct gl_texture_object *texObj ) +{ + i830TextureObjectPtr tex; + + if (!texObj->DriverData) + i830AllocTexObj( texObj ); + + tex = (i830TextureObjectPtr)texObj->DriverData; +} void i830InitTextureFuncs( struct dd_function_table *functions ) { + functions->BindTexture = i830BindTexture; functions->TexEnv = i830TexEnv; functions->TexParameter = i830TexParameter; } diff --git a/src/mesa/drivers/dri/i915/i830_vtbl.c b/src/mesa/drivers/dri/i915/i830_vtbl.c index 22939e8e5c..e8913e8063 100644 --- a/src/mesa/drivers/dri/i915/i830_vtbl.c +++ b/src/mesa/drivers/dri/i915/i830_vtbl.c @@ -361,6 +361,32 @@ do { \ ADVANCE_BATCH(); \ } while (0); +static GLuint get_state_size( struct i830_hw_state *state ) +{ + GLuint dirty = state->active & ~state->emitted; + GLuint sz = 0; + GLuint i; + + if (dirty & I830_UPLOAD_CTX) + sz += sizeof(state->Ctx); + + if (dirty & I830_UPLOAD_BUFFERS) + sz += sizeof(state->Buffer); + + if (dirty & I830_UPLOAD_STIPPLE) + sz += sizeof(state->Stipple); + + for (i = 0; i < I830_TEX_UNITS; i++) { + if ((dirty & I830_UPLOAD_TEX(i))) + sz += sizeof(state->Tex[i]); + + if (dirty & I830_UPLOAD_TEXBLEND(i)) + sz += state->TexBlendWordsUsed[i] * 4; + } + + return sz; +} + /* Push the state into the sarea and/or texture memory. */ @@ -369,10 +395,15 @@ static void i830_emit_state( intelContextPtr intel ) i830ContextPtr i830 = I830_CONTEXT(intel); struct i830_hw_state *state = i830->current; int i; - GLuint dirty; + GLuint dirty = state->active & ~state->emitted; + GLuint counter = intel->batch.counter; BATCH_LOCALS; - dirty = state->active & ~state->emitted; + if (intel->batch.space < get_state_size(state)) { + intelFlushBatch(intel, GL_TRUE); + dirty = state->active & ~state->emitted; + counter = intel->batch.counter; + } if (dirty & I830_UPLOAD_CTX) { if (VERBOSE) fprintf(stderr, "I830_UPLOAD_CTX:\n"); @@ -403,6 +434,8 @@ static void i830_emit_state( intelContextPtr intel ) } state->emitted |= dirty; + intel->batch.last_emit_state = counter; + assert(counter == intel->batch.counter); } static void i830_destroy_context( intelContextPtr intel ) @@ -410,13 +443,45 @@ static void i830_destroy_context( intelContextPtr intel ) _tnl_free_vertices(&intel->ctx); } -static void i830_set_draw_offset( intelContextPtr intel, int offset ) +static void +i830_set_color_region(intelContextPtr intel, const intelRegion *region) +{ + i830ContextPtr i830 = I830_CONTEXT(intel); + I830_STATECHANGE( i830, I830_UPLOAD_BUFFERS ); + i830->state.Buffer[I830_DESTREG_CBUFADDR1] = + (BUF_3D_ID_COLOR_BACK | BUF_3D_PITCH(region->pitch) | BUF_3D_USE_FENCE); + i830->state.Buffer[I830_DESTREG_CBUFADDR2] = region->offset; +} + + +static void +i830_set_z_region(intelContextPtr intel, const intelRegion *region) { i830ContextPtr i830 = I830_CONTEXT(intel); I830_STATECHANGE( i830, I830_UPLOAD_BUFFERS ); - i830->state.Buffer[I830_DESTREG_CBUFADDR2] = offset; + i830->state.Buffer[I830_DESTREG_DBUFADDR1] = + (BUF_3D_ID_DEPTH | BUF_3D_PITCH(region->pitch) | BUF_3D_USE_FENCE); + i830->state.Buffer[I830_DESTREG_DBUFADDR2] = region->offset; } + +static void +i830_update_color_z_regions(intelContextPtr intel, + const intelRegion *colorRegion, + const intelRegion *depthRegion) +{ + i830ContextPtr i830 = I830_CONTEXT(intel); + + i830->state.Buffer[I830_DESTREG_CBUFADDR1] = + (BUF_3D_ID_COLOR_BACK | BUF_3D_PITCH(colorRegion->pitch) | BUF_3D_USE_FENCE); + i830->state.Buffer[I830_DESTREG_CBUFADDR2] = colorRegion->offset; + + i830->state.Buffer[I830_DESTREG_DBUFADDR1] = + (BUF_3D_ID_DEPTH | BUF_3D_PITCH(depthRegion->pitch) | BUF_3D_USE_FENCE); + i830->state.Buffer[I830_DESTREG_DBUFADDR2] = depthRegion->offset; +} + + /* This isn't really handled at the moment. */ static void i830_lost_hardware( intelContextPtr intel ) @@ -444,12 +509,15 @@ void i830InitVtbl( i830ContextPtr i830 ) i830->intel.vtbl.alloc_tex_obj = i830AllocTexObj; i830->intel.vtbl.check_vertex_size = i830_check_vertex_size; i830->intel.vtbl.clear_with_tris = i830ClearWithTris; + i830->intel.vtbl.rotate_window = i830RotateWindow; i830->intel.vtbl.destroy = i830_destroy_context; i830->intel.vtbl.emit_invarient_state = i830_emit_invarient_state; i830->intel.vtbl.emit_state = i830_emit_state; i830->intel.vtbl.lost_hardware = i830_lost_hardware; i830->intel.vtbl.reduced_primitive_state = i830_reduced_primitive_state; - i830->intel.vtbl.set_draw_offset = i830_set_draw_offset; + i830->intel.vtbl.set_color_region = i830_set_color_region; + i830->intel.vtbl.set_z_region = i830_set_z_region; + i830->intel.vtbl.update_color_z_regions = i830_update_color_z_regions; i830->intel.vtbl.update_texture_state = i830UpdateTextureState; i830->intel.vtbl.emit_flush = i830_emit_flush; i830->intel.vtbl.render_start = i830_render_start; diff --git a/src/mesa/drivers/dri/i915/i915_context.h b/src/mesa/drivers/dri/i915/i915_context.h index 8046277643..26b8c69be9 100644 --- a/src/mesa/drivers/dri/i915/i915_context.h +++ b/src/mesa/drivers/dri/i915/i915_context.h @@ -36,6 +36,8 @@ #define I915_FALLBACK_STIPPLE 0x8000 #define I915_FALLBACK_PROGRAM 0x10000 #define I915_FALLBACK_LOGICOP 0x20000 +#define I915_FALLBACK_POLYGON_SMOOTH 0x40000 +#define I915_FALLBACK_POINT_SMOOTH 0x80000 #define I915_UPLOAD_CTX 0x1 #define I915_UPLOAD_BUFFERS 0x2 @@ -309,7 +311,6 @@ extern void i915_print_ureg( const char *msg, GLuint ureg ); */ extern void i915InitStateFunctions( struct dd_function_table *functions ); extern void i915InitState( i915ContextPtr i915 ); -extern void i915_update_fog( GLcontext *ctx ); /*====================================================================== @@ -341,6 +342,10 @@ i915ClearWithTris( intelContextPtr intel, GLbitfield mask, GLboolean all, GLint cx, GLint cy, GLint cw, GLint ch); +extern void +i915RotateWindow(intelContextPtr intel, __DRIdrawablePrivate *dPriv, + GLuint srcBuf); + /*====================================================================== * i915_fragprog.c */ 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 ); +} + diff --git a/src/mesa/drivers/dri/i915/i915_reg.h b/src/mesa/drivers/dri/i915/i915_reg.h index 3241b36b66..e95d76c78f 100644 --- a/src/mesa/drivers/dri/i915/i915_reg.h +++ b/src/mesa/drivers/dri/i915/i915_reg.h @@ -749,6 +749,8 @@ #define MS4_MAX_LOD_SHIFT 9 #define MS4_MAX_LOD_MASK (0x3f<<9) #define MS4_MIP_LAYOUT_LEGACY (0<<8) +#define MS4_MIP_LAYOUT_BELOW_LPT (0<<8) +#define MS4_MIP_LAYOUT_RIGHT_LPT (1<<8) #define MS4_VOLUME_DEPTH_SHIFT 0 #define MS4_VOLUME_DEPTH_MASK (0xff<<0) diff --git a/src/mesa/drivers/dri/i915/i915_state.c b/src/mesa/drivers/dri/i915/i915_state.c index 0627f102da..bad947f5de 100644 --- a/src/mesa/drivers/dri/i915/i915_state.c +++ b/src/mesa/drivers/dri/i915/i915_state.c @@ -779,6 +779,14 @@ static void i915Enable(GLcontext *ctx, GLenum cap, GLboolean state) } break; + case GL_POLYGON_SMOOTH: + FALLBACK( &i915->intel, I915_FALLBACK_POLYGON_SMOOTH, state ); + break; + + case GL_POINT_SMOOTH: + FALLBACK( &i915->intel, I915_FALLBACK_POINT_SMOOTH, state ); + break; + default: ; } @@ -856,23 +864,27 @@ static void i915_init_packets( i915ContextPtr i915 ) { I915_STATECHANGE(i915, I915_UPLOAD_BUFFERS); + /* color buffer offset/stride */ i915->state.Buffer[I915_DESTREG_CBUFADDR0] = _3DSTATE_BUF_INFO_CMD; i915->state.Buffer[I915_DESTREG_CBUFADDR1] = (BUF_3D_ID_COLOR_BACK | - BUF_3D_PITCH(screen->front.pitch * screen->cpp) | + BUF_3D_PITCH(screen->front.pitch) | /* pitch in bytes */ BUF_3D_USE_FENCE); + /*i915->state.Buffer[I915_DESTREG_CBUFADDR2] is the offset */ + /* depth/Z buffer offset/stride */ i915->state.Buffer[I915_DESTREG_DBUFADDR0] = _3DSTATE_BUF_INFO_CMD; i915->state.Buffer[I915_DESTREG_DBUFADDR1] = (BUF_3D_ID_DEPTH | - BUF_3D_PITCH(screen->depth.pitch * screen->cpp) | + BUF_3D_PITCH(screen->depth.pitch) | /* pitch in bytes */ BUF_3D_USE_FENCE); i915->state.Buffer[I915_DESTREG_DBUFADDR2] = screen->depth.offset; i915->state.Buffer[I915_DESTREG_DV0] = _3DSTATE_DST_BUF_VARS_CMD; + /* color/depth pixel format */ switch (screen->fbFormat) { case DV_PF_555: case DV_PF_565: @@ -893,6 +905,8 @@ static void i915_init_packets( i915ContextPtr i915 ) DEPTH_FRMT_24_FIXED_8_OTHER); break; } + + /* scissor */ i915->state.Buffer[I915_DESTREG_SENABLE] = (_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT); i915->state.Buffer[I915_DESTREG_SR0] = _3DSTATE_SCISSOR_RECT_0_CMD; diff --git a/src/mesa/drivers/dri/i915/i915_tex.c b/src/mesa/drivers/dri/i915/i915_tex.c index 4f77833e19..d9609d3193 100644 --- a/src/mesa/drivers/dri/i915/i915_tex.c +++ b/src/mesa/drivers/dri/i915/i915_tex.c @@ -158,7 +158,12 @@ static void i915TexEnv( GLcontext *ctx, GLenum target, static void i915BindTexture( GLcontext *ctx, GLenum target, struct gl_texture_object *texObj ) { - i915TextureObjectPtr tex = (i915TextureObjectPtr)texObj->DriverData; + i915TextureObjectPtr tex; + + if (!texObj->DriverData) + i915AllocTexObj( texObj ); + + tex = (i915TextureObjectPtr)texObj->DriverData; if (tex->lastTarget != texObj->Target) { tex->intel.dirty = I915_UPLOAD_TEX_ALL; diff --git a/src/mesa/drivers/dri/i915/i915_texstate.c b/src/mesa/drivers/dri/i915/i915_texstate.c index efd6fc9450..87eddfecde 100644 --- a/src/mesa/drivers/dri/i915/i915_texstate.c +++ b/src/mesa/drivers/dri/i915/i915_texstate.c @@ -496,7 +496,8 @@ static void i915SetTexImages( i915ContextPtr i915, } - if (i915->intel.intelScreen->deviceID == PCI_CHIP_I945_G) + if (i915->intel.intelScreen->deviceID == PCI_CHIP_I945_G || + i915->intel.intelScreen->deviceID == PCI_CHIP_I945_GM) i945LayoutTextureImages( i915, tObj ); else i915LayoutTextureImages( i915, tObj ); diff --git a/src/mesa/drivers/dri/i915/i915_vtbl.c b/src/mesa/drivers/dri/i915/i915_vtbl.c index 7952866010..25575e5ed2 100644 --- a/src/mesa/drivers/dri/i915/i915_vtbl.c +++ b/src/mesa/drivers/dri/i915/i915_vtbl.c @@ -213,6 +213,58 @@ do { \ ADVANCE_BATCH(); \ } while (0); +static GLuint get_dirty( struct i915_hw_state *state ) +{ + GLuint dirty; + + /* Workaround the multitex hang - if one texture unit state is + * modified, emit all texture units. + */ + dirty = state->active & ~state->emitted; + if (dirty & I915_UPLOAD_TEX_ALL) + state->emitted &= ~I915_UPLOAD_TEX_ALL; + dirty = state->active & ~state->emitted; + + return dirty; +} + + +static GLuint get_state_size( struct i915_hw_state *state ) +{ + GLuint dirty = get_dirty(state); + GLuint i; + GLuint sz = 0; + + if (dirty & I915_UPLOAD_CTX) + sz += sizeof(state->Ctx); + + if (dirty & I915_UPLOAD_BUFFERS) + sz += sizeof(state->Buffer); + + if (dirty & I915_UPLOAD_STIPPLE) + sz += sizeof(state->Stipple); + + if (dirty & I915_UPLOAD_FOG) + sz += sizeof(state->Fog); + + if (dirty & I915_UPLOAD_TEX_ALL) { + int nr = 0; + for (i = 0; i < I915_TEX_UNITS; i++) + if (dirty & I915_UPLOAD_TEX(i)) + nr++; + + sz += (2+nr*3) * sizeof(GLuint) * 2; + } + + if (dirty & I915_UPLOAD_CONSTANTS) + sz += state->ConstantSize * sizeof(GLuint); + + if (dirty & I915_UPLOAD_PROGRAM) + sz += state->ProgramSize * sizeof(GLuint); + + return sz; +} + /* Push the state into the sarea and/or texture memory. */ @@ -221,17 +273,15 @@ static void i915_emit_state( intelContextPtr intel ) i915ContextPtr i915 = I915_CONTEXT(intel); struct i915_hw_state *state = i915->current; int i; - GLuint dirty; + GLuint dirty = get_dirty(state); + GLuint counter = intel->batch.counter; BATCH_LOCALS; - /* More to workaround the multitex hang - if one texture unit state - * is modified, emit all texture units. - */ - dirty = state->active & ~state->emitted; - if (dirty & I915_UPLOAD_TEX_ALL) - state->emitted &= ~I915_UPLOAD_TEX_ALL; - dirty = state->active & ~state->emitted; - + if (intel->batch.space < get_state_size(state)) { + intelFlushBatch(intel, GL_TRUE); + dirty = get_dirty(state); + counter = intel->batch.counter; + } if (VERBOSE) fprintf(stderr, "%s dirty: %x\n", __FUNCTION__, dirty); @@ -305,6 +355,8 @@ static void i915_emit_state( intelContextPtr intel ) } state->emitted |= dirty; + intel->batch.last_emit_state = counter; + assert(counter == intel->batch.counter); } static void i915_destroy_context( intelContextPtr intel ) @@ -312,13 +364,58 @@ static void i915_destroy_context( intelContextPtr intel ) _tnl_free_vertices(&intel->ctx); } -static void i915_set_draw_offset( intelContextPtr intel, int offset ) + +/** + * Set the color buffer drawing region. + */ +static void +i915_set_color_region( intelContextPtr intel, const intelRegion *region) +{ + i915ContextPtr i915 = I915_CONTEXT(intel); + I915_STATECHANGE( i915, I915_UPLOAD_BUFFERS ); + i915->state.Buffer[I915_DESTREG_CBUFADDR1] = + (BUF_3D_ID_COLOR_BACK | BUF_3D_PITCH(region->pitch) | BUF_3D_USE_FENCE); + i915->state.Buffer[I915_DESTREG_CBUFADDR2] = region->offset; +} + + +/** + * specify the z-buffer/stencil region + */ +static void +i915_set_z_region( intelContextPtr intel, const intelRegion *region) { i915ContextPtr i915 = I915_CONTEXT(intel); I915_STATECHANGE( i915, I915_UPLOAD_BUFFERS ); - i915->state.Buffer[I915_DESTREG_CBUFADDR2] = offset; + i915->state.Buffer[I915_DESTREG_DBUFADDR1] = + (BUF_3D_ID_DEPTH | BUF_3D_PITCH(region->pitch) | BUF_3D_USE_FENCE); + i915->state.Buffer[I915_DESTREG_DBUFADDR2] = region->offset; +} + + +/** + * Set both the color and Z/stencil drawing regions. + * Similar to two previous functions, but don't use I915_STATECHANGE() + */ +static void +i915_update_color_z_regions(intelContextPtr intel, + const intelRegion *colorRegion, + const intelRegion *depthRegion) +{ + i915ContextPtr i915 = I915_CONTEXT(intel); + + i915->state.Buffer[I915_DESTREG_CBUFADDR1] = + (BUF_3D_ID_COLOR_BACK | BUF_3D_PITCH(colorRegion->pitch) | BUF_3D_USE_FENCE); + i915->state.Buffer[I915_DESTREG_CBUFADDR2] = colorRegion->offset; + + i915->state.Buffer[I915_DESTREG_DBUFADDR1] = + (BUF_3D_ID_DEPTH | + BUF_3D_PITCH(depthRegion->pitch) | /* pitch in bytes */ + BUF_3D_USE_FENCE); + i915->state.Buffer[I915_DESTREG_DBUFADDR2] = depthRegion->offset; } + static void i915_lost_hardware( intelContextPtr intel ) { I915_CONTEXT(intel)->state.emitted = 0; @@ -340,13 +437,16 @@ void i915InitVtbl( i915ContextPtr i915 ) i915->intel.vtbl.alloc_tex_obj = i915AllocTexObj; i915->intel.vtbl.check_vertex_size = i915_check_vertex_size; i915->intel.vtbl.clear_with_tris = i915ClearWithTris; + i915->intel.vtbl.rotate_window = i915RotateWindow; i915->intel.vtbl.destroy = i915_destroy_context; i915->intel.vtbl.emit_invarient_state = i915_emit_invarient_state; i915->intel.vtbl.emit_state = i915_emit_state; i915->intel.vtbl.lost_hardware = i915_lost_hardware; i915->intel.vtbl.reduced_primitive_state = i915_reduced_primitive_state; i915->intel.vtbl.render_start = i915_render_start; - i915->intel.vtbl.set_draw_offset = i915_set_draw_offset; + i915->intel.vtbl.set_color_region = i915_set_color_region; + i915->intel.vtbl.set_z_region = i915_set_z_region; + i915->intel.vtbl.update_color_z_regions = i915_update_color_z_regions; i915->intel.vtbl.update_texture_state = i915UpdateTextureState; i915->intel.vtbl.emit_flush = i915_emit_flush; } diff --git a/src/mesa/drivers/dri/i915/intel_batchbuffer.c b/src/mesa/drivers/dri/i915/intel_batchbuffer.c index 84ec70e2b9..323d0b2212 100644 --- a/src/mesa/drivers/dri/i915/intel_batchbuffer.c +++ b/src/mesa/drivers/dri/i915/intel_batchbuffer.c @@ -49,13 +49,19 @@ static void intel_fill_box( intelContextPtr intel, GLshort w, GLshort h, GLubyte r, GLubyte g, GLubyte b ) { - intelEmitFillBlitLocked( intel, - intel->intelScreen->cpp, - intel->intelScreen->back.pitch, - intel->intelScreen->front.offset, - x, y, w, h, - INTEL_PACKCOLOR(intel->intelScreen->fbFormat, - r,g,b,0xff)); + x += intel->drawX; + y += intel->drawY; + + if (x >= 0 && y >= 0 && + x+w < intel->intelScreen->width && + y+h < intel->intelScreen->height) + intelEmitFillBlitLocked( intel, + intel->intelScreen->cpp, + intel->intelScreen->back.pitch, + intel->intelScreen->back.offset, + x, y, w, h, + INTEL_PACKCOLOR(intel->intelScreen->fbFormat, + r,g,b,0xff)); } static void intel_draw_performance_boxes( intelContextPtr intel ) @@ -203,9 +209,10 @@ void intelStartInlinePrimitive( intelContextPtr intel, GLuint prim ) /* Make sure there is some space in this buffer: */ - if (intel->vertex_size * 10 * sizeof(GLuint) >= intel->batch.space) + if (intel->vertex_size * 10 * sizeof(GLuint) >= intel->batch.space) { intelFlushBatch(intel, GL_TRUE); - + intel->vtbl.emit_state( intel ); + } #if 1 if (((int)intel->batch.ptr) & 0x4) { @@ -224,6 +231,7 @@ void intelStartInlinePrimitive( intelContextPtr intel, GLuint prim ) intel->prim.start_ptr = batch_ptr; intel->prim.primitive = prim; intel->prim.flush = intel_flush_inline_primitive; + intel->batch.contains_geometry = 1; OUT_BATCH( 0 ); ADVANCE_BATCH(); @@ -270,6 +278,11 @@ GLuint *intelEmitInlinePrimitiveLocked(intelContextPtr intel, */ intel->vtbl.emit_state( intel ); + if ((1+dwords)*4 >= intel->batch.space) { + intelFlushBatch(intel, GL_TRUE); + intel->vtbl.emit_state( intel ); + } + if (1) { int used = dwords * 4; @@ -309,6 +322,8 @@ GLuint *intelEmitInlinePrimitiveLocked(intelContextPtr intel, ADVANCE_BATCH(); + intel->batch.contains_geometry = 1; + do_discard: return tmp; } @@ -334,33 +349,33 @@ void intelCopyBuffer( const __DRIdrawablePrivate *dPriv ) intelFlush( &intel->ctx ); LOCK_HARDWARE( intel ); { - intelScreenPrivate *intelScreen = intel->intelScreen; - __DRIdrawablePrivate *dPriv = intel->driDrawable; - int nbox = dPriv->numClipRects; - drm_clip_rect_t *pbox = dPriv->pClipRects; - int pitch = intelScreen->front.pitch; - int cpp = intelScreen->cpp; + const intelScreenPrivate *intelScreen = intel->intelScreen; + const __DRIdrawablePrivate *dPriv = intel->driDrawable; + const int nbox = dPriv->numClipRects; + const drm_clip_rect_t *pbox = dPriv->pClipRects; + const int cpp = intelScreen->cpp; + const int pitch = intelScreen->front.pitch; /* in bytes */ int i; GLuint CMD, BR13; BATCH_LOCALS; switch(cpp) { case 2: - BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24); + BR13 = (pitch) | (0xCC << 16) | (1<<24); CMD = XY_SRC_COPY_BLT_CMD; break; case 4: - BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24) | (1<<25); + BR13 = (pitch) | (0xCC << 16) | (1<<24) | (1<<25); CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | XY_SRC_COPY_BLT_WRITE_RGB); break; default: - BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24); + BR13 = (pitch) | (0xCC << 16) | (1<<24); CMD = XY_SRC_COPY_BLT_CMD; break; } - - if (0) + + if (0) intel_draw_performance_boxes( intel ); for (i = 0 ; i < nbox; i++, pbox++) @@ -368,9 +383,11 @@ void intelCopyBuffer( const __DRIdrawablePrivate *dPriv ) if (pbox->x1 > pbox->x2 || pbox->y1 > pbox->y2 || pbox->x2 > intelScreen->width || - pbox->y2 > intelScreen->height) + pbox->y2 > intelScreen->height) { + _mesa_warning(&intel->ctx, "Bad cliprect in intelCopyBuffer()"); continue; - + } + BEGIN_BATCH( 8); OUT_BATCH( CMD ); OUT_BATCH( BR13 ); @@ -402,7 +419,7 @@ void intelCopyBuffer( const __DRIdrawablePrivate *dPriv ) void intelEmitFillBlitLocked( intelContextPtr intel, GLuint cpp, - GLshort dst_pitch, + GLshort dst_pitch, /* in bytes */ GLuint dst_offset, GLshort x, GLshort y, GLshort w, GLshort h, @@ -411,8 +428,6 @@ void intelEmitFillBlitLocked( intelContextPtr intel, GLuint BR13, CMD; BATCH_LOCALS; - dst_pitch *= cpp; - switch(cpp) { case 1: case 2: @@ -502,13 +517,17 @@ void intelClearWithBlit(GLcontext *ctx, GLbitfield flags, GLboolean all, intelScreenPrivate *intelScreen = intel->intelScreen; GLuint clear_depth, clear_color; GLint cx, cy; - GLint pitch = intelScreen->front.pitch; + GLint pitch; GLint cpp = intelScreen->cpp; GLint i; GLuint BR13, CMD, D_CMD; BATCH_LOCALS; - + intelFlush( &intel->ctx ); + LOCK_HARDWARE( intel ); + + pitch = intelScreen->front.pitch; + clear_color = intel->ClearColor; clear_depth = 0; @@ -522,11 +541,11 @@ void intelClearWithBlit(GLcontext *ctx, GLbitfield flags, GLboolean all, switch(cpp) { case 2: - BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24); + BR13 = (0xF0 << 16) | (pitch) | (1<<24); D_CMD = CMD = XY_COLOR_BLT_CMD; break; case 4: - BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24) | (1<<25); + BR13 = (0xF0 << 16) | (pitch) | (1<<24) | (1<<25); CMD = (XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB); @@ -535,13 +554,11 @@ void intelClearWithBlit(GLcontext *ctx, GLbitfield flags, GLboolean all, if (flags & BUFFER_BIT_STENCIL) D_CMD |= XY_COLOR_BLT_WRITE_ALPHA; break; default: - BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24); + BR13 = (0xF0 << 16) | (pitch) | (1<<24); D_CMD = CMD = XY_COLOR_BLT_CMD; break; } - intelFlush( &intel->ctx ); - LOCK_HARDWARE( intel ); { /* flip top to bottom */ cy = intel->driDrawable->h-cy1-ch; @@ -635,10 +652,17 @@ void intelDestroyBatchBuffer( GLcontext *ctx ) { intelContextPtr intel = INTEL_CONTEXT(ctx); - if (intel->alloc.ptr) { + if (intel->alloc.offset) { intelFreeAGP( intel, intel->alloc.ptr ); - intel->alloc.ptr = 0; + intel->alloc.ptr = NULL; + intel->alloc.offset = 0; + } + else if (intel->alloc.ptr) { + free(intel->alloc.ptr); + intel->alloc.ptr = NULL; } + + memset(&intel->batch, 0, sizeof(intel->batch)); } @@ -646,12 +670,9 @@ void intelInitBatchBuffer( GLcontext *ctx ) { intelContextPtr intel = INTEL_CONTEXT(ctx); - if (!intel->intelScreen->allow_batchbuffer || getenv("INTEL_NO_BATCH")) { - intel->alloc.size = 8 * 1024; - intel->alloc.ptr = malloc( intel->alloc.size ); - intel->alloc.offset = 0; - } - else { + /* This path isn't really safe with rotate: + */ + if (getenv("INTEL_BATCH") && intel->intelScreen->allow_batchbuffer) { switch (intel->intelScreen->deviceID) { case PCI_CHIP_I865_G: /* HW bug? Seems to crash if batchbuffer crosses 4k boundary. @@ -666,23 +687,28 @@ void intelInitBatchBuffer( GLcontext *ctx ) break; } + /* KW: temporary - this make crashes & lockups more frequent, so + * leave in until they are solved. + */ + intel->alloc.size = 8 * 1024; + intel->alloc.ptr = intelAllocateAGP( intel, intel->alloc.size ); if (intel->alloc.ptr) intel->alloc.offset = intelAgpOffsetFromVirtual( intel, intel->alloc.ptr ); + else + intel->alloc.offset = 0; /* OK? */ } + /* The default is now to use a local buffer and pass that to the + * kernel. This is also a fallback if allocation fails on the + * above path: + */ if (!intel->alloc.ptr) { - FALLBACK(intel, INTEL_FALLBACK_NO_BATCHBUFFER, 1); + intel->alloc.size = 8 * 1024; + intel->alloc.ptr = malloc( intel->alloc.size ); + intel->alloc.offset = 0; } - else { - intel->prim.flush = 0; - intel->vtbl.emit_invarient_state( intel ); - /* Make sure this gets to the hardware, even if we have no cliprects: - */ - LOCK_HARDWARE( intel ); - intelFlushBatchLocked( intel, GL_TRUE, GL_FALSE, GL_TRUE ); - UNLOCK_HARDWARE( intel ); - } + assert(intel->alloc.ptr); } diff --git a/src/mesa/drivers/dri/i915/intel_batchbuffer.h b/src/mesa/drivers/dri/i915/intel_batchbuffer.h index bd879af159..dcc63b23c8 100644 --- a/src/mesa/drivers/dri/i915/intel_batchbuffer.h +++ b/src/mesa/drivers/dri/i915/intel_batchbuffer.h @@ -47,6 +47,7 @@ do { \ (n), __FUNCTION__, intel->batch.space/4); \ if (intel->batch.space < (n)*4) \ intelFlushBatch(intel, GL_TRUE); \ + if (intel->batch.space == intel->batch.size) intel->batch.func = __FUNCTION__; \ batch_ptr = intel->batch.ptr; \ } while (0) diff --git a/src/mesa/drivers/dri/i915/intel_context.c b/src/mesa/drivers/dri/i915/intel_context.c index 170d1df25d..60b588e7e0 100644 --- a/src/mesa/drivers/dri/i915/intel_context.c +++ b/src/mesa/drivers/dri/i915/intel_context.c @@ -118,6 +118,8 @@ const GLubyte *intelGetString( GLcontext *ctx, GLenum name ) chipset = "Intel(R) 915GM"; break; case PCI_CHIP_I945_G: chipset = "Intel(R) 945G"; break; + case PCI_CHIP_I945_GM: + chipset = "Intel(R) 945GM"; break; default: chipset = "Unknown Intel Chipset"; break; } @@ -256,8 +258,8 @@ void intelInitDriverFunctions( struct dd_function_table *functions ) { _mesa_init_driver_functions( functions ); - functions->Flush = intelFlush; functions->Clear = intelClear; + functions->Flush = intelglFlush; functions->Finish = intelFinish; functions->GetBufferSize = intelBufferSize; functions->ResizeBuffers = _mesa_resize_framebuffer; @@ -273,6 +275,20 @@ void intelInitDriverFunctions( struct dd_function_table *functions ) intelInitStateFuncs( functions ); } +static void intel_emit_invarient_state( GLcontext *ctx ) +{ + intelContextPtr intel = INTEL_CONTEXT(ctx); + + intel->vtbl.emit_invarient_state( intel ); + intel->prim.flush = 0; + + /* Make sure this gets to the hardware, even if we have no cliprects: + */ + LOCK_HARDWARE( intel ); + intelFlushBatchLocked( intel, GL_TRUE, GL_FALSE, GL_TRUE ); + UNLOCK_HARDWARE( intel ); +} + GLboolean intelInitContext( intelContextPtr intel, @@ -387,7 +403,8 @@ GLboolean intelInitContext( intelContextPtr intel, /* DRI_TEXMGR_DO_TEXTURE_RECT ); */ - intel->prim.flush = intelInitBatchBuffer; + intelInitBatchBuffer(&intel->ctx); + intel->prim.flush = intel_emit_invarient_state; intel->prim.primitive = ~0; @@ -580,12 +597,40 @@ GLboolean intelMakeCurrent(__DRIcontextPrivate *driContextPriv, return GL_TRUE; } +/** + * Use the information in the sarea to update the screen parameters + * related to screen rotation. + */ +static void +intelUpdateScreenRotation(intelContextPtr intel, + __DRIscreenPrivate *sPriv, + drmI830Sarea *sarea) +{ + intelScreenPrivate *intelScreen = (intelScreenPrivate *)sPriv->private; + intelRegion *colorBuf; + + intelUnmapScreenRegions(intelScreen); + + intelUpdateScreenFromSAREA(intelScreen, sarea); + + /* update the current hw offsets for the color and depth buffers */ + if (intel->ctx.DrawBuffer->_ColorDrawBufferMask[0] == BUFFER_BIT_BACK_LEFT) + colorBuf = &intelScreen->back; + else + colorBuf = &intelScreen->front; + intel->vtbl.update_color_z_regions(intel, colorBuf, &intelScreen->depth); + + if (!intelMapScreenRegions(sPriv)) { + fprintf(stderr, "ERROR Remapping screen regions!!!\n"); + } +} + void intelGetLock( intelContextPtr intel, GLuint flags ) { __DRIdrawablePrivate *dPriv = intel->driDrawable; __DRIscreenPrivate *sPriv = intel->driScreen; + intelScreenPrivate *intelScreen = (intelScreenPrivate *)sPriv->private; drmI830Sarea * sarea = intel->sarea; - int me = intel->hHWContext; unsigned i; drmGetLock(intel->driFd, intel->hHWContext, flags); @@ -598,32 +643,54 @@ void intelGetLock( intelContextPtr intel, GLuint flags ) if (dPriv) DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv); + if (dPriv && intel->lastStamp != dPriv->lastStamp) { + intelWindowMoved( intel ); + intel->lastStamp = dPriv->lastStamp; + } + /* If we lost context, need to dump all registers to hardware. * Note that we don't care about 2d contexts, even if they perform * accelerated commands, so the DRI locking in the X server is even * more broken than usual. */ - if (sarea->ctxOwner != me) { - intel->perf_boxes |= I830_BOX_LOST_CONTEXT; - sarea->ctxOwner = me; + if (sarea->width != intelScreen->width || + sarea->height != intelScreen->height || + sarea->rotation != intelScreen->current_rotation) { + intelUpdateScreenRotation(intel, sPriv, sarea); + + /* This will drop the outstanding batchbuffer on the floor */ + intel->batch.ptr -= (intel->batch.size - intel->batch.space); + intel->batch.space = intel->batch.size; + /* lose all primitives */ + intel->prim.primitive = ~0; + intel->prim.start_ptr = 0; + intel->prim.flush = 0; + intel->vtbl.lost_hardware( intel ); + + intel->lastStamp = 0; /* force window update */ + + /* Release batch buffer + */ + intelDestroyBatchBuffer(&intel->ctx); + intelInitBatchBuffer(&intel->ctx); + intel->prim.flush = intel_emit_invarient_state; + + /* Still need to reset the global LRU? + */ + intel_driReinitTextureHeap( intel->texture_heaps[0], intel->intelScreen->tex.size ); } /* Shared texture managment - if another client has played with * texture space, figure out which if any of our textures have been * ejected, and update our global LRU. */ - for ( i = 0 ; i < intel->nr_heaps ; i++ ) { DRI_AGE_TEXTURES( intel->texture_heaps[ i ] ); } - - if (dPriv && intel->lastStamp != dPriv->lastStamp) { - intelWindowMoved( intel ); - intel->lastStamp = dPriv->lastStamp; - } } + void intelSwapBuffers( __DRIdrawablePrivate *dPriv ) { if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) { @@ -632,12 +699,16 @@ void intelSwapBuffers( __DRIdrawablePrivate *dPriv ) intel = (intelContextPtr) dPriv->driContextPriv->driverPrivate; ctx = &intel->ctx; if (ctx->Visual.doubleBufferMode) { + intelScreenPrivate *screen = intel->intelScreen; _mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */ if ( 0 /*intel->doPageFlip*/ ) { /* doPageFlip is never set !!! */ intelPageFlip( dPriv ); } else { intelCopyBuffer( dPriv ); } + if (screen->current_rotation != 0) { + intelRotateWindow(intel, dPriv, BUFFER_BIT_FRONT_LEFT); + } } } else { /* XXX this shouldn't be an error but we can't handle it for now */ diff --git a/src/mesa/drivers/dri/i915/intel_context.h b/src/mesa/drivers/dri/i915/intel_context.h index 20e2660dc3..b1c175726d 100644 --- a/src/mesa/drivers/dri/i915/intel_context.h +++ b/src/mesa/drivers/dri/i915/intel_context.h @@ -111,9 +111,12 @@ struct intel_context void (*update_texture_state)( intelContextPtr intel ); void (*render_start)( intelContextPtr intel ); - void (*set_draw_offset)( intelContextPtr intel, int offset ); + void (*set_color_region)( intelContextPtr intel, const intelRegion *reg ); + void (*set_z_region)( intelContextPtr intel, const intelRegion *reg ); + void (*update_color_z_regions)(intelContextPtr intel, + const intelRegion *colorRegion, + const intelRegion *depthRegion); void (*emit_flush)( intelContextPtr intel ); - void (*reduced_primitive_state)( intelContextPtr intel, GLenum rprim ); GLboolean (*check_vertex_size)( intelContextPtr intel, GLuint expected ); @@ -122,6 +125,9 @@ struct intel_context GLboolean all, GLint cx, GLint cy, GLint cw, GLint ch); + void (*rotate_window)( intelContextPtr intel, + __DRIdrawablePrivate *dPriv, GLuint srcBuf); + intelTextureObjectPtr (*alloc_tex_obj)( struct gl_texture_object *tObj ); } vtbl; @@ -135,6 +141,11 @@ struct intel_context GLint size; GLint space; GLubyte *ptr; + GLuint counter; + GLuint last_emit_state; + GLboolean contains_geometry; + const char *func; + GLuint last_swap; } batch; struct { @@ -204,9 +215,11 @@ struct intel_context intel_line_func draw_line; intel_tri_func draw_tri; - /* These refer to the current draw (front vs. back) buffer: + /* Drawing buffer state */ - GLuint drawOffset; /* agp offset of drawbuffer */ + intelRegion *drawRegion; /* current drawing buffer */ + intelRegion *readRegion; /* current reading buffer */ + int drawX; /* origin of drawable in draw buffer */ int drawY; GLuint numClipRects; /* cliprects for that buffer */ @@ -411,6 +424,7 @@ extern int INTEL_DEBUG; #define PCI_CHIP_I915_G 0x2582 #define PCI_CHIP_I915_GM 0x2592 #define PCI_CHIP_I945_G 0x2772 +#define PCI_CHIP_I945_GM 0x27A2 /* ================================================================ diff --git a/src/mesa/drivers/dri/i915/intel_ioctl.c b/src/mesa/drivers/dri/i915/intel_ioctl.c index dd1e1d7587..8834f871ee 100644 --- a/src/mesa/drivers/dri/i915/intel_ioctl.c +++ b/src/mesa/drivers/dri/i915/intel_ioctl.c @@ -45,7 +45,7 @@ static int intelEmitIrqLocked( intelContextPtr intel ) { drmI830IrqEmit ie; - int ret, seq = 0; + int ret, seq; assert(((*(int *)intel->driHwLock) & ~DRM_LOCK_CONT) == (DRM_LOCK_HELD|intel->hHWContext)); @@ -130,7 +130,7 @@ void intelRefillBatchLocked( intelContextPtr intel, GLboolean allow_unlock ) fprintf(stderr, "%s: now using half %d\n", __FUNCTION__, buf); intel->batch.start_offset = intel->alloc.offset + buf * half; - intel->batch.ptr = (GLubyte *)intel->alloc.ptr + buf * half; + intel->batch.ptr = (char *)intel->alloc.ptr + buf * half; intel->batch.size = half - 8; intel->batch.space = half - 8; assert(intel->batch.space >= 0); @@ -149,14 +149,15 @@ void intelFlushBatchLocked( intelContextPtr intel, assert(intel->locked); if (0) - fprintf(stderr, "%s used %d of %d offset %x..%x refill %d\n", + fprintf(stderr, "%s used %d of %d offset %x..%x refill %d (started in %s)\n", __FUNCTION__, (intel->batch.size - intel->batch.space), intel->batch.size, intel->batch.start_offset, intel->batch.start_offset + (intel->batch.size - intel->batch.space), - refill); + refill, + intel->batch.func); /* Throw away non-effective packets. Won't work once we have * hardware contexts which would preserve statechanges beyond a @@ -183,6 +184,12 @@ void intelFlushBatchLocked( intelContextPtr intel, } if (intel->batch.space != intel->batch.size) { + + if (intel->sarea->ctxOwner != intel->hHWContext) { + intel->perf_boxes |= I830_BOX_LOST_CONTEXT; + intel->sarea->ctxOwner = intel->hHWContext; + } + batch.start = intel->batch.start_offset; batch.used = intel->batch.size - intel->batch.space; batch.cliprects = intel->pClipRects; @@ -210,13 +217,6 @@ void intelFlushBatchLocked( intelContextPtr intel, (int *)(intel->batch.ptr - batch.used), batch.used ); - if (0) - fprintf(stderr, "%s: 0x%x..0x%x DR4: %x cliprects: %d\n", - __FUNCTION__, - batch.start, - batch.start + batch.used, - batch.DR4, batch.num_cliprects); - intel->batch.start_offset += batch.used; intel->batch.size -= batch.used; @@ -268,6 +268,12 @@ void intelFlushBatchLocked( intelContextPtr intel, /* FIXME: use hardware contexts to avoid 'losing' hardware after * each buffer flush. */ + if (intel->batch.contains_geometry) + assert(intel->batch.last_emit_state == intel->batch.counter); + + intel->batch.counter++; + intel->batch.contains_geometry = 0; + intel->batch.func = 0; intel->vtbl.lost_hardware( intel ); } @@ -288,11 +294,6 @@ void intelFlushBatch( intelContextPtr intel, GLboolean refill ) } - - - - - void intelWaitForIdle( intelContextPtr intel ) { if (0) @@ -309,7 +310,28 @@ void intelWaitForIdle( intelContextPtr intel ) } +/** + * Check if we need to rotate/warp the front color buffer to the + * rotated screen. We generally need to do this when we get a glFlush + * or glFinish after drawing to the front color buffer. + */ +static void +intelCheckFrontRotate(GLcontext *ctx) +{ + intelContextPtr intel = INTEL_CONTEXT( ctx ); + if (intel->ctx.DrawBuffer->_ColorDrawBufferMask[0] == BUFFER_BIT_FRONT_LEFT) { + intelScreenPrivate *screen = intel->intelScreen; + if (screen->current_rotation != 0) { + __DRIdrawablePrivate *dPriv = intel->driDrawable; + intelRotateWindow(intel, dPriv, BUFFER_BIT_FRONT_LEFT); + } + } +} + +/** + * NOT directly called via glFlush. + */ void intelFlush( GLcontext *ctx ) { intelContextPtr intel = INTEL_CONTEXT( ctx ); @@ -323,11 +345,23 @@ void intelFlush( GLcontext *ctx ) intelFlushBatch( intel, GL_FALSE ); } + +/** + * Called via glFlush. + */ +void intelglFlush( GLcontext *ctx ) +{ + intelFlush(ctx); + intelCheckFrontRotate(ctx); +} + + void intelFinish( GLcontext *ctx ) { intelContextPtr intel = INTEL_CONTEXT( ctx ); intelFlush( ctx ); intelWaitForIdle( intel ); + intelCheckFrontRotate(ctx); } @@ -395,10 +429,19 @@ void intelClear(GLcontext *ctx, GLbitfield mask, GLboolean all, } +void +intelRotateWindow(intelContextPtr intel, __DRIdrawablePrivate *dPriv, + GLuint srcBuffer) +{ + if (intel->vtbl.rotate_window) { + intel->vtbl.rotate_window(intel, dPriv, srcBuffer); + } +} + void *intelAllocateAGP( intelContextPtr intel, GLsizei size ) { - int region_offset = 0; + int region_offset; drmI830MemAlloc alloc; int ret; diff --git a/src/mesa/drivers/dri/i915/intel_ioctl.h b/src/mesa/drivers/dri/i915/intel_ioctl.h index 7e62951676..07b8a9c8df 100644 --- a/src/mesa/drivers/dri/i915/intel_ioctl.h +++ b/src/mesa/drivers/dri/i915/intel_ioctl.h @@ -36,6 +36,10 @@ extern void intelClear(GLcontext *ctx, GLbitfield mask, GLboolean all, GLint cx, GLint cy, GLint cw, GLint ch); extern void intelPageFlip( const __DRIdrawablePrivate *dpriv ); + +extern void intelRotateWindow(intelContextPtr intel, + __DRIdrawablePrivate *dPriv, GLuint srcBuffer); + extern void intelWaitForIdle( intelContextPtr intel ); extern void intelFlushBatch( intelContextPtr intel, GLboolean refill ); extern void intelFlushBatchLocked( intelContextPtr intel, @@ -45,6 +49,7 @@ extern void intelFlushBatchLocked( intelContextPtr intel, extern void intelRefillBatchLocked( intelContextPtr intel, GLboolean allow_unlock ); extern void intelFinish( GLcontext *ctx ); extern void intelFlush( GLcontext *ctx ); +extern void intelglFlush( GLcontext *ctx ); extern void *intelAllocateAGP( intelContextPtr intel, GLsizei size ); extern void intelFreeAGP( intelContextPtr intel, void *pointer ); diff --git a/src/mesa/drivers/dri/i915/intel_pixel.c b/src/mesa/drivers/dri/i915/intel_pixel.c index a79bed45fb..aaafe84a6a 100644 --- a/src/mesa/drivers/dri/i915/intel_pixel.c +++ b/src/mesa/drivers/dri/i915/intel_pixel.c @@ -94,16 +94,20 @@ check_color_per_fragment_ops( const GLcontext *ctx ) } - +/** + * Clip the given rectangle against the buffer's bounds (including scissor). + * \param size returns the + * \return GL_TRUE if any pixels remain, GL_FALSE if totally clipped. + * + * XXX Replace this with _mesa_clip_drawpixels() and _mesa_clip_readpixels() + * from Mesa 6.4. We shouldn't apply scissor for ReadPixels. + */ static GLboolean clip_pixelrect( const GLcontext *ctx, const GLframebuffer *buffer, GLint *x, GLint *y, - GLsizei *width, GLsizei *height, - GLint *size ) + GLsizei *width, GLsizei *height) { - intelContextPtr intel = INTEL_CONTEXT(ctx); - /* left clipping */ if (*x < buffer->_Xmin) { *width -= (buffer->_Xmin - *x); @@ -130,12 +134,41 @@ clip_pixelrect( const GLcontext *ctx, if (*height <= 0) return GL_FALSE; - *size = ((*y + *height - 1) * intel->intelScreen->front.pitch + - (*x + *width - 1) * intel->intelScreen->cpp); + return GL_TRUE; +} + +/** + * Compute intersection of a clipping rectangle and pixel rectangle, + * returning results in x/y/w/hOut vars. + * \return GL_TRUE if there's intersection, GL_FALSE if disjoint. + */ +static INLINE GLboolean +intersect_region(const drm_clip_rect_t *box, + GLint x, GLint y, GLsizei width, GLsizei height, + GLint *xOut, GLint *yOut, GLint *wOut, GLint *hOut) +{ + GLint bx = box->x1; + GLint by = box->y1; + GLint bw = box->x2 - bx; + GLint bh = box->y2 - by; + + if (bx < x) bw -= x - bx, bx = x; + if (by < y) bh -= y - by, by = y; + if (bx + bw > x + width) bw = x + width - bx; + if (by + bh > y + height) bh = y + height - by; + if (bw <= 0) return GL_FALSE; + if (bh <= 0) return GL_FALSE; + + *xOut = bx; + *yOut = by; + *wOut = bw; + *hOut = bh; return GL_TRUE; } + + static GLboolean intelTryReadPixels( GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, @@ -144,7 +177,7 @@ intelTryReadPixels( GLcontext *ctx, GLvoid *pixels ) { intelContextPtr intel = INTEL_CONTEXT(ctx); - GLint size = 0; + GLint size = 0; /* not really used */ GLint pitch = pack->RowLength ? pack->RowLength : width; if (INTEL_DEBUG & DEBUG_PIXEL) @@ -180,7 +213,7 @@ intelTryReadPixels( GLcontext *ctx, /* Although the blits go on the command buffer, need to do this and - * fire with lock held to guarentee cliprects and drawOffset are + * fire with lock held to guarentee cliprects and drawing offset are * correct. * * This is an unusual situation however, as the code which flushes @@ -192,14 +225,15 @@ intelTryReadPixels( GLcontext *ctx, { __DRIdrawablePrivate *dPriv = intel->driDrawable; int nbox = dPriv->numClipRects; - int src_offset = intel->drawOffset; + int src_offset = intel->readRegion->offset; int src_pitch = intel->intelScreen->front.pitch; int dst_offset = intelAgpOffsetFromVirtual( intel, pixels); drm_clip_rect_t *box = dPriv->pClipRects; int i; - if (!clip_pixelrect(ctx, ctx->ReadBuffer, &x, &y, &width, &height, - &size)) { + assert(dst_offset != ~0); /* should have been caught above */ + + if (!clip_pixelrect(ctx, ctx->ReadBuffer, &x, &y, &width, &height)) { UNLOCK_HARDWARE( intel ); if (INTEL_DEBUG & DEBUG_PIXEL) fprintf(stderr, "%s totally clipped -- nothing to do\n", @@ -207,37 +241,32 @@ intelTryReadPixels( GLcontext *ctx, return GL_TRUE; } - + /* convert to screen coords (y=0=top) */ y = dPriv->h - y - height; x += dPriv->x; y += dPriv->y; - if (INTEL_DEBUG & DEBUG_PIXEL) fprintf(stderr, "readpixel blit src_pitch %d dst_pitch %d\n", src_pitch, pitch); + /* We don't really have to do window clipping for readpixels. + * The OpenGL spec says that pixels read from outside the + * visible window region (pixel ownership) have undefined value. + */ for (i = 0 ; i < nbox ; i++) { - GLint bx = box[i].x1; - GLint by = box[i].y1; - GLint bw = box[i].x2 - bx; - GLint bh = box[i].y2 - by; - - if (bx < x) bw -= x - bx, bx = x; - if (by < y) bh -= y - by, by = y; - if (bx + bw > x + width) bw = x + width - bx; - if (by + bh > y + height) bh = y + height - by; - if (bw <= 0) continue; - if (bh <= 0) continue; - - intelEmitCopyBlitLocked( intel, - intel->intelScreen->cpp, - src_pitch, src_offset, - pitch, dst_offset, - bx, by, - bx - x, by - y, - bw, bh ); + GLint bx, by, bw, bh; + if (intersect_region(box+i, x, y, width, height, + &bx, &by, &bw, &bh)) { + intelEmitCopyBlitLocked( intel, + intel->intelScreen->cpp, + src_pitch, src_offset, + pitch, dst_offset, + bx, by, + bx - x, by - y, + bw, bh ); + } } } UNLOCK_HARDWARE( intel ); @@ -257,7 +286,7 @@ intelReadPixels( GLcontext *ctx, fprintf(stderr, "%s\n", __FUNCTION__); if (!intelTryReadPixels( ctx, x, y, width, height, format, type, pack, - pixels)) + pixels)) _swrast_ReadPixels( ctx, x, y, width, height, format, type, pack, pixels); } @@ -276,10 +305,11 @@ static void do_draw_pix( GLcontext *ctx, drm_clip_rect_t *box = dPriv->pClipRects; int nbox = dPriv->numClipRects; int i; - int size; int src_offset = intelAgpOffsetFromVirtual( intel, pixels); int src_pitch = pitch; + assert(src_offset != ~0); /* should be caught earlier */ + if (INTEL_DEBUG & DEBUG_PIXEL) fprintf(stderr, "%s\n", __FUNCTION__); @@ -290,8 +320,7 @@ static void do_draw_pix( GLcontext *ctx, y -= height; /* cope with pixel zoom */ if (!clip_pixelrect(ctx, ctx->DrawBuffer, - &x, &y, &width, &height, - &size)) { + &x, &y, &width, &height)) { UNLOCK_HARDWARE( intel ); return; } @@ -300,29 +329,20 @@ static void do_draw_pix( GLcontext *ctx, x += dPriv->x; y += dPriv->y; - for (i = 0 ; i < nbox ; i++ ) { - GLint bx = box[i].x1; - GLint by = box[i].y1; - GLint bw = box[i].x2 - bx; - GLint bh = box[i].y2 - by; - - if (bx < x) bw -= x - bx, bx = x; - if (by < y) bh -= y - by, by = y; - if (bx + bw > x + width) bw = x + width - bx; - if (by + bh > y + height) bh = y + height - by; - if (bw <= 0) continue; - if (bh <= 0) continue; - - intelEmitCopyBlitLocked( intel, - intel->intelScreen->cpp, - src_pitch, src_offset, - intel->intelScreen->front.pitch, - intel->drawOffset, - bx - x, by - y, - bx, by, - bw, bh ); + GLint bx, by, bw, bh; + if (intersect_region(box + i, x, y, width, height, + &bx, &by, &bw, &bh)) { + intelEmitCopyBlitLocked( intel, + intel->intelScreen->cpp, + src_pitch, src_offset, + intel->intelScreen->front.pitch, + intel->drawRegion->offset, + bx - x, by - y, + bx, by, + bw, bh ); + } } } UNLOCK_HARDWARE( intel ); @@ -331,7 +351,6 @@ static void do_draw_pix( GLcontext *ctx, - static GLboolean intelTryDrawPixels( GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, @@ -352,7 +371,7 @@ intelTryDrawPixels( GLcontext *ctx, case GL_RGB: case GL_RGBA: case GL_BGRA: - dest = intel->drawOffset; + dest = intel->drawRegion->offset; /* Planemask doesn't have full support in blits. */ @@ -391,8 +410,7 @@ intelTryDrawPixels( GLcontext *ctx, if ( intelIsAgpMemory(intel, pixels, size) ) { - do_draw_pix( ctx, x, y, width, height, pitch, pixels, - dest ); + do_draw_pix( ctx, x, y, width, height, pitch, pixels, dest ); return GL_TRUE; } else if (0) @@ -418,7 +436,7 @@ intelDrawPixels( GLcontext *ctx, fprintf(stderr, "%s\n", __FUNCTION__); if (!intelTryDrawPixels( ctx, x, y, width, height, format, type, - unpack, pixels )) + unpack, pixels )) _swrast_DrawPixels( ctx, x, y, width, height, format, type, unpack, pixels ); } diff --git a/src/mesa/drivers/dri/i915/intel_rotate.c b/src/mesa/drivers/dri/i915/intel_rotate.c new file mode 100644 index 0000000000..a77640ee54 --- /dev/null +++ b/src/mesa/drivers/dri/i915/intel_rotate.c @@ -0,0 +1,221 @@ + +/** + * Routines for simple 2D->2D transformations for rotated, flipped screens. + * + * XXX This code is not intel-specific. Move it into a common/utility + * someday. + */ + +#include "intel_rotate.h" + +#define MIN2(A, B) ( ((A) < (B)) ? (A) : (B) ) + +#define ABS(A) ( ((A) < 0) ? -(A) : (A) ) + + +void +matrix23Set(struct matrix23 *m, + int m00, int m01, int m02, + int m10, int m11, int m12) +{ + m->m00 = m00; m->m01 = m01; m->m02 = m02; + m->m10 = m10; m->m11 = m11; m->m12 = m12; +} + + +/* + * Transform (x,y) coordinate by the given matrix. + */ +void +matrix23TransformCoordf(const struct matrix23 *m, float *x, float *y) +{ + const float x0 = *x; + const float y0 = *y; + + *x = m->m00 * x0 + m->m01 * y0 + m->m02; + *y = m->m10 * x0 + m->m11 * y0 + m->m12; +} + + +void +matrix23TransformCoordi(const struct matrix23 *m, int *x, int *y) +{ + const int x0 = *x; + const int y0 = *y; + + *x = m->m00 * x0 + m->m01 * y0 + m->m02; + *y = m->m10 * x0 + m->m11 * y0 + m->m12; +} + + +/* + * Transform a width and height by the given matrix. + * XXX this could be optimized quite a bit. + */ +void +matrix23TransformDistance(const struct matrix23 *m, int *xDist, int *yDist) +{ + int x0 = 0, y0 = 0; + int x1 = *xDist, y1 = 0; + int x2 = 0, y2 = *yDist; + matrix23TransformCoordi(m, &x0, &y0); + matrix23TransformCoordi(m, &x1, &y1); + matrix23TransformCoordi(m, &x2, &y2); + + *xDist = (x1 - x0) + (x2 - x0); + *yDist = (y1 - y0) + (y2 - y0); + + if (*xDist < 0) + *xDist = -*xDist; + if (*yDist < 0) + *yDist = -*yDist; +} + + +/** + * Transform the rect defined by (x, y, w, h) by m. + */ +void +matrix23TransformRect(const struct matrix23 *m, int *x, int *y, int *w, int *h) +{ + int x0 = *x, y0 = *y; + int x1 = *x + *w, y1 = *y; + int x2 = *x + *w, y2 = *y + *h; + int x3 = *x, y3 = *y + *h; + matrix23TransformCoordi(m, &x0, &y0); + matrix23TransformCoordi(m, &x1, &y1); + matrix23TransformCoordi(m, &x2, &y2); + matrix23TransformCoordi(m, &x3, &y3); + *w = ABS(x1 - x0) + ABS(x2 - x1); + /**w = ABS(*w);*/ + *h = ABS(y1 - y0) + ABS(y2 - y1); + /**h = ABS(*h);*/ + *x = MIN2(x0, x1); + *x = MIN2(*x, x2); + *y = MIN2(y0, y1); + *y = MIN2(*y, y2); +} + + +/* + * Make rotation matrix for width X height screen. + */ +void +matrix23Rotate(struct matrix23 *m, int width, int height, int angle) +{ + switch (angle) { + case 0: + matrix23Set(m, 1, 0, 0, 0, 1, 0); + break; + case 90: + matrix23Set(m, 0, 1, 0, -1, 0, width); + break; + case 180: + matrix23Set(m, -1, 0, width, 0, -1, height); + break; + case 270: + matrix23Set(m, 0, -1, height, 1, 0, 0); + break; + default: + /*abort()*/; + } +} + + +/* + * Make flip/reflection matrix for width X height screen. + */ +void +matrix23Flip(struct matrix23 *m, int width, int height, int xflip, int yflip) +{ + if (xflip) { + m->m00 = -1; m->m01 = 0; m->m02 = width - 1; + } + else { + m->m00 = 1; m->m01 = 0; m->m02 = 0; + } + if (yflip) { + m->m10 = 0; m->m11 = -1; m->m12 = height - 1; + } + else { + m->m10 = 0; m->m11 = 1; m->m12 = 0; + } +} + + +/* + * result = a * b + */ +void +matrix23Multiply(struct matrix23 *result, + const struct matrix23 *a, const struct matrix23 *b) +{ + result->m00 = a->m00 * b->m00 + a->m01 * b->m10; + result->m01 = a->m00 * b->m01 + a->m01 * b->m11; + result->m02 = a->m00 * b->m02 + a->m01 * b->m12 + a->m02; + + result->m10 = a->m10 * b->m00 + a->m11 * b->m10; + result->m11 = a->m10 * b->m01 + a->m11 * b->m11; + result->m12 = a->m10 * b->m02 + a->m11 * b->m12 + a->m12; +} + + +#if 000 + +#include <stdio.h> + +int +main(int argc, char *argv[]) +{ + int width = 500, height = 400; + int rot; + int fx = 0, fy = 0; /* flip x and/or y ? */ + int coords[4][2]; + + /* four corner coords to test with */ + coords[0][0] = 0; coords[0][1] = 0; + coords[1][0] = width-1; coords[1][1] = 0; + coords[2][0] = width-1; coords[2][1] = height-1; + coords[3][0] = 0; coords[3][1] = height-1; + + + for (rot = 0; rot < 360; rot += 90) { + struct matrix23 rotate, flip, m; + int i; + + printf("Rot %d, xFlip %d, yFlip %d:\n", rot, fx, fy); + + /* make transformation matrix 'm' */ + matrix23Rotate(&rotate, width, height, rot); + matrix23Flip(&flip, width, height, fx, fy); + matrix23Multiply(&m, &rotate, &flip); + + /* xform four coords */ + for (i = 0; i < 4; i++) { + int x = coords[i][0]; + int y = coords[i][1]; + matrix23TransformCoordi(&m, &x, &y); + printf(" %d, %d -> %d %d\n", coords[i][0], coords[i][1], x, y); + } + + /* xform width, height */ + { + int x = width; + int y = height; + matrix23TransformDistance(&m, &x, &y); + printf(" %d x %d -> %d x %d\n", width, height, x, y); + } + + /* xform rect */ + { + int x = 50, y = 10, w = 200, h = 100; + matrix23TransformRect(&m, &x, &y, &w, &h); + printf(" %d,%d %d x %d -> %d, %d %d x %d\n", 50, 10, 200, 100, + x, y, w, h); + } + + } + + return 0; +} +#endif diff --git a/src/mesa/drivers/dri/i915/intel_rotate.h b/src/mesa/drivers/dri/i915/intel_rotate.h new file mode 100644 index 0000000000..0da45d20ce --- /dev/null +++ b/src/mesa/drivers/dri/i915/intel_rotate.h @@ -0,0 +1,41 @@ +#ifndef INTEL_ROTATE_H +#define INTEL_ROTATE_H 1 + +struct matrix23 +{ + int m00, m01, m02; + int m10, m11, m12; +}; + + + +extern void +matrix23Set(struct matrix23 *m, + int m00, int m01, int m02, + int m10, int m11, int m12); + +extern void +matrix23TransformCoordi(const struct matrix23 *m, int *x, int *y); + +extern void +matrix23TransformCoordf(const struct matrix23 *m, float *x, float *y); + +extern void +matrix23TransformDistance(const struct matrix23 *m, int *xDist, int *yDist); + +extern void +matrix23TransformRect(const struct matrix23 *m, + int *x, int *y, int *w, int *h); + +extern void +matrix23Rotate(struct matrix23 *m, int width, int height, int angle); + +extern void +matrix23Flip(struct matrix23 *m, int width, int height, int xflip, int yflip); + +extern void +matrix23Multiply(struct matrix23 *result, + const struct matrix23 *a, const struct matrix23 *b); + + +#endif /* INTEL_ROTATE_H */ diff --git a/src/mesa/drivers/dri/i915/intel_screen.c b/src/mesa/drivers/dri/i915/intel_screen.c index c4a2e53b3d..752379c9d4 100644 --- a/src/mesa/drivers/dri/i915/intel_screen.c +++ b/src/mesa/drivers/dri/i915/intel_screen.c @@ -42,39 +42,211 @@ #include "intel_tris.h" #include "intel_ioctl.h" - - #include "i830_dri.h" PUBLIC const char __driConfigOptions[] = DRI_CONF_BEGIN - DRI_CONF_SECTION_PERFORMANCE - DRI_CONF_FORCE_S3TC_ENABLE(false) - DRI_CONF_SECTION_END + DRI_CONF_SECTION_PERFORMANCE + DRI_CONF_FORCE_S3TC_ENABLE(false) + DRI_CONF_SECTION_END DRI_CONF_END; const GLuint __driNConfigOptions = 1; +#ifdef USE_NEW_INTERFACE +static PFNGLXCREATECONTEXTMODES create_context_modes = NULL; +#endif /*USE_NEW_INTERFACE*/ + extern const struct dri_extension card_extensions[]; -static void intelPrintDRIInfo(intelScreenPrivate *intelScreen, - __DRIscreenPrivate *sPriv, - I830DRIPtr gDRIPriv) +/** + * Map all the memory regions described by the screen. + * \return GL_TRUE if success, GL_FALSE if error. + */ +GLboolean +intelMapScreenRegions(__DRIscreenPrivate *sPriv) +{ + intelScreenPrivate *intelScreen = (intelScreenPrivate *)sPriv->private; + + if (intelScreen->front.handle) { + if (drmMap(sPriv->fd, + intelScreen->front.handle, + intelScreen->front.size, + (drmAddress *)&intelScreen->front.map) != 0) { + _mesa_problem(NULL, "drmMap(frontbuffer) failed!"); + return GL_FALSE; + } + } + else { + _mesa_warning(NULL, "no front buffer handle in intelMapScreenRegions!"); + } + + if (drmMap(sPriv->fd, + intelScreen->back.handle, + intelScreen->back.size, + (drmAddress *)&intelScreen->back.map) != 0) { + intelUnmapScreenRegions(intelScreen); + return GL_FALSE; + } + + if (drmMap(sPriv->fd, + intelScreen->depth.handle, + intelScreen->depth.size, + (drmAddress *)&intelScreen->depth.map) != 0) { + intelUnmapScreenRegions(intelScreen); + return GL_FALSE; + } + + if (drmMap(sPriv->fd, + intelScreen->tex.handle, + intelScreen->tex.size, + (drmAddress *)&intelScreen->tex.map) != 0) { + intelUnmapScreenRegions(intelScreen); + return GL_FALSE; + } + + if (0) + printf("Mappings: front: %p back: %p depth: %p tex: %p\n", + intelScreen->front.map, + intelScreen->back.map, + intelScreen->depth.map, + intelScreen->tex.map); + return GL_TRUE; +} + + +void +intelUnmapScreenRegions(intelScreenPrivate *intelScreen) +{ +#define REALLY_UNMAP 1 + if (intelScreen->front.map) { +#if REALLY_UNMAP + if (drmUnmap(intelScreen->front.map, intelScreen->front.size) != 0) + printf("drmUnmap front failed!\n"); +#endif + intelScreen->front.map = NULL; + } + if (intelScreen->back.map) { +#if REALLY_UNMAP + if (drmUnmap(intelScreen->back.map, intelScreen->back.size) != 0) + printf("drmUnmap back failed!\n"); +#endif + intelScreen->back.map = NULL; + } + if (intelScreen->depth.map) { +#if REALLY_UNMAP + drmUnmap(intelScreen->depth.map, intelScreen->depth.size); + intelScreen->depth.map = NULL; +#endif + } + if (intelScreen->tex.map) { +#if REALLY_UNMAP + drmUnmap(intelScreen->tex.map, intelScreen->tex.size); + intelScreen->tex.map = NULL; +#endif + } +} + + +static void +intelPrintDRIInfo(intelScreenPrivate *intelScreen, + __DRIscreenPrivate *sPriv, + I830DRIPtr gDRIPriv) { - fprintf(stderr, "Front size : 0x%x\n", sPriv->fbSize); - fprintf(stderr, "Front offset : 0x%x\n", intelScreen->front.offset); - fprintf(stderr, "Back size : 0x%x\n", intelScreen->back.size); - fprintf(stderr, "Back offset : 0x%x\n", intelScreen->back.offset); - fprintf(stderr, "Depth size : 0x%x\n", intelScreen->depth.size); - fprintf(stderr, "Depth offset : 0x%x\n", intelScreen->depth.offset); - fprintf(stderr, "Texture size : 0x%x\n", intelScreen->tex.size); - fprintf(stderr, "Texture offset : 0x%x\n", intelScreen->tex.offset); - fprintf(stderr, "Memory : 0x%x\n", gDRIPriv->mem); + fprintf(stderr, "*** Front size: 0x%x offset: 0x%x pitch: %d\n", + sPriv->fbSize, intelScreen->front.offset, + intelScreen->front.pitch); + fprintf(stderr, "*** Back size: 0x%x offset: 0x%x pitch: %d\n", + intelScreen->back.size, intelScreen->back.offset, + intelScreen->back.pitch); + fprintf(stderr, "*** Depth size: 0x%x offset: 0x%x pitch: %d\n", + intelScreen->depth.size, intelScreen->depth.offset, + intelScreen->depth.pitch); + fprintf(stderr, "*** Rotated size: 0x%x offset: 0x%x pitch: %d\n", + intelScreen->rotated.size, intelScreen->rotated.offset, + intelScreen->rotated.pitch); + fprintf(stderr, "*** Texture size: 0x%x offset: 0x%x\n", + intelScreen->tex.size, intelScreen->tex.offset); + fprintf(stderr, "*** Memory : 0x%x\n", gDRIPriv->mem); } + +static void +intelPrintSAREA(const drmI830Sarea *sarea) +{ + fprintf(stderr, "SAREA: sarea width %d height %d\n", sarea->width, sarea->height); + fprintf(stderr, "SAREA: pitch: %d\n", sarea->pitch); + fprintf(stderr, + "SAREA: front offset: 0x%08x size: 0x%x handle: 0x%x\n", + sarea->front_offset, sarea->front_size, + (unsigned) sarea->front_handle); + fprintf(stderr, + "SAREA: back offset: 0x%08x size: 0x%x handle: 0x%x\n", + sarea->back_offset, sarea->back_size, + (unsigned) sarea->back_handle); + fprintf(stderr, "SAREA: depth offset: 0x%08x size: 0x%x handle: 0x%x\n", + sarea->depth_offset, sarea->depth_size, + (unsigned) sarea->depth_handle); + fprintf(stderr, "SAREA: tex offset: 0x%08x size: 0x%x handle: 0x%x\n", + sarea->tex_offset, sarea->tex_size, + (unsigned) sarea->tex_handle); + fprintf(stderr, "SAREA: rotation: %d\n", sarea->rotation); + fprintf(stderr, + "SAREA: rotated offset: 0x%08x size: 0x%x\n", + sarea->rotated_offset, sarea->rotated_size); + fprintf(stderr, "SAREA: rotated pitch: %d\n", sarea->rotated_pitch); +} + + +/** + * A number of the screen parameters are obtained/computed from + * information in the SAREA. This function updates those parameters. + */ +void +intelUpdateScreenFromSAREA(intelScreenPrivate *intelScreen, + drmI830Sarea *sarea) +{ + intelScreen->width = sarea->width; + intelScreen->height = sarea->height; + + intelScreen->front.offset = sarea->front_offset; + intelScreen->front.pitch = sarea->pitch * intelScreen->cpp; + intelScreen->front.handle = sarea->front_handle; + intelScreen->front.size = sarea->front_size; + + intelScreen->back.offset = sarea->back_offset; + intelScreen->back.pitch = sarea->pitch * intelScreen->cpp; + intelScreen->back.handle = sarea->back_handle; + intelScreen->back.size = sarea->back_size; + + intelScreen->depth.offset = sarea->depth_offset; + intelScreen->depth.pitch = sarea->pitch * intelScreen->cpp; + intelScreen->depth.handle = sarea->depth_handle; + intelScreen->depth.size = sarea->depth_size; + + intelScreen->tex.offset = sarea->tex_offset; + intelScreen->logTextureGranularity = sarea->log_tex_granularity; + intelScreen->tex.handle = sarea->tex_handle; + intelScreen->tex.size = sarea->tex_size; + + intelScreen->rotated.offset = sarea->rotated_offset; + intelScreen->rotated.pitch = sarea->rotated_pitch * intelScreen->cpp; + intelScreen->rotated.size = sarea->rotated_size; + intelScreen->current_rotation = sarea->rotation; + matrix23Rotate(&intelScreen->rotMatrix, + sarea->width, sarea->height, sarea->rotation); + intelScreen->rotatedWidth = sarea->virtualX; + intelScreen->rotatedHeight = sarea->virtualY; + + if (0) + intelPrintSAREA(sarea); +} + + static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv) { intelScreenPrivate *intelScreen; I830DRIPtr gDRIPriv = (I830DRIPtr)sPriv->pDevPriv; + drmI830Sarea *sarea; PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension = (PFNGLXSCRENABLEEXTENSIONPROC) (*dri_interface->getProcAddress("glxEnableExtension")); void * const psc = sPriv->psc->screenConfigs; @@ -96,80 +268,35 @@ static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv) intelScreen->driScrnPriv = sPriv; sPriv->private = (void *)intelScreen; + intelScreen->sarea_priv_offset = gDRIPriv->sarea_priv_offset; + sarea = (drmI830Sarea *) + (((GLubyte *)sPriv->pSAREA)+intelScreen->sarea_priv_offset); intelScreen->deviceID = gDRIPriv->deviceID; - intelScreen->width = gDRIPriv->width; - intelScreen->height = gDRIPriv->height; intelScreen->mem = gDRIPriv->mem; intelScreen->cpp = gDRIPriv->cpp; - + switch (gDRIPriv->bitsPerPixel) { case 15: intelScreen->fbFormat = DV_PF_555; break; case 16: intelScreen->fbFormat = DV_PF_565; break; case 32: intelScreen->fbFormat = DV_PF_8888; break; } - - intelScreen->front.pitch = gDRIPriv->fbStride; - intelScreen->front.offset = gDRIPriv->fbOffset; - intelScreen->front.map = sPriv->pFB; - - intelScreen->back.offset = gDRIPriv->backOffset; - intelScreen->back.pitch = gDRIPriv->backPitch; - intelScreen->back.handle = gDRIPriv->backbuffer; - intelScreen->back.size = gDRIPriv->backbufferSize; - if (drmMap(sPriv->fd, - intelScreen->back.handle, - intelScreen->back.size, - (drmAddress *)&intelScreen->back.map) != 0) { - fprintf(stderr, "\nERROR: line %d, Function %s, File %s\n", - __LINE__, __FUNCTION__, __FILE__); - FREE(intelScreen); - sPriv->private = NULL; - return GL_FALSE; - } + intelUpdateScreenFromSAREA(intelScreen, sarea); - intelScreen->depth.offset = gDRIPriv->depthOffset; - intelScreen->depth.pitch = gDRIPriv->depthPitch; - intelScreen->depth.handle = gDRIPriv->depthbuffer; - intelScreen->depth.size = gDRIPriv->depthbufferSize; - - if (drmMap(sPriv->fd, - intelScreen->depth.handle, - intelScreen->depth.size, - (drmAddress *)&intelScreen->depth.map) != 0) { - fprintf(stderr, "\nERROR: line %d, Function %s, File %s\n", - __LINE__, __FUNCTION__, __FILE__); - FREE(intelScreen); - drmUnmap(intelScreen->back.map, intelScreen->back.size); - sPriv->private = NULL; - return GL_FALSE; - } - - intelScreen->tex.offset = gDRIPriv->textureOffset; - intelScreen->logTextureGranularity = gDRIPriv->logTextureGranularity; - intelScreen->tex.handle = gDRIPriv->textures; - intelScreen->tex.size = gDRIPriv->textureSize; + if (0) + intelPrintDRIInfo(intelScreen, sPriv, gDRIPriv); - if (drmMap(sPriv->fd, - intelScreen->tex.handle, - intelScreen->tex.size, - (drmAddress *)&intelScreen->tex.map) != 0) { - fprintf(stderr, "\nERROR: line %d, Function %s, File %s\n", - __LINE__, __FUNCTION__, __FILE__); - FREE(intelScreen); - drmUnmap(intelScreen->back.map, intelScreen->back.size); - drmUnmap(intelScreen->depth.map, intelScreen->depth.size); + if (!intelMapScreenRegions(sPriv)) { + fprintf(stderr,"\nERROR! mapping regions\n"); + _mesa_free(intelScreen); sPriv->private = NULL; return GL_FALSE; } - - intelScreen->sarea_priv_offset = gDRIPriv->sarea_priv_offset; - - if (0) intelPrintDRIInfo(intelScreen, sPriv, gDRIPriv); intelScreen->drmMinor = sPriv->drmMinor; + /* Determine if IRQs are active? */ { int ret; drmI830GetParam gp; @@ -185,6 +312,7 @@ static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv) } } + /* Determine if batchbuffers are allowed */ { int ret; drmI830GetParam gp; @@ -217,11 +345,7 @@ static void intelDestroyScreen(__DRIscreenPrivate *sPriv) { intelScreenPrivate *intelScreen = (intelScreenPrivate *)sPriv->private; - /* Need to unmap all the bufs and maps here: - */ - drmUnmap(intelScreen->back.map, intelScreen->back.size); - drmUnmap(intelScreen->depth.map, intelScreen->depth.size); - drmUnmap(intelScreen->tex.map, intelScreen->tex.size); + intelUnmapScreenRegions(intelScreen); FREE(intelScreen); sPriv->private = NULL; } @@ -348,6 +472,7 @@ static GLboolean intelCreateContext( const __GLcontextModes *mesaVis, case PCI_CHIP_I915_G: case PCI_CHIP_I915_GM: case PCI_CHIP_I945_G: + case PCI_CHIP_I945_GM: return i915CreateContext( mesaVis, driContextPriv, sharedContextPrivate ); @@ -482,7 +607,7 @@ void * __driCreateNewScreen_20050727( __DRInativeDisplay *dpy, int scrn, __DRIsc __DRIscreenPrivate *psp; static const __DRIversion ddx_expected = { 1, 4, 0 }; static const __DRIversion dri_expected = { 4, 0, 0 }; - static const __DRIversion drm_expected = { 1, 1, 0 }; + static const __DRIversion drm_expected = { 1, 4, 0 }; dri_interface = interface; diff --git a/src/mesa/drivers/dri/i915/intel_screen.h b/src/mesa/drivers/dri/i915/intel_screen.h index ebecffa4cb..0cdcc14044 100644 --- a/src/mesa/drivers/dri/i915/intel_screen.h +++ b/src/mesa/drivers/dri/i915/intel_screen.h @@ -29,21 +29,26 @@ #define _INTEL_INIT_H_ #include <sys/time.h> -#include "dri_util.h" #include "xmlconfig.h" +#include "dri_util.h" +#include "intel_rotate.h" +#include "i830_common.h" + +/* This roughly corresponds to a gl_renderbuffer (Mesa 6.4) */ typedef struct { drm_handle_t handle; drmSize size; /* region size in bytes */ char *map; /* memory map */ int offset; /* from start of video mem, in bytes */ - int pitch; /* row stride, in pixels */ + int pitch; /* row stride, in bytes */ } intelRegion; typedef struct { intelRegion front; intelRegion back; + intelRegion rotated; intelRegion depth; intelRegion tex; @@ -51,9 +56,8 @@ typedef struct int width; int height; int mem; /* unused */ - + int cpp; /* for front and back buffers */ - int bitsPerPixel; /* unused */ int fbFormat; int logTextureGranularity; @@ -66,13 +70,28 @@ typedef struct int irq_active; int allow_batchbuffer; + struct matrix23 rotMatrix; + + int current_rotation; /* 0, 90, 180 or 270 */ + int rotatedWidth, rotatedHeight; + /** - * Configuration cache with default values for all contexts - */ + * Configuration cache with default values for all contexts + */ driOptionCache optionCache; } intelScreenPrivate; +extern GLboolean +intelMapScreenRegions(__DRIscreenPrivate *sPriv); + +extern void +intelUnmapScreenRegions(intelScreenPrivate *intelScreen); + +extern void +intelUpdateScreenFromSAREA(intelScreenPrivate *intelScreen, + drmI830Sarea *sarea); + extern void intelDestroyContext(__DRIcontextPrivate *driContextPriv); @@ -81,10 +100,10 @@ intelUnbindContext(__DRIcontextPrivate *driContextPriv); extern GLboolean intelMakeCurrent(__DRIcontextPrivate *driContextPriv, - __DRIdrawablePrivate *driDrawPriv, - __DRIdrawablePrivate *driReadPriv); + __DRIdrawablePrivate *driDrawPriv, + __DRIdrawablePrivate *driReadPriv); extern void -intelSwapBuffers( __DRIdrawablePrivate *dPriv); +intelSwapBuffers(__DRIdrawablePrivate *dPriv); #endif diff --git a/src/mesa/drivers/dri/i915/intel_state.c b/src/mesa/drivers/dri/i915/intel_state.c index a2f2b20738..e5988a5ed6 100644 --- a/src/mesa/drivers/dri/i915/intel_state.c +++ b/src/mesa/drivers/dri/i915/intel_state.c @@ -167,7 +167,6 @@ int intel_translate_logic_op( GLenum opcode ) static void intelDrawBuffer(GLcontext *ctx, GLenum mode ) { intelContextPtr intel = INTEL_CONTEXT(ctx); - intelScreenPrivate *screen = intel->intelScreen; int front = 0; if (!ctx->DrawBuffer) @@ -193,12 +192,14 @@ static void intelDrawBuffer(GLcontext *ctx, GLenum mode ) intelSetFrontClipRects( intel ); if (front) { - intel->drawOffset = screen->front.offset; + intel->drawRegion = &intel->intelScreen->front; + intel->readRegion = &intel->intelScreen->front; } else { - intel->drawOffset = screen->back.offset; + intel->drawRegion = &intel->intelScreen->back; + intel->readRegion = &intel->intelScreen->back; } - intel->vtbl.set_draw_offset( intel, intel->drawOffset ); + intel->vtbl.set_color_region( intel, intel->drawRegion ); } static void intelReadBuffer( GLcontext *ctx, GLenum mode ) diff --git a/src/mesa/drivers/dri/i915/intel_tex.c b/src/mesa/drivers/dri/i915/intel_tex.c index d256dbf7cb..4bd7f92db0 100644 --- a/src/mesa/drivers/dri/i915/intel_tex.c +++ b/src/mesa/drivers/dri/i915/intel_tex.c @@ -672,6 +672,46 @@ static void intelUploadTexImage( intelContextPtr intel, break; } } + /* Time for another vtbl entry: + */ + else if (intel->intelScreen->deviceID == PCI_CHIP_I945_G || + intel->intelScreen->deviceID == PCI_CHIP_I945_GM) { + GLuint row_len = image->Width * image->TexFormat->TexelBytes; + GLubyte *dst = (GLubyte *)(t->BufAddr + offset); + GLubyte *src = (GLubyte *)image->Data; + GLuint d, j; + + if (INTEL_DEBUG & DEBUG_TEXTURE) + fprintf(stderr, + "Upload image %dx%dx%d offset %xm row_len %x " + "pitch %x depth_pitch %x\n", + image->Width, image->Height, image->Depth, offset, + row_len, t->Pitch, t->depth_pitch); + + if (row_len == t->Pitch) { + memcpy( dst, src, row_len * image->Height * image->Depth ); + } + else { + GLuint x = 0, y = 0; + + for (d = 0 ; d < image->Depth ; d++) { + GLubyte *dst0 = dst + x + y * t->Pitch; + + for (j = 0 ; j < image->Height ; j++) { + __memcpy(dst0, src, row_len ); + src += row_len; + dst0 += t->Pitch; + } + + x += MIN2(4, row_len); /* Guess: 4 byte minimum alignment */ + if (x > t->Pitch) { + x = 0; + y += image->Height; + } + } + } + + } else { GLuint row_len = image->Width * image->TexFormat->TexelBytes; GLubyte *dst = (GLubyte *)(t->BufAddr + offset); diff --git a/src/mesa/drivers/dri/i915/intel_tex.h b/src/mesa/drivers/dri/i915/intel_tex.h index 0a1f697e9d..9b7e550232 100644 --- a/src/mesa/drivers/dri/i915/intel_tex.h +++ b/src/mesa/drivers/dri/i915/intel_tex.h @@ -39,4 +39,7 @@ void intelDestroyTexObj( intelContextPtr intel, intelTextureObjectPtr t ); int intelUploadTexImages( intelContextPtr intel, intelTextureObjectPtr t, GLuint face ); +GLboolean +intel_driReinitTextureHeap( driTexHeap *heap, + unsigned size ); #endif diff --git a/src/mesa/drivers/dri/i915/intel_texmem.c b/src/mesa/drivers/dri/i915/intel_texmem.c new file mode 100644 index 0000000000..09beec95b8 --- /dev/null +++ b/src/mesa/drivers/dri/i915/intel_texmem.c @@ -0,0 +1,72 @@ +#include "texmem.h" +#include "simple_list.h" +#include "imports.h" +#include "macros.h" + +#include "intel_tex.h" + +static GLuint +driLog2( GLuint n ) +{ + GLuint log2; + + for ( log2 = 1 ; n > 1 ; log2++ ) { + n >>= 1; + } + + return log2; +} + +static void calculate_heap_size( driTexHeap * heap, unsigned size, + unsigned nr_regions, unsigned alignmentShift ) +{ + unsigned l; + + l = driLog2( (size - 1) / nr_regions ); + if ( l < alignmentShift ) + { + l = alignmentShift; + } + + heap->logGranularity = l; + heap->size = size & ~((1L << l) - 1); +} + + +GLboolean +intel_driReinitTextureHeap( driTexHeap *heap, + unsigned size ) +{ + driTextureObject *t, *tmp; + + /* Kick out everything: + */ + foreach_s ( t, tmp, & heap->texture_objects ) { + if ( t->tObj != NULL ) { + driSwapOutTextureObject( t ); + } + else { + driDestroyTextureObject( t ); + } + } + + /* Destroy the memory manager: + */ + mmDestroy( heap->memory_heap ); + + /* Recreate the memory manager: + */ + calculate_heap_size(heap, size, heap->nrRegions, heap->alignmentShift); + heap->memory_heap = mmInit( 0, heap->size ); + if ( heap->memory_heap == NULL ) { + fprintf(stderr, "driReinitTextureHeap: couldn't recreate memory heap\n"); + FREE( heap ); + return GL_FALSE; + } + + make_empty_list( & heap->texture_objects ); + + return GL_TRUE; +} + + diff --git a/src/mesa/drivers/dri/i915/server/i830_common.h b/src/mesa/drivers/dri/i915/server/i830_common.h index c03f742897..41b5cc3c01 100644 --- a/src/mesa/drivers/dri/i915/server/i830_common.h +++ b/src/mesa/drivers/dri/i915/server/i830_common.h @@ -51,6 +51,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #define DRM_I830_FREE 0x09 #define DRM_I830_INIT_HEAP 0x0a #define DRM_I830_CMDBUFFER 0x0b +#define DRM_I830_DESTROY_HEAP 0x0c typedef struct { enum { @@ -87,6 +88,30 @@ typedef struct { int pf_active; int pf_current_page; /* which buffer is being displayed? */ int perf_boxes; /* performance boxes to be displayed */ + int width, height; /* screen size in pixels */ + + drm_handle_t front_handle; + int front_offset; + int front_size; + + drm_handle_t back_handle; + int back_offset; + int back_size; + + drm_handle_t depth_handle; + int depth_offset; + int depth_size; + + drm_handle_t tex_handle; + int tex_offset; + int tex_size; + int log_tex_granularity; + int pitch; + int rotation; /* 0, 90, 180 or 270 */ + int rotated_offset; + int rotated_size; + int rotated_pitch; + int virtualX, virtualY; } drmI830Sarea; /* Flags for perf_boxes @@ -115,8 +140,7 @@ typedef struct { int num_cliprects; /* mulitpass with multiple cliprects? */ drm_clip_rect_t *cliprects; /* pointer to userspace cliprects */ } drmI830CmdBuffer; - - + typedef struct { int *irq_seq; } drmI830IrqEmit; @@ -165,5 +189,9 @@ typedef struct { int start; } drmI830MemInitHeap; +typedef struct { + int region; +} drmI830MemDestroyHeap; + #endif /* _I830_DRM_H_ */ diff --git a/src/mesa/drivers/dri/i915/server/i830_dri.h b/src/mesa/drivers/dri/i915/server/i830_dri.h index 978f47a2b3..6c9a709021 100644 --- a/src/mesa/drivers/dri/i915/server/i830_dri.h +++ b/src/mesa/drivers/dri/i915/server/i830_dri.h @@ -14,9 +14,6 @@ #define I830_REG_SIZE 0x80000 -/* Note: This structure has changed slightly from what is expected by - * the i830_drv.o driver. Maybe that should be reverted. - */ typedef struct _I830DRIRec { drm_handle_t regs; drmSize regsSize; @@ -27,6 +24,9 @@ typedef struct _I830DRIRec { drmSize depthbufferSize; drm_handle_t depthbuffer; + drmSize rotatedSize; + drm_handle_t rotatedbuffer; + drm_handle_t textures; int textureSize; @@ -39,6 +39,7 @@ typedef struct _I830DRIRec { int mem; int cpp; int bitsPerPixel; + int fbOffset; int fbStride; @@ -48,6 +49,9 @@ typedef struct _I830DRIRec { int depthOffset; int depthPitch; + int rotatedOffset; + int rotatedPitch; + int logTextureGranularity; int textureOffset; |