1 /**************************************************************************
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
33 #include "main/imports.h"
34 #include "main/image.h"
36 #include "st_context.h"
40 #include "st_program.h"
41 #include "st_cb_drawpixels.h"
42 #include "st_cb_texture.h"
44 #include "st_format.h"
45 #include "pipe/p_context.h"
46 #include "pipe/p_defines.h"
47 #include "pipe/tgsi/mesa/mesa_to_tgsi.h"
48 #include "shader/prog_instruction.h"
54 * Create a simple fragment shader that does a TEX() instruction to get
57 static struct st_fragment_program
*
58 make_fragment_shader(struct st_context
*st
, GLboolean bitmapMode
)
60 GLcontext
*ctx
= st
->ctx
;
61 struct st_fragment_program
*stfp
;
65 p
= ctx
->Driver
.NewProgram(ctx
, GL_FRAGMENT_PROGRAM_ARB
, 0);
69 #define CULL 1 /* Use KIL to cull 0 bits/pixels in bitmap? */
73 p
->NumInstructions
= 7;
75 p
->NumInstructions
= 3;
78 p
->NumInstructions
= 2;
80 p
->Instructions
= _mesa_alloc_instructions(p
->NumInstructions
);
81 if (!p
->Instructions
) {
82 ctx
->Driver
.DeleteProgram(ctx
, p
);
85 _mesa_init_instructions(p
->Instructions
, p
->NumInstructions
);
88 * XXX This is temporary
89 * We actually need to cull the fragment if the texture value is zero.
90 * But TGSI doesn't support conditionals yet.
91 * Also, we need to compose this fragment shader with the current
92 * user-provided fragment shader so the fragment program is applied
93 * to the fragments which aren't culled.
95 /* TEX temp0, fragment.texcoord[0], texture[0], 2D; */
96 p
->Instructions
[ic
].Opcode
= OPCODE_TEX
;
97 p
->Instructions
[ic
].DstReg
.File
= PROGRAM_TEMPORARY
;
98 p
->Instructions
[ic
].DstReg
.Index
= 0;
99 p
->Instructions
[ic
].SrcReg
[0].File
= PROGRAM_INPUT
;
100 p
->Instructions
[ic
].SrcReg
[0].Index
= FRAG_ATTRIB_TEX0
;
101 p
->Instructions
[ic
].TexSrcUnit
= 0;
102 p
->Instructions
[ic
].TexSrcTarget
= TEXTURE_2D_INDEX
;
106 p
->Instructions
[ic
].Opcode
= OPCODE_IF
;
107 p
->Instructions
[ic
].SrcReg
[0].File
= PROGRAM_TEMPORARY
;
108 p
->Instructions
[ic
].SrcReg
[0].Index
= 0;
109 p
->Instructions
[ic
].SrcReg
[0].Swizzle
= SWIZZLE_WWWW
;
110 p
->Instructions
[ic
].BranchTarget
= ic
+ 2;
113 /* MOV result.color, fragment.color */
114 p
->Instructions
[ic
].Opcode
= OPCODE_MOV
;
115 p
->Instructions
[ic
].DstReg
.File
= PROGRAM_OUTPUT
;
116 p
->Instructions
[ic
].DstReg
.Index
= FRAG_RESULT_COLR
;
117 p
->Instructions
[ic
].SrcReg
[0].File
= PROGRAM_INPUT
;
118 p
->Instructions
[ic
].SrcReg
[0].Index
= FRAG_ATTRIB_COL0
;
122 p
->Instructions
[ic
].Opcode
= OPCODE_ELSE
;
123 p
->Instructions
[ic
].BranchTarget
= ic
+ 2;
127 p
->Instructions
[ic
].Opcode
= OPCODE_KIL_NV
;
131 p
->Instructions
[ic
].Opcode
= OPCODE_ENDIF
;
134 /* MUL result.color, temp0.xxxx, fragment.color */
135 p
->Instructions
[ic
].Opcode
= OPCODE_MUL
;
136 p
->Instructions
[ic
].DstReg
.File
= PROGRAM_OUTPUT
;
137 p
->Instructions
[ic
].DstReg
.Index
= FRAG_RESULT_COLR
;
138 p
->Instructions
[ic
].SrcReg
[0].File
= PROGRAM_TEMPORARY
;
139 p
->Instructions
[ic
].SrcReg
[0].Index
= 0;
140 p
->Instructions
[ic
].SrcReg
[0].Swizzle
= SWIZZLE_WWWW
;
141 p
->Instructions
[ic
].SrcReg
[1].File
= PROGRAM_INPUT
;
142 p
->Instructions
[ic
].SrcReg
[1].Index
= FRAG_ATTRIB_COL0
;
147 /* DrawPixels mode */
148 /* TEX result.color, fragment.texcoord[0], texture[0], 2D; */
149 p
->Instructions
[ic
].Opcode
= OPCODE_TEX
;
150 p
->Instructions
[ic
].DstReg
.File
= PROGRAM_OUTPUT
;
151 p
->Instructions
[ic
].DstReg
.Index
= FRAG_RESULT_COLR
;
152 p
->Instructions
[ic
].SrcReg
[0].File
= PROGRAM_INPUT
;
153 p
->Instructions
[ic
].SrcReg
[0].Index
= FRAG_ATTRIB_TEX0
;
154 p
->Instructions
[ic
].TexSrcUnit
= 0;
155 p
->Instructions
[ic
].TexSrcTarget
= TEXTURE_2D_INDEX
;
159 p
->Instructions
[ic
++].Opcode
= OPCODE_END
;
161 assert(ic
== p
->NumInstructions
);
163 p
->InputsRead
= FRAG_BIT_TEX0
;
164 p
->OutputsWritten
= (1 << FRAG_RESULT_COLR
);
166 p
->InputsRead
|= FRAG_BIT_COL0
;
169 stfp
= (struct st_fragment_program
*) p
;
170 st_translate_fragment_program(st
, stfp
, NULL
,
171 stfp
->tokens
, ST_MAX_SHADER_TOKENS
);
178 * Create a simple vertex shader that just passes through the
179 * vertex position and texcoord (and color).
181 static struct st_vertex_program
*
182 make_vertex_shader(struct st_context
*st
, GLboolean passColor
)
184 GLcontext
*ctx
= st
->ctx
;
185 struct st_vertex_program
*stvp
;
186 struct gl_program
*p
;
189 p
= ctx
->Driver
.NewProgram(ctx
, GL_VERTEX_PROGRAM_ARB
, 0);
194 p
->NumInstructions
= 4;
196 p
->NumInstructions
= 3;
198 p
->Instructions
= _mesa_alloc_instructions(p
->NumInstructions
);
199 if (!p
->Instructions
) {
200 ctx
->Driver
.DeleteProgram(ctx
, p
);
203 _mesa_init_instructions(p
->Instructions
, p
->NumInstructions
);
204 /* MOV result.pos, vertex.pos; */
205 p
->Instructions
[0].Opcode
= OPCODE_MOV
;
206 p
->Instructions
[0].DstReg
.File
= PROGRAM_OUTPUT
;
207 p
->Instructions
[0].DstReg
.Index
= VERT_RESULT_HPOS
;
208 p
->Instructions
[0].SrcReg
[0].File
= PROGRAM_INPUT
;
209 p
->Instructions
[0].SrcReg
[0].Index
= VERT_ATTRIB_POS
;
210 /* MOV result.texcoord0, vertex.texcoord0; */
211 p
->Instructions
[1].Opcode
= OPCODE_MOV
;
212 p
->Instructions
[1].DstReg
.File
= PROGRAM_OUTPUT
;
213 p
->Instructions
[1].DstReg
.Index
= VERT_RESULT_TEX0
;
214 p
->Instructions
[1].SrcReg
[0].File
= PROGRAM_INPUT
;
215 p
->Instructions
[1].SrcReg
[0].Index
= VERT_ATTRIB_TEX0
;
218 /* MOV result.color0, vertex.color0; */
219 p
->Instructions
[ic
].Opcode
= OPCODE_MOV
;
220 p
->Instructions
[ic
].DstReg
.File
= PROGRAM_OUTPUT
;
221 p
->Instructions
[ic
].DstReg
.Index
= VERT_RESULT_COL0
;
222 p
->Instructions
[ic
].SrcReg
[0].File
= PROGRAM_INPUT
;
223 p
->Instructions
[ic
].SrcReg
[0].Index
= VERT_ATTRIB_COLOR0
;
228 p
->Instructions
[ic
].Opcode
= OPCODE_END
;
231 assert(ic
== p
->NumInstructions
);
233 p
->InputsRead
= VERT_BIT_POS
| VERT_BIT_TEX0
;
234 p
->OutputsWritten
= ((1 << VERT_RESULT_TEX0
) |
235 (1 << VERT_RESULT_HPOS
));
237 p
->InputsRead
|= VERT_BIT_COLOR0
;
238 p
->OutputsWritten
|= (1 << VERT_RESULT_COL0
);
241 stvp
= (struct st_vertex_program
*) p
;
242 st_translate_vertex_program(st
, stvp
, NULL
,
243 stvp
->tokens
, ST_MAX_SHADER_TOKENS
);
250 * Make mipmap tree containing the glDrawPixels image.
252 static struct pipe_mipmap_tree
*
253 make_mipmap_tree(struct st_context
*st
,
254 GLsizei width
, GLsizei height
, GLenum format
, GLenum type
,
255 const struct gl_pixelstore_attrib
*unpack
,
256 const GLvoid
*pixels
)
258 struct pipe_context
*pipe
= st
->pipe
;
259 const struct gl_texture_format
*mformat
;
260 const GLbitfield flags
= PIPE_SURFACE_FLAG_TEXTURE
;
261 struct pipe_mipmap_tree
*mt
;
262 GLuint pipeFormat
, cpp
;
264 mformat
= st_ChooseTextureFormat(st
->ctx
, GL_RGBA
, format
, type
);
267 pipeFormat
= st_mesa_format_to_pipe_format(mformat
->MesaFormat
);
269 cpp
= st_sizeof_format(pipeFormat
);
271 mt
= CALLOC_STRUCT(pipe_mipmap_tree
);
275 if (unpack
->BufferObj
&& unpack
->BufferObj
->Name
) {
277 mt->region = buffer_object_region(unpack->BufferObj);
279 printf("st_DrawPixels (sourcing from PBO not implemented yet)\n");
282 static const GLuint dstImageOffsets
= 0;
287 /* allocate texture region/storage */
288 mt
->region
= st
->pipe
->region_alloc(st
->pipe
, cpp
, width
, height
, flags
);
289 pitch
= mt
->region
->pitch
;
291 /* map texture region */
292 dest
= pipe
->region_map(pipe
, mt
->region
);
294 /* Put image into texture region.
295 * Note that the image is actually going to be upside down in
296 * the texture. We deal with that with texcoords.
298 success
= mformat
->StoreImage(st
->ctx
, 2, /* dims */
299 GL_RGBA
, /* baseInternalFormat */
300 mformat
, /* gl_texture_format */
302 0, 0, 0, /* dstX/Y/Zoffset */
303 pitch
* cpp
, /* dstRowStride, bytes */
304 &dstImageOffsets
, /* dstImageOffsets */
305 width
, height
, 1, /* size */
306 format
, type
, /* src format/type */
307 pixels
, /* data source */
311 pipe
->region_unmap(pipe
, mt
->region
);
316 mt
->target
= PIPE_TEXTURE_2D
;
317 mt
->internal_format
= GL_RGBA
;
318 mt
->format
= pipeFormat
;
322 mt
->height0
= height
;
326 mt
->pitch
= mt
->region
->pitch
;
328 mt
->total_height
= height
;
329 mt
->level
[0].level_offset
= 0;
330 mt
->level
[0].width
= width
;
331 mt
->level
[0].height
= height
;
332 mt
->level
[0].depth
= 1;
333 mt
->level
[0].nr_images
= 1;
334 mt
->level
[0].image_offset
= NULL
;
342 free_mipmap_tree(struct pipe_context
*pipe
, struct pipe_mipmap_tree
*mt
)
344 pipe
->region_release(pipe
, &mt
->region
);
350 * Draw textured quad.
351 * Coords are window coords with y=0=bottom.
354 draw_quad(GLcontext
*ctx
, GLfloat x0
, GLfloat y0
, GLfloat z
,
355 GLfloat x1
, GLfloat y1
)
357 GLfloat verts
[4][2][4]; /* four verts, two attribs, XYZW */
361 verts
[0][0][0] = x0
; /* attr[0].x */
362 verts
[0][0][1] = y0
; /* attr[0].x */
363 verts
[0][1][0] = 0.0; /* attr[1].s */
364 verts
[0][1][1] = 0.0; /* attr[1].t */
369 verts
[1][1][0] = 1.0;
370 verts
[1][1][1] = 0.0;
375 verts
[2][1][0] = 1.0;
376 verts
[2][1][1] = 1.0;
381 verts
[3][1][0] = 0.0;
382 verts
[3][1][1] = 1.0;
384 /* same for all verts: */
385 for (i
= 0; i
< 4; i
++) {
386 verts
[i
][0][2] = z
; /*Z*/
387 verts
[i
][0][3] = 1.0; /*W*/
388 verts
[i
][1][2] = 0.0; /*R*/
389 verts
[i
][1][3] = 1.0; /*Q*/
392 st_draw_vertices(ctx
, PIPE_PRIM_QUADS
, 4, (float *) verts
, 2);
397 draw_quad_colored(GLcontext
*ctx
, GLfloat x0
, GLfloat y0
, GLfloat z
,
398 GLfloat x1
, GLfloat y1
, const GLfloat
*color
)
400 GLfloat verts
[4][3][4]; /* four verts, three attribs, XYZW */
404 verts
[0][0][0] = x0
; /* attr[0].x */
405 verts
[0][0][1] = y0
; /* attr[0].x */
406 verts
[0][2][0] = 0.0; /* attr[2].s */
407 verts
[0][2][1] = 0.0; /* attr[2].t */
412 verts
[1][2][0] = 1.0;
413 verts
[1][2][1] = 0.0;
418 verts
[2][2][0] = 1.0;
419 verts
[2][2][1] = 1.0;
424 verts
[3][2][0] = 0.0;
425 verts
[3][2][1] = 1.0;
427 /* same for all verts: */
428 for (i
= 0; i
< 4; i
++) {
429 verts
[i
][0][2] = z
; /*Z*/
430 verts
[i
][0][3] = 1.0; /*W*/
431 verts
[i
][1][0] = color
[0];
432 verts
[i
][1][1] = color
[1];
433 verts
[i
][1][2] = color
[2];
434 verts
[i
][1][3] = color
[3];
435 verts
[i
][2][2] = 0.0; /*R*/
436 verts
[i
][2][3] = 1.0; /*Q*/
439 st_draw_vertices(ctx
, PIPE_PRIM_QUADS
, 4, (float *) verts
, 3);
445 draw_textured_quad(GLcontext
*ctx
, GLint x
, GLint y
, GLfloat z
,
446 GLsizei width
, GLsizei height
,
447 GLfloat zoomX
, GLfloat zoomY
,
448 struct pipe_mipmap_tree
*mt
,
449 struct st_vertex_program
*stvp
,
450 struct st_fragment_program
*stfp
,
451 const GLfloat
*color
)
453 const GLuint unit
= 0;
454 struct pipe_context
*pipe
= ctx
->st
->pipe
;
455 GLfloat x0
, y0
, x1
, y1
;
456 GLuint maxWidth
, maxHeight
;
459 /* XXX if DrawPixels image is larger than max texture size, break
462 pipe
->max_texture_size(pipe
, PIPE_TEXTURE_2D
, &maxWidth
, &maxHeight
, NULL
);
463 assert(width
<= maxWidth
);
464 assert(height
<= maxHeight
);
466 /* setup state: just scissor */
468 struct pipe_rasterizer_state setup
;
469 const struct cso_rasterizer
*cso
;
470 memset(&setup
, 0, sizeof(setup
));
471 if (ctx
->Scissor
.Enabled
)
473 cso
= st_cached_rasterizer_state(ctx
->st
, &setup
);
474 pipe
->bind_rasterizer_state(pipe
, cso
->data
);
477 /* fragment shader state: TEX lookup program */
478 pipe
->bind_fs_state(pipe
, stfp
->fs
->data
);
480 /* vertex shader state: position + texcoord pass-through */
481 pipe
->bind_vs_state(pipe
, stvp
->vs
->data
);
483 /* texture sampling state: */
485 struct pipe_sampler_state sampler
;
486 const struct cso_sampler
*cso
;
487 memset(&sampler
, 0, sizeof(sampler
));
488 sampler
.wrap_s
= PIPE_TEX_WRAP_REPEAT
;
489 sampler
.wrap_t
= PIPE_TEX_WRAP_REPEAT
;
490 sampler
.wrap_r
= PIPE_TEX_WRAP_REPEAT
;
491 sampler
.min_img_filter
= PIPE_TEX_FILTER_NEAREST
;
492 sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NONE
;
493 sampler
.mag_img_filter
= PIPE_TEX_FILTER_NEAREST
;
494 cso
= st_cached_sampler_state(ctx
->st
, &sampler
);
495 pipe
->bind_sampler_state(pipe
, unit
, cso
->data
);
498 /* viewport state: viewport matching window dims */
500 const float width
= ctx
->DrawBuffer
->Width
;
501 const float height
= ctx
->DrawBuffer
->Height
;
502 struct pipe_viewport_state vp
;
503 vp
.scale
[0] = 0.5 * width
;
504 vp
.scale
[1] = -0.5 * height
;
507 vp
.translate
[0] = 0.5 * width
;
508 vp
.translate
[1] = 0.5 * height
;
509 vp
.translate
[2] = 0.5;
510 vp
.translate
[3] = 0.0;
511 pipe
->set_viewport_state(pipe
, &vp
);
514 /* mipmap tree state: */
516 pipe
->set_texture_state(pipe
, unit
, mt
);
519 /* Compute window coords (y=0=bottom) with pixel zoom.
520 * Recall that these coords are transformed by the current
521 * vertex shader and viewport transformation.
524 x1
= x
+ width
* ctx
->Pixel
.ZoomX
;
526 y1
= y
+ height
* ctx
->Pixel
.ZoomY
;
528 /* draw textured quad */
530 draw_quad_colored(ctx
, x0
, y0
, z
, x1
, y1
, color
);
532 draw_quad(ctx
, x0
, y0
, z
, x1
, y1
);
534 /* restore GL state */
535 pipe
->bind_rasterizer_state(pipe
, ctx
->st
->state
.rasterizer
->data
);
536 pipe
->bind_fs_state(pipe
, ctx
->st
->state
.fs
->data
);
537 pipe
->bind_vs_state(pipe
, ctx
->st
->state
.vs
->data
);
538 pipe
->set_texture_state(pipe
, unit
, ctx
->st
->state
.texture
[unit
]);
539 pipe
->bind_sampler_state(pipe
, unit
, ctx
->st
->state
.sampler
[unit
]->data
);
540 pipe
->set_viewport_state(pipe
, &ctx
->st
->state
.viewport
);
545 * Check if a GL format/type combination is a match to the given pipe format.
546 * XXX probably move this to a re-usable place.
549 compatible_formats(GLenum format
, GLenum type
, GLuint pipeFormat
)
551 static const GLuint one
= 1;
552 GLubyte littleEndian
= *((GLubyte
*) &one
);
554 if (pipeFormat
== PIPE_FORMAT_U_R8_G8_B8_A8
&&
556 type
== GL_UNSIGNED_BYTE
&&
560 else if (pipeFormat
== PIPE_FORMAT_U_R8_G8_B8_A8
&&
561 format
== GL_ABGR_EXT
&&
562 type
== GL_UNSIGNED_BYTE
&&
566 else if (pipeFormat
== PIPE_FORMAT_U_A8_R8_G8_B8
&&
568 type
== GL_UNSIGNED_BYTE
&&
572 else if (pipeFormat
== PIPE_FORMAT_U_R5_G6_B5
&&
574 type
== GL_UNSIGNED_SHORT_5_6_5
) {
575 /* endian don't care */
578 else if (pipeFormat
== PIPE_FORMAT_U_R5_G6_B5
&&
580 type
== GL_UNSIGNED_SHORT_5_6_5_REV
) {
581 /* endian don't care */
584 else if (pipeFormat
== PIPE_FORMAT_U_S8
&&
585 format
== GL_STENCIL_INDEX
&&
586 type
== GL_UNSIGNED_BYTE
) {
589 else if (pipeFormat
== PIPE_FORMAT_U_Z32
&&
590 format
== GL_DEPTH_COMPONENT
&&
591 type
== GL_UNSIGNED_INT
) {
594 /* XXX add more cases */
602 * Check if any per-fragment ops are enabled.
603 * XXX probably move this to a re-usable place.
606 any_fragment_ops(const struct st_context
*st
)
608 if (st
->state
.alpha_test
->state
.enabled
||
609 st
->state
.blend
->state
.blend_enable
||
610 st
->state
.blend
->state
.logicop_enable
||
611 st
->state
.depth_stencil
->state
.depth
.enabled
)
612 /* XXX more checks */
620 * Check if any pixel transfer ops are enabled.
621 * XXX probably move this to a re-usable place.
624 any_pixel_transfer_ops(const struct st_context
*st
)
626 if (st
->ctx
->Pixel
.RedScale
!= 1.0 ||
627 st
->ctx
->Pixel
.RedBias
!= 0.0 ||
628 st
->ctx
->Pixel
.GreenScale
!= 1.0 ||
629 st
->ctx
->Pixel
.GreenBias
!= 0.0 ||
630 st
->ctx
->Pixel
.BlueScale
!= 1.0 ||
631 st
->ctx
->Pixel
.BlueBias
!= 0.0 ||
632 st
->ctx
->Pixel
.AlphaScale
!= 1.0 ||
633 st
->ctx
->Pixel
.AlphaBias
!= 0.0 ||
634 st
->ctx
->Pixel
.MapColorFlag
)
635 /* XXX more checks */
643 * Draw image with a blit, or other non-textured quad method.
646 draw_blit(struct st_context
*st
,
647 GLsizei width
, GLsizei height
,
648 GLenum format
, GLenum type
, const GLvoid
*pixels
)
656 * Called via ctx->Driver.DrawPixels()
659 st_DrawPixels(GLcontext
*ctx
, GLint x
, GLint y
, GLsizei width
, GLsizei height
,
660 GLenum format
, GLenum type
,
661 const struct gl_pixelstore_attrib
*unpack
, const GLvoid
*pixels
)
663 static struct st_fragment_program
*stfp
= NULL
;
664 static struct st_vertex_program
*stvp
= NULL
;
665 struct st_context
*st
= ctx
->st
;
666 struct pipe_surface
*ps
;
669 /* create the fragment program if needed */
671 stfp
= make_fragment_shader(ctx
->st
, GL_FALSE
);
673 /* and vertex program */
675 stvp
= make_vertex_shader(ctx
->st
, GL_FALSE
);
678 st_validate_state(st
);
680 if (format
== GL_DEPTH_COMPONENT
) {
681 ps
= st
->state
.framebuffer
.zbuf
;
683 else if (format
== GL_STENCIL_INDEX
) {
684 ps
= st
->state
.framebuffer
.sbuf
;
687 ps
= st
->state
.framebuffer
.cbufs
[0];
690 bufferFormat
= ps
->format
;
692 if (any_fragment_ops(st
) ||
693 any_pixel_transfer_ops(st
) ||
694 !compatible_formats(format
, type
, ps
->format
)) {
696 struct pipe_mipmap_tree
*mt
697 = make_mipmap_tree(ctx
->st
, width
, height
, format
, type
,
700 draw_textured_quad(ctx
, x
, y
, ctx
->Current
.RasterPos
[2],
701 width
, height
, ctx
->Pixel
.ZoomX
, ctx
->Pixel
.ZoomY
,
702 mt
, stvp
, stfp
, NULL
);
703 free_mipmap_tree(st
->pipe
, mt
);
708 draw_blit(st
, width
, height
, format
, type
, pixels
);
715 * Create a texture which represents a bitmap image.
717 static struct pipe_mipmap_tree
*
718 make_bitmap_texture(GLcontext
*ctx
, GLsizei width
, GLsizei height
,
719 const struct gl_pixelstore_attrib
*unpack
,
720 const GLubyte
*bitmap
)
722 struct pipe_context
*pipe
= ctx
->st
->pipe
;
723 const uint flags
= PIPE_SURFACE_FLAG_TEXTURE
;
724 uint numFormats
, i
, format
= 0, cpp
, comp
, pitch
;
725 const uint
*formats
= ctx
->st
->pipe
->supported_formats(pipe
, &numFormats
);
727 struct pipe_mipmap_tree
*mt
;
730 /* find a texture format we know */
731 for (i
= 0; i
< numFormats
; i
++) {
732 switch (formats
[i
]) {
733 case PIPE_FORMAT_U_I8
:
738 case PIPE_FORMAT_U_A8_R8_G8_B8
:
741 comp
= 3; /* alpha channel */ /*XXX little-endian dependency */
744 /* XXX support more formats */
751 * Create a mipmap tree.
753 mt
= CALLOC_STRUCT(pipe_mipmap_tree
);
757 if (unpack
->BufferObj
&& unpack
->BufferObj
->Name
) {
759 mt->region = buffer_object_region(unpack->BufferObj);
761 printf("st_Bitmap (sourcing from PBO not implemented yet)\n");
765 /* allocate texture region/storage */
766 mt
->region
= pipe
->region_alloc(pipe
, cpp
, width
, height
, flags
);
767 pitch
= mt
->region
->pitch
;
769 /* map texture region */
770 dest
= pipe
->region_map(pipe
, mt
->region
);
772 printf("st_Bitmap region_map() failed!?!");
776 /* Put image into texture region.
777 * Note that the image is actually going to be upside down in
778 * the texture. We deal with that with texcoords.
781 for (row
= 0; row
< height
; row
++) {
782 const GLubyte
*src
= (const GLubyte
*) _mesa_image_address2d(unpack
,
783 bitmap
, width
, height
, GL_COLOR_INDEX
, GL_BITMAP
, row
, 0);
784 ubyte
*destRow
= dest
+ row
* pitch
* cpp
;
786 if (unpack
->LsbFirst
) {
788 GLubyte mask
= 1U << (unpack
->SkipPixels
& 0x7);
790 for (col
= 0; col
< width
; col
++) {
792 /* set texel to 255 if bit is set */
793 destRow
[comp
] = (*src
& mask
) ? 255 : 0;
805 /* get ready for next row */
811 GLubyte mask
= 128U >> (unpack
->SkipPixels
& 0x7);
812 for (col
= 0; col
< width
; col
++) {
814 /* set texel to 255 if bit is set */
815 destRow
[comp
] =(*src
& mask
) ? 255 : 0;
827 /* get ready for next row */
835 pipe
->region_unmap(pipe
, mt
->region
);
837 mt
->target
= PIPE_TEXTURE_2D
;
838 mt
->internal_format
= GL_RGBA
;
843 mt
->height0
= height
;
847 mt
->pitch
= mt
->region
->pitch
;
849 mt
->total_height
= height
;
850 mt
->level
[0].level_offset
= 0;
851 mt
->level
[0].width
= width
;
852 mt
->level
[0].height
= height
;
853 mt
->level
[0].depth
= 1;
854 mt
->level
[0].nr_images
= 1;
855 mt
->level
[0].image_offset
= NULL
;
864 st_Bitmap(GLcontext
*ctx
, GLint x
, GLint y
, GLsizei width
, GLsizei height
,
865 const struct gl_pixelstore_attrib
*unpack
, const GLubyte
*bitmap
)
867 static struct st_vertex_program
*stvp
= NULL
;
868 static struct st_fragment_program
*stfp
= NULL
;
869 struct st_context
*st
= ctx
->st
;
870 struct pipe_mipmap_tree
*mt
;
872 /* create the fragment program if needed */
874 stfp
= make_fragment_shader(ctx
->st
, GL_TRUE
);
876 /* and vertex program */
878 stvp
= make_vertex_shader(ctx
->st
, GL_TRUE
);
881 st_validate_state(st
);
883 mt
= make_bitmap_texture(ctx
, width
, height
, unpack
, bitmap
);
885 draw_textured_quad(ctx
, x
, y
, ctx
->Current
.RasterPos
[2],
886 width
, height
, 1.0, 1.0,
888 ctx
->Current
.RasterColor
);
890 free_mipmap_tree(st
->pipe
, mt
);
896 st_CopyPixels(GLcontext
*ctx
, GLint srcx
, GLint srcy
,
897 GLsizei width
, GLsizei height
,
898 GLint dstx
, GLint dsty
, GLenum type
)
900 struct st_context
*st
= ctx
->st
;
902 st_validate_state(st
);
904 fprintf(stderr
, "st_CopyPixels not implemented yet\n");
910 void st_init_drawpixels_functions(struct dd_function_table
*functions
)
912 functions
->DrawPixels
= st_DrawPixels
;
913 functions
->CopyPixels
= st_CopyPixels
;
914 functions
->Bitmap
= st_Bitmap
;