intel_pixel_draw.c revision 8fb727548a652c47d8cf9593e2ae412ef2040119
1/************************************************************************** 2 * 3 * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portionsalloc 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28#include "main/glheader.h" 29#include "main/enums.h" 30#include "main/image.h" 31#include "main/mtypes.h" 32#include "main/macros.h" 33#include "main/bufferobj.h" 34#include "main/teximage.h" 35#include "main/texenv.h" 36#include "main/texobj.h" 37#include "main/texstate.h" 38#include "main/texparam.h" 39#include "main/varray.h" 40#include "main/attrib.h" 41#include "main/enable.h" 42#include "main/buffers.h" 43#include "main/fbobject.h" 44#include "main/renderbuffer.h" 45#include "main/depth.h" 46#include "main/hash.h" 47#include "main/blend.h" 48#include "glapi/dispatch.h" 49#include "swrast/swrast.h" 50 51#include "intel_screen.h" 52#include "intel_context.h" 53#include "intel_batchbuffer.h" 54#include "intel_blit.h" 55#include "intel_buffers.h" 56#include "intel_regions.h" 57#include "intel_pixel.h" 58#include "intel_buffer_objects.h" 59#include "intel_fbo.h" 60 61static GLboolean 62intel_texture_drawpixels(GLcontext * ctx, 63 GLint x, GLint y, 64 GLsizei width, GLsizei height, 65 GLenum format, 66 GLenum type, 67 const struct gl_pixelstore_attrib *unpack, 68 const GLvoid *pixels) 69{ 70 struct intel_context *intel = intel_context(ctx); 71 GLuint texname; 72 GLfloat vertices[4][4]; 73 GLfloat texcoords[4][2]; 74 75 /* We're going to mess with texturing with no regard to existing texture 76 * state, so if there is some set up we have to bail. 77 */ 78 if (ctx->Texture._EnabledUnits != 0) { 79 if (INTEL_DEBUG & DEBUG_FALLBACKS) 80 fprintf(stderr, "glDrawPixels() fallback: texturing enabled\n"); 81 return GL_FALSE; 82 } 83 84 /* Can't do textured DrawPixels with a fragment program, unless we were 85 * to generate a new program that sampled our texture and put the results 86 * in the fragment color before the user's program started. 87 */ 88 if (ctx->FragmentProgram.Enabled) { 89 if (INTEL_DEBUG & DEBUG_FALLBACKS) 90 fprintf(stderr, "glDrawPixels() fallback: fragment program enabled\n"); 91 return GL_FALSE; 92 } 93 94 /* We don't have a way to generate fragments with stencil values which * 95 * will set the resulting stencil value. 96 */ 97 if (format == GL_STENCIL_INDEX) 98 return GL_FALSE; 99 100 /* Check that we can load in a texture this big. */ 101 if (width > (1 << (ctx->Const.MaxTextureLevels - 1)) || 102 height > (1 << (ctx->Const.MaxTextureLevels - 1))) { 103 if (INTEL_DEBUG & DEBUG_FALLBACKS) 104 fprintf(stderr, "glDrawPixels() fallback: bitmap too large (%dx%d)\n", 105 width, height); 106 return GL_FALSE; 107 } 108 109 /* To do DEPTH_COMPONENT, we would need to change our setup to not draw to 110 * the color buffer, and sample the texture values into the fragment depth 111 * in a program. 112 */ 113 if (format == GL_DEPTH_COMPONENT) { 114 if (INTEL_DEBUG & DEBUG_FALLBACKS) 115 fprintf(stderr, 116 "glDrawPixels() fallback: format == GL_DEPTH_COMPONENT\n"); 117 return GL_FALSE; 118 } 119 120 _mesa_PushAttrib(GL_ENABLE_BIT | GL_TEXTURE_BIT | 121 GL_CURRENT_BIT); 122 _mesa_PushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT); 123 124 /* XXX: pixel store stuff */ 125 _mesa_Disable(GL_POLYGON_STIPPLE); 126 127 _mesa_ActiveTextureARB(GL_TEXTURE0_ARB); 128 _mesa_Enable(GL_TEXTURE_2D); 129 _mesa_GenTextures(1, &texname); 130 _mesa_BindTexture(GL_TEXTURE_2D, texname); 131 _mesa_TexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 132 _mesa_TexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 133 _mesa_TexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 134 /* 135 _mesa_TexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE); 136 _mesa_TexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); 137 */ 138 _mesa_TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, format, 139 type, pixels); 140 141 intel_meta_set_passthrough_transform(intel); 142 143 /* Create the vertex buffer based on the current raster pos. The x and y 144 * we're handed are ctx->Current.RasterPos[0,1] rounded to integers. 145 * We also apply the depth. However, the W component is already multiplied 146 * into ctx->Current.RasterPos[0,1,2] and we can ignore it at this point. 147 */ 148 vertices[0][0] = x; 149 vertices[0][1] = y; 150 vertices[0][2] = ctx->Current.RasterPos[2]; 151 vertices[0][3] = 1.0; 152 vertices[1][0] = x + width * ctx->Pixel.ZoomX; 153 vertices[1][1] = y; 154 vertices[1][2] = ctx->Current.RasterPos[2]; 155 vertices[1][3] = 1.0; 156 vertices[2][0] = x + width * ctx->Pixel.ZoomX; 157 vertices[2][1] = y + height * ctx->Pixel.ZoomY; 158 vertices[2][2] = ctx->Current.RasterPos[2]; 159 vertices[2][3] = 1.0; 160 vertices[3][0] = x; 161 vertices[3][1] = y + height * ctx->Pixel.ZoomY; 162 vertices[3][2] = ctx->Current.RasterPos[2]; 163 vertices[3][3] = 1.0; 164 165 texcoords[0][0] = 0.0; 166 texcoords[0][1] = 0.0; 167 texcoords[1][0] = 1.0; 168 texcoords[1][1] = 0.0; 169 texcoords[2][0] = 1.0; 170 texcoords[2][1] = 1.0; 171 texcoords[3][0] = 0.0; 172 texcoords[3][1] = 1.0; 173 174 _mesa_VertexPointer(4, GL_FLOAT, 4 * sizeof(GLfloat), &vertices); 175 _mesa_TexCoordPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), &texcoords); 176 _mesa_Enable(GL_VERTEX_ARRAY); 177 _mesa_Enable(GL_TEXTURE_COORD_ARRAY); 178 CALL_DrawArrays(ctx->Exec, (GL_TRIANGLE_FAN, 0, 4)); 179 180 intel_meta_restore_transform(intel); 181 _mesa_PopClientAttrib(); 182 _mesa_PopAttrib(); 183 184 _mesa_DeleteTextures(1, &texname); 185 186 return GL_TRUE; 187} 188 189static GLboolean 190intel_stencil_drawpixels(GLcontext * ctx, 191 GLint x, GLint y, 192 GLsizei width, GLsizei height, 193 GLenum format, 194 GLenum type, 195 const struct gl_pixelstore_attrib *unpack, 196 const GLvoid *pixels) 197{ 198 struct intel_context *intel = intel_context(ctx); 199 GLuint texname, rb_name, fb_name, old_fb_name; 200 GLfloat vertices[4][2]; 201 GLfloat texcoords[4][2]; 202 struct intel_renderbuffer *irb; 203 struct intel_renderbuffer *depth_irb; 204 struct gl_renderbuffer *rb; 205 struct gl_pixelstore_attrib old_unpack; 206 GLstencil *stencil_pixels; 207 int row; 208 209 if (format != GL_STENCIL_INDEX) 210 return GL_FALSE; 211 212 /* If there's nothing to write, we're done. */ 213 if (ctx->Stencil.WriteMask[0] == 0) 214 return GL_TRUE; 215 216 /* Can't do a per-bit writemask while treating stencil as rgba data. */ 217 if ((ctx->Stencil.WriteMask[0] & 0xff) != 0xff) { 218 if (INTEL_DEBUG & DEBUG_FALLBACKS) 219 fprintf(stderr, "glDrawPixels(STENCIL_INDEX) fallback: " 220 "stencil mask enabled\n"); 221 return GL_FALSE; 222 } 223 224 /* We use FBOs for our wrapping of the depthbuffer into a color 225 * destination. 226 */ 227 if (!ctx->Extensions.EXT_framebuffer_object) 228 return GL_FALSE; 229 230 /* We're going to mess with texturing with no regard to existing texture 231 * state, so if there is some set up we have to bail. 232 */ 233 if (ctx->Texture._EnabledUnits != 0) { 234 if (INTEL_DEBUG & DEBUG_FALLBACKS) 235 fprintf(stderr, "glDrawPixels(STENCIL_INDEX) fallback: " 236 "texturing enabled\n"); 237 return GL_FALSE; 238 } 239 240 /* Can't do textured DrawPixels with a fragment program, unless we were 241 * to generate a new program that sampled our texture and put the results 242 * in the fragment color before the user's program started. 243 */ 244 if (ctx->FragmentProgram.Enabled) { 245 if (INTEL_DEBUG & DEBUG_FALLBACKS) 246 fprintf(stderr, "glDrawPixels(STENCIL_INDEX) fallback: " 247 "fragment program enabled\n"); 248 return GL_FALSE; 249 } 250 251 /* Check that we can load in a texture this big. */ 252 if (width > (1 << (ctx->Const.MaxTextureLevels - 1)) || 253 height > (1 << (ctx->Const.MaxTextureLevels - 1))) { 254 if (INTEL_DEBUG & DEBUG_FALLBACKS) 255 fprintf(stderr, "glDrawPixels(STENCIL_INDEX) fallback: " 256 "bitmap too large (%dx%d)\n", 257 width, height); 258 return GL_FALSE; 259 } 260 261 _mesa_PushAttrib(GL_ENABLE_BIT | GL_TEXTURE_BIT | 262 GL_CURRENT_BIT | GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 263 _mesa_PushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT); 264 old_fb_name = ctx->DrawBuffer->Name; 265 266 _mesa_Disable(GL_POLYGON_STIPPLE); 267 _mesa_Disable(GL_DEPTH_TEST); 268 _mesa_Disable(GL_STENCIL_TEST); 269 270 /* Unpack the supplied stencil values into a ubyte buffer. */ 271 assert(sizeof(GLstencil) == sizeof(GLubyte)); 272 stencil_pixels = _mesa_malloc(width * height * sizeof(GLstencil)); 273 for (row = 0; row < height; row++) { 274 GLvoid *source = _mesa_image_address2d(unpack, pixels, 275 width, height, 276 GL_COLOR_INDEX, type, 277 row, 0); 278 _mesa_unpack_stencil_span(ctx, width, GL_UNSIGNED_BYTE, 279 stencil_pixels + 280 row * width * sizeof(GLstencil), 281 type, source, unpack, ctx->_ImageTransferState); 282 } 283 284 /* Take the current depth/stencil renderbuffer, and make a new one wrapping 285 * it which will be treated as GL_RGBA8 so we can render to it as a color 286 * buffer. 287 */ 288 depth_irb = intel_get_renderbuffer(ctx->DrawBuffer, BUFFER_DEPTH); 289 irb = intel_create_renderbuffer(GL_RGBA8); 290 rb = &irb->Base; 291 irb->Base.Width = depth_irb->Base.Width; 292 irb->Base.Height = depth_irb->Base.Height; 293 intel_renderbuffer_set_region(irb, depth_irb->region); 294 295 /* Create a name for our renderbuffer, which lets us use other mesa 296 * rb functions for convenience. 297 */ 298 _mesa_GenRenderbuffersEXT(1, &rb_name); 299 irb->Base.RefCount++; 300 _mesa_HashInsert(ctx->Shared->RenderBuffers, rb_name, &irb->Base); 301 302 /* Bind the new renderbuffer to the color attachment point. */ 303 _mesa_GenFramebuffersEXT(1, &fb_name); 304 _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb_name); 305 _mesa_FramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, 306 GL_COLOR_ATTACHMENT0_EXT, 307 GL_RENDERBUFFER_EXT, 308 rb_name); 309 /* Choose to render to the color attachment. */ 310 _mesa_DrawBuffer(GL_COLOR_ATTACHMENT0_EXT); 311 312 _mesa_DepthMask(GL_FALSE); 313 _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); 314 315 _mesa_ActiveTextureARB(GL_TEXTURE0_ARB); 316 _mesa_Enable(GL_TEXTURE_2D); 317 _mesa_GenTextures(1, &texname); 318 _mesa_BindTexture(GL_TEXTURE_2D, texname); 319 _mesa_TexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 320 _mesa_TexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 321 _mesa_TexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 322 old_unpack = ctx->Unpack; 323 ctx->Unpack = ctx->DefaultPacking; 324 _mesa_TexImage2D(GL_TEXTURE_2D, 0, GL_INTENSITY, width, height, 0, 325 GL_RED, GL_UNSIGNED_BYTE, stencil_pixels); 326 ctx->Unpack = old_unpack; 327 _mesa_free(stencil_pixels); 328 329 intel_meta_set_passthrough_transform(intel); 330 331 vertices[0][0] = x; 332 vertices[0][1] = y; 333 vertices[1][0] = x + width * ctx->Pixel.ZoomX; 334 vertices[1][1] = y; 335 vertices[2][0] = x + width * ctx->Pixel.ZoomX; 336 vertices[2][1] = y + height * ctx->Pixel.ZoomY; 337 vertices[3][0] = x; 338 vertices[3][1] = y + height * ctx->Pixel.ZoomY; 339 340 texcoords[0][0] = 0.0; 341 texcoords[0][1] = 0.0; 342 texcoords[1][0] = 1.0; 343 texcoords[1][1] = 0.0; 344 texcoords[2][0] = 1.0; 345 texcoords[2][1] = 1.0; 346 texcoords[3][0] = 0.0; 347 texcoords[3][1] = 1.0; 348 349 _mesa_VertexPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), &vertices); 350 _mesa_TexCoordPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), &texcoords); 351 _mesa_Enable(GL_VERTEX_ARRAY); 352 _mesa_Enable(GL_TEXTURE_COORD_ARRAY); 353 CALL_DrawArrays(ctx->Exec, (GL_TRIANGLE_FAN, 0, 4)); 354 355 intel_meta_restore_transform(intel); 356 357 _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, old_fb_name); 358 359 _mesa_PopClientAttrib(); 360 _mesa_PopAttrib(); 361 362 _mesa_DeleteTextures(1, &texname); 363 _mesa_DeleteFramebuffersEXT(1, &fb_name); 364 _mesa_DeleteRenderbuffersEXT(1, &rb_name); 365 366 return GL_TRUE; 367} 368 369void 370intelDrawPixels(GLcontext * ctx, 371 GLint x, GLint y, 372 GLsizei width, GLsizei height, 373 GLenum format, 374 GLenum type, 375 const struct gl_pixelstore_attrib *unpack, 376 const GLvoid * pixels) 377{ 378 if (intel_texture_drawpixels(ctx, x, y, width, height, format, type, 379 unpack, pixels)) 380 return; 381 382 if (intel_stencil_drawpixels(ctx, x, y, width, height, format, type, 383 unpack, pixels)) 384 return; 385 386 if (INTEL_DEBUG & DEBUG_PIXEL) 387 _mesa_printf("%s: fallback to swrast\n", __FUNCTION__); 388 389 _swrast_DrawPixels(ctx, x, y, width, height, format, type, 390 unpack, pixels); 391} 392