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
91 ctx
->Current
.RasterPosValid
);
98 * Clip the given rectangle against the buffer's bounds (including scissor).
99 * \param size returns the
100 * \return GL_TRUE if any pixels remain, GL_FALSE if totally clipped.
102 * XXX Replace this with _mesa_clip_drawpixels() and _mesa_clip_readpixels()
103 * from Mesa 6.4. We shouldn't apply scissor for ReadPixels.
106 clip_pixelrect( const GLcontext
*ctx
,
107 const GLframebuffer
*buffer
,
109 GLsizei
*width
, GLsizei
*height
)
112 if (*x
< buffer
->_Xmin
) {
113 *width
-= (buffer
->_Xmin
- *x
);
118 if (*x
+ *width
> buffer
->_Xmax
)
119 *width
-= (*x
+ *width
- buffer
->_Xmax
- 1);
124 /* bottom clipping */
125 if (*y
< buffer
->_Ymin
) {
126 *height
-= (buffer
->_Ymin
- *y
);
131 if (*y
+ *height
> buffer
->_Ymax
)
132 *height
-= (*y
+ *height
- buffer
->_Ymax
- 1);
142 * Compute intersection of a clipping rectangle and pixel rectangle,
143 * returning results in x/y/w/hOut vars.
144 * \return GL_TRUE if there's intersection, GL_FALSE if disjoint.
146 static INLINE GLboolean
147 intersect_region(const drm_clip_rect_t
*box
,
148 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
149 GLint
*xOut
, GLint
*yOut
, GLint
*wOut
, GLint
*hOut
)
153 GLint bw
= box
->x2
- bx
;
154 GLint bh
= box
->y2
- by
;
156 if (bx
< x
) bw
-= x
- bx
, bx
= x
;
157 if (by
< y
) bh
-= y
- by
, by
= y
;
158 if (bx
+ bw
> x
+ width
) bw
= x
+ width
- bx
;
159 if (by
+ bh
> y
+ height
) bh
= y
+ height
- by
;
166 if (bw
<= 0) return GL_FALSE
;
167 if (bh
<= 0) return GL_FALSE
;
175 intelTryReadPixels( GLcontext
*ctx
,
176 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
177 GLenum format
, GLenum type
,
178 const struct gl_pixelstore_attrib
*pack
,
181 intelContextPtr intel
= INTEL_CONTEXT(ctx
);
182 GLint size
= 0; /* not really used */
183 GLint pitch
= pack
->RowLength
? pack
->RowLength
: width
;
185 if (INTEL_DEBUG
& DEBUG_PIXEL
)
186 fprintf(stderr
, "%s\n", __FUNCTION__
);
188 /* Only accelerate reading to agp buffers.
190 if ( !intelIsAgpMemory(intel
, pixels
,
191 pitch
* height
* intel
->intelScreen
->cpp
) ) {
192 if (INTEL_DEBUG
& DEBUG_PIXEL
)
193 fprintf(stderr
, "%s: dest not agp\n", __FUNCTION__
);
197 /* Need GL_PACK_INVERT_MESA to cope with upsidedown results from
201 if (INTEL_DEBUG
& DEBUG_PIXEL
)
202 fprintf(stderr
, "%s: MESA_PACK_INVERT not set\n", __FUNCTION__
);
206 if (!check_color(ctx
, type
, format
, pack
, pixels
, size
, pitch
))
209 switch ( intel
->intelScreen
->cpp
) {
217 /* Although the blits go on the command buffer, need to do this and
218 * fire with lock held to guarentee cliprects and drawing offset are
221 * This is an unusual situation however, as the code which flushes
222 * a full command buffer expects to be called unlocked. As a
223 * workaround, immediately flush the buffer on aquiring the lock.
225 intelFlush( &intel
->ctx
);
226 LOCK_HARDWARE( intel
);
228 __DRIdrawablePrivate
*dPriv
= intel
->driDrawable
;
229 int nbox
= dPriv
->numClipRects
;
230 int src_offset
= intel
->readRegion
->offset
;
231 int src_pitch
= intel
->intelScreen
->front
.pitch
;
232 int dst_offset
= intelAgpOffsetFromVirtual( intel
, pixels
);
233 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
236 assert(dst_offset
!= ~0); /* should have been caught above */
238 if (!clip_pixelrect(ctx
, ctx
->ReadBuffer
, &x
, &y
, &width
, &height
)) {
239 UNLOCK_HARDWARE( intel
);
240 if (INTEL_DEBUG
& DEBUG_PIXEL
)
241 fprintf(stderr
, "%s totally clipped -- nothing to do\n",
246 /* convert to screen coords (y=0=top) */
247 y
= dPriv
->h
- y
- height
;
251 if (INTEL_DEBUG
& DEBUG_PIXEL
)
252 fprintf(stderr
, "readpixel blit src_pitch %d dst_pitch %d\n",
255 /* We don't really have to do window clipping for readpixels.
256 * The OpenGL spec says that pixels read from outside the
257 * visible window region (pixel ownership) have undefined value.
259 for (i
= 0 ; i
< nbox
; i
++)
261 GLint bx
, by
, bw
, bh
;
262 if (intersect_region(box
+i
, x
, y
, width
, height
,
263 &bx
, &by
, &bw
, &bh
)) {
264 intelEmitCopyBlitLocked( intel
,
265 intel
->intelScreen
->cpp
,
266 src_pitch
, src_offset
,
274 UNLOCK_HARDWARE( intel
);
275 intelFinish( &intel
->ctx
);
281 intelReadPixels( GLcontext
*ctx
,
282 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
283 GLenum format
, GLenum type
,
284 const struct gl_pixelstore_attrib
*pack
,
287 if (INTEL_DEBUG
& DEBUG_PIXEL
)
288 fprintf(stderr
, "%s\n", __FUNCTION__
);
290 if (!intelTryReadPixels( ctx
, x
, y
, width
, height
, format
, type
, pack
,
292 _swrast_ReadPixels( ctx
, x
, y
, width
, height
, format
, type
, pack
,
299 static void do_draw_pix( GLcontext
*ctx
,
300 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
305 intelContextPtr intel
= INTEL_CONTEXT(ctx
);
306 __DRIdrawablePrivate
*dPriv
= intel
->driDrawable
;
307 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
308 int nbox
= dPriv
->numClipRects
;
310 int src_offset
= intelAgpOffsetFromVirtual( intel
, pixels
);
311 int src_pitch
= pitch
;
313 assert(src_offset
!= ~0); /* should be caught earlier */
315 if (INTEL_DEBUG
& DEBUG_PIXEL
)
316 fprintf(stderr
, "%s\n", __FUNCTION__
);
318 intelFlush( &intel
->ctx
);
319 LOCK_HARDWARE( intel
);
322 y
-= height
; /* cope with pixel zoom */
324 if (!clip_pixelrect(ctx
, ctx
->DrawBuffer
,
325 &x
, &y
, &width
, &height
)) {
326 UNLOCK_HARDWARE( intel
);
330 y
= dPriv
->h
- y
- height
; /* convert from gl to hardware coords */
334 for (i
= 0 ; i
< nbox
; i
++ )
336 GLint bx
, by
, bw
, bh
;
337 if (intersect_region(box
+ i
, x
, y
, width
, height
,
338 &bx
, &by
, &bw
, &bh
)) {
339 intelEmitCopyBlitLocked( intel
,
340 intel
->intelScreen
->cpp
,
341 src_pitch
, src_offset
,
342 intel
->intelScreen
->front
.pitch
,
343 intel
->drawRegion
->offset
,
350 UNLOCK_HARDWARE( intel
);
351 intelFinish( &intel
->ctx
);
357 intelTryDrawPixels( GLcontext
*ctx
,
358 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
359 GLenum format
, GLenum type
,
360 const struct gl_pixelstore_attrib
*unpack
,
361 const GLvoid
*pixels
)
363 intelContextPtr intel
= INTEL_CONTEXT(ctx
);
364 GLint pitch
= unpack
->RowLength
? unpack
->RowLength
: width
;
366 GLuint cpp
= intel
->intelScreen
->cpp
;
367 GLint size
= width
* pitch
* cpp
;
369 if (INTEL_DEBUG
& DEBUG_PIXEL
)
370 fprintf(stderr
, "%s\n", __FUNCTION__
);
376 dest
= intel
->drawRegion
->offset
;
378 /* Planemask doesn't have full support in blits.
380 if (!ctx
->Color
.ColorMask
[RCOMP
] ||
381 !ctx
->Color
.ColorMask
[GCOMP
] ||
382 !ctx
->Color
.ColorMask
[BCOMP
] ||
383 !ctx
->Color
.ColorMask
[ACOMP
]) {
384 if (INTEL_DEBUG
& DEBUG_PIXEL
)
385 fprintf(stderr
, "%s: planemask\n", __FUNCTION__
);
389 /* Can't do conversions on agp reads/draws.
391 if ( !intelIsAgpMemory( intel
, pixels
, size
) ) {
392 if (INTEL_DEBUG
& DEBUG_PIXEL
)
393 fprintf(stderr
, "%s: not agp memory\n", __FUNCTION__
);
397 if (!check_color(ctx
, type
, format
, unpack
, pixels
, size
, pitch
)) {
400 if (!check_color_per_fragment_ops(ctx
)) {
404 if (ctx
->Pixel
.ZoomX
!= 1.0F
||
405 ctx
->Pixel
.ZoomY
!= -1.0F
)
413 if ( intelIsAgpMemory(intel
, pixels
, size
) )
415 do_draw_pix( ctx
, x
, y
, width
, height
, pitch
, pixels
, dest
);
420 /* Pixels is in regular memory -- get dma buffers and perform
421 * upload through them. No point doing this for regular uploads
422 * but once we remove some of the restrictions above (colormask,
423 * pixelformat conversion, zoom?, etc), this could be a win.
433 intelDrawPixels( GLcontext
*ctx
,
434 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
435 GLenum format
, GLenum type
,
436 const struct gl_pixelstore_attrib
*unpack
,
437 const GLvoid
*pixels
)
439 if (INTEL_DEBUG
& DEBUG_PIXEL
)
440 fprintf(stderr
, "%s\n", __FUNCTION__
);
442 if (intelTryDrawPixels( ctx
, x
, y
, width
, height
, format
, type
,
446 if (ctx
->FragmentProgram
._Current
== ctx
->FragmentProgram
._TexEnvProgram
) {
448 * We don't want the i915 texenv program to be applied to DrawPixels.
449 * This is really just a performance optimization (mesa will other-
450 * wise happily run the fragment program on each pixel in the image).
452 struct gl_fragment_program
*fpSave
= ctx
->FragmentProgram
._Current
;
453 ctx
->FragmentProgram
._Current
= NULL
;
454 _swrast_DrawPixels( ctx
, x
, y
, width
, height
, format
, type
,
456 ctx
->FragmentProgram
._Current
= fpSave
;
459 _swrast_DrawPixels( ctx
, x
, y
, width
, height
, format
, type
,
468 * Implement glCopyPixels for the front color buffer (or back buffer Pixmap)
469 * for the color buffer. Don't support zooming, pixel transfer, etc.
470 * We do support copying from one window to another, ala glXMakeCurrentRead.
473 intelCopyPixels( GLcontext
*ctx
,
474 GLint srcx
, GLint srcy
, GLsizei width
, GLsizei height
,
475 GLint destx
, GLint desty
, GLenum type
)
478 const XMesaContext xmesa
= XMESA_CONTEXT(ctx
);
479 const SWcontext
*swrast
= SWRAST_CONTEXT( ctx
);
480 XMesaDisplay
*dpy
= xmesa
->xm_visual
->display
;
481 const XMesaDrawable drawBuffer
= xmesa
->xm_draw_buffer
->buffer
;
482 const XMesaDrawable readBuffer
= xmesa
->xm_read_buffer
->buffer
;
483 const XMesaGC gc
= xmesa
->xm_draw_buffer
->gc
;
488 if (drawBuffer
&& /* buffer != 0 means it's a Window or Pixmap */
491 (swrast
->_RasterMask
& ~CLIP_BIT
) == 0 && /* no blend, z-test, etc */
492 ctx
->_ImageTransferState
== 0 && /* no color tables, scale/bias, etc */
493 ctx
->Pixel
.ZoomX
== 1.0 && /* no zooming */
494 ctx
->Pixel
.ZoomY
== 1.0) {
495 /* Note: we don't do any special clipping work here. We could,
496 * but X will do it for us.
498 srcy
= FLIP(xmesa
->xm_read_buffer
, srcy
) - height
+ 1;
499 desty
= FLIP(xmesa
->xm_draw_buffer
, desty
) - height
+ 1;
500 XCopyArea(dpy
, readBuffer
, drawBuffer
, gc
,
501 srcx
, srcy
, width
, height
, destx
, desty
);
504 _swrast_CopyPixels(ctx
, srcx
, srcy
, width
, height
, destx
, desty
, type
);
511 void intelInitPixelFuncs( struct dd_function_table
*functions
)
513 functions
->CopyPixels
= intelCopyPixels
;
514 if (!getenv("INTEL_NO_BLITS")) {
515 functions
->ReadPixels
= intelReadPixels
;
516 functions
->DrawPixels
= intelDrawPixels
;