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
);
99 clip_pixelrect( const GLcontext
*ctx
,
100 const GLframebuffer
*buffer
,
102 GLsizei
*width
, GLsizei
*height
,
105 intelContextPtr intel
= INTEL_CONTEXT(ctx
);
108 if (*x
< buffer
->_Xmin
) {
109 *width
-= (buffer
->_Xmin
- *x
);
114 if (*x
+ *width
> buffer
->_Xmax
)
115 *width
-= (*x
+ *width
- buffer
->_Xmax
- 1);
120 /* bottom clipping */
121 if (*y
< buffer
->_Ymin
) {
122 *height
-= (buffer
->_Ymin
- *y
);
127 if (*y
+ *height
> buffer
->_Ymax
)
128 *height
-= (*y
+ *height
- buffer
->_Ymax
- 1);
133 *size
= ((*y
+ *height
- 1) * intel
->intelScreen
->frontPitch
+
134 (*x
+ *width
- 1) * intel
->intelScreen
->cpp
);
140 intelTryReadPixels( GLcontext
*ctx
,
141 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
142 GLenum format
, GLenum type
,
143 const struct gl_pixelstore_attrib
*pack
,
146 intelContextPtr intel
= INTEL_CONTEXT(ctx
);
148 GLint pitch
= pack
->RowLength
? pack
->RowLength
: width
;
150 if (INTEL_DEBUG
& DEBUG_PIXEL
)
151 fprintf(stderr
, "%s\n", __FUNCTION__
);
153 /* Only accelerate reading to agp buffers.
155 if ( !intelIsAgpMemory(intel
, pixels
,
156 pitch
* height
* intel
->intelScreen
->cpp
) ) {
157 if (INTEL_DEBUG
& DEBUG_PIXEL
)
158 fprintf(stderr
, "%s: dest not agp\n", __FUNCTION__
);
162 /* Need GL_PACK_INVERT_MESA to cope with upsidedown results from
166 if (INTEL_DEBUG
& DEBUG_PIXEL
)
167 fprintf(stderr
, "%s: MESA_PACK_INVERT not set\n", __FUNCTION__
);
171 if (!check_color(ctx
, type
, format
, pack
, pixels
, size
, pitch
))
174 switch ( intel
->intelScreen
->cpp
) {
182 /* Although the blits go on the command buffer, need to do this and
183 * fire with lock held to guarentee cliprects and drawOffset are
186 * This is an unusual situation however, as the code which flushes
187 * a full command buffer expects to be called unlocked. As a
188 * workaround, immediately flush the buffer on aquiring the lock.
190 intelFlush( &intel
->ctx
);
191 LOCK_HARDWARE( intel
);
193 __DRIdrawablePrivate
*dPriv
= intel
->driDrawable
;
194 int nbox
= dPriv
->numClipRects
;
195 int src_offset
= intel
->drawOffset
;
196 int src_pitch
= intel
->intelScreen
->frontPitch
;
197 int dst_offset
= intelAgpOffsetFromVirtual( intel
, pixels
);
198 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
201 if (!clip_pixelrect(ctx
, ctx
->ReadBuffer
, &x
, &y
, &width
, &height
,
203 UNLOCK_HARDWARE( intel
);
204 if (INTEL_DEBUG
& DEBUG_PIXEL
)
205 fprintf(stderr
, "%s totally clipped -- nothing to do\n",
211 y
= dPriv
->h
- y
- height
;
216 if (INTEL_DEBUG
& DEBUG_PIXEL
)
217 fprintf(stderr
, "readpixel blit src_pitch %d dst_pitch %d\n",
220 for (i
= 0 ; i
< nbox
; i
++)
222 GLint bx
= box
[i
].x1
;
223 GLint by
= box
[i
].y1
;
224 GLint bw
= box
[i
].x2
- bx
;
225 GLint bh
= box
[i
].y2
- by
;
227 if (bx
< x
) bw
-= x
- bx
, bx
= x
;
228 if (by
< y
) bh
-= y
- by
, by
= y
;
229 if (bx
+ bw
> x
+ width
) bw
= x
+ width
- bx
;
230 if (by
+ bh
> y
+ height
) bh
= y
+ height
- by
;
231 if (bw
<= 0) continue;
232 if (bh
<= 0) continue;
234 intelEmitCopyBlitLocked( intel
,
235 intel
->intelScreen
->cpp
,
236 src_pitch
, src_offset
,
243 UNLOCK_HARDWARE( intel
);
244 intelFinish( &intel
->ctx
);
250 intelReadPixels( GLcontext
*ctx
,
251 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
252 GLenum format
, GLenum type
,
253 const struct gl_pixelstore_attrib
*pack
,
256 if (INTEL_DEBUG
& DEBUG_PIXEL
)
257 fprintf(stderr
, "%s\n", __FUNCTION__
);
259 if (!intelTryReadPixels( ctx
, x
, y
, width
, height
, format
, type
, pack
,
261 _swrast_ReadPixels( ctx
, x
, y
, width
, height
, format
, type
, pack
,
268 static void do_draw_pix( GLcontext
*ctx
,
269 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
274 intelContextPtr intel
= INTEL_CONTEXT(ctx
);
275 __DRIdrawablePrivate
*dPriv
= intel
->driDrawable
;
276 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
277 int nbox
= dPriv
->numClipRects
;
280 int src_offset
= intelAgpOffsetFromVirtual( intel
, pixels
);
281 int src_pitch
= pitch
;
283 if (INTEL_DEBUG
& DEBUG_PIXEL
)
284 fprintf(stderr
, "%s\n", __FUNCTION__
);
286 intelFlush( &intel
->ctx
);
287 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
;