Fix writemasks on texture arb fp instructions.
[mesa.git] / src / mesa / drivers / dri / i915 / i915_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 #include "intel_rotate.h"
38
39 #include "i915_context.h"
40 #include "i915_reg.h"
41
42 /* A large amount of state doesn't need to be uploaded.
43 */
44 #define ACTIVE (I915_UPLOAD_INVARIENT | \
45 I915_UPLOAD_PROGRAM | \
46 I915_UPLOAD_STIPPLE | \
47 I915_UPLOAD_CTX | \
48 I915_UPLOAD_BUFFERS | \
49 I915_UPLOAD_TEX(0))
50
51 #define SET_STATE( i915, STATE ) \
52 do { \
53 i915->current->emitted &= ~ACTIVE; \
54 i915->current = &i915->STATE; \
55 i915->current->emitted &= ~ACTIVE; \
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( i915ContextPtr i915 )
63 {
64 memcpy(&i915->meta, &i915->initial, sizeof(i915->meta) );
65 i915->meta.active = ACTIVE;
66 i915->meta.emitted = 0;
67 }
68
69
70 static void set_no_depth_stencil_write( i915ContextPtr i915 )
71 {
72 /* ctx->Driver.Enable( ctx, GL_STENCIL_TEST, GL_FALSE )
73 */
74 i915->meta.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_TEST_ENABLE |
75 S5_STENCIL_WRITE_ENABLE);
76
77 /* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_FALSE )
78 */
79 i915->meta.Ctx[I915_CTXREG_LIS6] &= ~(S6_DEPTH_TEST_ENABLE |
80 S6_DEPTH_WRITE_ENABLE);
81
82 i915->meta.emitted &= ~I915_UPLOAD_CTX;
83 }
84
85 /* Set stencil unit to replace always with the reference value.
86 */
87 static void set_stencil_replace( i915ContextPtr i915,
88 GLuint s_mask,
89 GLuint s_clear)
90 {
91 GLuint op = STENCILOP_REPLACE;
92 GLuint func = COMPAREFUNC_ALWAYS;
93
94 /* ctx->Driver.Enable( ctx, GL_STENCIL_TEST, GL_TRUE )
95 */
96 i915->meta.Ctx[I915_CTXREG_LIS5] |= (S5_STENCIL_TEST_ENABLE |
97 S5_STENCIL_WRITE_ENABLE);
98
99
100 /* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_FALSE )
101 */
102 i915->meta.Ctx[I915_CTXREG_LIS6] &= ~(S6_DEPTH_TEST_ENABLE |
103 S6_DEPTH_WRITE_ENABLE);
104
105
106 /* ctx->Driver.StencilMask( ctx, s_mask )
107 */
108 i915->meta.Ctx[I915_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_WRITE_MASK;
109
110 i915->meta.Ctx[I915_CTXREG_STATE4] |= (ENABLE_STENCIL_WRITE_MASK |
111 STENCIL_WRITE_MASK(s_mask));
112
113
114 /* ctx->Driver.StencilOp( ctx, GL_REPLACE, GL_REPLACE, GL_REPLACE )
115 */
116 i915->meta.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_FAIL_MASK |
117 S5_STENCIL_PASS_Z_FAIL_MASK |
118 S5_STENCIL_PASS_Z_PASS_MASK);
119
120 i915->meta.Ctx[I915_CTXREG_LIS5] |= ((op << S5_STENCIL_FAIL_SHIFT) |
121 (op << S5_STENCIL_PASS_Z_FAIL_SHIFT) |
122 (op << S5_STENCIL_PASS_Z_PASS_SHIFT));
123
124
125 /* ctx->Driver.StencilFunc( ctx, GL_ALWAYS, s_ref, ~0 )
126 */
127 i915->meta.Ctx[I915_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_TEST_MASK;
128 i915->meta.Ctx[I915_CTXREG_STATE4] |= (ENABLE_STENCIL_TEST_MASK |
129 STENCIL_TEST_MASK(0xff));
130
131 i915->meta.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_REF_MASK |
132 S5_STENCIL_TEST_FUNC_MASK);
133
134 i915->meta.Ctx[I915_CTXREG_LIS5] |= ((s_clear << S5_STENCIL_REF_SHIFT) |
135 (func << S5_STENCIL_TEST_FUNC_SHIFT));
136
137
138 i915->meta.emitted &= ~I915_UPLOAD_CTX;
139 }
140
141
142 static void set_color_mask( i915ContextPtr i915, GLboolean state )
143 {
144 const GLuint mask = (S5_WRITEDISABLE_RED |
145 S5_WRITEDISABLE_GREEN |
146 S5_WRITEDISABLE_BLUE |
147 S5_WRITEDISABLE_ALPHA);
148
149 /* Copy colormask state from "regular" hw context.
150 */
151 if (state) {
152 i915->meta.Ctx[I915_CTXREG_LIS5] &= ~mask;
153 i915->meta.Ctx[I915_CTXREG_LIS5] |=
154 (i915->state.Ctx[I915_CTXREG_LIS5] & mask);
155 }
156 else
157 i915->meta.Ctx[I915_CTXREG_LIS5] |= mask;
158
159 i915->meta.emitted &= ~I915_UPLOAD_CTX;
160 }
161
162
163
164
165 #define REG( type, nr ) (((type)<<5)|(nr))
166
167 #define REG_R(x) REG(REG_TYPE_R, x)
168 #define REG_T(x) REG(REG_TYPE_T, x)
169 #define REG_CONST(x) REG(REG_TYPE_CONST, x)
170 #define REG_S(x) REG(REG_TYPE_S, x)
171 #define REG_OC REG(REG_TYPE_OC, 0)
172 #define REG_OD REG(REG_TYPE_OD, 0)
173 #define REG_U(x) REG(REG_TYPE_U, x)
174
175 #define REG_T_DIFFUSE REG(REG_TYPE_T, T_DIFFUSE)
176 #define REG_T_SPECULAR REG(REG_TYPE_T, T_SPECULAR)
177 #define REG_T_FOG_W REG(REG_TYPE_T, T_FOG_W)
178 #define REG_T_TEX(x) REG(REG_TYPE_T, x)
179
180
181 #define A0_DEST_REG( reg ) ( (reg) << A0_DEST_NR_SHIFT )
182 #define A0_SRC0_REG( reg ) ( (reg) << A0_SRC0_NR_SHIFT )
183 #define A1_SRC1_REG( reg ) ( (reg) << A1_SRC1_NR_SHIFT )
184 #define A1_SRC2_REG( reg ) ( (reg) << A1_SRC2_NR_SHIFT )
185 #define A2_SRC2_REG( reg ) ( (reg) << A2_SRC2_NR_SHIFT )
186 #define D0_DECL_REG( reg ) ( (reg) << D0_NR_SHIFT )
187 #define T0_DEST_REG( reg ) ( (reg) << T0_DEST_NR_SHIFT )
188
189 #define T0_SAMPLER( unit ) ((unit)<<T0_SAMPLER_NR_SHIFT)
190
191 #define T1_ADDRESS_REG( type, nr ) (((type)<<T1_ADDRESS_REG_TYPE_SHIFT)| \
192 ((nr)<<T1_ADDRESS_REG_NR_SHIFT))
193
194
195 #define A1_SRC0_XYZW ((SRC_X << A1_SRC0_CHANNEL_X_SHIFT) | \
196 (SRC_Y << A1_SRC0_CHANNEL_Y_SHIFT) | \
197 (SRC_Z << A1_SRC0_CHANNEL_Z_SHIFT) | \
198 (SRC_W << A1_SRC0_CHANNEL_W_SHIFT))
199
200 #define A1_SRC1_XY ((SRC_X << A1_SRC1_CHANNEL_X_SHIFT) | \
201 (SRC_Y << A1_SRC1_CHANNEL_Y_SHIFT))
202
203 #define A2_SRC1_ZW ((SRC_Z << A2_SRC1_CHANNEL_Z_SHIFT) | \
204 (SRC_W << A2_SRC1_CHANNEL_W_SHIFT))
205
206 #define A2_SRC2_XYZW ((SRC_X << A2_SRC2_CHANNEL_X_SHIFT) | \
207 (SRC_Y << A2_SRC2_CHANNEL_Y_SHIFT) | \
208 (SRC_Z << A2_SRC2_CHANNEL_Z_SHIFT) | \
209 (SRC_W << A2_SRC2_CHANNEL_W_SHIFT))
210
211
212
213
214
215 static void set_no_texture( i915ContextPtr i915 )
216 {
217 static const GLuint prog[] = {
218 _3DSTATE_PIXEL_SHADER_PROGRAM,
219
220 /* Declare incoming diffuse color:
221 */
222 (D0_DCL |
223 D0_DECL_REG( REG_T_DIFFUSE ) |
224 D0_CHANNEL_ALL),
225 D1_MBZ,
226 D2_MBZ,
227
228 /* output-color = mov(t_diffuse)
229 */
230 (A0_MOV |
231 A0_DEST_REG( REG_OC ) |
232 A0_DEST_CHANNEL_ALL |
233 A0_SRC0_REG( REG_T_DIFFUSE )),
234 (A1_SRC0_XYZW),
235 0,
236 };
237
238
239 memcpy( i915->meta.Program, prog, sizeof(prog) );
240 i915->meta.ProgramSize = sizeof(prog) / sizeof(*prog);
241 i915->meta.Program[0] |= i915->meta.ProgramSize - 2;
242 i915->meta.emitted &= ~I915_UPLOAD_PROGRAM;
243 }
244
245
246 static void enable_texture_blend_replace( i915ContextPtr i915 )
247 {
248 static const GLuint prog[] = {
249 _3DSTATE_PIXEL_SHADER_PROGRAM,
250
251 /* Declare the sampler:
252 */
253 (D0_DCL |
254 D0_DECL_REG( REG_S(0) ) |
255 D0_SAMPLE_TYPE_2D |
256 D0_CHANNEL_NONE),
257 D1_MBZ,
258 D2_MBZ,
259
260 /* Declare the interpolated texture coordinate:
261 */
262 (D0_DCL |
263 D0_DECL_REG( REG_T_TEX(0) ) |
264 D0_CHANNEL_ALL),
265 D1_MBZ,
266 D2_MBZ,
267
268 /* output-color = texld(sample0, texcoord0)
269 */
270 (T0_TEXLD |
271 T0_DEST_REG( REG_OC ) |
272 T0_SAMPLER( 0 )),
273 T1_ADDRESS_REG(REG_TYPE_T, 0),
274 T2_MBZ
275 };
276
277 memcpy( i915->meta.Program, prog, sizeof(prog) );
278 i915->meta.ProgramSize = sizeof(prog) / sizeof(*prog);
279 i915->meta.Program[0] |= i915->meta.ProgramSize - 2;
280 i915->meta.emitted &= ~I915_UPLOAD_PROGRAM;
281 }
282
283
284
285
286
287 /* Set up an arbitary piece of memory as a rectangular texture
288 * (including the front or back buffer).
289 */
290 static void set_tex_rect_source( i915ContextPtr i915,
291 GLuint offset,
292 GLuint width,
293 GLuint height,
294 GLuint pitch, /* in bytes! */
295 GLuint textureFormat )
296 {
297 GLuint unit = 0;
298 GLint numLevels = 1;
299 GLuint *state = i915->meta.Tex[0];
300
301 #if 0
302 printf("TexRect source offset 0x%x pitch %d\n", offset, pitch);
303 #endif
304
305 /* fprintf(stderr, "%s: offset: %x w: %d h: %d pitch %d format %x\n", */
306 /* __FUNCTION__, offset, width, height, pitch, textureFormat ); */
307
308 state[I915_TEXREG_MS2] = offset;
309 state[I915_TEXREG_MS3] = (((height - 1) << MS3_HEIGHT_SHIFT) |
310 ((width - 1) << MS3_WIDTH_SHIFT) |
311 textureFormat |
312 MS3_USE_FENCE_REGS);
313
314 state[I915_TEXREG_MS4] = ((((pitch / 4) - 1) << MS4_PITCH_SHIFT) |
315 ((((numLevels-1) * 4)) << MS4_MAX_LOD_SHIFT));
316
317 state[I915_TEXREG_SS2] = ((FILTER_NEAREST << SS2_MIN_FILTER_SHIFT) |
318 (MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT) |
319 (FILTER_NEAREST << SS2_MAG_FILTER_SHIFT));
320 state[I915_TEXREG_SS3] = ((TEXCOORDMODE_WRAP << SS3_TCX_ADDR_MODE_SHIFT) |
321 (TEXCOORDMODE_WRAP << SS3_TCY_ADDR_MODE_SHIFT) |
322 (TEXCOORDMODE_WRAP << SS3_TCZ_ADDR_MODE_SHIFT) |
323 (unit<<SS3_TEXTUREMAP_INDEX_SHIFT));
324
325 state[I915_TEXREG_SS4] = 0;
326
327 i915->meta.emitted &= ~I915_UPLOAD_TEX(0);
328 }
329
330
331 /* Select between front and back draw buffers.
332 */
333 static void set_draw_region( i915ContextPtr i915, const intelRegion *region )
334 {
335 #if 0
336 printf("Rotate into region: offset 0x%x pitch %d\n",
337 region->offset, region->pitch);
338 #endif
339 i915->meta.Buffer[I915_DESTREG_CBUFADDR1] =
340 (BUF_3D_ID_COLOR_BACK | BUF_3D_PITCH(region->pitch) | BUF_3D_USE_FENCE);
341 i915->meta.Buffer[I915_DESTREG_CBUFADDR2] = region->offset;
342 i915->meta.emitted &= ~I915_UPLOAD_BUFFERS;
343 }
344
345
346 #if 0
347 /* Setup an arbitary draw format, useful for targeting texture or agp
348 * memory.
349 */
350 static void set_draw_format( i915ContextPtr i915,
351 GLuint format,
352 GLuint depth_format)
353 {
354 i915->meta.Buffer[I915_DESTREG_DV1] = (DSTORG_HORT_BIAS(0x8) | /* .5 */
355 DSTORG_VERT_BIAS(0x8) | /* .5 */
356 format |
357 LOD_PRECLAMP_OGL |
358 TEX_DEFAULT_COLOR_OGL |
359 depth_format);
360
361 i915->meta.emitted &= ~I915_UPLOAD_BUFFERS;
362 /* fprintf(stderr, "%s: DV1: %x\n", */
363 /* __FUNCTION__, i915->meta.Buffer[I915_DESTREG_DV1]); */
364 }
365 #endif
366
367 static void set_vertex_format( i915ContextPtr i915 )
368 {
369 i915->meta.Ctx[I915_CTXREG_LIS2] =
370 (S2_TEXCOORD_FMT(0, TEXCOORDFMT_2D) |
371 S2_TEXCOORD_FMT(1, TEXCOORDFMT_NOT_PRESENT) |
372 S2_TEXCOORD_FMT(2, TEXCOORDFMT_NOT_PRESENT) |
373 S2_TEXCOORD_FMT(3, TEXCOORDFMT_NOT_PRESENT) |
374 S2_TEXCOORD_FMT(4, TEXCOORDFMT_NOT_PRESENT) |
375 S2_TEXCOORD_FMT(5, TEXCOORDFMT_NOT_PRESENT) |
376 S2_TEXCOORD_FMT(6, TEXCOORDFMT_NOT_PRESENT) |
377 S2_TEXCOORD_FMT(7, TEXCOORDFMT_NOT_PRESENT));
378
379 i915->meta.Ctx[I915_CTXREG_LIS4] &= ~S4_VFMT_MASK;
380
381 i915->meta.Ctx[I915_CTXREG_LIS4] |=
382 (S4_VFMT_COLOR |
383 S4_VFMT_SPEC_FOG |
384 S4_VFMT_XYZW);
385
386 i915->meta.emitted &= ~I915_UPLOAD_CTX;
387
388 }
389
390
391 static void draw_quad(i915ContextPtr i915,
392 GLfloat x0, GLfloat x1,
393 GLfloat y0, GLfloat y1,
394 GLubyte red, GLubyte green,
395 GLubyte blue, GLubyte alpha,
396 GLfloat s0, GLfloat s1,
397 GLfloat t0, GLfloat t1 )
398 {
399 GLuint vertex_size = 8;
400 GLuint *vb = intelEmitInlinePrimitiveLocked( &i915->intel,
401 PRIM3D_TRIFAN,
402 4 * vertex_size,
403 vertex_size );
404 intelVertex tmp;
405 int i;
406
407 if (0)
408 fprintf(stderr, "%s: %f,%f-%f,%f 0x%x%x%x%x %f,%f-%f,%f\n",
409 __FUNCTION__,
410 x0,y0,x1,y1,red,green,blue,alpha,s0,t0,s1,t1);
411
412
413 /* initial vertex, left bottom */
414 tmp.v.x = x0;
415 tmp.v.y = y0;
416 tmp.v.z = 1.0;
417 tmp.v.w = 1.0;
418 tmp.v.color.red = red;
419 tmp.v.color.green = green;
420 tmp.v.color.blue = blue;
421 tmp.v.color.alpha = alpha;
422 tmp.v.specular.red = 0;
423 tmp.v.specular.green = 0;
424 tmp.v.specular.blue = 0;
425 tmp.v.specular.alpha = 0;
426 tmp.v.u0 = s0;
427 tmp.v.v0 = t0;
428
429 for (i = 0 ; i < vertex_size ; i++)
430 vb[i] = tmp.ui[i];
431
432 /* right bottom */
433 vb += vertex_size;
434 tmp.v.x = x1;
435 tmp.v.u0 = s1;
436 for (i = 0 ; i < vertex_size ; i++)
437 vb[i] = tmp.ui[i];
438
439 /* right top */
440 vb += vertex_size;
441 tmp.v.y = y1;
442 tmp.v.v0 = t1;
443 for (i = 0 ; i < vertex_size ; i++)
444 vb[i] = tmp.ui[i];
445
446 /* left top */
447 vb += vertex_size;
448 tmp.v.x = x0;
449 tmp.v.u0 = s0;
450 for (i = 0 ; i < vertex_size ; i++)
451 vb[i] = tmp.ui[i];
452 }
453
454
455 static void draw_poly(i915ContextPtr i915,
456 GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha,
457 GLuint numVerts,
458 /*const*/ GLfloat verts[][2],
459 /*const*/ GLfloat texcoords[][2])
460 {
461 GLuint vertex_size = 8;
462 GLuint *vb = intelEmitInlinePrimitiveLocked( &i915->intel,
463 PRIM3D_TRIFAN,
464 numVerts * vertex_size,
465 vertex_size );
466 intelVertex tmp;
467 int i, k;
468
469 /* initial constant vertex fields */
470 tmp.v.z = 1.0;
471 tmp.v.w = 1.0;
472 tmp.v.color.red = red;
473 tmp.v.color.green = green;
474 tmp.v.color.blue = blue;
475 tmp.v.color.alpha = alpha;
476 tmp.v.specular.red = 0;
477 tmp.v.specular.green = 0;
478 tmp.v.specular.blue = 0;
479 tmp.v.specular.alpha = 0;
480
481 for (k = 0; k < numVerts; k++) {
482 tmp.v.x = verts[k][0];
483 tmp.v.y = verts[k][1];
484 tmp.v.u0 = texcoords[k][0];
485 tmp.v.v0 = texcoords[k][1];
486
487 for (i = 0 ; i < vertex_size ; i++)
488 vb[i] = tmp.ui[i];
489
490 vb += vertex_size;
491 }
492 }
493
494
495 void
496 i915ClearWithTris(intelContextPtr intel, GLbitfield mask,
497 GLboolean all,
498 GLint cx, GLint cy, GLint cw, GLint ch)
499 {
500 i915ContextPtr i915 = I915_CONTEXT( intel );
501 __DRIdrawablePrivate *dPriv = intel->driDrawable;
502 intelScreenPrivate *screen = intel->intelScreen;
503 int x0, y0, x1, y1;
504
505 SET_STATE( i915, meta );
506 set_initial_state( i915 );
507 set_no_texture( i915 );
508 set_vertex_format( i915 );
509
510 LOCK_HARDWARE(intel);
511
512 if (!all) {
513 x0 = cx;
514 y0 = cy;
515 x1 = x0 + cw;
516 y1 = y0 + ch;
517 } else {
518 x0 = 0;
519 y0 = 0;
520 x1 = x0 + dPriv->w;
521 y1 = y0 + dPriv->h;
522 }
523
524 /* Don't do any clipping to screen - these are window coordinates.
525 * The active cliprects will be applied as for any other geometry.
526 */
527
528 if (mask & BUFFER_BIT_FRONT_LEFT) {
529 set_no_depth_stencil_write( i915 );
530 set_color_mask( i915, GL_TRUE );
531 set_draw_region( i915, &screen->front );
532
533 draw_quad(i915, x0, x1, y0, y1,
534 intel->clear_red, intel->clear_green,
535 intel->clear_blue, intel->clear_alpha,
536 0, 0, 0, 0);
537 }
538
539 if (mask & BUFFER_BIT_BACK_LEFT) {
540 set_no_depth_stencil_write( i915 );
541 set_color_mask( i915, GL_TRUE );
542 set_draw_region( i915, &screen->back );
543
544 draw_quad(i915, x0, x1, y0, y1,
545 intel->clear_red, intel->clear_green,
546 intel->clear_blue, intel->clear_alpha,
547 0, 0, 0, 0);
548 }
549
550 if (mask & BUFFER_BIT_STENCIL) {
551 set_stencil_replace( i915,
552 intel->ctx.Stencil.WriteMask[0],
553 intel->ctx.Stencil.Clear);
554
555 set_color_mask( i915, GL_FALSE );
556 set_draw_region( i915, &screen->front ); /* could be either? */
557
558 draw_quad( i915, x0, x1, y0, y1, 0, 0, 0, 0, 0, 0, 0, 0 );
559 }
560
561 UNLOCK_HARDWARE(intel);
562
563 SET_STATE( i915, state );
564 }
565
566
567 /**
568 * Copy the window contents named by dPriv to the rotated (or reflected)
569 * color buffer.
570 * srcBuf is BUFFER_BIT_FRONT_LEFT or BUFFER_BIT_BACK_LEFT to indicate the source.
571 */
572 void
573 i915RotateWindow(intelContextPtr intel, __DRIdrawablePrivate *dPriv,
574 GLuint srcBuf)
575 {
576 i915ContextPtr i915 = I915_CONTEXT( intel );
577 intelScreenPrivate *screen = intel->intelScreen;
578 const GLuint cpp = screen->cpp;
579 drm_clip_rect_t fullRect;
580 GLuint textureFormat, srcOffset, srcPitch;
581 const drm_clip_rect_t *clipRects;
582 int numClipRects;
583 int i;
584
585 int xOrig, yOrig;
586 int origNumClipRects;
587 drm_clip_rect_t *origRects;
588
589 /*
590 * set up hardware state
591 */
592 intelFlush( &intel->ctx );
593
594 SET_STATE( i915, meta );
595 set_initial_state( i915 );
596 set_no_texture( i915 );
597 set_vertex_format( i915 );
598 set_no_depth_stencil_write( i915 );
599 set_color_mask( i915, GL_TRUE );
600
601 LOCK_HARDWARE(intel);
602
603 /* save current drawing origin and cliprects (restored at end) */
604 xOrig = intel->drawX;
605 yOrig = intel->drawY;
606 origNumClipRects = intel->numClipRects;
607 origRects = intel->pClipRects;
608
609 if (!intel->numClipRects)
610 goto done;
611
612 /*
613 * set drawing origin, cliprects for full-screen access to rotated screen
614 */
615 fullRect.x1 = 0;
616 fullRect.y1 = 0;
617 fullRect.x2 = screen->rotatedWidth;
618 fullRect.y2 = screen->rotatedHeight;
619 intel->drawX = 0;
620 intel->drawY = 0;
621 intel->numClipRects = 1;
622 intel->pClipRects = &fullRect;
623
624 set_draw_region( i915, &screen->rotated );
625
626 if (cpp == 4)
627 textureFormat = MAPSURF_32BIT | MT_32BIT_ARGB8888;
628 else
629 textureFormat = MAPSURF_16BIT | MT_16BIT_RGB565;
630
631 if (srcBuf == BUFFER_BIT_FRONT_LEFT) {
632 srcPitch = screen->front.pitch; /* in bytes */
633 srcOffset = screen->front.offset; /* bytes */
634 clipRects = dPriv->pClipRects;
635 numClipRects = dPriv->numClipRects;
636 }
637 else {
638 srcPitch = screen->back.pitch; /* in bytes */
639 srcOffset = screen->back.offset; /* bytes */
640 clipRects = dPriv->pBackClipRects;
641 numClipRects = dPriv->numBackClipRects;
642 }
643
644 /* set the whole screen up as a texture to avoid alignment issues */
645 set_tex_rect_source(i915,
646 srcOffset,
647 screen->width,
648 screen->height,
649 srcPitch,
650 textureFormat);
651
652 enable_texture_blend_replace(i915);
653
654 /*
655 * loop over the source window's cliprects
656 */
657 for (i = 0; i < numClipRects; i++) {
658 int srcX0 = clipRects[i].x1;
659 int srcY0 = clipRects[i].y1;
660 int srcX1 = clipRects[i].x2;
661 int srcY1 = clipRects[i].y2;
662 GLfloat verts[4][2], tex[4][2];
663 int j;
664
665 /* build vertices for four corners of clip rect */
666 verts[0][0] = srcX0; verts[0][1] = srcY0;
667 verts[1][0] = srcX1; verts[1][1] = srcY0;
668 verts[2][0] = srcX1; verts[2][1] = srcY1;
669 verts[3][0] = srcX0; verts[3][1] = srcY1;
670
671 /* .. and texcoords */
672 tex[0][0] = srcX0; tex[0][1] = srcY0;
673 tex[1][0] = srcX1; tex[1][1] = srcY0;
674 tex[2][0] = srcX1; tex[2][1] = srcY1;
675 tex[3][0] = srcX0; tex[3][1] = srcY1;
676
677 /* transform coords to rotated screen coords */
678 for (j = 0; j < 4; j++) {
679 matrix23TransformCoordf(&screen->rotMatrix,
680 &verts[j][0], &verts[j][1]);
681 }
682
683 /* draw polygon to map source image to dest region */
684 draw_poly(i915, 255, 255, 255, 255, 4, verts, tex);
685
686 } /* cliprect loop */
687
688 intelFlushBatchLocked( intel, GL_FALSE, GL_FALSE, GL_FALSE );
689
690 done:
691 /* restore original drawing origin and cliprects */
692 intel->drawX = xOrig;
693 intel->drawY = yOrig;
694 intel->numClipRects = origNumClipRects;
695 intel->pClipRects = origRects;
696
697 UNLOCK_HARDWARE(intel);
698
699 SET_STATE( i915, state );
700 }
701