fix up radeon span functions using latest r200 code from Brian,
[mesa.git] / src / mesa / drivers / dri / i915 / i830_metaops.c
1 /**************************************************************************
2 *
3 * Copyright 2003 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 #include "glheader.h"
29 #include "enums.h"
30 #include "mtypes.h"
31 #include "macros.h"
32 #include "utils.h"
33
34 #include "intel_screen.h"
35 #include "intel_batchbuffer.h"
36 #include "intel_ioctl.h"
37
38 #include "i830_context.h"
39 #include "i830_reg.h"
40
41 /* A large amount of state doesn't need to be uploaded.
42 */
43 #define ACTIVE (I830_UPLOAD_TEXBLEND(0) | \
44 I830_UPLOAD_STIPPLE | \
45 I830_UPLOAD_CTX | \
46 I830_UPLOAD_BUFFERS | \
47 I830_UPLOAD_TEX(0))
48
49
50 #define SET_STATE( i830, STATE ) \
51 do { \
52 i830->current->emitted &= ~ACTIVE; \
53 i830->current = &i830->STATE; \
54 i830->current->emitted &= ~ACTIVE; \
55 } while (0)
56
57 /* Operations where the 3D engine is decoupled temporarily from the
58 * current GL state and used for other purposes than simply rendering
59 * incoming triangles.
60 */
61 static void set_initial_state( i830ContextPtr i830 )
62 {
63 memcpy(&i830->meta, &i830->initial, sizeof(i830->meta) );
64 i830->meta.active = ACTIVE;
65 i830->meta.emitted = 0;
66 }
67
68
69 static void set_no_depth_stencil_write( i830ContextPtr i830 )
70 {
71 /* ctx->Driver.Enable( ctx, GL_STENCIL_TEST, GL_FALSE )
72 */
73 i830->meta.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_STENCIL_TEST;
74 i830->meta.Ctx[I830_CTXREG_ENABLES_2] &= ~ENABLE_STENCIL_WRITE;
75 i830->meta.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_STENCIL_TEST;
76 i830->meta.Ctx[I830_CTXREG_ENABLES_2] |= DISABLE_STENCIL_WRITE;
77
78
79 /* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_FALSE )
80 */
81 i830->meta.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_DIS_DEPTH_TEST_MASK;
82 i830->meta.Ctx[I830_CTXREG_ENABLES_2] &= ~ENABLE_DIS_DEPTH_WRITE_MASK;
83 i830->meta.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_DEPTH_TEST;
84 i830->meta.Ctx[I830_CTXREG_ENABLES_2] |= DISABLE_DEPTH_WRITE;
85
86 i830->meta.emitted &= ~I830_UPLOAD_CTX;
87 }
88
89 /* Set stencil unit to replace always with the reference value.
90 */
91 static void set_stencil_replace( i830ContextPtr i830,
92 GLuint s_mask,
93 GLuint s_clear)
94 {
95 /* ctx->Driver.Enable( ctx, GL_STENCIL_TEST, GL_TRUE )
96 */
97 i830->meta.Ctx[I830_CTXREG_ENABLES_1] |= ENABLE_STENCIL_TEST;
98 i830->meta.Ctx[I830_CTXREG_ENABLES_2] |= ENABLE_STENCIL_WRITE;
99
100
101 /* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_FALSE )
102 */
103 i830->meta.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_DIS_DEPTH_TEST_MASK;
104 i830->meta.Ctx[I830_CTXREG_ENABLES_2] &= ~ENABLE_DIS_DEPTH_WRITE_MASK;
105 i830->meta.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_DEPTH_TEST;
106 i830->meta.Ctx[I830_CTXREG_ENABLES_2] |= DISABLE_DEPTH_WRITE;
107
108 /* ctx->Driver.StencilMask( ctx, s_mask )
109 */
110 i830->meta.Ctx[I830_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_WRITE_MASK;
111 i830->meta.Ctx[I830_CTXREG_STATE4] |= (ENABLE_STENCIL_WRITE_MASK |
112 STENCIL_WRITE_MASK((s_mask&0xff)));
113
114 /* ctx->Driver.StencilOp( ctx, GL_REPLACE, GL_REPLACE, GL_REPLACE )
115 */
116 i830->meta.Ctx[I830_CTXREG_STENCILTST] &= ~(STENCIL_OPS_MASK);
117 i830->meta.Ctx[I830_CTXREG_STENCILTST] |=
118 (ENABLE_STENCIL_PARMS |
119 STENCIL_FAIL_OP(STENCILOP_REPLACE) |
120 STENCIL_PASS_DEPTH_FAIL_OP(STENCILOP_REPLACE) |
121 STENCIL_PASS_DEPTH_PASS_OP(STENCILOP_REPLACE));
122
123 /* ctx->Driver.StencilFunc( ctx, GL_ALWAYS, s_clear, ~0 )
124 */
125 i830->meta.Ctx[I830_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_TEST_MASK;
126 i830->meta.Ctx[I830_CTXREG_STATE4] |= (ENABLE_STENCIL_TEST_MASK |
127 STENCIL_TEST_MASK(0xff));
128
129 i830->meta.Ctx[I830_CTXREG_STENCILTST] &= ~(STENCIL_REF_VALUE_MASK |
130 ENABLE_STENCIL_TEST_FUNC_MASK);
131 i830->meta.Ctx[I830_CTXREG_STENCILTST] |=
132 (ENABLE_STENCIL_REF_VALUE |
133 ENABLE_STENCIL_TEST_FUNC |
134 STENCIL_REF_VALUE((s_clear&0xff)) |
135 STENCIL_TEST_FUNC(COMPAREFUNC_ALWAYS));
136
137
138
139 i830->meta.emitted &= ~I830_UPLOAD_CTX;
140 }
141
142
143 static void set_color_mask( i830ContextPtr i830, GLboolean state )
144 {
145 const GLuint mask = ((1 << WRITEMASK_RED_SHIFT) |
146 (1 << WRITEMASK_GREEN_SHIFT) |
147 (1 << WRITEMASK_BLUE_SHIFT) |
148 (1 << WRITEMASK_ALPHA_SHIFT));
149
150 if (state) {
151 i830->meta.Ctx[I830_CTXREG_ENABLES_2] &= ~mask;
152 i830->meta.Ctx[I830_CTXREG_ENABLES_2] |=
153 (i830->state.Ctx[I830_CTXREG_ENABLES_2] & mask);
154 }
155 else
156 i830->meta.Ctx[I830_CTXREG_ENABLES_2] |= mask;
157
158 i830->meta.emitted &= ~I830_UPLOAD_CTX;
159 }
160
161 /* Installs a one-stage passthrough texture blend pipeline. Is there
162 * more that can be done to turn off texturing?
163 */
164 static void set_no_texture( i830ContextPtr i830 )
165 {
166 static const struct gl_tex_env_combine_state comb = {
167 GL_NONE, GL_NONE,
168 { GL_TEXTURE, 0, 0, }, { GL_TEXTURE, 0, 0, },
169 { GL_SRC_COLOR, 0, 0 }, { GL_SRC_ALPHA, 0, 0 },
170 0, 0, 0, 0
171 };
172
173 i830->meta.TexBlendWordsUsed[0] =
174 i830SetTexEnvCombine( i830, & comb, 0, TEXBLENDARG_TEXEL0,
175 i830->meta.TexBlend[0], NULL);
176
177 i830->meta.TexBlend[0][0] |= TEXOP_LAST_STAGE;
178 i830->meta.emitted &= ~I830_UPLOAD_TEXBLEND(0);
179 }
180
181 /* Set up a single element blend stage for 'replace' texturing with no
182 * funny ops.
183 */
184 static void enable_texture_blend_replace( i830ContextPtr i830,
185 GLenum format )
186 {
187 static const struct gl_tex_env_combine_state comb = {
188 GL_REPLACE, GL_REPLACE,
189 { GL_TEXTURE, 0, 0, }, { GL_TEXTURE, 0, 0, },
190 { GL_SRC_COLOR, 0, 0 }, { GL_SRC_ALPHA, 0, 0 },
191 0, 0, 1, 1
192 };
193
194 i830->meta.TexBlendWordsUsed[0] =
195 i830SetTexEnvCombine( i830, & comb, 0, TEXBLENDARG_TEXEL0,
196 i830->meta.TexBlend[0], NULL);
197
198 i830->meta.TexBlend[0][0] |= TEXOP_LAST_STAGE;
199 i830->meta.emitted &= ~I830_UPLOAD_TEXBLEND(0);
200
201 /* fprintf(stderr, "%s: TexBlendWordsUsed[0]: %d\n", */
202 /* __FUNCTION__, i830->meta.TexBlendWordsUsed[0]); */
203 }
204
205
206
207 /* Set up an arbitary piece of memory as a rectangular texture
208 * (including the front or back buffer).
209 */
210 static void set_tex_rect_source( i830ContextPtr i830,
211 GLuint offset,
212 GLuint width,
213 GLuint height,
214 GLuint pitch,
215 GLuint textureFormat )
216 {
217 GLint numLevels = 1;
218 GLuint *setup = i830->meta.Tex[0];
219
220 pitch *= i830->intel.intelScreen->cpp;
221
222 /* fprintf(stderr, "%s: offset: %x w: %d h: %d pitch %d format %x\n", */
223 /* __FUNCTION__, offset, width, height, pitch, textureFormat ); */
224
225 setup[I830_TEXREG_TM0LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
226 (LOAD_TEXTURE_MAP0 << 0) | 4);
227 setup[I830_TEXREG_TM0S0] = (TM0S0_USE_FENCE | offset);
228 setup[I830_TEXREG_TM0S1] = (((height - 1) << TM0S1_HEIGHT_SHIFT) |
229 ((width - 1) << TM0S1_WIDTH_SHIFT) |
230 textureFormat);
231 setup[I830_TEXREG_TM0S2] = ((((pitch / 4) - 1) << TM0S2_PITCH_SHIFT));
232 setup[I830_TEXREG_TM0S3] &= ~TM0S3_MAX_MIP_MASK;
233 setup[I830_TEXREG_TM0S3] &= ~TM0S3_MIN_MIP_MASK;
234 setup[I830_TEXREG_TM0S3] |= ((numLevels - 1)*4) << TM0S3_MIN_MIP_SHIFT;
235
236 setup[I830_TEXREG_MCS] = (_3DSTATE_MAP_COORD_SET_CMD |
237 MAP_UNIT(0) |
238 ENABLE_TEXCOORD_PARAMS |
239 TEXCOORDS_ARE_IN_TEXELUNITS |
240 TEXCOORDTYPE_CARTESIAN |
241 ENABLE_ADDR_V_CNTL |
242 TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_WRAP) |
243 ENABLE_ADDR_U_CNTL |
244 TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_WRAP));
245
246 i830->meta.emitted &= ~I830_UPLOAD_TEX(0);
247 }
248
249
250 /* Select between front and back draw buffers.
251 */
252 static void set_draw_offset( i830ContextPtr i830,
253 GLuint offset )
254 {
255 i830->meta.Buffer[I830_DESTREG_CBUFADDR2] = offset;
256 i830->meta.emitted &= ~I830_UPLOAD_BUFFERS;
257 }
258
259 /* Setup an arbitary draw format, useful for targeting
260 * texture or agp memory.
261 */
262 static void set_draw_format( i830ContextPtr i830,
263 GLuint format,
264 GLuint depth_format)
265 {
266 i830->meta.Buffer[I830_DESTREG_DV1] = (DSTORG_HORT_BIAS(0x8) | /* .5 */
267 DSTORG_VERT_BIAS(0x8) | /* .5 */
268 format |
269 DEPTH_IS_Z |
270 depth_format);
271 }
272
273
274 static void set_vertex_format( i830ContextPtr i830 )
275 {
276 i830->meta.Ctx[I830_CTXREG_VF] = (_3DSTATE_VFT0_CMD |
277 VFT0_TEX_COUNT(1) |
278 VFT0_DIFFUSE |
279 VFT0_SPEC |
280 VFT0_XYZW);
281 i830->meta.Ctx[I830_CTXREG_VF2] = (_3DSTATE_VFT1_CMD |
282 VFT1_TEX0_FMT(TEXCOORDFMT_2D) |
283 VFT1_TEX1_FMT(TEXCOORDFMT_2D) |
284 VFT1_TEX2_FMT(TEXCOORDFMT_2D) |
285 VFT1_TEX3_FMT(TEXCOORDFMT_2D));
286 i830->meta.emitted &= ~I830_UPLOAD_CTX;
287 }
288
289
290 static void draw_quad(i830ContextPtr i830,
291 GLfloat x0, GLfloat x1,
292 GLfloat y0, GLfloat y1,
293 GLubyte red, GLubyte green,
294 GLubyte blue, GLubyte alpha,
295 GLfloat s0, GLfloat s1,
296 GLfloat t0, GLfloat t1 )
297 {
298 GLuint vertex_size = 8;
299 GLuint *vb = intelEmitInlinePrimitiveLocked( &i830->intel,
300 PRIM3D_TRIFAN,
301 4*vertex_size,
302 vertex_size );
303 intelVertex tmp;
304 int i;
305
306
307 /* fprintf(stderr, "%s: %f,%f-%f,%f 0x%x%x%x%x %f,%f-%f,%f\n", */
308 /* __FUNCTION__, */
309 /* x0,y0,x1,y1,red,green,blue,alpha,s0,t0,s1,t1); */
310
311
312 /* initial vertex, left bottom */
313 tmp.v.x = x0;
314 tmp.v.y = y0;
315 tmp.v.z = 1.0;
316 tmp.v.w = 1.0;
317 tmp.v.color.red = red;
318 tmp.v.color.green = green;
319 tmp.v.color.blue = blue;
320 tmp.v.color.alpha = alpha;
321 tmp.v.specular.red = 0;
322 tmp.v.specular.green = 0;
323 tmp.v.specular.blue = 0;
324 tmp.v.specular.alpha = 0;
325 tmp.v.u0 = s0;
326 tmp.v.v0 = t0;
327 for (i = 0 ; i < 8 ; i++)
328 vb[i] = tmp.ui[i];
329
330 /* right bottom */
331 vb += 8;
332 tmp.v.x = x1;
333 tmp.v.u0 = s1;
334 for (i = 0 ; i < 8 ; i++)
335 vb[i] = tmp.ui[i];
336
337 /* right top */
338 vb += 8;
339 tmp.v.y = y1;
340 tmp.v.v0 = t1;
341 for (i = 0 ; i < 8 ; i++)
342 vb[i] = tmp.ui[i];
343
344 /* left top */
345 vb += 8;
346 tmp.v.x = x0;
347 tmp.v.u0 = s0;
348 for (i = 0 ; i < 8 ; i++)
349 vb[i] = tmp.ui[i];
350
351 /* fprintf(stderr, "%s: DV1: %x\n", */
352 /* __FUNCTION__, i830->meta.Buffer[I830_DESTREG_DV1]); */
353 }
354
355 void
356 i830ClearWithTris(intelContextPtr intel, GLbitfield mask,
357 GLboolean all,
358 GLint cx, GLint cy, GLint cw, GLint ch)
359 {
360 i830ContextPtr i830 = I830_CONTEXT( intel );
361 __DRIdrawablePrivate *dPriv = intel->driDrawable;
362 intelScreenPrivate *screen = intel->intelScreen;
363 int x0, y0, x1, y1;
364
365
366 SET_STATE( i830, meta );
367 set_initial_state( i830 );
368 set_no_texture( i830 );
369 set_vertex_format( i830 );
370
371 LOCK_HARDWARE(intel);
372
373 if(!all) {
374 x0 = cx;
375 y0 = cy;
376 x1 = x0 + cw;
377 y1 = y0 + ch;
378 } else {
379 x0 = 0;
380 y0 = 0;
381 x1 = x0 + dPriv->w;
382 y1 = y0 + dPriv->h;
383 }
384
385 /* Don't do any clipping to screen - these are window coordinates.
386 * The active cliprects will be applied as for any other geometry.
387 */
388
389 if(mask & BUFFER_BIT_FRONT_LEFT) {
390 set_no_depth_stencil_write( i830 );
391 set_color_mask( i830, GL_TRUE );
392 set_draw_offset( i830, screen->front.offset );
393 draw_quad(i830, x0, x1, y0, y1,
394 intel->clear_red, intel->clear_green,
395 intel->clear_blue, intel->clear_alpha,
396 0, 0, 0, 0);
397 }
398
399 if(mask & BUFFER_BIT_BACK_LEFT) {
400 set_no_depth_stencil_write( i830 );
401 set_color_mask( i830, GL_TRUE );
402 set_draw_offset( i830, screen->back.offset );
403
404 draw_quad(i830, x0, x1, y0, y1,
405 intel->clear_red, intel->clear_green,
406 intel->clear_blue, intel->clear_alpha,
407 0, 0, 0, 0);
408 }
409
410 if(mask & BUFFER_BIT_STENCIL) {
411 set_stencil_replace( i830,
412 intel->ctx.Stencil.WriteMask[0],
413 intel->ctx.Stencil.Clear);
414
415 set_color_mask( i830, GL_FALSE );
416 set_draw_offset( i830, screen->front.offset );
417 draw_quad( i830, x0, x1, y0, y1, 0, 0, 0, 0, 0, 0, 0, 0 );
418 }
419
420 UNLOCK_HARDWARE(intel);
421
422 SET_STATE( i830, state );
423 }
424
425
426
427
428 GLboolean
429 i830TryTextureReadPixels( GLcontext *ctx,
430 GLint x, GLint y, GLsizei width, GLsizei height,
431 GLenum format, GLenum type,
432 const struct gl_pixelstore_attrib *pack,
433 GLvoid *pixels )
434 {
435 i830ContextPtr i830 = I830_CONTEXT(ctx);
436 intelContextPtr intel = INTEL_CONTEXT(ctx);
437 intelScreenPrivate *screen = i830->intel.intelScreen;
438 GLint pitch = pack->RowLength ? pack->RowLength : width;
439 __DRIdrawablePrivate *dPriv = i830->intel.driDrawable;
440 int textureFormat;
441 GLenum glTextureFormat;
442 int src_offset = i830->meta.Buffer[I830_DESTREG_CBUFADDR2];
443 int destOffset = intelAgpOffsetFromVirtual( &i830->intel, pixels);
444 int destFormat, depthFormat, destPitch;
445 drm_clip_rect_t tmp;
446
447 if (INTEL_DEBUG & DEBUG_PIXEL)
448 fprintf(stderr, "%s\n", __FUNCTION__);
449
450
451 if ( ctx->_ImageTransferState ||
452 pack->SwapBytes ||
453 pack->LsbFirst ||
454 !pack->Invert) {
455 fprintf(stderr, "%s: check_color failed\n", __FUNCTION__);
456 return GL_FALSE;
457 }
458
459 switch (screen->fbFormat) {
460 case DV_PF_565:
461 textureFormat = MAPSURF_16BIT | MT_16BIT_RGB565;
462 glTextureFormat = GL_RGB;
463 break;
464 case DV_PF_555:
465 textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB1555;
466 glTextureFormat = GL_RGBA;
467 break;
468 case DV_PF_8888:
469 textureFormat = MAPSURF_32BIT | MT_32BIT_ARGB8888;
470 glTextureFormat = GL_RGBA;
471 break;
472 default:
473 fprintf(stderr, "%s: textureFormat failed %x\n", __FUNCTION__,
474 screen->fbFormat);
475 return GL_FALSE;
476 }
477
478
479 switch (type) {
480 case GL_UNSIGNED_SHORT_5_6_5:
481 if (format != GL_RGB) return GL_FALSE;
482 destFormat = COLR_BUF_RGB565;
483 depthFormat = DEPTH_FRMT_16_FIXED;
484 destPitch = pitch * 2;
485 break;
486 case GL_UNSIGNED_INT_8_8_8_8_REV:
487 if (format != GL_BGRA) return GL_FALSE;
488 destFormat = COLR_BUF_ARGB8888;
489 depthFormat = DEPTH_FRMT_24_FIXED_8_OTHER;
490 destPitch = pitch * 4;
491 break;
492 default:
493 fprintf(stderr, "%s: destFormat failed %s\n", __FUNCTION__,
494 _mesa_lookup_enum_by_nr(type));
495 return GL_FALSE;
496 }
497
498 destFormat |= (0x02<<24);
499
500 /* fprintf(stderr, "type: %s destFormat: %x\n", */
501 /* _mesa_lookup_enum_by_nr(type), */
502 /* destFormat); */
503
504 intelFlush( ctx );
505
506 SET_STATE( i830, meta );
507 set_initial_state( i830 );
508 set_no_depth_stencil_write( i830 );
509
510 LOCK_HARDWARE( intel );
511 {
512 intelWaitForIdle( intel ); /* required by GL */
513
514 if (!driClipRectToFramebuffer(ctx->ReadBuffer, &x, &y, &width, &height)) {
515 UNLOCK_HARDWARE( intel );
516 SET_STATE(i830, state);
517 fprintf(stderr, "%s: cliprect failed\n", __FUNCTION__);
518 return GL_TRUE;
519 }
520
521 #if 0
522 /* FIXME -- Just emit the correct state
523 */
524 if (i830SetParam(i830->driFd, I830_SETPARAM_CBUFFER_PITCH,
525 destPitch) != 0) {
526 UNLOCK_HARDWARE( intel );
527 SET_STATE(i830, state);
528 fprintf(stderr, "%s: setparam failed\n", __FUNCTION__);
529 return GL_FALSE;
530 }
531 #endif
532
533
534 y = dPriv->h - y - height;
535 x += dPriv->x;
536 y += dPriv->y;
537
538
539 /* Set the frontbuffer up as a large rectangular texture.
540 */
541 set_tex_rect_source( i830,
542 src_offset,
543 screen->width,
544 screen->height,
545 screen->front.pitch,
546 textureFormat );
547
548
549 enable_texture_blend_replace( i830, glTextureFormat );
550
551
552 /* Set the 3d engine to draw into the agp memory
553 */
554
555 set_draw_offset( i830, destOffset );
556 set_draw_format( i830, destFormat, depthFormat );
557
558
559 /* Draw a single quad, no cliprects:
560 */
561 i830->intel.numClipRects = 1;
562 i830->intel.pClipRects = &tmp;
563 i830->intel.pClipRects[0].x1 = 0;
564 i830->intel.pClipRects[0].y1 = 0;
565 i830->intel.pClipRects[0].x2 = width;
566 i830->intel.pClipRects[0].y2 = height;
567
568 draw_quad( i830,
569 0, width, 0, height,
570 0, 255, 0, 0,
571 x, x+width, y, y+height );
572
573 intelWindowMoved( intel );
574 }
575 UNLOCK_HARDWARE( intel );
576 intelFinish( ctx ); /* required by GL */
577
578 SET_STATE( i830, state );
579 return GL_TRUE;
580 }
581
582
583 GLboolean
584 i830TryTextureDrawPixels( GLcontext *ctx,
585 GLint x, GLint y, GLsizei width, GLsizei height,
586 GLenum format, GLenum type,
587 const struct gl_pixelstore_attrib *unpack,
588 const GLvoid *pixels )
589 {
590 intelContextPtr intel = INTEL_CONTEXT(ctx);
591 i830ContextPtr i830 = I830_CONTEXT(ctx);
592 GLint pitch = unpack->RowLength ? unpack->RowLength : width;
593 __DRIdrawablePrivate *dPriv = intel->driDrawable;
594 int textureFormat;
595 GLenum glTextureFormat;
596 int dst_offset = i830->meta.Buffer[I830_DESTREG_CBUFADDR2];
597 int src_offset = intelAgpOffsetFromVirtual( intel, pixels );
598
599 if (INTEL_DEBUG & DEBUG_PIXEL)
600 fprintf(stderr, "%s\n", __FUNCTION__);
601
602 /* Todo -- upload images that aren't in agp space, then texture
603 * from them.
604 */
605
606 if ( !intelIsAgpMemory( intel, pixels, pitch*height ) ) {
607 fprintf(stderr, "%s: intelIsAgpMemory failed\n", __FUNCTION__);
608 return GL_FALSE;
609 }
610
611 /* Todo -- don't want to clobber all the drawing state like we do
612 * for readpixels -- most of this state can be handled just fine.
613 */
614 if ( ctx->_ImageTransferState ||
615 unpack->SwapBytes ||
616 unpack->LsbFirst ||
617 ctx->Color.AlphaEnabled ||
618 ctx->Depth.Test ||
619 ctx->Fog.Enabled ||
620 ctx->Scissor.Enabled ||
621 ctx->Stencil.Enabled ||
622 !ctx->Color.ColorMask[0] ||
623 !ctx->Color.ColorMask[1] ||
624 !ctx->Color.ColorMask[2] ||
625 !ctx->Color.ColorMask[3] ||
626 ctx->Color.ColorLogicOpEnabled ||
627 ctx->Texture._EnabledUnits) {
628 fprintf(stderr, "%s: other tests failed\n", __FUNCTION__);
629 return GL_FALSE;
630 }
631
632 /* Todo -- remove these restrictions:
633 */
634 if (ctx->Pixel.ZoomX != 1.0F ||
635 ctx->Pixel.ZoomY != -1.0F)
636 return GL_FALSE;
637
638
639
640 switch (type) {
641 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
642 if (format != GL_BGRA) return GL_FALSE;
643 textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB1555;
644 glTextureFormat = GL_RGBA;
645 break;
646 case GL_UNSIGNED_SHORT_5_6_5:
647 if (format != GL_RGB) return GL_FALSE;
648 textureFormat = MAPSURF_16BIT | MT_16BIT_RGB565;
649 glTextureFormat = GL_RGB;
650 break;
651 case GL_UNSIGNED_SHORT_8_8_MESA:
652 if (format != GL_YCBCR_MESA) return GL_FALSE;
653 textureFormat = (MAPSURF_422 | MT_422_YCRCB_SWAPY
654 /* | TM0S1_COLORSPACE_CONVERSION */
655 );
656 glTextureFormat = GL_YCBCR_MESA;
657 break;
658 case GL_UNSIGNED_SHORT_8_8_REV_MESA:
659 if (format != GL_YCBCR_MESA) return GL_FALSE;
660 textureFormat = (MAPSURF_422 | MT_422_YCRCB_NORMAL
661 /* | TM0S1_COLORSPACE_CONVERSION */
662 );
663 glTextureFormat = GL_YCBCR_MESA;
664 break;
665 case GL_UNSIGNED_INT_8_8_8_8_REV:
666 if (format != GL_BGRA) return GL_FALSE;
667 textureFormat = MAPSURF_32BIT | MT_32BIT_ARGB8888;
668 glTextureFormat = GL_RGBA;
669 break;
670 default:
671 fprintf(stderr, "%s: destFormat failed\n", __FUNCTION__);
672 return GL_FALSE;
673 }
674
675 intelFlush( ctx );
676
677 SET_STATE( i830, meta );
678
679 LOCK_HARDWARE( intel );
680 {
681 intelWaitForIdle( intel ); /* required by GL */
682
683 y -= height; /* cope with pixel zoom */
684
685 if (!driClipRectToFramebuffer(ctx->ReadBuffer, &x, &y, &width, &height)) {
686 UNLOCK_HARDWARE( intel );
687 SET_STATE(i830, state);
688 fprintf(stderr, "%s: cliprect failed\n", __FUNCTION__);
689 return GL_TRUE;
690 }
691
692
693 y = dPriv->h - y - height;
694
695 set_initial_state( i830 );
696
697 /* Set the pixel image up as a rectangular texture.
698 */
699 set_tex_rect_source( i830,
700 src_offset,
701 width,
702 height,
703 pitch, /* XXXX!!!! -- /2 sometimes */
704 textureFormat );
705
706
707 enable_texture_blend_replace( i830, glTextureFormat );
708
709
710 /* Draw to the current draw buffer:
711 */
712 set_draw_offset( i830, dst_offset );
713
714 /* Draw a quad, use regular cliprects
715 */
716 /* fprintf(stderr, "x: %d y: %d width %d height %d\n", x, y, width, height); */
717
718 draw_quad( i830,
719 x, x+width, y, y+height,
720 0, 255, 0, 0,
721 0, width, 0, height );
722
723 intelWindowMoved( intel );
724 }
725 UNLOCK_HARDWARE( intel );
726 intelFinish( ctx ); /* required by GL */
727
728 SET_STATE(i830, state);
729
730 return GL_TRUE;
731 }
732