st_cb_drawpixels.c revision 519aacef031e3271e16693308ca462346a8a160c
1/************************************************************************** 2 * 3 * Copyright 2007 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 portions 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 /* 29 * Authors: 30 * Brian Paul 31 */ 32 33#include "imports.h" 34 35#include "st_context.h" 36#include "st_atom.h" 37#include "st_draw.h" 38#include "st_program.h" 39#include "st_cb_drawpixels.h" 40#include "st_cb_texture.h" 41#include "st_format.h" 42#include "pipe/p_context.h" 43#include "pipe/p_defines.h" 44#include "pipe/tgsi/mesa/mesa_to_tgsi.h" 45#include "shader/prog_instruction.h" 46#include "vf/vf.h" 47 48 49 50/** 51 * Create a simple fragment shader that passes the texture color through 52 * to the fragment color. 53 */ 54static struct st_fragment_program * 55make_drawpixels_shader(struct st_context *st) 56{ 57 GLcontext *ctx = st->ctx; 58 struct st_fragment_program *stfp; 59 struct gl_program *p; 60 GLboolean b; 61 62 p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0); 63 if (!p) 64 return NULL; 65 66 p->NumInstructions = 2; 67 p->Instructions = _mesa_alloc_instructions(2); 68 if (!p->Instructions) { 69 ctx->Driver.DeleteProgram(ctx, p); 70 return NULL; 71 } 72 _mesa_init_instructions(p->Instructions, 2); 73 /* TEX result.color, fragment.texcoord[0], texture[0], 2D; */ 74 p->Instructions[0].Opcode = OPCODE_TEX; 75 p->Instructions[0].DstReg.File = PROGRAM_OUTPUT; 76 p->Instructions[0].DstReg.Index = FRAG_RESULT_COLR; 77 p->Instructions[0].SrcReg[0].File = PROGRAM_INPUT; 78 p->Instructions[0].SrcReg[0].Index = FRAG_ATTRIB_TEX0; 79 p->Instructions[0].TexSrcUnit = 0; 80 p->Instructions[0].TexSrcTarget = TEXTURE_2D_INDEX; 81 /* END; */ 82 p->Instructions[1].Opcode = OPCODE_END; 83 84 p->InputsRead = FRAG_BIT_TEX0; 85 p->OutputsWritten = (1 << FRAG_RESULT_COLR); 86 87 stfp = (struct st_fragment_program *) p; 88 /* compile into tgsi format */ 89 b = tgsi_mesa_compile_fp_program(&stfp->Base, 90 stfp->tokens, ST_FP_MAX_TOKENS); 91 assert(b); 92 93 return stfp; 94} 95 96 97static struct pipe_mipmap_tree * 98make_mipmap_tree(struct st_context *st, 99 GLsizei width, GLsizei height, GLenum format, GLenum type, 100 const struct gl_pixelstore_attrib *unpack, 101 const GLvoid *pixels) 102{ 103 GLuint pipeFormat = st_choose_pipe_format(st->pipe, GL_RGBA, format, type); 104 int cpp = 4, pitch; 105 struct pipe_mipmap_tree *mt = CALLOC_STRUCT(pipe_mipmap_tree); 106 107 assert(pipeFormat); 108 109 pitch = width; /* XXX pad */ 110 111 if (unpack->BufferObj) { 112 /* 113 mt->region = buffer_object_region(unpack->BufferObj); 114 */ 115 } 116 else { 117 mt->region = st->pipe->region_alloc(st->pipe, cpp, pitch, height); 118 /* XXX do texstore() here */ 119 } 120 121 mt->target = GL_TEXTURE_2D; 122 mt->internal_format = GL_RGBA; 123 mt->format = pipeFormat; 124 mt->first_level = 0; 125 mt->last_level = 0; 126 mt->width0 = width; 127 mt->height0 = height; 128 mt->depth0 = 1; 129 mt->cpp = cpp; 130 mt->compressed = 0; 131 mt->pitch = pitch; 132 mt->depth_pitch = 0; 133 mt->total_height = height; 134 mt->level[0].level_offset = 0; 135 mt->level[0].width = width; 136 mt->level[0].height = height; 137 mt->level[0].depth = 1; 138 mt->level[0].nr_images = 1; 139 mt->level[0].image_offset = NULL; 140 mt->refcount = 1; 141 142 return mt; 143} 144 145 146static void 147free_mipmap_tree(struct pipe_context *pipe, struct pipe_mipmap_tree *mt) 148{ 149 pipe->region_release(pipe, &mt->region); 150} 151 152 153 154static void 155draw_quad(struct st_context *st, GLfloat x, GLfloat y, GLfloat z, 156 GLsizei width, GLsizei height) 157{ 158 static const GLuint attribs[2] = { 159 VF_ATTRIB_POS, 160 VF_ATTRIB_TEX0 161 }; 162 GLfloat verts[4][2][4]; /* four verts, two attribs, XYZW */ 163 GLuint i; 164 165 /* lower-left */ 166 verts[0][0][0] = x; 167 verts[0][0][1] = y; 168 verts[0][1][0] = 0.0; 169 verts[0][1][1] = 0.0; 170 171 /* lower-right */ 172 verts[1][0][0] = x + width; 173 verts[1][0][1] = y; 174 verts[1][1][0] = 1.0; 175 verts[1][1][1] = 0.0; 176 177 /* upper-right */ 178 verts[2][0][0] = x + width; 179 verts[2][0][1] = y + height; 180 verts[2][1][0] = 1.0; 181 verts[2][1][1] = 1.0; 182 183 /* upper-left */ 184 verts[3][0][0] = x; 185 verts[3][0][1] = y + height; 186 verts[3][1][0] = 0.0; 187 verts[3][1][1] = 11.0; 188 189 /* same for all verts: */ 190 for (i = 0; i < 4; i++) { 191 verts[i][0][2] = z; /*Z*/ 192 verts[i][0][3] = 1.0; /*W*/ 193 verts[i][1][2] = 0.0; /*R*/ 194 verts[i][1][3] = 1.0; /*Q*/ 195 } 196 197 st->pipe->draw_vertices(st->pipe, GL_QUADS, 198 4, (GLfloat *) verts, 2, attribs); 199} 200 201 202static void 203draw_textured_quad(struct st_context *st, GLfloat x, GLfloat y, GLfloat z, 204 GLsizei width, GLsizei height, GLenum format, GLenum type, 205 const struct gl_pixelstore_attrib *unpack, 206 const GLvoid *pixels) 207{ 208 static struct st_fragment_program *stfp = NULL; 209 struct pipe_mipmap_tree *mt; 210 struct pipe_setup_state setup; 211 struct pipe_fs_state fs; 212 213 /* setup state: just scissor */ 214 memset(&setup, 0, sizeof(setup)); 215 if (st->ctx->Scissor.Enabled) 216 setup.scissor = 1; 217 st->pipe->set_setup_state(st->pipe, &setup); 218 219 /* fragment shader state: color pass-through program */ 220 if (!stfp) { 221 stfp = make_drawpixels_shader(st); 222 } 223 memset(&fs, 0, sizeof(fs)); 224 fs.inputs_read = stfp->Base.Base.InputsRead; 225 fs.tokens = &stfp->tokens[0]; 226 fs.constants = NULL; 227 st->pipe->set_fs_state(st->pipe, &fs); 228 229 /* mipmap tree state: */ 230 mt = make_mipmap_tree(st, width, height, format, type, unpack, pixels); 231 st->pipe->set_texture_state(st->pipe, 0, mt); 232 233 /* draw! */ 234 draw_quad(st, x, y, z, width, height); 235 236 /* restore GL state */ 237 st->pipe->set_setup_state(st->pipe, &st->state.setup); 238 st->pipe->set_fs_state(st->pipe, &st->state.fs); 239 240 free_mipmap_tree(st->pipe, mt); 241} 242 243 244/** 245 * Check if a GL format/type combination is a match to the given pipe format. 246 * XXX probably move this to a re-usable place. 247 */ 248static GLboolean 249compatible_formats(GLenum format, GLenum type, GLuint pipeFormat) 250{ 251 static const GLuint one = 1; 252 GLubyte littleEndian = *((GLubyte *) &one); 253 254 if (pipeFormat == PIPE_FORMAT_U_R8_G8_B8_A8 && 255 format == GL_RGBA && 256 type == GL_UNSIGNED_BYTE && 257 !littleEndian) { 258 return GL_TRUE; 259 } 260 else if (pipeFormat == PIPE_FORMAT_U_R8_G8_B8_A8 && 261 format == GL_ABGR_EXT && 262 type == GL_UNSIGNED_BYTE && 263 littleEndian) { 264 return GL_TRUE; 265 } 266 else if (pipeFormat == PIPE_FORMAT_U_A8_R8_G8_B8 && 267 format == GL_BGRA && 268 type == GL_UNSIGNED_BYTE && 269 littleEndian) { 270 return GL_TRUE; 271 } 272 else if (pipeFormat == PIPE_FORMAT_U_R5_G6_B5 && 273 format == GL_RGB && 274 type == GL_UNSIGNED_SHORT_5_6_5) { 275 /* endian don't care */ 276 return GL_TRUE; 277 } 278 else if (pipeFormat == PIPE_FORMAT_U_R5_G6_B5 && 279 format == GL_BGR && 280 type == GL_UNSIGNED_SHORT_5_6_5_REV) { 281 /* endian don't care */ 282 return GL_TRUE; 283 } 284 else if (pipeFormat == PIPE_FORMAT_U_S8 && 285 format == GL_STENCIL_INDEX && 286 type == GL_UNSIGNED_BYTE) { 287 return GL_TRUE; 288 } 289 else if (pipeFormat == PIPE_FORMAT_U_Z32 && 290 format == GL_DEPTH_COMPONENT && 291 type == GL_UNSIGNED_INT) { 292 return GL_TRUE; 293 } 294 /* XXX add more cases */ 295 else { 296 return GL_FALSE; 297 } 298} 299 300 301/** 302 * Check if any per-fragment ops are enabled. 303 * XXX probably move this to a re-usable place. 304 */ 305static GLboolean 306any_fragment_ops(const struct st_context *st) 307{ 308 if (st->state.alpha_test.enabled || 309 st->state.blend.blend_enable || 310 st->state.blend.logicop_enable || 311 st->state.depth.enabled) 312 /* XXX more checks */ 313 return GL_TRUE; 314 else 315 return GL_FALSE; 316} 317 318 319/** 320 * Check if any pixel transfer ops are enabled. 321 * XXX probably move this to a re-usable place. 322 */ 323static GLboolean 324any_pixel_transfer_ops(const struct st_context *st) 325{ 326 if (st->ctx->Pixel.RedScale != 1.0 || 327 st->ctx->Pixel.RedBias != 0.0 || 328 st->ctx->Pixel.GreenScale != 1.0 || 329 st->ctx->Pixel.GreenBias != 0.0 || 330 st->ctx->Pixel.BlueScale != 1.0 || 331 st->ctx->Pixel.BlueBias != 0.0 || 332 st->ctx->Pixel.AlphaScale != 1.0 || 333 st->ctx->Pixel.AlphaBias != 0.0 || 334 st->ctx->Pixel.MapColorFlag) 335 /* XXX more checks */ 336 return GL_TRUE; 337 else 338 return GL_FALSE; 339} 340 341 342/** 343 * Draw image with a blit, or other non-textured quad method. 344 */ 345static void 346draw_blit(struct st_context *st, 347 GLsizei width, GLsizei height, 348 GLenum format, GLenum type, const GLvoid *pixels) 349{ 350 351 352} 353 354 355/** 356 * Called via ctx->Driver.DrawPixels() 357 */ 358static void 359st_drawpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, 360 GLenum format, GLenum type, 361 const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels) 362{ 363 struct st_context *st = ctx->st; 364 struct pipe_surface *ps; 365 GLuint bufferFormat; 366 367 if (format == GL_DEPTH_COMPONENT) { 368 ps = st->state.framebuffer.zbuf; 369 } 370 else if (format == GL_STENCIL_INDEX) { 371 ps = st->state.framebuffer.sbuf; 372 } 373 else { 374 ps = st->state.framebuffer.cbufs[0]; 375 } 376 377 bufferFormat = ps->format; 378 379 if (any_fragment_ops(st) || 380 any_pixel_transfer_ops(st) || 381 !compatible_formats(format, type, ps->format)) { 382 /* textured quad */ 383 draw_textured_quad(st, x, y, ctx->Current.RasterPos[2], width, height, 384 format, type, unpack, pixels); 385 } 386 else { 387 /* blit */ 388 draw_blit(st, width, height, format, type, pixels); 389 } 390} 391 392 393void st_init_drawpixels_functions(struct dd_function_table *functions) 394{ 395 functions->DrawPixels = st_drawpixels; 396} 397 398