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