1 /**************************************************************************
3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
6 **************************************************************************/
12 #include "swrast/swrast.h"
14 #include "intel_screen.h"
15 #include "intel_context.h"
16 #include "intel_ioctl.h"
17 #include "intel_batchbuffer.h"
22 check_color( const GLcontext
*ctx
, GLenum type
, GLenum format
,
23 const struct gl_pixelstore_attrib
*packing
,
24 const void *pixels
, GLint sz
, GLint pitch
)
26 intelContextPtr intel
= INTEL_CONTEXT(ctx
);
27 GLuint cpp
= intel
->intelScreen
->cpp
;
29 if (INTEL_DEBUG
& DEBUG_PIXEL
)
30 fprintf(stderr
, "%s\n", __FUNCTION__
);
33 ctx
->_ImageTransferState
||
36 if (INTEL_DEBUG
& DEBUG_PIXEL
)
37 fprintf(stderr
, "%s: failed 1\n", __FUNCTION__
);
41 if ( type
== GL_UNSIGNED_INT_8_8_8_8_REV
&&
44 if (INTEL_DEBUG
& DEBUG_PIXEL
)
45 fprintf(stderr
, "%s: passed 2\n", __FUNCTION__
);
49 if (INTEL_DEBUG
& DEBUG_PIXEL
)
50 fprintf(stderr
, "%s: failed\n", __FUNCTION__
);
56 check_color_per_fragment_ops( const GLcontext
*ctx
)
59 result
= (!( ctx
->Color
.AlphaEnabled
||
62 ctx
->Scissor
.Enabled
||
63 ctx
->Stencil
.Enabled
||
64 !ctx
->Color
.ColorMask
[0] ||
65 !ctx
->Color
.ColorMask
[1] ||
66 !ctx
->Color
.ColorMask
[2] ||
67 !ctx
->Color
.ColorMask
[3] ||
68 ctx
->Color
.ColorLogicOpEnabled
||
69 ctx
->Texture
._EnabledUnits
||
70 ctx
->Depth
.OcclusionTest
72 ctx
->Current
.RasterPosValid
);
80 clip_pixelrect( const GLcontext
*ctx
,
81 const GLframebuffer
*buffer
,
83 GLsizei
*width
, GLsizei
*height
,
86 intelContextPtr intel
= INTEL_CONTEXT(ctx
);
89 if (*x
< buffer
->_Xmin
) {
90 *width
-= (buffer
->_Xmin
- *x
);
95 if (*x
+ *width
> buffer
->_Xmax
)
96 *width
-= (*x
+ *width
- buffer
->_Xmax
- 1);
101 /* bottom clipping */
102 if (*y
< buffer
->_Ymin
) {
103 *height
-= (buffer
->_Ymin
- *y
);
108 if (*y
+ *height
> buffer
->_Ymax
)
109 *height
-= (*y
+ *height
- buffer
->_Ymax
- 1);
114 *size
= ((*y
+ *height
- 1) * intel
->intelScreen
->frontPitch
+
115 (*x
+ *width
- 1) * intel
->intelScreen
->cpp
);
121 intelTryReadPixels( GLcontext
*ctx
,
122 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
123 GLenum format
, GLenum type
,
124 const struct gl_pixelstore_attrib
*pack
,
127 intelContextPtr intel
= INTEL_CONTEXT(ctx
);
129 GLint pitch
= pack
->RowLength
? pack
->RowLength
: width
;
131 if (INTEL_DEBUG
& DEBUG_PIXEL
)
132 fprintf(stderr
, "%s\n", __FUNCTION__
);
134 /* Only accelerate reading to agp buffers.
136 if ( !intelIsAgpMemory(intel
, pixels
,
137 pitch
* height
* intel
->intelScreen
->cpp
) ) {
138 if (INTEL_DEBUG
& DEBUG_PIXEL
)
139 fprintf(stderr
, "%s: dest not agp\n", __FUNCTION__
);
143 /* Need GL_PACK_INVERT_MESA to cope with upsidedown results from
147 if (INTEL_DEBUG
& DEBUG_PIXEL
)
148 fprintf(stderr
, "%s: MESA_PACK_INVERT not set\n", __FUNCTION__
);
152 if (!check_color(ctx
, type
, format
, pack
, pixels
, size
, pitch
))
155 switch ( intel
->intelScreen
->cpp
) {
163 /* Although the blits go on the command buffer, need to do this and
164 * fire with lock held to guarentee cliprects and drawOffset are
167 * This is an unusual situation however, as the code which flushes
168 * a full command buffer expects to be called unlocked. As a
169 * workaround, immediately flush the buffer on aquiring the lock.
171 intelFlush( &intel
->ctx
);
172 LOCK_HARDWARE( intel
);
174 __DRIdrawablePrivate
*dPriv
= intel
->driDrawable
;
175 int nbox
= dPriv
->numClipRects
;
176 int src_offset
= intel
->drawOffset
;
177 int src_pitch
= intel
->intelScreen
->frontPitch
;
178 int dst_offset
= intelAgpOffsetFromVirtual( intel
, pixels
);
179 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
182 if (!clip_pixelrect(ctx
, ctx
->ReadBuffer
, &x
, &y
, &width
, &height
,
184 UNLOCK_HARDWARE( intel
);
185 if (INTEL_DEBUG
& DEBUG_PIXEL
)
186 fprintf(stderr
, "%s totally clipped -- nothing to do\n",
192 y
= dPriv
->h
- y
- height
;
197 if (INTEL_DEBUG
& DEBUG_PIXEL
)
198 fprintf(stderr
, "readpixel blit src_pitch %d dst_pitch %d\n",
201 for (i
= 0 ; i
< nbox
; i
++)
203 GLint bx
= box
[i
].x1
;
204 GLint by
= box
[i
].y1
;
205 GLint bw
= box
[i
].x2
- bx
;
206 GLint bh
= box
[i
].y2
- by
;
208 if (bx
< x
) bw
-= x
- bx
, bx
= x
;
209 if (by
< y
) bh
-= y
- by
, by
= y
;
210 if (bx
+ bw
> x
+ width
) bw
= x
+ width
- bx
;
211 if (by
+ bh
> y
+ height
) bh
= y
+ height
- by
;
212 if (bw
<= 0) continue;
213 if (bh
<= 0) continue;
215 intelEmitCopyBlitLocked( intel
,
216 intel
->intelScreen
->cpp
,
217 src_pitch
, src_offset
,
224 UNLOCK_HARDWARE( intel
);
225 intelFinish( &intel
->ctx
);
231 intelReadPixels( GLcontext
*ctx
,
232 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
233 GLenum format
, GLenum type
,
234 const struct gl_pixelstore_attrib
*pack
,
237 if (INTEL_DEBUG
& DEBUG_PIXEL
)
238 fprintf(stderr
, "%s\n", __FUNCTION__
);
240 if (!intelTryReadPixels( ctx
, x
, y
, width
, height
, format
, type
, pack
,
242 _swrast_ReadPixels( ctx
, x
, y
, width
, height
, format
, type
, pack
,
249 static void do_draw_pix( GLcontext
*ctx
,
250 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
255 intelContextPtr intel
= INTEL_CONTEXT(ctx
);
256 __DRIdrawablePrivate
*dPriv
= intel
->driDrawable
;
257 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
258 int nbox
= dPriv
->numClipRects
;
261 int src_offset
= intelAgpOffsetFromVirtual( intel
, pixels
);
262 int src_pitch
= pitch
;
264 if (INTEL_DEBUG
& DEBUG_PIXEL
)
265 fprintf(stderr
, "%s\n", __FUNCTION__
);
267 intelFlush( &intel
->ctx
);
268 LOCK_HARDWARE( intel
);
270 y
-= height
; /* cope with pixel zoom */
272 if (!clip_pixelrect(ctx
, ctx
->DrawBuffer
,
273 &x
, &y
, &width
, &height
,
275 UNLOCK_HARDWARE( intel
);
279 y
= dPriv
->h
- y
- height
; /* convert from gl to hardware coords */
284 for (i
= 0 ; i
< nbox
; i
++ )
286 GLint bx
= box
[i
].x1
;
287 GLint by
= box
[i
].y1
;
288 GLint bw
= box
[i
].x2
- bx
;
289 GLint bh
= box
[i
].y2
- by
;
291 if (bx
< x
) bw
-= x
- bx
, bx
= x
;
292 if (by
< y
) bh
-= y
- by
, by
= y
;
293 if (bx
+ bw
> x
+ width
) bw
= x
+ width
- bx
;
294 if (by
+ bh
> y
+ height
) bh
= y
+ height
- by
;
295 if (bw
<= 0) continue;
296 if (bh
<= 0) continue;
298 intelEmitCopyBlitLocked( intel
,
299 intel
->intelScreen
->cpp
,
300 src_pitch
, src_offset
,
301 intel
->intelScreen
->frontPitch
,
308 UNLOCK_HARDWARE( intel
);
309 intelFinish( &intel
->ctx
);
316 intelTryDrawPixels( GLcontext
*ctx
,
317 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
318 GLenum format
, GLenum type
,
319 const struct gl_pixelstore_attrib
*unpack
,
320 const GLvoid
*pixels
)
322 intelContextPtr intel
= INTEL_CONTEXT(ctx
);
323 GLint pitch
= unpack
->RowLength
? unpack
->RowLength
: width
;
325 GLuint cpp
= intel
->intelScreen
->cpp
;
326 GLint size
= width
* pitch
* cpp
;
328 if (INTEL_DEBUG
& DEBUG_PIXEL
)
329 fprintf(stderr
, "%s\n", __FUNCTION__
);
335 dest
= intel
->drawOffset
;
337 /* Planemask doesn't have full support in blits.
339 if (!ctx
->Color
.ColorMask
[RCOMP
] ||
340 !ctx
->Color
.ColorMask
[GCOMP
] ||
341 !ctx
->Color
.ColorMask
[BCOMP
] ||
342 !ctx
->Color
.ColorMask
[ACOMP
]) {
343 if (INTEL_DEBUG
& DEBUG_PIXEL
)
344 fprintf(stderr
, "%s: planemask\n", __FUNCTION__
);
348 /* Can't do conversions on agp reads/draws.
350 if ( !intelIsAgpMemory( intel
, pixels
, size
) ) {
351 if (INTEL_DEBUG
& DEBUG_PIXEL
)
352 fprintf(stderr
, "%s: not agp memory\n", __FUNCTION__
);
356 if (!check_color(ctx
, type
, format
, unpack
, pixels
, size
, pitch
)) {
359 if (!check_color_per_fragment_ops(ctx
)) {
363 if (ctx
->Pixel
.ZoomX
!= 1.0F
||
364 ctx
->Pixel
.ZoomY
!= -1.0F
)
372 if ( intelIsAgpMemory(intel
, pixels
, size
) )
374 do_draw_pix( ctx
, x
, y
, width
, height
, pitch
, pixels
,
380 /* Pixels is in regular memory -- get dma buffers and perform
381 * upload through them. No point doing this for regular uploads
382 * but once we remove some of the restrictions above (colormask,
383 * pixelformat conversion, zoom?, etc), this could be a win.
391 intelDrawPixels( GLcontext
*ctx
,
392 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
393 GLenum format
, GLenum type
,
394 const struct gl_pixelstore_attrib
*unpack
,
395 const GLvoid
*pixels
)
397 if (INTEL_DEBUG
& DEBUG_PIXEL
)
398 fprintf(stderr
, "%s\n", __FUNCTION__
);
400 if (!intelTryDrawPixels( ctx
, x
, y
, width
, height
, format
, type
,
402 _swrast_DrawPixels( ctx
, x
, y
, width
, height
, format
, type
,
410 * Implement glCopyPixels for the front color buffer (or back buffer Pixmap)
411 * for the color buffer. Don't support zooming, pixel transfer, etc.
412 * We do support copying from one window to another, ala glXMakeCurrentRead.
415 intelCopyPixels( GLcontext
*ctx
,
416 GLint srcx
, GLint srcy
, GLsizei width
, GLsizei height
,
417 GLint destx
, GLint desty
, GLenum type
)
420 const XMesaContext xmesa
= XMESA_CONTEXT(ctx
);
421 const SWcontext
*swrast
= SWRAST_CONTEXT( ctx
);
422 XMesaDisplay
*dpy
= xmesa
->xm_visual
->display
;
423 const XMesaDrawable drawBuffer
= xmesa
->xm_draw_buffer
->buffer
;
424 const XMesaDrawable readBuffer
= xmesa
->xm_read_buffer
->buffer
;
425 const XMesaGC gc
= xmesa
->xm_draw_buffer
->gc
;
430 if (drawBuffer
&& /* buffer != 0 means it's a Window or Pixmap */
433 (swrast
->_RasterMask
& ~CLIP_BIT
) == 0 && /* no blend, z-test, etc */
434 ctx
->_ImageTransferState
== 0 && /* no color tables, scale/bias, etc */
435 ctx
->Pixel
.ZoomX
== 1.0 && /* no zooming */
436 ctx
->Pixel
.ZoomY
== 1.0) {
437 /* Note: we don't do any special clipping work here. We could,
438 * but X will do it for us.
440 srcy
= FLIP(xmesa
->xm_read_buffer
, srcy
) - height
+ 1;
441 desty
= FLIP(xmesa
->xm_draw_buffer
, desty
) - height
+ 1;
442 XCopyArea(dpy
, readBuffer
, drawBuffer
, gc
,
443 srcx
, srcy
, width
, height
, destx
, desty
);
446 _swrast_CopyPixels(ctx
, srcx
, srcy
, width
, height
, destx
, desty
, type
);
453 void intelInitPixelFuncs( struct dd_function_table
*functions
)
455 /* Pixel path fallbacks.
457 functions
->Accum
= _swrast_Accum
;
458 functions
->Bitmap
= _swrast_Bitmap
;
459 functions
->CopyPixels
= intelCopyPixels
;
461 if (!getenv("INTEL_NO_BLITS")) {
462 functions
->ReadPixels
= intelReadPixels
;
463 functions
->DrawPixels
= intelDrawPixels
;
466 functions
->ReadPixels
= _swrast_ReadPixels
;
467 functions
->DrawPixels
= _swrast_DrawPixels
;