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 **************************************************************************/
32 #include "swrast/swrast.h"
34 #include "intel_screen.h"
35 #include "intel_context.h"
36 #include "intel_ioctl.h"
37 #include "intel_batchbuffer.h"
42 check_color( const GLcontext
*ctx
, GLenum type
, GLenum format
,
43 const struct gl_pixelstore_attrib
*packing
,
44 const void *pixels
, GLint sz
, GLint pitch
)
46 intelContextPtr intel
= INTEL_CONTEXT(ctx
);
47 GLuint cpp
= intel
->intelScreen
->cpp
;
49 if (INTEL_DEBUG
& DEBUG_PIXEL
)
50 fprintf(stderr
, "%s\n", __FUNCTION__
);
53 ctx
->_ImageTransferState
||
56 if (INTEL_DEBUG
& DEBUG_PIXEL
)
57 fprintf(stderr
, "%s: failed 1\n", __FUNCTION__
);
61 if ( type
== GL_UNSIGNED_INT_8_8_8_8_REV
&&
64 if (INTEL_DEBUG
& DEBUG_PIXEL
)
65 fprintf(stderr
, "%s: passed 2\n", __FUNCTION__
);
69 if (INTEL_DEBUG
& DEBUG_PIXEL
)
70 fprintf(stderr
, "%s: failed\n", __FUNCTION__
);
76 check_color_per_fragment_ops( const GLcontext
*ctx
)
79 result
= (!( ctx
->Color
.AlphaEnabled
||
82 ctx
->Scissor
.Enabled
||
83 ctx
->Stencil
.Enabled
||
84 !ctx
->Color
.ColorMask
[0] ||
85 !ctx
->Color
.ColorMask
[1] ||
86 !ctx
->Color
.ColorMask
[2] ||
87 !ctx
->Color
.ColorMask
[3] ||
88 ctx
->Color
.ColorLogicOpEnabled
||
89 ctx
->Texture
._EnabledUnits
||
90 ctx
->Depth
.OcclusionTest
92 ctx
->Current
.RasterPosValid
);
100 clip_pixelrect( const GLcontext
*ctx
,
101 const GLframebuffer
*buffer
,
103 GLsizei
*width
, GLsizei
*height
,
106 intelContextPtr intel
= INTEL_CONTEXT(ctx
);
109 if (*x
< buffer
->_Xmin
) {
110 *width
-= (buffer
->_Xmin
- *x
);
115 if (*x
+ *width
> buffer
->_Xmax
)
116 *width
-= (*x
+ *width
- buffer
->_Xmax
- 1);
121 /* bottom clipping */
122 if (*y
< buffer
->_Ymin
) {
123 *height
-= (buffer
->_Ymin
- *y
);
128 if (*y
+ *height
> buffer
->_Ymax
)
129 *height
-= (*y
+ *height
- buffer
->_Ymax
- 1);
134 *size
= ((*y
+ *height
- 1) * intel
->intelScreen
->frontPitch
+
135 (*x
+ *width
- 1) * intel
->intelScreen
->cpp
);
141 intelTryReadPixels( GLcontext
*ctx
,
142 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
143 GLenum format
, GLenum type
,
144 const struct gl_pixelstore_attrib
*pack
,
147 intelContextPtr intel
= INTEL_CONTEXT(ctx
);
149 GLint pitch
= pack
->RowLength
? pack
->RowLength
: width
;
151 if (INTEL_DEBUG
& DEBUG_PIXEL
)
152 fprintf(stderr
, "%s\n", __FUNCTION__
);
154 /* Only accelerate reading to agp buffers.
156 if ( !intelIsAgpMemory(intel
, pixels
,
157 pitch
* height
* intel
->intelScreen
->cpp
) ) {
158 if (INTEL_DEBUG
& DEBUG_PIXEL
)
159 fprintf(stderr
, "%s: dest not agp\n", __FUNCTION__
);
163 /* Need GL_PACK_INVERT_MESA to cope with upsidedown results from
167 if (INTEL_DEBUG
& DEBUG_PIXEL
)
168 fprintf(stderr
, "%s: MESA_PACK_INVERT not set\n", __FUNCTION__
);
172 if (!check_color(ctx
, type
, format
, pack
, pixels
, size
, pitch
))
175 switch ( intel
->intelScreen
->cpp
) {
183 /* Although the blits go on the command buffer, need to do this and
184 * fire with lock held to guarentee cliprects and drawOffset are
187 * This is an unusual situation however, as the code which flushes
188 * a full command buffer expects to be called unlocked. As a
189 * workaround, immediately flush the buffer on aquiring the lock.
191 intelFlush( &intel
->ctx
);
192 LOCK_HARDWARE( intel
);
194 __DRIdrawablePrivate
*dPriv
= intel
->driDrawable
;
195 int nbox
= dPriv
->numClipRects
;
196 int src_offset
= intel
->drawOffset
;
197 int src_pitch
= intel
->intelScreen
->frontPitch
;
198 int dst_offset
= intelAgpOffsetFromVirtual( intel
, pixels
);
199 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
202 if (!clip_pixelrect(ctx
, ctx
->ReadBuffer
, &x
, &y
, &width
, &height
,
204 UNLOCK_HARDWARE( intel
);
205 if (INTEL_DEBUG
& DEBUG_PIXEL
)
206 fprintf(stderr
, "%s totally clipped -- nothing to do\n",
212 y
= dPriv
->h
- y
- height
;
217 if (INTEL_DEBUG
& DEBUG_PIXEL
)
218 fprintf(stderr
, "readpixel blit src_pitch %d dst_pitch %d\n",
221 for (i
= 0 ; i
< nbox
; i
++)
223 GLint bx
= box
[i
].x1
;
224 GLint by
= box
[i
].y1
;
225 GLint bw
= box
[i
].x2
- bx
;
226 GLint bh
= box
[i
].y2
- by
;
228 if (bx
< x
) bw
-= x
- bx
, bx
= x
;
229 if (by
< y
) bh
-= y
- by
, by
= y
;
230 if (bx
+ bw
> x
+ width
) bw
= x
+ width
- bx
;
231 if (by
+ bh
> y
+ height
) bh
= y
+ height
- by
;
232 if (bw
<= 0) continue;
233 if (bh
<= 0) continue;
235 intelEmitCopyBlitLocked( intel
,
236 intel
->intelScreen
->cpp
,
237 src_pitch
, src_offset
,
244 UNLOCK_HARDWARE( intel
);
245 intelFinish( &intel
->ctx
);
251 intelReadPixels( GLcontext
*ctx
,
252 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
253 GLenum format
, GLenum type
,
254 const struct gl_pixelstore_attrib
*pack
,
257 if (INTEL_DEBUG
& DEBUG_PIXEL
)
258 fprintf(stderr
, "%s\n", __FUNCTION__
);
260 if (!intelTryReadPixels( ctx
, x
, y
, width
, height
, format
, type
, pack
,
262 _swrast_ReadPixels( ctx
, x
, y
, width
, height
, format
, type
, pack
,
269 static void do_draw_pix( GLcontext
*ctx
,
270 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
275 intelContextPtr intel
= INTEL_CONTEXT(ctx
);
276 __DRIdrawablePrivate
*dPriv
= intel
->driDrawable
;
277 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
278 int nbox
= dPriv
->numClipRects
;
281 int src_offset
= intelAgpOffsetFromVirtual( intel
, pixels
);
282 int src_pitch
= pitch
;
284 if (INTEL_DEBUG
& DEBUG_PIXEL
)
285 fprintf(stderr
, "%s\n", __FUNCTION__
);
287 intelFlush( &intel
->ctx
);
288 LOCK_HARDWARE( intel
);
290 y
-= height
; /* cope with pixel zoom */
292 if (!clip_pixelrect(ctx
, ctx
->DrawBuffer
,
293 &x
, &y
, &width
, &height
,
295 UNLOCK_HARDWARE( intel
);
299 y
= dPriv
->h
- y
- height
; /* convert from gl to hardware coords */
304 for (i
= 0 ; i
< nbox
; i
++ )
306 GLint bx
= box
[i
].x1
;
307 GLint by
= box
[i
].y1
;
308 GLint bw
= box
[i
].x2
- bx
;
309 GLint bh
= box
[i
].y2
- by
;
311 if (bx
< x
) bw
-= x
- bx
, bx
= x
;
312 if (by
< y
) bh
-= y
- by
, by
= y
;
313 if (bx
+ bw
> x
+ width
) bw
= x
+ width
- bx
;
314 if (by
+ bh
> y
+ height
) bh
= y
+ height
- by
;
315 if (bw
<= 0) continue;
316 if (bh
<= 0) continue;
318 intelEmitCopyBlitLocked( intel
,
319 intel
->intelScreen
->cpp
,
320 src_pitch
, src_offset
,
321 intel
->intelScreen
->frontPitch
,
328 UNLOCK_HARDWARE( intel
);
329 intelFinish( &intel
->ctx
);
336 intelTryDrawPixels( GLcontext
*ctx
,
337 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
338 GLenum format
, GLenum type
,
339 const struct gl_pixelstore_attrib
*unpack
,
340 const GLvoid
*pixels
)
342 intelContextPtr intel
= INTEL_CONTEXT(ctx
);
343 GLint pitch
= unpack
->RowLength
? unpack
->RowLength
: width
;
345 GLuint cpp
= intel
->intelScreen
->cpp
;
346 GLint size
= width
* pitch
* cpp
;
348 if (INTEL_DEBUG
& DEBUG_PIXEL
)
349 fprintf(stderr
, "%s\n", __FUNCTION__
);
355 dest
= intel
->drawOffset
;
357 /* Planemask doesn't have full support in blits.
359 if (!ctx
->Color
.ColorMask
[RCOMP
] ||
360 !ctx
->Color
.ColorMask
[GCOMP
] ||
361 !ctx
->Color
.ColorMask
[BCOMP
] ||
362 !ctx
->Color
.ColorMask
[ACOMP
]) {
363 if (INTEL_DEBUG
& DEBUG_PIXEL
)
364 fprintf(stderr
, "%s: planemask\n", __FUNCTION__
);
368 /* Can't do conversions on agp reads/draws.
370 if ( !intelIsAgpMemory( intel
, pixels
, size
) ) {
371 if (INTEL_DEBUG
& DEBUG_PIXEL
)
372 fprintf(stderr
, "%s: not agp memory\n", __FUNCTION__
);
376 if (!check_color(ctx
, type
, format
, unpack
, pixels
, size
, pitch
)) {
379 if (!check_color_per_fragment_ops(ctx
)) {
383 if (ctx
->Pixel
.ZoomX
!= 1.0F
||
384 ctx
->Pixel
.ZoomY
!= -1.0F
)
392 if ( intelIsAgpMemory(intel
, pixels
, size
) )
394 do_draw_pix( ctx
, x
, y
, width
, height
, pitch
, pixels
,
400 /* Pixels is in regular memory -- get dma buffers and perform
401 * upload through them. No point doing this for regular uploads
402 * but once we remove some of the restrictions above (colormask,
403 * pixelformat conversion, zoom?, etc), this could be a win.
411 intelDrawPixels( GLcontext
*ctx
,
412 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
413 GLenum format
, GLenum type
,
414 const struct gl_pixelstore_attrib
*unpack
,
415 const GLvoid
*pixels
)
417 if (INTEL_DEBUG
& DEBUG_PIXEL
)
418 fprintf(stderr
, "%s\n", __FUNCTION__
);
420 if (!intelTryDrawPixels( ctx
, x
, y
, width
, height
, format
, type
,
422 _swrast_DrawPixels( ctx
, x
, y
, width
, height
, format
, type
,
430 * Implement glCopyPixels for the front color buffer (or back buffer Pixmap)
431 * for the color buffer. Don't support zooming, pixel transfer, etc.
432 * We do support copying from one window to another, ala glXMakeCurrentRead.
435 intelCopyPixels( GLcontext
*ctx
,
436 GLint srcx
, GLint srcy
, GLsizei width
, GLsizei height
,
437 GLint destx
, GLint desty
, GLenum type
)
440 const XMesaContext xmesa
= XMESA_CONTEXT(ctx
);
441 const SWcontext
*swrast
= SWRAST_CONTEXT( ctx
);
442 XMesaDisplay
*dpy
= xmesa
->xm_visual
->display
;
443 const XMesaDrawable drawBuffer
= xmesa
->xm_draw_buffer
->buffer
;
444 const XMesaDrawable readBuffer
= xmesa
->xm_read_buffer
->buffer
;
445 const XMesaGC gc
= xmesa
->xm_draw_buffer
->gc
;
450 if (drawBuffer
&& /* buffer != 0 means it's a Window or Pixmap */
453 (swrast
->_RasterMask
& ~CLIP_BIT
) == 0 && /* no blend, z-test, etc */
454 ctx
->_ImageTransferState
== 0 && /* no color tables, scale/bias, etc */
455 ctx
->Pixel
.ZoomX
== 1.0 && /* no zooming */
456 ctx
->Pixel
.ZoomY
== 1.0) {
457 /* Note: we don't do any special clipping work here. We could,
458 * but X will do it for us.
460 srcy
= FLIP(xmesa
->xm_read_buffer
, srcy
) - height
+ 1;
461 desty
= FLIP(xmesa
->xm_draw_buffer
, desty
) - height
+ 1;
462 XCopyArea(dpy
, readBuffer
, drawBuffer
, gc
,
463 srcx
, srcy
, width
, height
, destx
, desty
);
466 _swrast_CopyPixels(ctx
, srcx
, srcy
, width
, height
, destx
, desty
, type
);
473 void intelInitPixelFuncs( struct dd_function_table
*functions
)
475 /* Pixel path fallbacks.
477 functions
->Accum
= _swrast_Accum
;
478 functions
->Bitmap
= _swrast_Bitmap
;
479 functions
->CopyPixels
= intelCopyPixels
;
481 if (!getenv("INTEL_NO_BLITS")) {
482 functions
->ReadPixels
= intelReadPixels
;
483 functions
->DrawPixels
= intelDrawPixels
;
486 functions
->ReadPixels
= _swrast_ReadPixels
;
487 functions
->DrawPixels
= _swrast_DrawPixels
;