fix compiler warnings
[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_INVARIENT | \
44 I830_UPLOAD_TEXBLEND(0) | \
45 I830_UPLOAD_STIPPLE | \
46 I830_UPLOAD_CTX | \
47 I830_UPLOAD_BUFFERS | \
48 I830_UPLOAD_TEX(0))
49
50
51 #define SET_STATE( i830, STATE ) \
52 do { \
53 assert(!i830->intel.prim.flush); \
54 i830->current->emitted = 0; \
55 i830->current = &i830->STATE; \
56 i830->current->emitted = 0; \
57 } while (0)
58
59 /* Operations where the 3D engine is decoupled temporarily from the
60 * current GL state and used for other purposes than simply rendering
61 * incoming triangles.
62 */
63 static void set_initial_state( i830ContextPtr i830 )
64 {
65 memcpy(&i830->meta, &i830->initial, sizeof(i830->meta) );
66 i830->meta.active = ACTIVE;
67 i830->meta.emitted = 0;
68 }
69
70
71 static void set_no_depth_stencil_write( i830ContextPtr i830 )
72 {
73 /* ctx->Driver.Enable( ctx, GL_STENCIL_TEST, GL_FALSE )
74 */
75 i830->meta.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_STENCIL_TEST;
76 i830->meta.Ctx[I830_CTXREG_ENABLES_2] &= ~ENABLE_STENCIL_WRITE;
77 i830->meta.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_STENCIL_TEST;
78 i830->meta.Ctx[I830_CTXREG_ENABLES_2] |= DISABLE_STENCIL_WRITE;
79
80
81 /* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_FALSE )
82 */
83 i830->meta.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_DIS_DEPTH_TEST_MASK;
84 i830->meta.Ctx[I830_CTXREG_ENABLES_2] &= ~ENABLE_DIS_DEPTH_WRITE_MASK;
85 i830->meta.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_DEPTH_TEST;
86 i830->meta.Ctx[I830_CTXREG_ENABLES_2] |= DISABLE_DEPTH_WRITE;
87
88 i830->meta.emitted &= ~I830_UPLOAD_CTX;
89 }
90
91 /* Set stencil unit to replace always with the reference value.
92 */
93 static void set_stencil_replace( i830ContextPtr i830,
94 GLuint s_mask,
95 GLuint s_clear)
96 {
97 /* ctx->Driver.Enable( ctx, GL_STENCIL_TEST, GL_TRUE )
98 */
99 i830->meta.Ctx[I830_CTXREG_ENABLES_1] |= ENABLE_STENCIL_TEST;
100 i830->meta.Ctx[I830_CTXREG_ENABLES_2] |= ENABLE_STENCIL_WRITE;
101
102
103 /* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_FALSE )
104 */
105 i830->meta.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_DIS_DEPTH_TEST_MASK;
106 i830->meta.Ctx[I830_CTXREG_ENABLES_2] &= ~ENABLE_DIS_DEPTH_WRITE_MASK;
107 i830->meta.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_DEPTH_TEST;
108 i830->meta.Ctx[I830_CTXREG_ENABLES_2] |= DISABLE_DEPTH_WRITE;
109
110 /* ctx->Driver.StencilMask( ctx, s_mask )
111 */
112 i830->meta.Ctx[I830_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_WRITE_MASK;
113 i830->meta.Ctx[I830_CTXREG_STATE4] |= (ENABLE_STENCIL_WRITE_MASK |
114 STENCIL_WRITE_MASK((s_mask&0xff)));
115
116 /* ctx->Driver.StencilOp( ctx, GL_REPLACE, GL_REPLACE, GL_REPLACE )
117 */
118 i830->meta.Ctx[I830_CTXREG_STENCILTST] &= ~(STENCIL_OPS_MASK);
119 i830->meta.Ctx[I830_CTXREG_STENCILTST] |=
120 (ENABLE_STENCIL_PARMS |
121 STENCIL_FAIL_OP(STENCILOP_REPLACE) |
122 STENCIL_PASS_DEPTH_FAIL_OP(STENCILOP_REPLACE) |
123 STENCIL_PASS_DEPTH_PASS_OP(STENCILOP_REPLACE));
124
125 /* ctx->Driver.StencilFunc( ctx, GL_ALWAYS, s_clear, ~0 )
126 */
127 i830->meta.Ctx[I830_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_TEST_MASK;
128 i830->meta.Ctx[I830_CTXREG_STATE4] |= (ENABLE_STENCIL_TEST_MASK |
129 STENCIL_TEST_MASK(0xff));
130
131 i830->meta.Ctx[I830_CTXREG_STENCILTST] &= ~(STENCIL_REF_VALUE_MASK |
132 ENABLE_STENCIL_TEST_FUNC_MASK);
133 i830->meta.Ctx[I830_CTXREG_STENCILTST] |=
134 (ENABLE_STENCIL_REF_VALUE |
135 ENABLE_STENCIL_TEST_FUNC |
136 STENCIL_REF_VALUE((s_clear&0xff)) |
137 STENCIL_TEST_FUNC(COMPAREFUNC_ALWAYS));
138
139
140
141 i830->meta.emitted &= ~I830_UPLOAD_CTX;
142 }
143
144
145 static void set_color_mask( i830ContextPtr i830, GLboolean state )
146 {
147 const GLuint mask = ((1 << WRITEMASK_RED_SHIFT) |
148 (1 << WRITEMASK_GREEN_SHIFT) |
149 (1 << WRITEMASK_BLUE_SHIFT) |
150 (1 << WRITEMASK_ALPHA_SHIFT));
151
152 i830->meta.Ctx[I830_CTXREG_ENABLES_2] &= ~mask;
153
154 if (state) {
155 i830->meta.Ctx[I830_CTXREG_ENABLES_2] |=
156 (i830->state.Ctx[I830_CTXREG_ENABLES_2] & mask);
157 }
158
159 i830->meta.emitted &= ~I830_UPLOAD_CTX;
160 }
161
162 /* Installs a one-stage passthrough texture blend pipeline. Is there
163 * more that can be done to turn off texturing?
164 */
165 static void set_no_texture( i830ContextPtr i830 )
166 {
167 static const struct gl_tex_env_combine_state comb = {
168 GL_NONE, GL_NONE,
169 { GL_TEXTURE, 0, 0, }, { GL_TEXTURE, 0, 0, },
170 { GL_SRC_COLOR, 0, 0 }, { GL_SRC_ALPHA, 0, 0 },
171 0, 0, 0, 0
172 };
173
174 i830->meta.TexBlendWordsUsed[0] =
175 i830SetTexEnvCombine( i830, & comb, 0, TEXBLENDARG_TEXEL0,
176 i830->meta.TexBlend[0], NULL);
177
178 i830->meta.TexBlend[0][0] |= TEXOP_LAST_STAGE;
179 i830->meta.emitted &= ~I830_UPLOAD_TEXBLEND(0);
180 }
181
182 /* Set up a single element blend stage for 'replace' texturing with no
183 * funny ops.
184 */
185 static void enable_texture_blend_replace( i830ContextPtr i830 )
186 {
187 static const struct gl_tex_env_combine_state comb = {
188 GL_REPLACE, GL_REPLACE,
189 { GL_TEXTURE, GL_TEXTURE, GL_TEXTURE }, { GL_TEXTURE, GL_TEXTURE, GL_TEXTURE, },
190 { GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR }, { GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA },
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, /* in bytes */
215 GLuint textureFormat )
216 {
217 GLint numLevels = 1;
218 GLuint *setup = i830->meta.Tex[0];
219
220 /* fprintf(stderr, "%s: offset: %x w: %d h: %d pitch %d format %x\n", */
221 /* __FUNCTION__, offset, width, height, pitch, textureFormat ); */
222
223 setup[I830_TEXREG_TM0LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
224 (LOAD_TEXTURE_MAP0 << 0) | 4);
225 setup[I830_TEXREG_TM0S0] = (TM0S0_USE_FENCE | offset);
226 setup[I830_TEXREG_TM0S1] = (((height - 1) << TM0S1_HEIGHT_SHIFT) |
227 ((width - 1) << TM0S1_WIDTH_SHIFT) |
228 textureFormat);
229 setup[I830_TEXREG_TM0S2] = ((((pitch / 4) - 1) << TM0S2_PITCH_SHIFT));
230 setup[I830_TEXREG_TM0S3] &= ~TM0S3_MAX_MIP_MASK;
231 setup[I830_TEXREG_TM0S3] &= ~TM0S3_MIN_MIP_MASK;
232 setup[I830_TEXREG_TM0S3] |= ((numLevels - 1)*4) << TM0S3_MIN_MIP_SHIFT;
233
234 setup[I830_TEXREG_MCS] = (_3DSTATE_MAP_COORD_SET_CMD |
235 MAP_UNIT(0) |
236 ENABLE_TEXCOORD_PARAMS |
237 TEXCOORDS_ARE_IN_TEXELUNITS |
238 TEXCOORDTYPE_CARTESIAN |
239 ENABLE_ADDR_V_CNTL |
240 TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_WRAP) |
241 ENABLE_ADDR_U_CNTL |
242 TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_WRAP));
243
244 i830->meta.emitted &= ~I830_UPLOAD_TEX(0);
245 }
246
247
248 /* Select between front and back draw buffers.
249 */
250 static void set_draw_region( i830ContextPtr i830,
251 const intelRegion *region )
252 {
253 i830->meta.Buffer[I830_DESTREG_CBUFADDR1] =
254 (BUF_3D_ID_COLOR_BACK | BUF_3D_PITCH(region->pitch) | BUF_3D_USE_FENCE);
255 i830->meta.Buffer[I830_DESTREG_CBUFADDR2] = region->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 #if 0
263 static void set_draw_format( i830ContextPtr i830,
264 GLuint format,
265 GLuint depth_format)
266 {
267 i830->meta.Buffer[I830_DESTREG_DV1] = (DSTORG_HORT_BIAS(0x8) | /* .5 */
268 DSTORG_VERT_BIAS(0x8) | /* .5 */
269 format |
270 DEPTH_IS_Z |
271 depth_format);
272 }
273 #endif
274
275
276 static void set_vertex_format( i830ContextPtr i830 )
277 {
278 i830->meta.Ctx[I830_CTXREG_VF] = (_3DSTATE_VFT0_CMD |
279 VFT0_TEX_COUNT(1) |
280 VFT0_DIFFUSE |
281 VFT0_SPEC |
282 VFT0_XYZW);
283 i830->meta.Ctx[I830_CTXREG_VF2] = (_3DSTATE_VFT1_CMD |
284 VFT1_TEX0_FMT(TEXCOORDFMT_2D) |
285 VFT1_TEX1_FMT(TEXCOORDFMT_2D) |
286 VFT1_TEX2_FMT(TEXCOORDFMT_2D) |
287 VFT1_TEX3_FMT(TEXCOORDFMT_2D));
288 i830->meta.emitted &= ~I830_UPLOAD_CTX;
289 }
290
291
292 static void draw_quad(i830ContextPtr i830,
293 GLfloat x0, GLfloat x1,
294 GLfloat y0, GLfloat y1,
295 GLubyte red, GLubyte green,
296 GLubyte blue, GLubyte alpha,
297 GLfloat s0, GLfloat s1,
298 GLfloat t0, GLfloat t1 )
299 {
300 GLuint vertex_size = 8;
301 GLuint *vb = intelEmitInlinePrimitiveLocked( &i830->intel,
302 PRIM3D_TRIFAN,
303 4*vertex_size,
304 vertex_size );
305 intelVertex tmp;
306 int i;
307
308
309 /* fprintf(stderr, "%s: %f,%f-%f,%f 0x%x%x%x%x %f,%f-%f,%f\n", */
310 /* __FUNCTION__, */
311 /* x0,y0,x1,y1,red,green,blue,alpha,s0,t0,s1,t1); */
312
313
314 /* initial vertex, left bottom */
315 tmp.v.x = x0;
316 tmp.v.y = y0;
317 tmp.v.z = 1.0;
318 tmp.v.w = 1.0;
319 tmp.v.color.red = red;
320 tmp.v.color.green = green;
321 tmp.v.color.blue = blue;
322 tmp.v.color.alpha = alpha;
323 tmp.v.specular.red = 0;
324 tmp.v.specular.green = 0;
325 tmp.v.specular.blue = 0;
326 tmp.v.specular.alpha = 0;
327 tmp.v.u0 = s0;
328 tmp.v.v0 = t0;
329 for (i = 0 ; i < 8 ; i++)
330 vb[i] = tmp.ui[i];
331
332 /* right bottom */
333 vb += 8;
334 tmp.v.x = x1;
335 tmp.v.u0 = s1;
336 for (i = 0 ; i < 8 ; i++)
337 vb[i] = tmp.ui[i];
338
339 /* right top */
340 vb += 8;
341 tmp.v.y = y1;
342 tmp.v.v0 = t1;
343 for (i = 0 ; i < 8 ; i++)
344 vb[i] = tmp.ui[i];
345
346 /* left top */
347 vb += 8;
348 tmp.v.x = x0;
349 tmp.v.u0 = s0;
350 for (i = 0 ; i < 8 ; i++)
351 vb[i] = tmp.ui[i];
352
353 /* fprintf(stderr, "%s: DV1: %x\n", */
354 /* __FUNCTION__, i830->meta.Buffer[I830_DESTREG_DV1]); */
355 }
356
357 static void draw_poly(i830ContextPtr i830,
358 GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha,
359 GLuint numVerts,
360 GLfloat verts[][2],
361 GLfloat texcoords[][2])
362 {
363 GLuint vertex_size = 8;
364 GLuint *vb = intelEmitInlinePrimitiveLocked( &i830->intel,
365 PRIM3D_TRIFAN,
366 numVerts * vertex_size,
367 vertex_size );
368 intelVertex tmp;
369 int i, k;
370
371 /* initial constant vertex fields */
372 tmp.v.z = 1.0;
373 tmp.v.w = 1.0;
374 tmp.v.color.red = red;
375 tmp.v.color.green = green;
376 tmp.v.color.blue = blue;
377 tmp.v.color.alpha = alpha;
378 tmp.v.specular.red = 0;
379 tmp.v.specular.green = 0;
380 tmp.v.specular.blue = 0;
381 tmp.v.specular.alpha = 0;
382
383 for (k = 0; k < numVerts; k++) {
384 tmp.v.x = verts[k][0];
385 tmp.v.y = verts[k][1];
386 tmp.v.u0 = texcoords[k][0];
387 tmp.v.v0 = texcoords[k][1];
388
389 for (i = 0 ; i < vertex_size ; i++)
390 vb[i] = tmp.ui[i];
391
392 vb += vertex_size;
393 }
394 }
395
396 void
397 i830ClearWithTris(intelContextPtr intel, GLbitfield mask,
398 GLboolean all,
399 GLint cx, GLint cy, GLint cw, GLint ch)
400 {
401 i830ContextPtr i830 = I830_CONTEXT( intel );
402 __DRIdrawablePrivate *dPriv = intel->driDrawable;
403 intelScreenPrivate *screen = intel->intelScreen;
404 int x0, y0, x1, y1;
405
406 INTEL_FIREVERTICES(intel);
407 SET_STATE( i830, meta );
408 set_initial_state( i830 );
409 /* set_no_texture( i830 ); */
410 set_vertex_format( i830 );
411
412 LOCK_HARDWARE(intel);
413
414 if(!all) {
415 x0 = cx;
416 y0 = cy;
417 x1 = x0 + cw;
418 y1 = y0 + ch;
419 } else {
420 x0 = 0;
421 y0 = 0;
422 x1 = x0 + dPriv->w;
423 y1 = y0 + dPriv->h;
424 }
425
426 /* Don't do any clipping to screen - these are window coordinates.
427 * The active cliprects will be applied as for any other geometry.
428 */
429
430 if(mask & BUFFER_BIT_FRONT_LEFT) {
431 set_no_depth_stencil_write( i830 );
432 set_color_mask( i830, GL_TRUE );
433 set_draw_region( i830, &screen->front );
434 draw_quad(i830, x0, x1, y0, y1,
435 intel->clear_red, intel->clear_green,
436 intel->clear_blue, intel->clear_alpha,
437 0, 0, 0, 0);
438 }
439
440 if(mask & BUFFER_BIT_BACK_LEFT) {
441 set_no_depth_stencil_write( i830 );
442 set_color_mask( i830, GL_TRUE );
443 set_draw_region( i830, &screen->back );
444
445 draw_quad(i830, x0, x1, y0, y1,
446 intel->clear_red, intel->clear_green,
447 intel->clear_blue, intel->clear_alpha,
448 0, 0, 0, 0);
449 }
450
451 if(mask & BUFFER_BIT_STENCIL) {
452 set_stencil_replace( i830,
453 intel->ctx.Stencil.WriteMask[0],
454 intel->ctx.Stencil.Clear);
455
456 set_color_mask( i830, GL_FALSE );
457 set_draw_region( i830, &screen->front );
458 draw_quad( i830, x0, x1, y0, y1, 0, 0, 0, 0, 0, 0, 0, 0 );
459 }
460
461 UNLOCK_HARDWARE(intel);
462
463 INTEL_FIREVERTICES(intel);
464 SET_STATE( i830, state );
465 }
466
467
468 #if 0
469
470 GLboolean
471 i830TryTextureReadPixels( GLcontext *ctx,
472 GLint x, GLint y, GLsizei width, GLsizei height,
473 GLenum format, GLenum type,
474 const struct gl_pixelstore_attrib *pack,
475 GLvoid *pixels )
476 {
477 i830ContextPtr i830 = I830_CONTEXT(ctx);
478 intelContextPtr intel = INTEL_CONTEXT(ctx);
479 intelScreenPrivate *screen = i830->intel.intelScreen;
480 GLint pitch = pack->RowLength ? pack->RowLength : width;
481 __DRIdrawablePrivate *dPriv = i830->intel.driDrawable;
482 int textureFormat;
483 GLenum glTextureFormat;
484 int src_offset = i830->meta.Buffer[I830_DESTREG_CBUFADDR2];
485 int destOffset = intelAgpOffsetFromVirtual( &i830->intel, pixels);
486 int destFormat, depthFormat, destPitch;
487 drm_clip_rect_t tmp;
488
489 if (INTEL_DEBUG & DEBUG_PIXEL)
490 fprintf(stderr, "%s\n", __FUNCTION__);
491
492
493 if ( ctx->_ImageTransferState ||
494 pack->SwapBytes ||
495 pack->LsbFirst ||
496 !pack->Invert) {
497 fprintf(stderr, "%s: check_color failed\n", __FUNCTION__);
498 return GL_FALSE;
499 }
500
501 switch (screen->fbFormat) {
502 case DV_PF_565:
503 textureFormat = MAPSURF_16BIT | MT_16BIT_RGB565;
504 glTextureFormat = GL_RGB;
505 break;
506 case DV_PF_555:
507 textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB1555;
508 glTextureFormat = GL_RGBA;
509 break;
510 case DV_PF_8888:
511 textureFormat = MAPSURF_32BIT | MT_32BIT_ARGB8888;
512 glTextureFormat = GL_RGBA;
513 break;
514 default:
515 fprintf(stderr, "%s: textureFormat failed %x\n", __FUNCTION__,
516 screen->fbFormat);
517 return GL_FALSE;
518 }
519
520
521 switch (type) {
522 case GL_UNSIGNED_SHORT_5_6_5:
523 if (format != GL_RGB) return GL_FALSE;
524 destFormat = COLR_BUF_RGB565;
525 depthFormat = DEPTH_FRMT_16_FIXED;
526 destPitch = pitch * 2;
527 break;
528 case GL_UNSIGNED_INT_8_8_8_8_REV:
529 if (format != GL_BGRA) return GL_FALSE;
530 destFormat = COLR_BUF_ARGB8888;
531 depthFormat = DEPTH_FRMT_24_FIXED_8_OTHER;
532 destPitch = pitch * 4;
533 break;
534 default:
535 fprintf(stderr, "%s: destFormat failed %s\n", __FUNCTION__,
536 _mesa_lookup_enum_by_nr(type));
537 return GL_FALSE;
538 }
539
540 destFormat |= (0x02<<24);
541
542 /* fprintf(stderr, "type: %s destFormat: %x\n", */
543 /* _mesa_lookup_enum_by_nr(type), */
544 /* destFormat); */
545
546 intelFlush( ctx );
547
548 SET_STATE( i830, meta );
549 set_initial_state( i830 );
550 set_no_depth_stencil_write( i830 );
551
552 LOCK_HARDWARE( intel );
553 {
554 intelWaitForIdle( intel ); /* required by GL */
555
556 if (!driClipRectToFramebuffer(ctx->ReadBuffer, &x, &y, &width, &height)) {
557 UNLOCK_HARDWARE( intel );
558 SET_STATE(i830, state);
559 fprintf(stderr, "%s: cliprect failed\n", __FUNCTION__);
560 return GL_TRUE;
561 }
562
563 #if 0
564 /* FIXME -- Just emit the correct state
565 */
566 if (i830SetParam(i830->driFd, I830_SETPARAM_CBUFFER_PITCH,
567 destPitch) != 0) {
568 UNLOCK_HARDWARE( intel );
569 SET_STATE(i830, state);
570 fprintf(stderr, "%s: setparam failed\n", __FUNCTION__);
571 return GL_FALSE;
572 }
573 #endif
574
575
576 y = dPriv->h - y - height;
577 x += dPriv->x;
578 y += dPriv->y;
579
580
581 /* Set the frontbuffer up as a large rectangular texture.
582 */
583 set_tex_rect_source( i830,
584 src_offset,
585 screen->width,
586 screen->height,
587 screen->front.pitch,
588 textureFormat );
589
590
591 enable_texture_blend_replace( i830 );
592
593
594 /* Set the 3d engine to draw into the agp memory
595 */
596
597 set_draw_region( i830, destOffset );
598 set_draw_format( i830, destFormat, depthFormat );
599
600
601 /* Draw a single quad, no cliprects:
602 */
603 i830->intel.numClipRects = 1;
604 i830->intel.pClipRects = &tmp;
605 i830->intel.pClipRects[0].x1 = 0;
606 i830->intel.pClipRects[0].y1 = 0;
607 i830->intel.pClipRects[0].x2 = width;
608 i830->intel.pClipRects[0].y2 = height;
609
610 draw_quad( i830,
611 0, width, 0, height,
612 0, 255, 0, 0,
613 x, x+width, y, y+height );
614
615 intelWindowMoved( intel );
616 }
617 UNLOCK_HARDWARE( intel );
618 intelFinish( ctx ); /* required by GL */
619
620 SET_STATE( i830, state );
621 return GL_TRUE;
622 }
623
624
625 GLboolean
626 i830TryTextureDrawPixels( GLcontext *ctx,
627 GLint x, GLint y, GLsizei width, GLsizei height,
628 GLenum format, GLenum type,
629 const struct gl_pixelstore_attrib *unpack,
630 const GLvoid *pixels )
631 {
632 intelContextPtr intel = INTEL_CONTEXT(ctx);
633 i830ContextPtr i830 = I830_CONTEXT(ctx);
634 GLint pitch = unpack->RowLength ? unpack->RowLength : width;
635 __DRIdrawablePrivate *dPriv = intel->driDrawable;
636 int textureFormat;
637 GLenum glTextureFormat;
638 int dst_offset = i830->meta.Buffer[I830_DESTREG_CBUFADDR2];
639 int src_offset = intelAgpOffsetFromVirtual( intel, pixels );
640
641 if (INTEL_DEBUG & DEBUG_PIXEL)
642 fprintf(stderr, "%s\n", __FUNCTION__);
643
644 /* Todo -- upload images that aren't in agp space, then texture
645 * from them.
646 */
647
648 if ( !intelIsAgpMemory( intel, pixels, pitch*height ) ) {
649 fprintf(stderr, "%s: intelIsAgpMemory failed\n", __FUNCTION__);
650 return GL_FALSE;
651 }
652
653 /* Todo -- don't want to clobber all the drawing state like we do
654 * for readpixels -- most of this state can be handled just fine.
655 */
656 if ( ctx->_ImageTransferState ||
657 unpack->SwapBytes ||
658 unpack->LsbFirst ||
659 ctx->Color.AlphaEnabled ||
660 ctx->Depth.Test ||
661 ctx->Fog.Enabled ||
662 ctx->Scissor.Enabled ||
663 ctx->Stencil.Enabled ||
664 !ctx->Color.ColorMask[0] ||
665 !ctx->Color.ColorMask[1] ||
666 !ctx->Color.ColorMask[2] ||
667 !ctx->Color.ColorMask[3] ||
668 ctx->Color.ColorLogicOpEnabled ||
669 ctx->Texture._EnabledUnits ||
670 ctx->Depth.OcclusionTest) {
671 fprintf(stderr, "%s: other tests failed\n", __FUNCTION__);
672 return GL_FALSE;
673 }
674
675 /* Todo -- remove these restrictions:
676 */
677 if (ctx->Pixel.ZoomX != 1.0F ||
678 ctx->Pixel.ZoomY != -1.0F)
679 return GL_FALSE;
680
681
682
683 switch (type) {
684 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
685 if (format != GL_BGRA) return GL_FALSE;
686 textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB1555;
687 glTextureFormat = GL_RGBA;
688 break;
689 case GL_UNSIGNED_SHORT_5_6_5:
690 if (format != GL_RGB) return GL_FALSE;
691 textureFormat = MAPSURF_16BIT | MT_16BIT_RGB565;
692 glTextureFormat = GL_RGB;
693 break;
694 case GL_UNSIGNED_SHORT_8_8_MESA:
695 if (format != GL_YCBCR_MESA) return GL_FALSE;
696 textureFormat = (MAPSURF_422 | MT_422_YCRCB_SWAPY
697 /* | TM0S1_COLORSPACE_CONVERSION */
698 );
699 glTextureFormat = GL_YCBCR_MESA;
700 break;
701 case GL_UNSIGNED_SHORT_8_8_REV_MESA:
702 if (format != GL_YCBCR_MESA) return GL_FALSE;
703 textureFormat = (MAPSURF_422 | MT_422_YCRCB_NORMAL
704 /* | TM0S1_COLORSPACE_CONVERSION */
705 );
706 glTextureFormat = GL_YCBCR_MESA;
707 break;
708 case GL_UNSIGNED_INT_8_8_8_8_REV:
709 if (format != GL_BGRA) return GL_FALSE;
710 textureFormat = MAPSURF_32BIT | MT_32BIT_ARGB8888;
711 glTextureFormat = GL_RGBA;
712 break;
713 default:
714 fprintf(stderr, "%s: destFormat failed\n", __FUNCTION__);
715 return GL_FALSE;
716 }
717
718 intelFlush( ctx );
719
720 SET_STATE( i830, meta );
721
722 LOCK_HARDWARE( intel );
723 {
724 intelWaitForIdle( intel ); /* required by GL */
725
726 y -= height; /* cope with pixel zoom */
727
728 if (!driClipRectToFramebuffer(ctx->ReadBuffer, &x, &y, &width, &height)) {
729 UNLOCK_HARDWARE( intel );
730 SET_STATE(i830, state);
731 fprintf(stderr, "%s: cliprect failed\n", __FUNCTION__);
732 return GL_TRUE;
733 }
734
735
736 y = dPriv->h - y - height;
737
738 set_initial_state( i830 );
739
740 /* Set the pixel image up as a rectangular texture.
741 */
742 set_tex_rect_source( i830,
743 src_offset,
744 width,
745 height,
746 pitch, /* XXXX!!!! -- /2 sometimes */
747 textureFormat );
748
749
750 enable_texture_blend_replace( i830 );
751
752
753 /* Draw to the current draw buffer:
754 */
755 set_draw_offset( i830, dst_offset );
756
757 /* Draw a quad, use regular cliprects
758 */
759 /* fprintf(stderr, "x: %d y: %d width %d height %d\n", x, y, width, height); */
760
761 draw_quad( i830,
762 x, x+width, y, y+height,
763 0, 255, 0, 0,
764 0, width, 0, height );
765
766 intelWindowMoved( intel );
767 }
768 UNLOCK_HARDWARE( intel );
769 intelFinish( ctx ); /* required by GL */
770
771 SET_STATE(i830, state);
772
773 return GL_TRUE;
774 }
775
776 #endif
777
778 /**
779 * Copy the window contents named by dPriv to the rotated (or reflected)
780 * color buffer.
781 * srcBuf is BUFFER_BIT_FRONT_LEFT or BUFFER_BIT_BACK_LEFT to indicate the source.
782 */
783 void
784 i830RotateWindow(intelContextPtr intel, __DRIdrawablePrivate *dPriv,
785 GLuint srcBuf)
786 {
787 i830ContextPtr i830 = I830_CONTEXT( intel );
788 intelScreenPrivate *screen = intel->intelScreen;
789 const GLuint cpp = screen->cpp;
790 drm_clip_rect_t fullRect;
791 GLuint textureFormat, srcOffset, srcPitch;
792 const drm_clip_rect_t *clipRects;
793 int numClipRects;
794 int i;
795
796 int xOrig, yOrig;
797 int origNumClipRects;
798 drm_clip_rect_t *origRects;
799
800 /*
801 * set up hardware state
802 */
803 intelFlush( &intel->ctx );
804
805 SET_STATE( i830, meta );
806 set_initial_state( i830 );
807 set_no_texture( i830 );
808 set_vertex_format( i830 );
809 set_no_depth_stencil_write( i830 );
810 set_color_mask( i830, GL_FALSE );
811
812 LOCK_HARDWARE(intel);
813
814 /* save current drawing origin and cliprects (restored at end) */
815 xOrig = intel->drawX;
816 yOrig = intel->drawY;
817 origNumClipRects = intel->numClipRects;
818 origRects = intel->pClipRects;
819
820 if (!intel->numClipRects)
821 goto done;
822
823 /*
824 * set drawing origin, cliprects for full-screen access to rotated screen
825 */
826 fullRect.x1 = 0;
827 fullRect.y1 = 0;
828 fullRect.x2 = screen->rotatedWidth;
829 fullRect.y2 = screen->rotatedHeight;
830 intel->drawX = 0;
831 intel->drawY = 0;
832 intel->numClipRects = 1;
833 intel->pClipRects = &fullRect;
834
835 set_draw_region( i830, &screen->rotated );
836
837 if (cpp == 4)
838 textureFormat = MAPSURF_32BIT | MT_32BIT_ARGB8888;
839 else
840 textureFormat = MAPSURF_16BIT | MT_16BIT_RGB565;
841
842 if (srcBuf == BUFFER_BIT_FRONT_LEFT) {
843 srcPitch = screen->front.pitch; /* in bytes */
844 srcOffset = screen->front.offset; /* bytes */
845 clipRects = dPriv->pClipRects;
846 numClipRects = dPriv->numClipRects;
847 }
848 else {
849 srcPitch = screen->back.pitch; /* in bytes */
850 srcOffset = screen->back.offset; /* bytes */
851 clipRects = dPriv->pBackClipRects;
852 numClipRects = dPriv->numBackClipRects;
853 }
854
855 /* set the whole screen up as a texture to avoid alignment issues */
856 set_tex_rect_source(i830,
857 srcOffset,
858 screen->width,
859 screen->height,
860 srcPitch,
861 textureFormat);
862
863 enable_texture_blend_replace(i830);
864
865 /*
866 * loop over the source window's cliprects
867 */
868 for (i = 0; i < numClipRects; i++) {
869 int srcX0 = clipRects[i].x1;
870 int srcY0 = clipRects[i].y1;
871 int srcX1 = clipRects[i].x2;
872 int srcY1 = clipRects[i].y2;
873 GLfloat verts[4][2], tex[4][2];
874 int j;
875
876 /* build vertices for four corners of clip rect */
877 verts[0][0] = srcX0; verts[0][1] = srcY0;
878 verts[1][0] = srcX1; verts[1][1] = srcY0;
879 verts[2][0] = srcX1; verts[2][1] = srcY1;
880 verts[3][0] = srcX0; verts[3][1] = srcY1;
881
882 /* .. and texcoords */
883 tex[0][0] = srcX0; tex[0][1] = srcY0;
884 tex[1][0] = srcX1; tex[1][1] = srcY0;
885 tex[2][0] = srcX1; tex[2][1] = srcY1;
886 tex[3][0] = srcX0; tex[3][1] = srcY1;
887
888 /* transform coords to rotated screen coords */
889
890 for (j = 0; j < 4; j++) {
891 matrix23TransformCoordf(&screen->rotMatrix,
892 &verts[j][0], &verts[j][1]);
893 }
894
895 /* draw polygon to map source image to dest region */
896 draw_poly(i830, 255, 255, 255, 255, 4, verts, tex);
897
898 } /* cliprect loop */
899
900 assert(!intel->prim.flush);
901 intelFlushBatchLocked( intel, GL_FALSE, GL_FALSE, GL_FALSE );
902
903 done:
904 /* restore original drawing origin and cliprects */
905 intel->drawX = xOrig;
906 intel->drawY = yOrig;
907 intel->numClipRects = origNumClipRects;
908 intel->pClipRects = origRects;
909
910 UNLOCK_HARDWARE(intel);
911
912 SET_STATE( i830, state );
913 }
914