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