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"
38 #include "i830_context.h"
41 /* A large amount of state doesn't need to be uploaded.
43 #define ACTIVE (I830_UPLOAD_INVARIENT | \
44 I830_UPLOAD_TEXBLEND(0) | \
45 I830_UPLOAD_STIPPLE | \
47 I830_UPLOAD_BUFFERS | \
51 #define SET_STATE( i830, STATE ) \
53 i830->current->emitted = 0; \
54 i830->current = &i830->STATE; \
55 i830->current->emitted = 0; \
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( i830ContextPtr i830
)
64 memcpy(&i830
->meta
, &i830
->initial
, sizeof(i830
->meta
) );
65 i830
->meta
.active
= ACTIVE
;
66 i830
->meta
.emitted
= 0;
70 static void set_no_depth_stencil_write( i830ContextPtr i830
)
72 /* ctx->Driver.Enable( ctx, GL_STENCIL_TEST, GL_FALSE )
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
;
80 /* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_FALSE )
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
;
87 i830
->meta
.emitted
&= ~I830_UPLOAD_CTX
;
90 /* Set stencil unit to replace always with the reference value.
92 static void set_stencil_replace( i830ContextPtr i830
,
96 /* ctx->Driver.Enable( ctx, GL_STENCIL_TEST, GL_TRUE )
98 i830
->meta
.Ctx
[I830_CTXREG_ENABLES_1
] |= ENABLE_STENCIL_TEST
;
99 i830
->meta
.Ctx
[I830_CTXREG_ENABLES_2
] |= ENABLE_STENCIL_WRITE
;
102 /* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_FALSE )
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
;
109 /* ctx->Driver.StencilMask( ctx, s_mask )
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)));
115 /* ctx->Driver.StencilOp( ctx, GL_REPLACE, GL_REPLACE, GL_REPLACE )
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
));
124 /* ctx->Driver.StencilFunc( ctx, GL_ALWAYS, s_clear, ~0 )
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));
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
));
140 i830
->meta
.emitted
&= ~I830_UPLOAD_CTX
;
144 static void set_color_mask( i830ContextPtr i830
, GLboolean state
)
146 const GLuint mask
= ((1 << WRITEMASK_RED_SHIFT
) |
147 (1 << WRITEMASK_GREEN_SHIFT
) |
148 (1 << WRITEMASK_BLUE_SHIFT
) |
149 (1 << WRITEMASK_ALPHA_SHIFT
));
151 i830
->meta
.Ctx
[I830_CTXREG_ENABLES_2
] &= ~mask
;
154 i830
->meta
.Ctx
[I830_CTXREG_ENABLES_2
] |=
155 (i830
->state
.Ctx
[I830_CTXREG_ENABLES_2
] & mask
);
158 i830
->meta
.emitted
&= ~I830_UPLOAD_CTX
;
161 /* Installs a one-stage passthrough texture blend pipeline. Is there
162 * more that can be done to turn off texturing?
164 static void set_no_texture( i830ContextPtr i830
)
166 static const struct gl_tex_env_combine_state comb
= {
168 { GL_TEXTURE
, 0, 0, }, { GL_TEXTURE
, 0, 0, },
169 { GL_SRC_COLOR
, 0, 0 }, { GL_SRC_ALPHA
, 0, 0 },
173 i830
->meta
.TexBlendWordsUsed
[0] =
174 i830SetTexEnvCombine( i830
, & comb
, 0, TEXBLENDARG_TEXEL0
,
175 i830
->meta
.TexBlend
[0], NULL
);
177 i830
->meta
.TexBlend
[0][0] |= TEXOP_LAST_STAGE
;
178 i830
->meta
.emitted
&= ~I830_UPLOAD_TEXBLEND(0);
181 /* Set up a single element blend stage for 'replace' texturing with no
184 static void enable_texture_blend_replace( i830ContextPtr i830
)
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
},
193 i830
->meta
.TexBlendWordsUsed
[0] =
194 i830SetTexEnvCombine( i830
, & comb
, 0, TEXBLENDARG_TEXEL0
,
195 i830
->meta
.TexBlend
[0], NULL
);
197 i830
->meta
.TexBlend
[0][0] |= TEXOP_LAST_STAGE
;
198 i830
->meta
.emitted
&= ~I830_UPLOAD_TEXBLEND(0);
200 /* fprintf(stderr, "%s: TexBlendWordsUsed[0]: %d\n", */
201 /* __FUNCTION__, i830->meta.TexBlendWordsUsed[0]); */
206 /* Set up an arbitary piece of memory as a rectangular texture
207 * (including the front or back buffer).
209 static void set_tex_rect_source( i830ContextPtr i830
,
213 GLuint pitch
, /* in bytes */
214 GLuint textureFormat
)
217 GLuint
*setup
= i830
->meta
.Tex
[0];
219 /* fprintf(stderr, "%s: offset: %x w: %d h: %d pitch %d format %x\n", */
220 /* __FUNCTION__, offset, width, height, pitch, textureFormat ); */
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
) |
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
;
233 setup
[I830_TEXREG_MCS
] = (_3DSTATE_MAP_COORD_SET_CMD
|
235 ENABLE_TEXCOORD_PARAMS
|
236 TEXCOORDS_ARE_IN_TEXELUNITS
|
237 TEXCOORDTYPE_CARTESIAN
|
239 TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_WRAP
) |
241 TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_WRAP
));
243 i830
->meta
.emitted
&= ~I830_UPLOAD_TEX(0);
247 /* Select between front and back draw buffers.
249 static void set_draw_region( i830ContextPtr i830
,
250 const intelRegion
*region
)
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
;
258 /* Setup an arbitary draw format, useful for targeting
259 * texture or agp memory.
262 static void set_draw_format( i830ContextPtr i830
,
266 i830
->meta
.Buffer
[I830_DESTREG_DV1
] = (DSTORG_HORT_BIAS(0x8) | /* .5 */
267 DSTORG_VERT_BIAS(0x8) | /* .5 */
275 static void set_vertex_format( i830ContextPtr i830
)
277 i830
->meta
.Ctx
[I830_CTXREG_VF
] = (_3DSTATE_VFT0_CMD
|
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
;
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
)
299 GLuint vertex_size
= 8;
300 GLuint
*vb
= intelEmitInlinePrimitiveLocked( &i830
->intel
,
308 /* fprintf(stderr, "%s: %f,%f-%f,%f 0x%x%x%x%x %f,%f-%f,%f\n", */
310 /* x0,y0,x1,y1,red,green,blue,alpha,s0,t0,s1,t1); */
313 /* initial vertex, left bottom */
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;
328 for (i
= 0 ; i
< 8 ; i
++)
335 for (i
= 0 ; i
< 8 ; i
++)
342 for (i
= 0 ; i
< 8 ; i
++)
349 for (i
= 0 ; i
< 8 ; i
++)
352 /* fprintf(stderr, "%s: DV1: %x\n", */
353 /* __FUNCTION__, i830->meta.Buffer[I830_DESTREG_DV1]); */
356 static void draw_poly(i830ContextPtr i830
,
357 GLubyte red
, GLubyte green
, GLubyte blue
, GLubyte alpha
,
360 GLfloat texcoords
[][2])
362 GLuint vertex_size
= 8;
363 GLuint
*vb
= intelEmitInlinePrimitiveLocked( &i830
->intel
,
365 numVerts
* vertex_size
,
370 /* initial constant vertex fields */
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;
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];
388 for (i
= 0 ; i
< vertex_size
; i
++)
396 i830ClearWithTris(intelContextPtr intel
, GLbitfield mask
,
398 GLint cxFoo
, GLint cyFoo
, GLint cwFoo
, GLint chFoo
)
400 i830ContextPtr i830
= I830_CONTEXT( intel
);
401 __DRIdrawablePrivate
*dPriv
= intel
->driDrawable
;
402 intelScreenPrivate
*screen
= intel
->intelScreen
;
404 GLint cx
, cy
, cw
, ch
;
407 INTEL_FIREVERTICES(intel
);
408 SET_STATE( i830
, meta
);
409 set_initial_state( i830
);
410 /* set_no_texture( i830 ); */
411 set_vertex_format( i830
);
413 LOCK_HARDWARE(intel
);
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
);
435 /* Don't do any clipping to screen - these are window coordinates.
436 * The active cliprects will be applied as for any other geometry.
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
,
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
);
454 draw_quad(i830
, x0
, x1
, y0
, y1
,
455 intel
->clear_red
, intel
->clear_green
,
456 intel
->clear_blue
, intel
->clear_alpha
,
460 if(mask
& BUFFER_BIT_STENCIL
) {
461 set_stencil_replace( i830
,
462 intel
->ctx
.Stencil
.WriteMask
[0],
463 intel
->ctx
.Stencil
.Clear
);
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 );
470 UNLOCK_HARDWARE(intel
);
472 INTEL_FIREVERTICES(intel
);
473 SET_STATE( i830
, state
);
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
,
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
;
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
;
498 if (INTEL_DEBUG
& DEBUG_PIXEL
)
499 fprintf(stderr
, "%s\n", __FUNCTION__
);
502 if ( ctx
->_ImageTransferState
||
506 fprintf(stderr
, "%s: check_color failed\n", __FUNCTION__
);
510 switch (screen
->fbFormat
) {
512 textureFormat
= MAPSURF_16BIT
| MT_16BIT_RGB565
;
513 glTextureFormat
= GL_RGB
;
516 textureFormat
= MAPSURF_16BIT
| MT_16BIT_ARGB1555
;
517 glTextureFormat
= GL_RGBA
;
520 textureFormat
= MAPSURF_32BIT
| MT_32BIT_ARGB8888
;
521 glTextureFormat
= GL_RGBA
;
524 fprintf(stderr
, "%s: textureFormat failed %x\n", __FUNCTION__
,
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;
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;
544 fprintf(stderr
, "%s: destFormat failed %s\n", __FUNCTION__
,
545 _mesa_lookup_enum_by_nr(type
));
549 destFormat
|= (0x02<<24);
551 /* fprintf(stderr, "type: %s destFormat: %x\n", */
552 /* _mesa_lookup_enum_by_nr(type), */
557 SET_STATE( i830
, meta
);
558 set_initial_state( i830
);
559 set_no_depth_stencil_write( i830
);
561 LOCK_HARDWARE( intel
);
563 intelWaitForIdle( intel
); /* required by GL */
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__
);
573 /* FIXME -- Just emit the correct state
575 if (i830SetParam(i830
->driFd
, I830_SETPARAM_CBUFFER_PITCH
,
577 UNLOCK_HARDWARE( intel
);
578 SET_STATE(i830
, state
);
579 fprintf(stderr
, "%s: setparam failed\n", __FUNCTION__
);
585 y
= dPriv
->h
- y
- height
;
590 /* Set the frontbuffer up as a large rectangular texture.
592 set_tex_rect_source( i830
,
600 enable_texture_blend_replace( i830
);
603 /* Set the 3d engine to draw into the agp memory
606 set_draw_region( i830
, destOffset
);
607 set_draw_format( i830
, destFormat
, depthFormat
);
610 /* Draw a single quad, no cliprects:
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
;
622 x
, x
+width
, y
, y
+height
);
624 intelWindowMoved( intel
);
626 UNLOCK_HARDWARE( intel
);
627 intelFinish( ctx
); /* required by GL */
629 SET_STATE( i830
, state
);
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
)
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
;
646 GLenum glTextureFormat
;
647 int dst_offset
= i830
->meta
.Buffer
[I830_DESTREG_CBUFADDR2
];
648 int src_offset
= intelAgpOffsetFromVirtual( intel
, pixels
);
650 if (INTEL_DEBUG
& DEBUG_PIXEL
)
651 fprintf(stderr
, "%s\n", __FUNCTION__
);
653 /* Todo -- upload images that aren't in agp space, then texture
657 if ( !intelIsAgpMemory( intel
, pixels
, pitch
*height
) ) {
658 fprintf(stderr
, "%s: intelIsAgpMemory failed\n", __FUNCTION__
);
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.
665 if ( ctx
->_ImageTransferState
||
668 ctx
->Color
.AlphaEnabled
||
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__
);
684 /* Todo -- remove these restrictions:
686 if (ctx
->Pixel
.ZoomX
!= 1.0F
||
687 ctx
->Pixel
.ZoomY
!= -1.0F
)
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
;
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
;
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 */
708 glTextureFormat
= GL_YCBCR_MESA
;
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 */
715 glTextureFormat
= GL_YCBCR_MESA
;
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
;
723 fprintf(stderr
, "%s: destFormat failed\n", __FUNCTION__
);
729 SET_STATE( i830
, meta
);
731 LOCK_HARDWARE( intel
);
733 intelWaitForIdle( intel
); /* required by GL */
735 y
-= height
; /* cope with pixel zoom */
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__
);
745 y
= dPriv
->h
- y
- height
;
747 set_initial_state( i830
);
749 /* Set the pixel image up as a rectangular texture.
751 set_tex_rect_source( i830
,
755 pitch
, /* XXXX!!!! -- /2 sometimes */
759 enable_texture_blend_replace( i830
);
762 /* Draw to the current draw buffer:
764 set_draw_offset( i830
, dst_offset
);
766 /* Draw a quad, use regular cliprects
768 /* fprintf(stderr, "x: %d y: %d width %d height %d\n", x, y, width, height); */
771 x
, x
+width
, y
, y
+height
,
773 0, width
, 0, height
);
775 intelWindowMoved( intel
);
777 UNLOCK_HARDWARE( intel
);
778 intelFinish( ctx
); /* required by GL */
780 SET_STATE(i830
, state
);
788 * Copy the window contents named by dPriv to the rotated (or reflected)
790 * srcBuf is BUFFER_BIT_FRONT_LEFT or BUFFER_BIT_BACK_LEFT to indicate the source.
793 i830RotateWindow(intelContextPtr intel
, __DRIdrawablePrivate
*dPriv
,
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
;
806 int origNumClipRects
;
807 drm_clip_rect_t
*origRects
;
810 * set up hardware state
812 intelFlush( &intel
->ctx
);
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
);
821 LOCK_HARDWARE(intel
);
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
;
829 if (!intel
->numClipRects
)
833 * set drawing origin, cliprects for full-screen access to rotated screen
837 fullRect
.x2
= screen
->rotatedWidth
;
838 fullRect
.y2
= screen
->rotatedHeight
;
841 intel
->numClipRects
= 1;
842 intel
->pClipRects
= &fullRect
;
844 set_draw_region( i830
, &screen
->rotated
);
847 textureFormat
= MAPSURF_32BIT
| MT_32BIT_ARGB8888
;
849 textureFormat
= MAPSURF_16BIT
| MT_16BIT_RGB565
;
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
;
858 srcPitch
= screen
->back
.pitch
; /* in bytes */
859 srcOffset
= screen
->back
.offset
; /* bytes */
860 clipRects
= dPriv
->pBackClipRects
;
861 numClipRects
= dPriv
->numBackClipRects
;
864 /* set the whole screen up as a texture to avoid alignment issues */
865 set_tex_rect_source(i830
,
872 enable_texture_blend_replace(i830
);
875 * loop over the source window's cliprects
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];
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
;
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
;
897 /* transform coords to rotated screen coords */
899 for (j
= 0; j
< 4; j
++) {
900 matrix23TransformCoordf(&screen
->rotMatrix
,
901 &verts
[j
][0], &verts
[j
][1]);
904 /* draw polygon to map source image to dest region */
905 draw_poly(i830
, 255, 255, 255, 255, 4, verts
, tex
);
907 } /* cliprect loop */
909 intelFlushBatchLocked( intel
, GL_FALSE
, GL_FALSE
, GL_FALSE
);
912 /* restore original drawing origin and cliprects */
913 intel
->drawX
= xOrig
;
914 intel
->drawY
= yOrig
;
915 intel
->numClipRects
= origNumClipRects
;
916 intel
->pClipRects
= origRects
;
918 UNLOCK_HARDWARE(intel
);
920 SET_STATE( i830
, state
);