From 5c39bad220c801490ac3d99af01d4c4a7e05dfd6 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 25 Sep 2008 19:11:03 -0700 Subject: intel: Add acceleration for glDrawPixels(GL_STENCIL_INDEX). This is nasty because there's no way in GL to output data to the stencil buffer directly, so we have to do a dance to wrap the depth/stencil buffer in an ARGB renderbuffer. Improves performance of several oglconform testcases by better than a factor of 2. --- src/mesa/drivers/dri/intel/intel_pixel_draw.c | 197 +++++++++++++++++++++++++- 1 file changed, 196 insertions(+), 1 deletion(-) (limited to 'src/mesa/drivers/dri') diff --git a/src/mesa/drivers/dri/intel/intel_pixel_draw.c b/src/mesa/drivers/dri/intel/intel_pixel_draw.c index b60dad7..50518a6 100644 --- a/src/mesa/drivers/dri/intel/intel_pixel_draw.c +++ b/src/mesa/drivers/dri/intel/intel_pixel_draw.c @@ -40,6 +40,12 @@ #include "main/varray.h" #include "main/attrib.h" #include "main/enable.h" +#include "main/buffers.h" +#include "main/fbobject.h" +#include "main/renderbuffer.h" +#include "main/depth.h" +#include "main/hash.h" +#include "main/blend.h" #include "glapi/dispatch.h" #include "swrast/swrast.h" @@ -51,7 +57,7 @@ #include "intel_regions.h" #include "intel_pixel.h" #include "intel_buffer_objects.h" - +#include "intel_fbo.h" static GLboolean intel_texture_drawpixels(GLcontext * ctx, @@ -89,6 +95,15 @@ intel_texture_drawpixels(GLcontext * ctx, if (format == GL_STENCIL_INDEX) return GL_FALSE; + /* Check that we can load in a texture this big. */ + if (width > (1 << (ctx->Const.MaxTextureLevels - 1)) || + height > (1 << (ctx->Const.MaxTextureLevels - 1))) { + if (INTEL_DEBUG & DEBUG_FALLBACKS) + fprintf(stderr, "glDrawPixels() fallback: bitmap too large (%dx%d)\n", + width, height); + return GL_FALSE; + } + /* To do DEPTH_COMPONENT, we would need to change our setup to not draw to * the color buffer, and sample the texture values into the fragment depth * in a program. @@ -170,6 +185,182 @@ intel_texture_drawpixels(GLcontext * ctx, return GL_TRUE; } +static GLboolean +intel_stencil_drawpixels(GLcontext * ctx, + GLint x, GLint y, + GLsizei width, GLsizei height, + GLenum format, + GLenum type, + const struct gl_pixelstore_attrib *unpack, + const GLvoid *pixels) +{ + GLuint texname, rb_name, fb_name, old_fb_name; + GLfloat vertices[4][2]; + GLfloat texcoords[4][2]; + struct intel_renderbuffer *irb; + struct intel_renderbuffer *depth_irb; + struct gl_renderbuffer *rb; + struct gl_pixelstore_attrib old_unpack; + GLstencil *stencil_pixels; + int row; + + if (format != GL_STENCIL_INDEX) + return GL_FALSE; + + /* If there's nothing to write, we're done. */ + if (ctx->Stencil.WriteMask[0] == 0) + return GL_TRUE; + + /* Can't do a per-bit writemask while treating stencil as rgba data. */ + if ((ctx->Stencil.WriteMask[0] & 0xff) != 0xff) + return GL_FALSE; + + /* We use FBOs for our wrapping of the depthbuffer into a color + * destination. + */ + if (!ctx->Extensions.EXT_framebuffer_object) + return GL_FALSE; + + /* We're going to mess with texturing with no regard to existing texture + * state, so if there is some set up we have to bail. + */ + if (ctx->Texture._EnabledUnits != 0) + return GL_FALSE; + + /* Can't do textured DrawPixels with a fragment program, unless we were + * to generate a new program that sampled our texture and put the results + * in the fragment color before the user's program started. + */ + if (ctx->FragmentProgram.Enabled) + return GL_FALSE; + + /* Check that we can load in a texture this big. */ + if (width > (1 << (ctx->Const.MaxTextureLevels - 1)) || + height > (1 << (ctx->Const.MaxTextureLevels - 1))) { + if (INTEL_DEBUG & DEBUG_FALLBACKS) + fprintf(stderr, "glDrawPixels(STENCIL_IDNEX) fallback: " + "bitmap too large (%dx%d)\n", + width, height); + return GL_FALSE; + } + + _mesa_PushAttrib(GL_ENABLE_BIT | GL_TRANSFORM_BIT | GL_TEXTURE_BIT | + GL_CURRENT_BIT | GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + _mesa_PushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT); + old_fb_name = ctx->DrawBuffer->Name; + + _mesa_Disable(GL_POLYGON_STIPPLE); + _mesa_Disable(GL_DEPTH_TEST); + _mesa_Disable(GL_STENCIL_TEST); + + /* Unpack the supplied stencil values into a ubyte buffer. */ + assert(sizeof(GLstencil) == sizeof(GLubyte)); + stencil_pixels = _mesa_malloc(width * height * sizeof(GLstencil)); + for (row = 0; row < height; row++) { + GLvoid *source = _mesa_image_address2d(unpack, pixels, + width, height, + GL_COLOR_INDEX, type, + row, 0); + _mesa_unpack_stencil_span(ctx, width, GL_UNSIGNED_BYTE, + stencil_pixels + + row * width * sizeof(GLstencil), + type, source, unpack, ctx->_ImageTransferState); + } + + /* Take the current depth/stencil renderbuffer, and make a new one wrapping + * it which will be treated as GL_RGBA8 so we can render to it as a color + * buffer. + */ + depth_irb = intel_get_renderbuffer(ctx->DrawBuffer, BUFFER_DEPTH); + irb = intel_create_renderbuffer(GL_RGBA8); + rb = &irb->Base; + irb->Base.Width = depth_irb->Base.Width; + irb->Base.Height = depth_irb->Base.Height; + intel_renderbuffer_set_region(irb, depth_irb->region); + + /* Create a name for our renderbuffer, which lets us use other mesa + * rb functions for convenience. + */ + _mesa_GenRenderbuffersEXT(1, &rb_name); + irb->Base.RefCount++; + _mesa_HashInsert(ctx->Shared->RenderBuffers, rb_name, &irb->Base); + + /* Bind the new renderbuffer to the color attachment point. */ + _mesa_GenFramebuffersEXT(1, &fb_name); + _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb_name); + _mesa_FramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, + GL_COLOR_ATTACHMENT0_EXT, + GL_RENDERBUFFER_EXT, + rb_name); + /* Choose to render to the color attachment. */ + _mesa_DrawBuffer(GL_COLOR_ATTACHMENT0_EXT); + + _mesa_DepthMask(GL_FALSE); + _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); + + _mesa_ActiveTextureARB(GL_TEXTURE0_ARB); + _mesa_Enable(GL_TEXTURE_2D); + _mesa_GenTextures(1, &texname); + _mesa_BindTexture(GL_TEXTURE_2D, texname); + _mesa_TexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + _mesa_TexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + _mesa_TexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + old_unpack = ctx->Unpack; + ctx->Unpack = ctx->DefaultPacking; + _mesa_TexImage2D(GL_TEXTURE_2D, 0, GL_INTENSITY, width, height, 0, + GL_RED, GL_UNSIGNED_BYTE, stencil_pixels); + ctx->Unpack = old_unpack; + _mesa_free(stencil_pixels); + + _mesa_MatrixMode(GL_PROJECTION); + _mesa_PushMatrix(); + _mesa_LoadIdentity(); + _mesa_Ortho(0, ctx->DrawBuffer->Width, 0, ctx->DrawBuffer->Height, 1, -1); + + _mesa_MatrixMode(GL_MODELVIEW); + _mesa_PushMatrix(); + _mesa_LoadIdentity(); + + vertices[0][0] = x; + vertices[0][1] = y; + vertices[1][0] = x + width * ctx->Pixel.ZoomX; + vertices[1][1] = y; + vertices[2][0] = x + width * ctx->Pixel.ZoomX; + vertices[2][1] = y + height * ctx->Pixel.ZoomY; + vertices[3][0] = x; + vertices[3][1] = y + height * ctx->Pixel.ZoomY; + + texcoords[0][0] = 0.0; + texcoords[0][1] = 0.0; + texcoords[1][0] = 1.0; + texcoords[1][1] = 0.0; + texcoords[2][0] = 1.0; + texcoords[2][1] = 1.0; + texcoords[3][0] = 0.0; + texcoords[3][1] = 1.0; + + _mesa_VertexPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), &vertices); + _mesa_TexCoordPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), &texcoords); + _mesa_Enable(GL_VERTEX_ARRAY); + _mesa_Enable(GL_TEXTURE_COORD_ARRAY); + CALL_DrawArrays(ctx->Exec, (GL_TRIANGLE_FAN, 0, 4)); + + _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, old_fb_name); + + _mesa_MatrixMode(GL_PROJECTION); + _mesa_PopMatrix(); + _mesa_MatrixMode(GL_MODELVIEW); + _mesa_PopMatrix(); + _mesa_PopClientAttrib(); + _mesa_PopAttrib(); + + _mesa_DeleteTextures(1, &texname); + _mesa_DeleteFramebuffersEXT(1, &fb_name); + _mesa_DeleteRenderbuffersEXT(1, &rb_name); + + return GL_TRUE; +} + void intelDrawPixels(GLcontext * ctx, GLint x, GLint y, @@ -183,6 +374,10 @@ intelDrawPixels(GLcontext * ctx, unpack, pixels)) return; + if (intel_stencil_drawpixels(ctx, x, y, width, height, format, type, + unpack, pixels)) + return; + if (INTEL_DEBUG & DEBUG_PIXEL) _mesa_printf("%s: fallback to swrast\n", __FUNCTION__); -- cgit v1.1 From c238098bbcfb644ea01b33d3274b949d84822512 Mon Sep 17 00:00:00 2001 From: "Xiang, Haihao" Date: Mon, 13 Oct 2008 13:04:04 +0800 Subject: i915: Texture instructions use r/t/oC/oD register as texture coordinate. Fix http://bugs.freedesktop.org/show_bug.cgi?id=16287. --- src/mesa/drivers/dri/i915/i915_program.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'src/mesa/drivers/dri') diff --git a/src/mesa/drivers/dri/i915/i915_program.c b/src/mesa/drivers/dri/i915/i915_program.c index 350da5e..e87700f 100644 --- a/src/mesa/drivers/dri/i915/i915_program.c +++ b/src/mesa/drivers/dri/i915/i915_program.c @@ -245,6 +245,19 @@ GLuint i915_emit_texld( struct i915_fragment_program *p, */ assert(GET_UREG_TYPE(coord) != REG_TYPE_U); + if ((GET_UREG_TYPE(coord) != REG_TYPE_R) && + (GET_UREG_TYPE(coord) != REG_TYPE_OC) && + (GET_UREG_TYPE(coord) != REG_TYPE_OD) && + (GET_UREG_TYPE(coord) != REG_TYPE_T)) { + GLuint tmpCoord = get_free_rreg(p, live_regs); + + if (tmpCoord == UREG_BAD) + return 0; + + i915_emit_arith(p, A0_MOV, tmpCoord, A0_DEST_CHANNEL_ALL, 0, coord, 0, 0); + coord = tmpCoord; + } + /* Output register being oC or oD defines a phase boundary */ if (GET_UREG_TYPE(dest) == REG_TYPE_OC || GET_UREG_TYPE(dest) == REG_TYPE_OD) -- cgit v1.1 From 73e119363216b75243dce170f8afd5c2f9bfce50 Mon Sep 17 00:00:00 2001 From: Roland Scheidegger Date: Thu, 16 Oct 2008 16:23:47 +0200 Subject: fix span issue with really old ddx and non-tcl r100 chips --- src/mesa/drivers/dri/radeon/radeon_screen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/mesa/drivers/dri') diff --git a/src/mesa/drivers/dri/radeon/radeon_screen.c b/src/mesa/drivers/dri/radeon/radeon_screen.c index 05107dd..5f32dd5 100644 --- a/src/mesa/drivers/dri/radeon/radeon_screen.c +++ b/src/mesa/drivers/dri/radeon/radeon_screen.c @@ -900,7 +900,7 @@ radeonCreateScreen( __DRIscreenPrivate *sPriv ) screen->depthHasSurface = (sPriv->ddx_version.major > 4) || /* these chips don't use tiled z without hyperz. So always pretend we have set up a surface which will cause linear reads/writes */ - ((screen->chip_family & RADEON_CLASS_R100) && + (IS_R100_CLASS(screen) && !(screen->chip_flags & RADEON_CHIPSET_TCL)); if ( dri_priv->textureSize == 0 ) { -- cgit v1.1 From b4bf9acc32ac8693b1fdf80f351523a468ba6bd1 Mon Sep 17 00:00:00 2001 From: "Xiang, Haihao" Date: Tue, 21 Oct 2008 10:30:39 +0800 Subject: i915: fix carsh in i830_emit_state. (bug #17766) --- src/mesa/drivers/dri/i915/i830_vtbl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/mesa/drivers/dri') diff --git a/src/mesa/drivers/dri/i915/i830_vtbl.c b/src/mesa/drivers/dri/i915/i830_vtbl.c index 773a8b4..3c9851e 100644 --- a/src/mesa/drivers/dri/i915/i830_vtbl.c +++ b/src/mesa/drivers/dri/i915/i830_vtbl.c @@ -449,7 +449,8 @@ i830_emit_state(struct intel_context *intel) aper_array[aper_count++] = intel->batch->buf; if (dirty & I830_UPLOAD_BUFFERS) { aper_array[aper_count++] = state->draw_region->buffer; - aper_array[aper_count++] = state->depth_region->buffer; + if (state->depth_region) + aper_array[aper_count++] = state->depth_region->buffer; } for (i = 0; i < I830_TEX_UNITS; i++) -- cgit v1.1 From f657c8191128c500c2aa7204009154a1182e2abd Mon Sep 17 00:00:00 2001 From: "Xiang, Haihao" Date: Fri, 24 Oct 2008 15:55:32 +0800 Subject: intel: fallback for intelEmitCopyBlit. Use _mesa_copy_rect instead of BLT operation if dri_bufmgr_check_aperture_space still fails after flushing batchbuffer. Partial fix for #17964. --- src/mesa/drivers/dri/intel/intel_blit.c | 49 ++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 10 deletions(-) (limited to 'src/mesa/drivers/dri') diff --git a/src/mesa/drivers/dri/intel/intel_blit.c b/src/mesa/drivers/dri/intel/intel_blit.c index 2917401..081d1dd 100644 --- a/src/mesa/drivers/dri/intel/intel_blit.c +++ b/src/mesa/drivers/dri/intel/intel_blit.c @@ -272,24 +272,53 @@ intelEmitCopyBlit(struct intel_context *intel, GLshort w, GLshort h, GLenum logic_op) { - GLuint CMD, BR13; + GLuint CMD, BR13, pass = 0; int dst_y2 = dst_y + h; int dst_x2 = dst_x + w; dri_bo *aper_array[3]; BATCH_LOCALS; /* do space/cliprects check before going any further */ - intel_batchbuffer_require_space(intel->batch, 8 * 4, NO_LOOP_CLIPRECTS); - again: - aper_array[0] = intel->batch->buf; - aper_array[1] = dst_buffer; - aper_array[2] = src_buffer; - - if (dri_bufmgr_check_aperture_space(aper_array, 3) != 0) { - intel_batchbuffer_flush(intel->batch); - goto again; + do { + aper_array[0] = intel->batch->buf; + aper_array[1] = dst_buffer; + aper_array[2] = src_buffer; + + if (dri_bufmgr_check_aperture_space(aper_array, 3) != 0) { + intel_batchbuffer_flush(intel->batch); + pass++; + } else + break; + } while (pass < 2); + + if (pass >= 2) { + GLboolean locked = GL_FALSE; + if (!intel->locked) { + LOCK_HARDWARE(intel); + locked = GL_TRUE; + } + + dri_bo_map(dst_buffer, GL_TRUE); + dri_bo_map(src_buffer, GL_TRUE); + _mesa_copy_rect((GLubyte *)dst_buffer->virtual + dst_offset, + cpp, + dst_pitch, + dst_x, dst_y, + w, h, + (GLubyte *)src_buffer->virtual + src_offset, + src_pitch, + src_x, src_y); + + dri_bo_unmap(src_buffer); + dri_bo_unmap(dst_buffer); + + if (locked) + UNLOCK_HARDWARE(intel); + + return; } + intel_batchbuffer_require_space(intel->batch, 8 * 4, NO_LOOP_CLIPRECTS); DBG("%s src:buf(%p)/%d+%d %d,%d dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n", __FUNCTION__, src_buffer, src_pitch, src_offset, src_x, src_y, -- cgit v1.1 From ec8076264ea2390d4cb749be5c88bbf2bf5d4847 Mon Sep 17 00:00:00 2001 From: "Xiang, Haihao" Date: Fri, 24 Oct 2008 16:05:48 +0800 Subject: i965: don't emit state when dri_bufmgr_check_aperture_space fails. This ensures there is an unfilled batchbuffer used for emitting states again. Partial fix for #17964. --- src/mesa/drivers/dri/i965/brw_curbe.c | 4 +++- src/mesa/drivers/dri/i965/brw_misc_state.c | 12 +++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) (limited to 'src/mesa/drivers/dri') diff --git a/src/mesa/drivers/dri/i965/brw_curbe.c b/src/mesa/drivers/dri/i965/brw_curbe.c index 7cddd3a..6ffa221 100644 --- a/src/mesa/drivers/dri/i965/brw_curbe.c +++ b/src/mesa/drivers/dri/i965/brw_curbe.c @@ -333,8 +333,10 @@ static void emit_constant_buffer(struct brw_context *brw) brw->curbe.curbe_bo, }; - if (dri_bufmgr_check_aperture_space(aper_array, ARRAY_SIZE(aper_array))) + if (dri_bufmgr_check_aperture_space(aper_array, ARRAY_SIZE(aper_array))) { intel_batchbuffer_flush(intel->batch); + return; + } BEGIN_BATCH(2, IGNORE_CLIPRECTS); if (sz == 0) { diff --git a/src/mesa/drivers/dri/i965/brw_misc_state.c b/src/mesa/drivers/dri/i965/brw_misc_state.c index 487c638..afa8694 100644 --- a/src/mesa/drivers/dri/i965/brw_misc_state.c +++ b/src/mesa/drivers/dri/i965/brw_misc_state.c @@ -86,8 +86,10 @@ static void upload_binding_table_pointers(struct brw_context *brw) brw->wm.bind_bo, }; - if (dri_bufmgr_check_aperture_space(aper_array, ARRAY_SIZE(aper_array))) + if (dri_bufmgr_check_aperture_space(aper_array, ARRAY_SIZE(aper_array))) { intel_batchbuffer_flush(intel->batch); + return; + } BEGIN_BATCH(6, IGNORE_CLIPRECTS); OUT_BATCH(CMD_BINDING_TABLE_PTRS << 16 | (6 - 2)); @@ -152,8 +154,10 @@ static void upload_psp_urb_cbs(struct brw_context *brw ) brw->cc.state_bo, }; - if (dri_bufmgr_check_aperture_space(aper_array, ARRAY_SIZE(aper_array))) + if (dri_bufmgr_check_aperture_space(aper_array, ARRAY_SIZE(aper_array))) { intel_batchbuffer_flush(intel->batch); + return; + } upload_pipelined_state_pointers(brw); brw_upload_urb_fence(brw); @@ -216,8 +220,10 @@ static void emit_depthbuffer(struct brw_context *brw) return; } - if (dri_bufmgr_check_aperture_space(aper_array, ARRAY_SIZE(aper_array))) + if (dri_bufmgr_check_aperture_space(aper_array, ARRAY_SIZE(aper_array))) { intel_batchbuffer_flush(intel->batch); + return; + } BEGIN_BATCH(len, IGNORE_CLIPRECTS); OUT_BATCH(CMD_DEPTH_BUFFER << 16 | (len - 2)); -- cgit v1.1 From 2a877411dbe35abdd8c15fb4821d9232619d89cc Mon Sep 17 00:00:00 2001 From: "Xiang, Haihao" Date: Sun, 26 Oct 2008 06:31:33 +0800 Subject: intel: GL_FALSE on a BO if it won't be modified when mapping this BO. (thanks Eric). --- src/mesa/drivers/dri/intel/intel_blit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/mesa/drivers/dri') diff --git a/src/mesa/drivers/dri/intel/intel_blit.c b/src/mesa/drivers/dri/intel/intel_blit.c index 081d1dd..3c1f7f6 100644 --- a/src/mesa/drivers/dri/intel/intel_blit.c +++ b/src/mesa/drivers/dri/intel/intel_blit.c @@ -299,7 +299,7 @@ intelEmitCopyBlit(struct intel_context *intel, } dri_bo_map(dst_buffer, GL_TRUE); - dri_bo_map(src_buffer, GL_TRUE); + dri_bo_map(src_buffer, GL_FALSE); _mesa_copy_rect((GLubyte *)dst_buffer->virtual + dst_offset, cpp, dst_pitch, -- cgit v1.1