Merge branch 'nouveau-import'
[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 buffers,
497 GLboolean allFoo,
498 GLint cxFoo, GLint cyFoo, GLint cwFoo, GLint chFoo)
499 {
500 i915ContextPtr i915 = I915_CONTEXT( intel );
501 __DRIdrawablePrivate *dPriv = intel->driDrawable;
502 intelScreenPrivate *screen = intel->intelScreen;
503 int x0, y0, x1, y1;
504 GLint cx, cy, cw, ch;
505 GLboolean all;
506
507 SET_STATE( i915, meta );
508 set_initial_state( i915 );
509 set_no_texture( i915 );
510 set_vertex_format( i915 );
511
512 LOCK_HARDWARE(intel);
513
514 /* get clear bounds after locking */
515 cx = intel->ctx.DrawBuffer->_Xmin;
516 cy = intel->ctx.DrawBuffer->_Ymin;
517 cw = intel->ctx.DrawBuffer->_Xmax - cx;
518 ch = intel->ctx.DrawBuffer->_Ymax - cy;
519 all = (cw == intel->ctx.DrawBuffer->Width &&
520 ch == intel->ctx.DrawBuffer->Height);
521
522 if (!all) {
523 x0 = cx;
524 y0 = cy;
525 x1 = x0 + cw;
526 y1 = y0 + ch;
527 } else {
528 x0 = 0;
529 y0 = 0;
530 x1 = x0 + dPriv->w;
531 y1 = y0 + dPriv->h;
532 }
533
534 /* Don't do any clipping to screen - these are window coordinates.
535 * The active cliprects will be applied as for any other geometry.
536 */
537
538 if (buffers & BUFFER_BIT_FRONT_LEFT) {
539 set_no_depth_stencil_write( i915 );
540 set_color_mask( i915, GL_TRUE );
541 set_draw_region( i915, &screen->front );
542
543 draw_quad(i915, x0, x1, y0, y1,
544 intel->clear_red, intel->clear_green,
545 intel->clear_blue, intel->clear_alpha,
546 0, 0, 0, 0);
547 }
548
549 if (buffers & BUFFER_BIT_BACK_LEFT) {
550 set_no_depth_stencil_write( i915 );
551 set_color_mask( i915, GL_TRUE );
552 set_draw_region( i915, &screen->back );
553
554 draw_quad(i915, x0, x1, y0, y1,
555 intel->clear_red, intel->clear_green,
556 intel->clear_blue, intel->clear_alpha,
557 0, 0, 0, 0);
558 }
559
560 if (buffers & BUFFER_BIT_STENCIL) {
561 set_stencil_replace( i915,
562 intel->ctx.Stencil.WriteMask[0],
563 intel->ctx.Stencil.Clear);
564
565 set_color_mask( i915, GL_FALSE );
566 set_draw_region( i915, &screen->front ); /* could be either? */
567
568 draw_quad( i915, x0, x1, y0, y1, 0, 0, 0, 0, 0, 0, 0, 0 );
569 }
570
571 UNLOCK_HARDWARE(intel);
572
573 SET_STATE( i915, state );
574 }
575
576
577 /**
578 * Copy the window contents named by dPriv to the rotated (or reflected)
579 * color buffer.
580 * srcBuf is BUFFER_BIT_FRONT_LEFT or BUFFER_BIT_BACK_LEFT to indicate the source.
581 */
582 void
583 i915RotateWindow(intelContextPtr intel, __DRIdrawablePrivate *dPriv,
584 GLuint srcBuf)
585 {
586 i915ContextPtr i915 = I915_CONTEXT( intel );
587 intelScreenPrivate *screen = intel->intelScreen;
588 const GLuint cpp = screen->cpp;
589 drm_clip_rect_t fullRect;
590 GLuint textureFormat, srcOffset, srcPitch;
591 const drm_clip_rect_t *clipRects;
592 int numClipRects;
593 int i;
594
595 int xOrig, yOrig;
596 int origNumClipRects;
597 drm_clip_rect_t *origRects;
598
599 /*
600 * set up hardware state
601 */
602 intelFlush( &intel->ctx );
603
604 SET_STATE( i915, meta );
605 set_initial_state( i915 );
606 set_no_texture( i915 );
607 set_vertex_format( i915 );
608 set_no_depth_stencil_write( i915 );
609 set_color_mask( i915, GL_TRUE );
610
611 LOCK_HARDWARE(intel);
612
613 /* save current drawing origin and cliprects (restored at end) */
614 xOrig = intel->drawX;
615 yOrig = intel->drawY;
616 origNumClipRects = intel->numClipRects;
617 origRects = intel->pClipRects;
618
619 if (!intel->numClipRects)
620 goto done;
621
622 /*
623 * set drawing origin, cliprects for full-screen access to rotated screen
624 */
625 fullRect.x1 = 0;
626 fullRect.y1 = 0;
627 fullRect.x2 = screen->rotatedWidth;
628 fullRect.y2 = screen->rotatedHeight;
629 intel->drawX = 0;
630 intel->drawY = 0;
631 intel->numClipRects = 1;
632 intel->pClipRects = &fullRect;
633
634 set_draw_region( i915, &screen->rotated );
635
636 if (cpp == 4)
637 textureFormat = MAPSURF_32BIT | MT_32BIT_ARGB8888;
638 else
639 textureFormat = MAPSURF_16BIT | MT_16BIT_RGB565;
640
641 if (srcBuf == BUFFER_BIT_FRONT_LEFT) {
642 srcPitch = screen->front.pitch; /* in bytes */
643 srcOffset = screen->front.offset; /* bytes */
644 clipRects = dPriv->pClipRects;
645 numClipRects = dPriv->numClipRects;
646 }
647 else {
648 srcPitch = screen->back.pitch; /* in bytes */
649 srcOffset = screen->back.offset; /* bytes */
650 clipRects = dPriv->pBackClipRects;
651 numClipRects = dPriv->numBackClipRects;
652 }
653
654 /* set the whole screen up as a texture to avoid alignment issues */
655 set_tex_rect_source(i915,
656 srcOffset,
657 screen->width,
658 screen->height,
659 srcPitch,
660 textureFormat);
661
662 enable_texture_blend_replace(i915);
663
664 /*
665 * loop over the source window's cliprects
666 */
667 for (i = 0; i < numClipRects; i++) {
668 int srcX0 = clipRects[i].x1;
669 int srcY0 = clipRects[i].y1;
670 int srcX1 = clipRects[i].x2;
671 int srcY1 = clipRects[i].y2;
672 GLfloat verts[4][2], tex[4][2];
673 int j;
674
675 /* build vertices for four corners of clip rect */
676 verts[0][0] = srcX0; verts[0][1] = srcY0;
677 verts[1][0] = srcX1; verts[1][1] = srcY0;
678 verts[2][0] = srcX1; verts[2][1] = srcY1;
679 verts[3][0] = srcX0; verts[3][1] = srcY1;
680
681 /* .. and texcoords */
682 tex[0][0] = srcX0; tex[0][1] = srcY0;
683 tex[1][0] = srcX1; tex[1][1] = srcY0;
684 tex[2][0] = srcX1; tex[2][1] = srcY1;
685 tex[3][0] = srcX0; tex[3][1] = srcY1;
686
687 /* transform coords to rotated screen coords */
688 for (j = 0; j < 4; j++) {
689 matrix23TransformCoordf(&screen->rotMatrix,
690 &verts[j][0], &verts[j][1]);
691 }
692
693 /* draw polygon to map source image to dest region */
694 draw_poly(i915, 255, 255, 255, 255, 4, verts, tex);
695
696 } /* cliprect loop */
697
698 intelFlushBatchLocked( intel, GL_FALSE, GL_FALSE, GL_FALSE );
699
700 done:
701 /* restore original drawing origin and cliprects */
702 intel->drawX = xOrig;
703 intel->drawY = yOrig;
704 intel->numClipRects = origNumClipRects;
705 intel->pClipRects = origRects;
706
707 UNLOCK_HARDWARE(intel);
708
709 SET_STATE( i915, state );
710 }
711