1 /**************************************************************************
3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
34 #include "intel_screen.h"
35 #include "intel_batchbuffer.h"
36 #include "intel_ioctl.h"
37 #include "intel_rotate.h"
39 #include "i915_context.h"
42 /* A large amount of state doesn't need to be uploaded.
44 #define ACTIVE (I915_UPLOAD_INVARIENT | \
45 I915_UPLOAD_PROGRAM | \
46 I915_UPLOAD_STIPPLE | \
48 I915_UPLOAD_BUFFERS | \
51 #define SET_STATE( i915, STATE ) \
53 i915->current->emitted &= ~ACTIVE; \
54 i915->current = &i915->STATE; \
55 i915->current->emitted &= ~ACTIVE; \
58 /* Operations where the 3D engine is decoupled temporarily from the
59 * current GL state and used for other purposes than simply rendering
62 static void set_initial_state( i915ContextPtr i915
)
64 memcpy(&i915
->meta
, &i915
->initial
, sizeof(i915
->meta
) );
65 i915
->meta
.active
= ACTIVE
;
66 i915
->meta
.emitted
= 0;
70 static void set_no_depth_stencil_write( i915ContextPtr i915
)
72 /* ctx->Driver.Enable( ctx, GL_STENCIL_TEST, GL_FALSE )
74 i915
->meta
.Ctx
[I915_CTXREG_LIS5
] &= ~(S5_STENCIL_TEST_ENABLE
|
75 S5_STENCIL_WRITE_ENABLE
);
77 /* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_FALSE )
79 i915
->meta
.Ctx
[I915_CTXREG_LIS6
] &= ~(S6_DEPTH_TEST_ENABLE
|
80 S6_DEPTH_WRITE_ENABLE
);
82 i915
->meta
.emitted
&= ~I915_UPLOAD_CTX
;
85 /* Set stencil unit to replace always with the reference value.
87 static void set_stencil_replace( i915ContextPtr i915
,
91 GLuint op
= STENCILOP_REPLACE
;
92 GLuint func
= COMPAREFUNC_ALWAYS
;
94 /* ctx->Driver.Enable( ctx, GL_STENCIL_TEST, GL_TRUE )
96 i915
->meta
.Ctx
[I915_CTXREG_LIS5
] |= (S5_STENCIL_TEST_ENABLE
|
97 S5_STENCIL_WRITE_ENABLE
);
100 /* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_FALSE )
102 i915
->meta
.Ctx
[I915_CTXREG_LIS6
] &= ~(S6_DEPTH_TEST_ENABLE
|
103 S6_DEPTH_WRITE_ENABLE
);
106 /* ctx->Driver.StencilMask( ctx, s_mask )
108 i915
->meta
.Ctx
[I915_CTXREG_STATE4
] &= ~MODE4_ENABLE_STENCIL_WRITE_MASK
;
110 i915
->meta
.Ctx
[I915_CTXREG_STATE4
] |= (ENABLE_STENCIL_WRITE_MASK
|
111 STENCIL_WRITE_MASK(s_mask
));
114 /* ctx->Driver.StencilOp( ctx, GL_REPLACE, GL_REPLACE, GL_REPLACE )
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
);
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
));
125 /* ctx->Driver.StencilFunc( ctx, GL_ALWAYS, s_ref, ~0 )
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));
131 i915
->meta
.Ctx
[I915_CTXREG_LIS5
] &= ~(S5_STENCIL_REF_MASK
|
132 S5_STENCIL_TEST_FUNC_MASK
);
134 i915
->meta
.Ctx
[I915_CTXREG_LIS5
] |= ((s_clear
<< S5_STENCIL_REF_SHIFT
) |
135 (func
<< S5_STENCIL_TEST_FUNC_SHIFT
));
138 i915
->meta
.emitted
&= ~I915_UPLOAD_CTX
;
142 static void set_color_mask( i915ContextPtr i915
, GLboolean state
)
144 const GLuint mask
= (S5_WRITEDISABLE_RED
|
145 S5_WRITEDISABLE_GREEN
|
146 S5_WRITEDISABLE_BLUE
|
147 S5_WRITEDISABLE_ALPHA
);
149 /* Copy colormask state from "regular" hw context.
152 i915
->meta
.Ctx
[I915_CTXREG_LIS5
] &= ~mask
;
153 i915
->meta
.Ctx
[I915_CTXREG_LIS5
] |=
154 (i915
->state
.Ctx
[I915_CTXREG_LIS5
] & mask
);
157 i915
->meta
.Ctx
[I915_CTXREG_LIS5
] |= mask
;
159 i915
->meta
.emitted
&= ~I915_UPLOAD_CTX
;
165 #define REG( type, nr ) (((type)<<5)|(nr))
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)
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)
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 )
189 #define T0_SAMPLER( unit ) ((unit)<<T0_SAMPLER_NR_SHIFT)
191 #define T1_ADDRESS_REG( type, nr ) (((type)<<T1_ADDRESS_REG_TYPE_SHIFT)| \
192 ((nr)<<T1_ADDRESS_REG_NR_SHIFT))
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))
200 #define A1_SRC1_XY ((SRC_X << A1_SRC1_CHANNEL_X_SHIFT) | \
201 (SRC_Y << A1_SRC1_CHANNEL_Y_SHIFT))
203 #define A2_SRC1_ZW ((SRC_Z << A2_SRC1_CHANNEL_Z_SHIFT) | \
204 (SRC_W << A2_SRC1_CHANNEL_W_SHIFT))
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))
215 static void set_no_texture( i915ContextPtr i915
)
217 static const GLuint prog
[] = {
218 _3DSTATE_PIXEL_SHADER_PROGRAM
,
220 /* Declare incoming diffuse color:
223 D0_DECL_REG( REG_T_DIFFUSE
) |
228 /* output-color = mov(t_diffuse)
231 A0_DEST_REG( REG_OC
) |
232 A0_DEST_CHANNEL_ALL
|
233 A0_SRC0_REG( REG_T_DIFFUSE
)),
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
;
246 static void enable_texture_blend_replace( i915ContextPtr i915
)
248 static const GLuint prog
[] = {
249 _3DSTATE_PIXEL_SHADER_PROGRAM
,
251 /* Declare the sampler:
254 D0_DECL_REG( REG_S(0) ) |
260 /* Declare the interpolated texture coordinate:
263 D0_DECL_REG( REG_T_TEX(0) ) |
268 /* output-color = texld(sample0, texcoord0)
271 T0_DEST_REG( REG_OC
) |
273 T1_ADDRESS_REG(REG_TYPE_T
, 0),
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
;
287 /* Set up an arbitary piece of memory as a rectangular texture
288 * (including the front or back buffer).
290 static void set_tex_rect_source( i915ContextPtr i915
,
294 GLuint pitch
, /* in bytes! */
295 GLuint textureFormat
)
299 GLuint
*state
= i915
->meta
.Tex
[0];
302 printf("TexRect source offset 0x%x pitch %d\n", offset
, pitch
);
305 /* fprintf(stderr, "%s: offset: %x w: %d h: %d pitch %d format %x\n", */
306 /* __FUNCTION__, offset, width, height, pitch, textureFormat ); */
308 state
[I915_TEXREG_MS2
] = offset
;
309 state
[I915_TEXREG_MS3
] = (((height
- 1) << MS3_HEIGHT_SHIFT
) |
310 ((width
- 1) << MS3_WIDTH_SHIFT
) |
314 state
[I915_TEXREG_MS4
] = ((((pitch
/ 4) - 1) << MS4_PITCH_SHIFT
) |
315 ((((numLevels
-1) * 4)) << MS4_MAX_LOD_SHIFT
));
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
));
325 state
[I915_TEXREG_SS4
] = 0;
327 i915
->meta
.emitted
&= ~I915_UPLOAD_TEX(0);
331 /* Select between front and back draw buffers.
333 static void set_draw_region( i915ContextPtr i915
, const intelRegion
*region
)
336 printf("Rotate into region: offset 0x%x pitch %d\n",
337 region
->offset
, region
->pitch
);
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
;
347 /* Setup an arbitary draw format, useful for targeting texture or agp
350 static void set_draw_format( i915ContextPtr i915
,
354 i915
->meta
.Buffer
[I915_DESTREG_DV1
] = (DSTORG_HORT_BIAS(0x8) | /* .5 */
355 DSTORG_VERT_BIAS(0x8) | /* .5 */
358 TEX_DEFAULT_COLOR_OGL
|
361 i915
->meta
.emitted
&= ~I915_UPLOAD_BUFFERS
;
362 /* fprintf(stderr, "%s: DV1: %x\n", */
363 /* __FUNCTION__, i915->meta.Buffer[I915_DESTREG_DV1]); */
367 static void set_vertex_format( i915ContextPtr i915
)
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
));
379 i915
->meta
.Ctx
[I915_CTXREG_LIS4
] &= ~S4_VFMT_MASK
;
381 i915
->meta
.Ctx
[I915_CTXREG_LIS4
] |=
386 i915
->meta
.emitted
&= ~I915_UPLOAD_CTX
;
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
)
399 GLuint vertex_size
= 8;
400 GLuint
*vb
= intelEmitInlinePrimitiveLocked( &i915
->intel
,
408 fprintf(stderr
, "%s: %f,%f-%f,%f 0x%x%x%x%x %f,%f-%f,%f\n",
410 x0
,y0
,x1
,y1
,red
,green
,blue
,alpha
,s0
,t0
,s1
,t1
);
413 /* initial vertex, left bottom */
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;
429 for (i
= 0 ; i
< vertex_size
; i
++)
436 for (i
= 0 ; i
< vertex_size
; i
++)
443 for (i
= 0 ; i
< vertex_size
; i
++)
450 for (i
= 0 ; i
< vertex_size
; i
++)
455 static void draw_poly(i915ContextPtr i915
,
456 GLubyte red
, GLubyte green
, GLubyte blue
, GLubyte alpha
,
458 /*const*/ GLfloat verts
[][2],
459 /*const*/ GLfloat texcoords
[][2])
461 GLuint vertex_size
= 8;
462 GLuint
*vb
= intelEmitInlinePrimitiveLocked( &i915
->intel
,
464 numVerts
* vertex_size
,
469 /* initial constant vertex fields */
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;
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];
487 for (i
= 0 ; i
< vertex_size
; i
++)
496 i915ClearWithTris(intelContextPtr intel
, GLbitfield buffers
,
498 GLint cxFoo
, GLint cyFoo
, GLint cwFoo
, GLint chFoo
)
500 i915ContextPtr i915
= I915_CONTEXT( intel
);
501 __DRIdrawablePrivate
*dPriv
= intel
->driDrawable
;
502 intelScreenPrivate
*screen
= intel
->intelScreen
;
504 GLint cx
, cy
, cw
, ch
;
507 SET_STATE( i915
, meta
);
508 set_initial_state( i915
);
509 set_no_texture( i915
);
510 set_vertex_format( i915
);
512 LOCK_HARDWARE(intel
);
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
);
534 /* Don't do any clipping to screen - these are window coordinates.
535 * The active cliprects will be applied as for any other geometry.
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
);
543 draw_quad(i915
, x0
, x1
, y0
, y1
,
544 intel
->clear_red
, intel
->clear_green
,
545 intel
->clear_blue
, intel
->clear_alpha
,
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
);
554 draw_quad(i915
, x0
, x1
, y0
, y1
,
555 intel
->clear_red
, intel
->clear_green
,
556 intel
->clear_blue
, intel
->clear_alpha
,
560 if (buffers
& BUFFER_BIT_STENCIL
) {
561 set_stencil_replace( i915
,
562 intel
->ctx
.Stencil
.WriteMask
[0],
563 intel
->ctx
.Stencil
.Clear
);
565 set_color_mask( i915
, GL_FALSE
);
566 set_draw_region( i915
, &screen
->front
); /* could be either? */
568 draw_quad( i915
, x0
, x1
, y0
, y1
, 0, 0, 0, 0, 0, 0, 0, 0 );
571 UNLOCK_HARDWARE(intel
);
573 SET_STATE( i915
, state
);
578 * Copy the window contents named by dPriv to the rotated (or reflected)
580 * srcBuf is BUFFER_BIT_FRONT_LEFT or BUFFER_BIT_BACK_LEFT to indicate the source.
583 i915RotateWindow(intelContextPtr intel
, __DRIdrawablePrivate
*dPriv
,
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
;
596 int origNumClipRects
;
597 drm_clip_rect_t
*origRects
;
600 * set up hardware state
602 intelFlush( &intel
->ctx
);
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
);
611 LOCK_HARDWARE(intel
);
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
;
619 if (!intel
->numClipRects
)
623 * set drawing origin, cliprects for full-screen access to rotated screen
627 fullRect
.x2
= screen
->rotatedWidth
;
628 fullRect
.y2
= screen
->rotatedHeight
;
631 intel
->numClipRects
= 1;
632 intel
->pClipRects
= &fullRect
;
634 set_draw_region( i915
, &screen
->rotated
);
637 textureFormat
= MAPSURF_32BIT
| MT_32BIT_ARGB8888
;
639 textureFormat
= MAPSURF_16BIT
| MT_16BIT_RGB565
;
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
;
648 srcPitch
= screen
->back
.pitch
; /* in bytes */
649 srcOffset
= screen
->back
.offset
; /* bytes */
650 clipRects
= dPriv
->pBackClipRects
;
651 numClipRects
= dPriv
->numBackClipRects
;
654 /* set the whole screen up as a texture to avoid alignment issues */
655 set_tex_rect_source(i915
,
662 enable_texture_blend_replace(i915
);
665 * loop over the source window's cliprects
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];
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
;
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
;
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]);
693 /* draw polygon to map source image to dest region */
694 draw_poly(i915
, 255, 255, 255, 255, 4, verts
, tex
);
696 } /* cliprect loop */
698 intelFlushBatchLocked( intel
, GL_FALSE
, GL_FALSE
, GL_FALSE
);
701 /* restore original drawing origin and cliprects */
702 intel
->drawX
= xOrig
;
703 intel
->drawY
= yOrig
;
704 intel
->numClipRects
= origNumClipRects
;
705 intel
->pClipRects
= origRects
;
707 UNLOCK_HARDWARE(intel
);
709 SET_STATE( i915
, state
);