1 /* $XFree86: xc/lib/GL/mesa/src/drv/r200/r200_pixel.c,v 1.2 2002/12/16 16:18:54 dawes Exp $ */
3 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
5 The Weather Channel (TM) funded Tungsten Graphics to develop the
6 initial release of the Radeon 8500 driver under the XFree86 license.
7 This notice must be preserved.
9 Permission is hereby granted, free of charge, to any person obtaining
10 a copy of this software and associated documentation files (the
11 "Software"), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sublicense, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial
19 portions of the Software.
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
25 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 * Keith Whitwell <keith@tungstengraphics.com>
39 #include "swrast/swrast.h"
41 #include "r200_context.h"
42 #include "r200_ioctl.h"
43 #include "r200_pixel.h"
44 #include "r200_swtcl.h"
46 #include "drirenderbuffer.h"
50 check_color( const GLcontext
*ctx
, GLenum type
, GLenum format
,
51 const struct gl_pixelstore_attrib
*packing
,
52 const void *pixels
, GLint sz
, GLint pitch
)
54 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
55 GLuint cpp
= rmesa
->r200Screen
->cpp
;
57 if (R200_DEBUG
& DEBUG_PIXEL
)
58 fprintf(stderr
, "%s\n", __FUNCTION__
);
61 ctx
->_ImageTransferState
||
64 if (R200_DEBUG
& DEBUG_PIXEL
)
65 fprintf(stderr
, "%s: failed 1\n", __FUNCTION__
);
69 if ( type
== GL_UNSIGNED_INT_8_8_8_8_REV
&&
72 if (R200_DEBUG
& DEBUG_PIXEL
)
73 fprintf(stderr
, "%s: passed 2\n", __FUNCTION__
);
77 if (R200_DEBUG
& DEBUG_PIXEL
)
78 fprintf(stderr
, "%s: failed\n", __FUNCTION__
);
84 check_color_per_fragment_ops( const GLcontext
*ctx
)
87 result
= (!( ctx
->Color
.AlphaEnabled
||
90 ctx
->Scissor
.Enabled
||
91 ctx
->Stencil
.Enabled
||
92 !ctx
->Color
.ColorMask
[0] ||
93 !ctx
->Color
.ColorMask
[1] ||
94 !ctx
->Color
.ColorMask
[2] ||
95 !ctx
->Color
.ColorMask
[3] ||
96 ctx
->Color
.ColorLogicOpEnabled
||
97 ctx
->Texture
._EnabledUnits
99 ctx
->Current
.RasterPosValid
);
107 clip_pixelrect( const GLcontext
*ctx
,
108 const GLframebuffer
*buffer
,
110 GLsizei
*width
, GLsizei
*height
,
113 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
116 if (*x
< buffer
->_Xmin
) {
117 *width
-= (buffer
->_Xmin
- *x
);
122 if (*x
+ *width
> buffer
->_Xmax
)
123 *width
-= (*x
+ *width
- buffer
->_Xmax
- 1);
128 /* bottom clipping */
129 if (*y
< buffer
->_Ymin
) {
130 *height
-= (buffer
->_Ymin
- *y
);
135 if (*y
+ *height
> buffer
->_Ymax
)
136 *height
-= (*y
+ *height
- buffer
->_Ymax
- 1);
141 *size
= ((*y
+ *height
- 1) * rmesa
->r200Screen
->frontPitch
+
142 (*x
+ *width
- 1) * rmesa
->r200Screen
->cpp
);
148 r200TryReadPixels( GLcontext
*ctx
,
149 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
150 GLenum format
, GLenum type
,
151 const struct gl_pixelstore_attrib
*pack
,
154 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
155 GLint pitch
= pack
->RowLength
? pack
->RowLength
: width
;
157 GLuint cpp
= rmesa
->r200Screen
->cpp
;
158 GLint size
= width
* height
* cpp
;
160 if (R200_DEBUG
& DEBUG_PIXEL
)
161 fprintf(stderr
, "%s\n", __FUNCTION__
);
163 /* Only accelerate reading to GART buffers.
165 if ( !r200IsGartMemory(rmesa
, pixels
,
166 pitch
* height
* rmesa
->r200Screen
->cpp
) ) {
167 if (R200_DEBUG
& DEBUG_PIXEL
)
168 fprintf(stderr
, "%s: dest not GART\n", __FUNCTION__
);
172 /* Need GL_PACK_INVERT_MESA to cope with upsidedown results from
176 if (R200_DEBUG
& DEBUG_PIXEL
)
177 fprintf(stderr
, "%s: MESA_PACK_INVERT not set\n", __FUNCTION__
);
181 if (!check_color(ctx
, type
, format
, pack
, pixels
, size
, pitch
))
184 switch ( rmesa
->r200Screen
->cpp
) {
186 blit_format
= R200_CP_COLOR_FORMAT_ARGB8888
;
193 /* Although the blits go on the command buffer, need to do this and
194 * fire with lock held to guarentee cliprects and drawOffset are
197 * This is an unusual situation however, as the code which flushes
198 * a full command buffer expects to be called unlocked. As a
199 * workaround, immediately flush the buffer on aquiring the lock.
201 LOCK_HARDWARE( rmesa
);
203 if (rmesa
->store
.cmd_used
)
204 r200FlushCmdBufLocked( rmesa
, __FUNCTION__
);
206 if (!clip_pixelrect(ctx
, ctx
->ReadBuffer
, &x
, &y
, &width
, &height
,
208 UNLOCK_HARDWARE( rmesa
);
209 if (R200_DEBUG
& DEBUG_PIXEL
)
210 fprintf(stderr
, "%s totally clipped -- nothing to do\n",
216 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
217 driRenderbuffer
*drb
= (driRenderbuffer
*) ctx
->ReadBuffer
->_ColorReadBuffer
;
218 int nbox
= dPriv
->numClipRects
;
219 int src_offset
= drb
->offset
220 + rmesa
->r200Screen
->fbLocation
;
221 int src_pitch
= drb
->pitch
* drb
->cpp
;
222 int dst_offset
= r200GartOffsetFromVirtual( rmesa
, pixels
);
223 int dst_pitch
= pitch
* rmesa
->r200Screen
->cpp
;
224 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
227 r200EmitWait( rmesa
, RADEON_WAIT_3D
);
229 y
= dPriv
->h
- y
- height
;
234 if (R200_DEBUG
& DEBUG_PIXEL
)
235 fprintf(stderr
, "readpixel blit src_pitch %d dst_pitch %d\n",
236 src_pitch
, dst_pitch
);
238 for (i
= 0 ; i
< nbox
; i
++)
240 GLint bx
= box
[i
].x1
;
241 GLint by
= box
[i
].y1
;
242 GLint bw
= box
[i
].x2
- bx
;
243 GLint bh
= box
[i
].y2
- by
;
245 if (bx
< x
) bw
-= x
- bx
, bx
= x
;
246 if (by
< y
) bh
-= y
- by
, by
= y
;
247 if (bx
+ bw
> x
+ width
) bw
= x
+ width
- bx
;
248 if (by
+ bh
> y
+ height
) bh
= y
+ height
- by
;
249 if (bw
<= 0) continue;
250 if (bh
<= 0) continue;
254 src_pitch
, src_offset
,
255 dst_pitch
, dst_offset
,
261 r200FlushCmdBufLocked( rmesa
, __FUNCTION__
);
263 UNLOCK_HARDWARE( rmesa
);
265 r200Finish( ctx
); /* required by GL */
271 r200ReadPixels( GLcontext
*ctx
,
272 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
273 GLenum format
, GLenum type
,
274 const struct gl_pixelstore_attrib
*pack
,
277 if (R200_DEBUG
& DEBUG_PIXEL
)
278 fprintf(stderr
, "%s\n", __FUNCTION__
);
280 if (!r200TryReadPixels( ctx
, x
, y
, width
, height
, format
, type
, pack
,
282 _swrast_ReadPixels( ctx
, x
, y
, width
, height
, format
, type
, pack
,
289 static void do_draw_pix( GLcontext
*ctx
,
290 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
295 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
296 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
297 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
298 struct gl_renderbuffer
*rb
= ctx
->ReadBuffer
->_ColorDrawBuffers
[0][0];
299 driRenderbuffer
*drb
= (driRenderbuffer
*) rb
;
300 int nbox
= dPriv
->numClipRects
;
304 int src_offset
= r200GartOffsetFromVirtual( rmesa
, pixels
);
305 int src_pitch
= pitch
* rmesa
->r200Screen
->cpp
;
307 if (R200_DEBUG
& DEBUG_PIXEL
)
308 fprintf(stderr
, "%s\n", __FUNCTION__
);
310 switch ( rmesa
->r200Screen
->cpp
) {
312 blit_format
= R200_CP_COLOR_FORMAT_RGB565
;
315 blit_format
= R200_CP_COLOR_FORMAT_ARGB8888
;
322 LOCK_HARDWARE( rmesa
);
324 if (rmesa
->store
.cmd_used
)
325 r200FlushCmdBufLocked( rmesa
, __FUNCTION__
);
327 y
-= height
; /* cope with pixel zoom */
329 if (!clip_pixelrect(ctx
, ctx
->DrawBuffer
,
330 &x
, &y
, &width
, &height
,
332 UNLOCK_HARDWARE( rmesa
);
336 y
= dPriv
->h
- y
- height
; /* convert from gl to hardware coords */
341 r200EmitWait( rmesa
, RADEON_WAIT_3D
);
343 for (i
= 0 ; i
< nbox
; i
++ )
345 GLint bx
= box
[i
].x1
;
346 GLint by
= box
[i
].y1
;
347 GLint bw
= box
[i
].x2
- bx
;
348 GLint bh
= box
[i
].y2
- by
;
350 if (bx
< x
) bw
-= x
- bx
, bx
= x
;
351 if (by
< y
) bh
-= y
- by
, by
= y
;
352 if (bx
+ bw
> x
+ width
) bw
= x
+ width
- bx
;
353 if (by
+ bh
> y
+ height
) bh
= y
+ height
- by
;
354 if (bw
<= 0) continue;
355 if (bh
<= 0) continue;
359 src_pitch
, src_offset
,
360 drb
->pitch
* drb
->cpp
,
361 drb
->offset
+ rmesa
->r200Screen
->fbLocation
,
367 r200FlushCmdBufLocked( rmesa
, __FUNCTION__
);
368 r200WaitForIdleLocked( rmesa
); /* required by GL */
369 UNLOCK_HARDWARE( rmesa
);
376 r200TryDrawPixels( GLcontext
*ctx
,
377 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
378 GLenum format
, GLenum type
,
379 const struct gl_pixelstore_attrib
*unpack
,
380 const GLvoid
*pixels
)
382 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
383 GLint pitch
= unpack
->RowLength
? unpack
->RowLength
: width
;
385 GLuint cpp
= rmesa
->r200Screen
->cpp
;
386 GLint size
= width
* pitch
* cpp
;
388 if (R200_DEBUG
& DEBUG_PIXEL
)
389 fprintf(stderr
, "%s\n", __FUNCTION__
);
391 /* check that we're drawing to exactly one color buffer */
392 if (ctx
->DrawBuffer
->_NumColorDrawBuffers
[0] != 1)
399 planemask
= r200PackColor(cpp
,
400 ctx
->Color
.ColorMask
[RCOMP
],
401 ctx
->Color
.ColorMask
[GCOMP
],
402 ctx
->Color
.ColorMask
[BCOMP
],
403 ctx
->Color
.ColorMask
[ACOMP
]);
406 planemask
|= planemask
<< 16;
409 return GL_FALSE
; /* fix me -- should be possible */
411 /* Can't do conversions on GART reads/draws.
413 if ( !r200IsGartMemory( rmesa
, pixels
, size
) ) {
414 if (R200_DEBUG
& DEBUG_PIXEL
)
415 fprintf(stderr
, "%s: not GART memory\n", __FUNCTION__
);
419 if (!check_color(ctx
, type
, format
, unpack
, pixels
, size
, pitch
)) {
422 if (!check_color_per_fragment_ops(ctx
)) {
426 if (ctx
->Pixel
.ZoomX
!= 1.0F
||
427 ctx
->Pixel
.ZoomY
!= -1.0F
)
435 if ( r200IsGartMemory(rmesa
, pixels
, size
) )
437 do_draw_pix( ctx
, x
, y
, width
, height
, pitch
, pixels
, planemask
);
442 /* Pixels is in regular memory -- get dma buffers and perform
443 * upload through them.
451 r200DrawPixels( GLcontext
*ctx
,
452 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
453 GLenum format
, GLenum type
,
454 const struct gl_pixelstore_attrib
*unpack
,
455 const GLvoid
*pixels
)
457 if (R200_DEBUG
& DEBUG_PIXEL
)
458 fprintf(stderr
, "%s\n", __FUNCTION__
);
460 if (!r200TryDrawPixels( ctx
, x
, y
, width
, height
, format
, type
,
462 _swrast_DrawPixels( ctx
, x
, y
, width
, height
, format
, type
,
468 r200Bitmap( GLcontext
*ctx
, GLint px
, GLint py
,
469 GLsizei width
, GLsizei height
,
470 const struct gl_pixelstore_attrib
*unpack
,
471 const GLubyte
*bitmap
)
473 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
476 _swrast_Bitmap( ctx
, px
, py
, width
, height
, unpack
, bitmap
);
478 r200PointsBitmap( ctx
, px
, py
, width
, height
, unpack
, bitmap
);
483 void r200InitPixelFuncs( GLcontext
*ctx
)
485 /* Pixel path fallbacks.
487 ctx
->Driver
.Accum
= _swrast_Accum
;
488 ctx
->Driver
.Bitmap
= _swrast_Bitmap
;
489 ctx
->Driver
.CopyPixels
= _swrast_CopyPixels
;
490 ctx
->Driver
.DrawPixels
= _swrast_DrawPixels
;
491 ctx
->Driver
.ReadPixels
= _swrast_ReadPixels
;
493 if (!getenv("R200_NO_BLITS") && R200_CONTEXT(ctx
)->dri
.drmMinor
>= 6) {
494 ctx
->Driver
.ReadPixels
= r200ReadPixels
;
495 ctx
->Driver
.DrawPixels
= r200DrawPixels
;
496 if (getenv("R200_HW_BITMAP"))
497 ctx
->Driver
.Bitmap
= r200Bitmap
;