intel_pixel_draw.c revision eeeed45c2cf6c876d79ae20a9a96172ece8642fe
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 GLfloat z; 75 76 /* We're going to mess with texturing with no regard to existing texture 77 * state, so if there is some set up we have to bail. 78 */ 79 if (ctx->Texture._EnabledUnits != 0) { 80 if (INTEL_DEBUG & DEBUG_FALLBACKS) 81 fprintf(stderr, "glDrawPixels() fallback: texturing enabled\n"); 82 return GL_FALSE; 83 } 84 85 /* Can't do textured DrawPixels with a fragment program, unless we were 86 * to generate a new program that sampled our texture and put the results 87 * in the fragment color before the user's program started. 88 */ 89 if (ctx->FragmentProgram.Enabled) { 90 if (INTEL_DEBUG & DEBUG_FALLBACKS) 91 fprintf(stderr, "glDrawPixels() fallback: fragment program enabled\n"); 92 return GL_FALSE; 93 } 94 95 /* We don't have a way to generate fragments with stencil values which * 96 * will set the resulting stencil value. 97 */ 98 if (format == GL_STENCIL_INDEX) 99 return GL_FALSE; 100 101 /* Check that we can load in a texture this big. */ 102 if (width > (1 << (ctx->Const.MaxTextureLevels - 1)) || 103 height > (1 << (ctx->Const.MaxTextureLevels - 1))) { 104 if (INTEL_DEBUG & DEBUG_FALLBACKS) 105 fprintf(stderr, "glDrawPixels() fallback: bitmap too large (%dx%d)\n", 106 width, height); 107 return GL_FALSE; 108 } 109 110 /* To do DEPTH_COMPONENT, we would need to change our setup to not draw to 111 * the color buffer, and sample the texture values into the fragment depth 112 * in a program. 113 */ 114 if (format == GL_DEPTH_COMPONENT) { 115 if (INTEL_DEBUG & DEBUG_FALLBACKS) 116 fprintf(stderr, 117 "glDrawPixels() fallback: format == GL_DEPTH_COMPONENT\n"); 118 return GL_FALSE; 119 } 120 121 _mesa_PushAttrib(GL_ENABLE_BIT | GL_TEXTURE_BIT | 122 GL_CURRENT_BIT); 123 _mesa_PushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT); 124 125 /* XXX: pixel store stuff */ 126 _mesa_Disable(GL_POLYGON_STIPPLE); 127 128 _mesa_ActiveTextureARB(GL_TEXTURE0_ARB); 129 _mesa_Enable(GL_TEXTURE_2D); 130 _mesa_GenTextures(1, &texname); 131 _mesa_BindTexture(GL_TEXTURE_2D, texname); 132 _mesa_TexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 133 _mesa_TexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 134 _mesa_TexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 135 /* 136 _mesa_TexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE); 137 _mesa_TexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); 138 */ 139 _mesa_TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, format, 140 type, pixels); 141 142 intel_meta_set_passthrough_transform(intel); 143 144 /* convert rasterpos Z from [0,1] to NDC coord in [-1,1] */ 145 z = -1.0 + 2.0 * ctx->Current.RasterPos[2]; 146 147 /* Create the vertex buffer based on the current raster pos. The x and y 148 * we're handed are ctx->Current.RasterPos[0,1] rounded to integers. 149 * We also apply the depth. However, the W component is already multiplied 150 * into ctx->Current.RasterPos[0,1,2] and we can ignore it at this point. 151 */ 152 vertices[0][0] = x; 153 vertices[0][1] = y; 154 vertices[0][2] = z; 155 vertices[0][3] = 1.0; 156 vertices[1][0] = x + width * ctx->Pixel.ZoomX; 157 vertices[1][1] = y; 158 vertices[1][2] = z; 159 vertices[1][3] = 1.0; 160 vertices[2][0] = x + width * ctx->Pixel.ZoomX; 161 vertices[2][1] = y + height * ctx->Pixel.ZoomY; 162 vertices[2][2] = z; 163 vertices[2][3] = 1.0; 164 vertices[3][0] = x; 165 vertices[3][1] = y + height * ctx->Pixel.ZoomY; 166 vertices[3][2] = z; 167 vertices[3][3] = 1.0; 168 169 texcoords[0][0] = 0.0; 170 texcoords[0][1] = 0.0; 171 texcoords[1][0] = 1.0; 172 texcoords[1][1] = 0.0; 173 texcoords[2][0] = 1.0; 174 texcoords[2][1] = 1.0; 175 texcoords[3][0] = 0.0; 176 texcoords[3][1] = 1.0; 177 178 _mesa_VertexPointer(4, GL_FLOAT, 4 * sizeof(GLfloat), &vertices); 179 _mesa_TexCoordPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), &texcoords); 180 _mesa_Enable(GL_VERTEX_ARRAY); 181 _mesa_Enable(GL_TEXTURE_COORD_ARRAY); 182 CALL_DrawArrays(ctx->Exec, (GL_TRIANGLE_FAN, 0, 4)); 183 184 intel_meta_restore_transform(intel); 185 _mesa_PopClientAttrib(); 186 _mesa_PopAttrib(); 187 188 _mesa_DeleteTextures(1, &texname); 189 190 return GL_TRUE; 191} 192 193static GLboolean 194intel_stencil_drawpixels(GLcontext * ctx, 195 GLint x, GLint y, 196 GLsizei width, GLsizei height, 197 GLenum format, 198 GLenum type, 199 const struct gl_pixelstore_attrib *unpack, 200 const GLvoid *pixels) 201{ 202 struct intel_context *intel = intel_context(ctx); 203 GLuint texname, rb_name, fb_name, old_fb_name; 204 GLfloat vertices[4][2]; 205 GLfloat texcoords[4][2]; 206 struct intel_renderbuffer *irb; 207 struct intel_renderbuffer *depth_irb; 208 struct gl_renderbuffer *rb; 209 struct gl_pixelstore_attrib old_unpack; 210 GLstencil *stencil_pixels; 211 int row; 212 213 if (format != GL_STENCIL_INDEX) 214 return GL_FALSE; 215 216 /* If there's nothing to write, we're done. */ 217 if (ctx->Stencil.WriteMask[0] == 0) 218 return GL_TRUE; 219 220 /* Can't do a per-bit writemask while treating stencil as rgba data. */ 221 if ((ctx->Stencil.WriteMask[0] & 0xff) != 0xff) { 222 if (INTEL_DEBUG & DEBUG_FALLBACKS) 223 fprintf(stderr, "glDrawPixels(STENCIL_INDEX) fallback: " 224 "stencil mask enabled\n"); 225 return GL_FALSE; 226 } 227 228 /* We use FBOs for our wrapping of the depthbuffer into a color 229 * destination. 230 */ 231 if (!ctx->Extensions.EXT_framebuffer_object) 232 return GL_FALSE; 233 234 /* We're going to mess with texturing with no regard to existing texture 235 * state, so if there is some set up we have to bail. 236 */ 237 if (ctx->Texture._EnabledUnits != 0) { 238 if (INTEL_DEBUG & DEBUG_FALLBACKS) 239 fprintf(stderr, "glDrawPixels(STENCIL_INDEX) fallback: " 240 "texturing enabled\n"); 241 return GL_FALSE; 242 } 243 244 /* Can't do textured DrawPixels with a fragment program, unless we were 245 * to generate a new program that sampled our texture and put the results 246 * in the fragment color before the user's program started. 247 */ 248 if (ctx->FragmentProgram.Enabled) { 249 if (INTEL_DEBUG & DEBUG_FALLBACKS) 250 fprintf(stderr, "glDrawPixels(STENCIL_INDEX) fallback: " 251 "fragment program enabled\n"); 252 return GL_FALSE; 253 } 254 255 /* Check that we can load in a texture this big. */ 256 if (width > (1 << (ctx->Const.MaxTextureLevels - 1)) || 257 height > (1 << (ctx->Const.MaxTextureLevels - 1))) { 258 if (INTEL_DEBUG & DEBUG_FALLBACKS) 259 fprintf(stderr, "glDrawPixels(STENCIL_INDEX) fallback: " 260 "bitmap too large (%dx%d)\n", 261 width, height); 262 return GL_FALSE; 263 } 264 265 _mesa_PushAttrib(GL_ENABLE_BIT | GL_TEXTURE_BIT | 266 GL_CURRENT_BIT | GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 267 _mesa_PushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT); 268 old_fb_name = ctx->DrawBuffer->Name; 269 270 _mesa_Disable(GL_POLYGON_STIPPLE); 271 _mesa_Disable(GL_DEPTH_TEST); 272 _mesa_Disable(GL_STENCIL_TEST); 273 274 /* Unpack the supplied stencil values into a ubyte buffer. */ 275 assert(sizeof(GLstencil) == sizeof(GLubyte)); 276 stencil_pixels = _mesa_malloc(width * height * sizeof(GLstencil)); 277 for (row = 0; row < height; row++) { 278 GLvoid *source = _mesa_image_address2d(unpack, pixels, 279 width, height, 280 GL_COLOR_INDEX, type, 281 row, 0); 282 _mesa_unpack_stencil_span(ctx, width, GL_UNSIGNED_BYTE, 283 stencil_pixels + 284 row * width * sizeof(GLstencil), 285 type, source, unpack, ctx->_ImageTransferState); 286 } 287 288 /* Take the current depth/stencil renderbuffer, and make a new one wrapping 289 * it which will be treated as GL_RGBA8 so we can render to it as a color 290 * buffer. 291 */ 292 depth_irb = intel_get_renderbuffer(ctx->DrawBuffer, BUFFER_DEPTH); 293 irb = intel_create_renderbuffer(GL_RGBA8); 294 rb = &irb->Base; 295 irb->Base.Width = depth_irb->Base.Width; 296 irb->Base.Height = depth_irb->Base.Height; 297 intel_renderbuffer_set_region(irb, depth_irb->region); 298 299 /* Create a name for our renderbuffer, which lets us use other mesa 300 * rb functions for convenience. 301 */ 302 _mesa_GenRenderbuffersEXT(1, &rb_name); 303 irb->Base.RefCount++; 304 _mesa_HashInsert(ctx->Shared->RenderBuffers, rb_name, &irb->Base); 305 306 /* Bind the new renderbuffer to the color attachment point. */ 307 _mesa_GenFramebuffersEXT(1, &fb_name); 308 _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb_name); 309 _mesa_FramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, 310 GL_COLOR_ATTACHMENT0_EXT, 311 GL_RENDERBUFFER_EXT, 312 rb_name); 313 /* Choose to render to the color attachment. */ 314 _mesa_DrawBuffer(GL_COLOR_ATTACHMENT0_EXT); 315 316 _mesa_DepthMask(GL_FALSE); 317 _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); 318 319 _mesa_ActiveTextureARB(GL_TEXTURE0_ARB); 320 _mesa_Enable(GL_TEXTURE_2D); 321 _mesa_GenTextures(1, &texname); 322 _mesa_BindTexture(GL_TEXTURE_2D, texname); 323 _mesa_TexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 324 _mesa_TexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 325 _mesa_TexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 326 old_unpack = ctx->Unpack; 327 ctx->Unpack = ctx->DefaultPacking; 328 _mesa_TexImage2D(GL_TEXTURE_2D, 0, GL_INTENSITY, width, height, 0, 329 GL_RED, GL_UNSIGNED_BYTE, stencil_pixels); 330 ctx->Unpack = old_unpack; 331 _mesa_free(stencil_pixels); 332 333 intel_meta_set_passthrough_transform(intel); 334 335 vertices[0][0] = x; 336 vertices[0][1] = y; 337 vertices[1][0] = x + width * ctx->Pixel.ZoomX; 338 vertices[1][1] = y; 339 vertices[2][0] = x + width * ctx->Pixel.ZoomX; 340 vertices[2][1] = y + height * ctx->Pixel.ZoomY; 341 vertices[3][0] = x; 342 vertices[3][1] = y + height * ctx->Pixel.ZoomY; 343 344 texcoords[0][0] = 0.0; 345 texcoords[0][1] = 0.0; 346 texcoords[1][0] = 1.0; 347 texcoords[1][1] = 0.0; 348 texcoords[2][0] = 1.0; 349 texcoords[2][1] = 1.0; 350 texcoords[3][0] = 0.0; 351 texcoords[3][1] = 1.0; 352 353 _mesa_VertexPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), &vertices); 354 _mesa_TexCoordPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), &texcoords); 355 _mesa_Enable(GL_VERTEX_ARRAY); 356 _mesa_Enable(GL_TEXTURE_COORD_ARRAY); 357 CALL_DrawArrays(ctx->Exec, (GL_TRIANGLE_FAN, 0, 4)); 358 359 intel_meta_restore_transform(intel); 360 361 _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, old_fb_name); 362 363 _mesa_PopClientAttrib(); 364 _mesa_PopAttrib(); 365 366 _mesa_DeleteTextures(1, &texname); 367 _mesa_DeleteFramebuffersEXT(1, &fb_name); 368 _mesa_DeleteRenderbuffersEXT(1, &rb_name); 369 370 return GL_TRUE; 371} 372 373void 374intelDrawPixels(GLcontext * ctx, 375 GLint x, GLint y, 376 GLsizei width, GLsizei height, 377 GLenum format, 378 GLenum type, 379 const struct gl_pixelstore_attrib *unpack, 380 const GLvoid * pixels) 381{ 382 if (intel_texture_drawpixels(ctx, x, y, width, height, format, type, 383 unpack, pixels)) 384 return; 385 386 if (intel_stencil_drawpixels(ctx, x, y, width, height, format, type, 387 unpack, pixels)) 388 return; 389 390 if (INTEL_DEBUG & DEBUG_PIXEL) 391 _mesa_printf("%s: fallback to swrast\n", __FUNCTION__); 392 393 _swrast_DrawPixels(ctx, x, y, width, height, format, type, 394 unpack, pixels); 395} 396