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 **************************************************************************/
33 #include "intel_fbo.h"
34 #include "intel_screen.h"
35 #include "intel_span.h"
36 #include "intel_regions.h"
37 #include "intel_ioctl.h"
38 #include "intel_tex.h"
40 #include "swrast/swrast.h"
43 * Deal with tiled surfaces
47 /* These are pre-965 tile swizzling functions -- power of two widths */
48 static uintptr_t x_tile_swizzle_pow2 (uintptr_t addr
, int n
)
51 uintptr_t base_mask
= (((~0) << (n
+ 4)) | 0xff);
52 uintptr_t x_mask
= ((~0) << 12) & ~base_mask
;
54 a
= ((a
& base_mask
) |
55 ((a
>> (n
-8)) & 0x7) |
57 _mesa_printf ("x_swizzle %08x (base %x yrow %x tile#x %x xsword %x byte %x) %08x\n",
60 (addr
>> (n
+ 1)) & 0x7,
61 (addr
>> 9) & ((1 << (n
-8)) - 1),
68 static uintptr_t y_tile_swizzle_pow2 (uintptr_t addr
, int n
)
70 uintptr_t a
= (uintptr_t) addr
;
71 uintptr_t base_mask
= (((~0) << (n
+ 6)) | 0xf);
72 uintptr_t x_mask
= ((~0) << 9) & ~base_mask
;
74 a
= ((a
& base_mask
) |
75 ((a
>> (n
-3)) & 0x1f) |
77 _mesa_printf ("y_swizzle %08x (base %x yrow %x tile#x %x xoword %x byte %x) %08x\n",
80 (addr
>> (n
+ 1)) & 0x01f,
81 (addr
>> 7) & ((1 << (n
-6)) - 1),
89 static GLubyte
*x_tile_swizzle(struct intel_renderbuffer
*irb
, struct intel_context
*intel
,
92 GLubyte
*buf
= (GLubyte
*) irb
->pfMap
;
95 int x_tile_off
, y_tile_off
;
96 int x_tile_number
, y_tile_number
;
97 int tile_off
, tile_base
;
99 tile_stride
= (irb
->pfPitch
* irb
->region
->cpp
) << 3;
104 xbyte
= x
* irb
->region
->cpp
;
106 x_tile_off
= xbyte
& 0x1ff;
109 x_tile_number
= xbyte
>> 9;
110 y_tile_number
= y
>> 3;
112 tile_off
= (y_tile_off
<< 9) + x_tile_off
;
113 tile_base
= (x_tile_number
<< 12) + y_tile_number
* tile_stride
;
115 return buf
+ tile_base
+ tile_off
;
118 static GLubyte
*y_tile_swizzle(struct intel_renderbuffer
*irb
, struct intel_context
*intel
,
121 GLubyte
*buf
= (GLubyte
*) irb
->pfMap
;
124 int x_tile_off
, y_tile_off
;
125 int x_tile_number
, y_tile_number
;
126 int tile_off
, tile_base
;
128 tile_stride
= (irb
->pfPitch
* irb
->region
->cpp
) << 3;
133 xbyte
= x
* irb
->region
->cpp
;
135 x_tile_off
= xbyte
& 0x7f;
136 y_tile_off
= y
& 0x1f;
138 x_tile_number
= xbyte
>> 7;
139 y_tile_number
= y
>> 5;
141 tile_off
= ((x_tile_off
& ~0xf) << 5) + (y_tile_off
<< 4) + (x_tile_off
& 0xf);
142 tile_base
= (x_tile_number
<< 12) + y_tile_number
* tile_stride
;
144 return buf
+ tile_base
+ tile_off
;
148 break intelWriteRGBASpan_ARGB8888
155 struct intel_context *intel = intel_context(ctx); \
156 struct intel_renderbuffer *irb = intel_renderbuffer(rb); \
157 const GLint yScale = irb->RenderToTexture ? 1 : -1; \
158 const GLint yBias = irb->RenderToTexture ? 0 : irb->Base.Height - 1; \
159 GLubyte *buf = (GLubyte *) irb->pfMap \
160 + (intel->drawY * irb->pfPitch + intel->drawX) * irb->region->cpp;\
163 (void) p; (void) buf;
165 /* XXX FBO: this is identical to the macro in spantmp2.h except we get
166 * the cliprect info from the context, not the driDrawable.
167 * Move this into spantmp2.h someday.
169 #define HW_CLIPLOOP() \
171 int _nc = intel->numClipRects; \
173 int minx = intel->pClipRects[_nc].x1 - intel->drawX; \
174 int miny = intel->pClipRects[_nc].y1 - intel->drawY; \
175 int maxx = intel->pClipRects[_nc].x2 - intel->drawX; \
176 int maxy = intel->pClipRects[_nc].y2 - intel->drawY;
182 #define Y_FLIP(_y) ((_y) * yScale + yBias)
184 /* XXX with GEM, these need to tell the kernel */
189 /* 16 bit, RGB565 color spanline and pixel functions
191 #define SPANTMP_PIXEL_FMT GL_RGB
192 #define SPANTMP_PIXEL_TYPE GL_UNSIGNED_SHORT_5_6_5
194 #define TAG(x) intel##x##_RGB565
195 #define TAG2(x,y) intel##x##_RGB565##y
196 #define GET_PTR(X,Y) (buf + ((Y) * irb->pfPitch + (X)) * 2)
197 #include "spantmp2.h"
199 /* 32 bit, ARGB8888 color spanline and pixel functions
201 #define SPANTMP_PIXEL_FMT GL_BGRA
202 #define SPANTMP_PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8_REV
204 #define TAG(x) intel##x##_ARGB8888
205 #define TAG2(x,y) intel##x##_ARGB8888##y
206 #define GET_PTR(X,Y) (buf + ((Y) * irb->pfPitch + (X)) * 4)
207 #include "spantmp2.h"
209 /* 16 bit RGB565 color tile spanline and pixel functions
212 #define SPANTMP_PIXEL_FMT GL_RGB
213 #define SPANTMP_PIXEL_TYPE GL_UNSIGNED_SHORT_5_6_5
215 #define TAG(x) intel_XTile_##x##_RGB565
216 #define TAG2(x,y) intel_XTile_##x##_RGB565##y
217 #define GET_PTR(X,Y) x_tile_swizzle(irb, intel, X, Y)
218 #include "spantmp2.h"
220 #define SPANTMP_PIXEL_FMT GL_RGB
221 #define SPANTMP_PIXEL_TYPE GL_UNSIGNED_SHORT_5_6_5
223 #define TAG(x) intel_YTile_##x##_RGB565
224 #define TAG2(x,y) intel_YTile_##x##_RGB565##y
225 #define GET_PTR(X,Y) y_tile_swizzle(irb, intel, X, Y)
226 #include "spantmp2.h"
228 /* 32 bit ARGB888 color tile spanline and pixel functions
231 #define SPANTMP_PIXEL_FMT GL_BGRA
232 #define SPANTMP_PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8_REV
234 #define TAG(x) intel_XTile_##x##_ARGB8888
235 #define TAG2(x,y) intel_XTile_##x##_ARGB8888##y
236 #define GET_PTR(X,Y) x_tile_swizzle(irb, intel, X, Y)
237 #include "spantmp2.h"
239 #define SPANTMP_PIXEL_FMT GL_BGRA
240 #define SPANTMP_PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8_REV
242 #define TAG(x) intel_YTile_##x##_ARGB8888
243 #define TAG2(x,y) intel_YTile_##x##_ARGB8888##y
244 #define GET_PTR(X,Y) y_tile_swizzle(irb, intel, X, Y)
245 #include "spantmp2.h"
247 #define LOCAL_DEPTH_VARS \
248 struct intel_context *intel = intel_context(ctx); \
249 struct intel_renderbuffer *irb = intel_renderbuffer(rb); \
250 const GLuint pitch = irb->pfPitch/***XXX region->pitch*/; /* in pixels */ \
251 const GLint yScale = irb->RenderToTexture ? 1 : -1; \
252 const GLint yBias = irb->RenderToTexture ? 0 : irb->Base.Height - 1; \
253 char *buf = (char *) irb->pfMap/*XXX use region->map*/ + \
254 (intel->drawY * pitch + intel->drawX) * irb->region->cpp; (void) buf;
257 #define LOCAL_STENCIL_VARS LOCAL_DEPTH_VARS
260 ** 16-bit depthbuffer functions.
262 #define WRITE_DEPTH( _x, _y, d ) \
263 ((GLushort *)buf)[(_x) + (_y) * pitch] = d;
265 #define READ_DEPTH( d, _x, _y ) \
266 d = ((GLushort *)buf)[(_x) + (_y) * pitch];
269 #define TAG(x) intel##x##_z16
270 #include "depthtmp.h"
274 ** 16-bit x tile depthbuffer functions.
276 #define WRITE_DEPTH( _x, _y, d ) \
277 (*((GLushort *)x_tile_swizzle (irb, intel, _x, _y)) = d)
279 #define READ_DEPTH( d, _x, _y ) \
280 d = *((GLushort *)x_tile_swizzle (irb, intel, _x, _y))
283 #define TAG(x) intel_XTile_##x##_z16
284 #include "depthtmp.h"
287 ** 16-bit y tile depthbuffer functions.
289 #define WRITE_DEPTH( _x, _y, d ) \
290 (*((GLushort *)y_tile_swizzle (irb, intel, _x, _y)) = d)
292 #define READ_DEPTH( d, _x, _y ) \
293 (d = *((GLushort *)y_tile_swizzle (irb, intel, _x, _y)))
296 #define TAG(x) intel_YTile_##x##_z16
297 #include "depthtmp.h"
301 ** 24/8-bit interleaved depth/stencil functions
302 ** Note: we're actually reading back combined depth+stencil values.
303 ** The wrappers in main/depthstencil.c are used to extract the depth
304 ** and stencil values.
306 /* Change ZZZS -> SZZZ */
307 #define WRITE_DEPTH( _x, _y, d ) { \
308 GLuint tmp = ((d) >> 8) | ((d) << 24); \
309 ((GLuint *)buf)[(_x) + (_y) * pitch] = tmp; \
312 /* Change SZZZ -> ZZZS */
313 #define READ_DEPTH( d, _x, _y ) { \
314 GLuint tmp = ((GLuint *)buf)[(_x) + (_y) * pitch]; \
315 d = (tmp << 8) | (tmp >> 24); \
318 #define TAG(x) intel##x##_z24_s8
319 #include "depthtmp.h"
323 ** 24/8-bit x-tile interleaved depth/stencil functions
324 ** Note: we're actually reading back combined depth+stencil values.
325 ** The wrappers in main/depthstencil.c are used to extract the depth
326 ** and stencil values.
328 /* Change ZZZS -> SZZZ */
329 #define WRITE_DEPTH( _x, _y, d ) { \
330 GLuint tmp = ((d) >> 8) | ((d) << 24); \
331 *((GLuint *)x_tile_swizzle (irb, intel, _x, _y)) = tmp; \
334 /* Change SZZZ -> ZZZS */
335 #define READ_DEPTH( d, _x, _y ) { \
336 GLuint tmp = *((GLuint *)x_tile_swizzle (irb, intel, _x, _y)); \
337 d = (tmp << 8) | (tmp >> 24); \
340 #define TAG(x) intel_XTile_##x##_z24_s8
341 #include "depthtmp.h"
344 ** 24/8-bit y-tile interleaved depth/stencil functions
345 ** Note: we're actually reading back combined depth+stencil values.
346 ** The wrappers in main/depthstencil.c are used to extract the depth
347 ** and stencil values.
349 /* Change ZZZS -> SZZZ */
350 #define WRITE_DEPTH( _x, _y, d ) { \
351 GLuint tmp = ((d) >> 8) | ((d) << 24); \
352 *((GLuint *)y_tile_swizzle (irb, intel, _x, _y)) = tmp; \
355 /* Change SZZZ -> ZZZS */
356 #define READ_DEPTH( d, _x, _y ) { \
357 GLuint tmp = *((GLuint *)y_tile_swizzle (irb, intel, _x, _y)); \
358 d = (tmp << 8) | (tmp >> 24); \
361 #define TAG(x) intel_YTile_##x##_z24_s8
362 #include "depthtmp.h"
366 ** 8-bit stencil function (XXX FBO: This is obsolete)
368 #define WRITE_STENCIL( _x, _y, d ) { \
369 GLuint tmp = ((GLuint *)buf)[(_x) + (_y) * pitch]; \
371 tmp |= ((d) << 24); \
372 ((GLuint *) buf)[(_x) + (_y) * pitch] = tmp; \
375 #define READ_STENCIL( d, _x, _y ) \
376 d = ((GLuint *)buf)[(_x) + (_y) * pitch] >> 24;
378 #define TAG(x) intel##x##_z24_s8
379 #include "stenciltmp.h"
382 ** 8-bit x-tile stencil function (XXX FBO: This is obsolete)
384 #define WRITE_STENCIL( _x, _y, d ) { \
385 GLuint *a = (GLuint *) x_tile_swizzle (irb, intel, _x, _y); \
388 tmp |= ((d) << 24); \
392 #define READ_STENCIL( d, _x, _y ) \
393 (d = *((GLuint*) x_tile_swizzle (irb, intel, _x, _y)) >> 24)
395 #define TAG(x) intel_XTile_##x##_z24_s8
396 #include "stenciltmp.h"
399 ** 8-bit y-tile stencil function (XXX FBO: This is obsolete)
401 #define WRITE_STENCIL( _x, _y, d ) { \
402 GLuint *a = (GLuint *) y_tile_swizzle (irb, intel, _x, _y); \
405 tmp |= ((d) << 24); \
409 #define READ_STENCIL( d, _x, _y ) \
410 (d = *((GLuint*) y_tile_swizzle (irb, intel, _x, _y)) >> 24)
412 #define TAG(x) intel_YTile_##x##_z24_s8
413 #include "stenciltmp.h"
418 * Map or unmap all the renderbuffers which we may need during
419 * software rendering.
420 * XXX in the future, we could probably convey extra information to
421 * reduce the number of mappings needed. I.e. if doing a glReadPixels
422 * from the depth buffer, we really only need one mapping.
424 * XXX Rewrite this function someday.
425 * We can probably just loop over all the renderbuffer attachments,
426 * map/unmap all of them, and not worry about the _ColorDrawBuffers
427 * _ColorReadBuffer, _DepthBuffer or _StencilBuffer fields.
430 intel_map_unmap_buffers(struct intel_context
*intel
, GLboolean map
)
432 GLcontext
*ctx
= &intel
->ctx
;
434 struct intel_renderbuffer
*irb
;
436 /* color draw buffers */
437 for (j
= 0; j
< ctx
->DrawBuffer
->_NumColorDrawBuffers
; j
++) {
438 struct gl_renderbuffer
*rb
= ctx
->DrawBuffer
->_ColorDrawBuffers
[j
];
439 irb
= intel_renderbuffer(rb
);
441 /* this is a user-created intel_renderbuffer */
444 intel_region_map(intel
, irb
->region
);
446 intel_region_unmap(intel
, irb
->region
);
447 irb
->pfMap
= irb
->region
->map
;
448 irb
->pfPitch
= irb
->region
->pitch
;
453 /* check for render to textures */
454 for (i
= 0; i
< BUFFER_COUNT
; i
++) {
455 struct gl_renderbuffer_attachment
*att
=
456 ctx
->DrawBuffer
->Attachment
+ i
;
457 struct gl_texture_object
*tex
= att
->Texture
;
459 /* render to texture */
460 ASSERT(att
->Renderbuffer
);
462 struct gl_texture_image
*texImg
;
463 texImg
= tex
->Image
[att
->CubeMapFace
][att
->TextureLevel
];
464 intel_tex_map_images(intel
, intel_texture_object(tex
));
467 intel_tex_unmap_images(intel
, intel_texture_object(tex
));
472 /* color read buffers */
473 irb
= intel_renderbuffer(ctx
->ReadBuffer
->_ColorReadBuffer
);
474 if (irb
&& irb
->region
) {
476 intel_region_map(intel
, irb
->region
);
478 intel_region_unmap(intel
, irb
->region
);
479 irb
->pfMap
= irb
->region
->map
;
480 irb
->pfPitch
= irb
->region
->pitch
;
483 /* Account for front/back color page flipping.
484 * The span routines use the pfMap and pfPitch fields which will
485 * swap the front/back region map/pitch if we're page flipped.
486 * Do this after mapping, above, so the map field is valid.
489 if (map
&& ctx
->DrawBuffer
->Name
== 0) {
490 struct intel_renderbuffer
*irbFront
491 = intel_get_renderbuffer(ctx
->DrawBuffer
, BUFFER_FRONT_LEFT
);
492 struct intel_renderbuffer
*irbBack
493 = intel_get_renderbuffer(ctx
->DrawBuffer
, BUFFER_BACK_LEFT
);
495 /* double buffered */
496 if (intel
->sarea
->pf_current_page
== 0) {
497 irbFront
->pfMap
= irbFront
->region
->map
;
498 irbFront
->pfPitch
= irbFront
->region
->pitch
;
499 irbBack
->pfMap
= irbBack
->region
->map
;
500 irbBack
->pfPitch
= irbBack
->region
->pitch
;
503 irbFront
->pfMap
= irbBack
->region
->map
;
504 irbFront
->pfPitch
= irbBack
->region
->pitch
;
505 irbBack
->pfMap
= irbFront
->region
->map
;
506 irbBack
->pfPitch
= irbFront
->region
->pitch
;
512 /* depth buffer (Note wrapper!) */
513 if (ctx
->DrawBuffer
->_DepthBuffer
) {
514 irb
= intel_renderbuffer(ctx
->DrawBuffer
->_DepthBuffer
->Wrapped
);
515 if (irb
&& irb
->region
) {
517 intel_region_map(intel
, irb
->region
);
518 irb
->pfMap
= irb
->region
->map
;
519 irb
->pfPitch
= irb
->region
->pitch
;
522 intel_region_unmap(intel
, irb
->region
);
523 irb
->pfMap
= irb
->region
->map
;
524 irb
->pfPitch
= irb
->region
->pitch
;
529 /* stencil buffer (Note wrapper!) */
530 if (ctx
->DrawBuffer
->_StencilBuffer
) {
531 irb
= intel_renderbuffer(ctx
->DrawBuffer
->_StencilBuffer
->Wrapped
);
532 if (irb
&& irb
->region
) {
534 intel_region_map(intel
, irb
->region
);
535 irb
->pfMap
= irb
->region
->map
;
536 irb
->pfPitch
= irb
->region
->pitch
;
539 intel_region_unmap(intel
, irb
->region
);
540 irb
->pfMap
= irb
->region
->map
;
541 irb
->pfPitch
= irb
->region
->pitch
;
550 * Prepare for softare rendering. Map current read/draw framebuffers'
551 * renderbuffes and all currently bound texture objects.
553 * Old note: Moved locking out to get reasonable span performance.
556 intelSpanRenderStart(GLcontext
* ctx
)
558 struct intel_context
*intel
= intel_context(ctx
);
561 intelFinish(&intel
->ctx
);
562 LOCK_HARDWARE(intel
);
565 /* Just map the framebuffer and all textures. Bufmgr code will
566 * take care of waiting on the necessary fences:
568 intel_region_map(intel
, intel
->front_region
);
569 intel_region_map(intel
, intel
->back_region
);
570 intel_region_map(intel
, intel
->depth_region
);
573 for (i
= 0; i
< ctx
->Const
.MaxTextureCoordUnits
; i
++) {
574 if (ctx
->Texture
.Unit
[i
]._ReallyEnabled
) {
575 struct gl_texture_object
*texObj
= ctx
->Texture
.Unit
[i
]._Current
;
576 intel_tex_map_images(intel
, intel_texture_object(texObj
));
580 intel_map_unmap_buffers(intel
, GL_TRUE
);
584 * Called when done softare rendering. Unmap the buffers we mapped in
585 * the above function.
588 intelSpanRenderFinish(GLcontext
* ctx
)
590 struct intel_context
*intel
= intel_context(ctx
);
595 /* Now unmap the framebuffer:
598 intel_region_unmap(intel
, intel
->front_region
);
599 intel_region_unmap(intel
, intel
->back_region
);
600 intel_region_unmap(intel
, intel
->depth_region
);
603 for (i
= 0; i
< ctx
->Const
.MaxTextureCoordUnits
; i
++) {
604 if (ctx
->Texture
.Unit
[i
]._ReallyEnabled
) {
605 struct gl_texture_object
*texObj
= ctx
->Texture
.Unit
[i
]._Current
;
606 intel_tex_unmap_images(intel
, intel_texture_object(texObj
));
610 intel_map_unmap_buffers(intel
, GL_FALSE
);
612 UNLOCK_HARDWARE(intel
);
617 intelInitSpanFuncs(GLcontext
* ctx
)
619 struct swrast_device_driver
*swdd
= _swrast_GetDeviceDriverReference(ctx
);
620 swdd
->SpanRenderStart
= intelSpanRenderStart
;
621 swdd
->SpanRenderFinish
= intelSpanRenderFinish
;
626 * Plug in appropriate span read/write functions for the given renderbuffer.
627 * These are used for the software fallbacks.
630 intel_set_span_functions(struct gl_renderbuffer
*rb
, int tiling
)
632 if (rb
->_ActualFormat
== GL_RGB5
) {
635 case INTEL_TILE_NONE
:
637 intelInitPointers_RGB565(rb
);
640 intel_XTile_InitPointers_RGB565(rb
);
643 intel_YTile_InitPointers_RGB565(rb
);
647 else if (rb
->_ActualFormat
== GL_RGBA8
) {
650 case INTEL_TILE_NONE
:
652 intelInitPointers_ARGB8888(rb
);
655 intel_XTile_InitPointers_ARGB8888(rb
);
658 intel_YTile_InitPointers_ARGB8888(rb
);
662 else if (rb
->_ActualFormat
== GL_DEPTH_COMPONENT16
) {
664 case INTEL_TILE_NONE
:
666 intelInitDepthPointers_z16(rb
);
669 intel_XTile_InitDepthPointers_z16(rb
);
672 intel_YTile_InitDepthPointers_z16(rb
);
676 else if (rb
->_ActualFormat
== GL_DEPTH_COMPONENT24
|| /* XXX FBO remove */
677 rb
->_ActualFormat
== GL_DEPTH24_STENCIL8_EXT
) {
679 case INTEL_TILE_NONE
:
681 intelInitDepthPointers_z24_s8(rb
);
684 intel_XTile_InitDepthPointers_z24_s8(rb
);
687 intel_YTile_InitDepthPointers_z24_s8(rb
);
691 else if (rb
->_ActualFormat
== GL_STENCIL_INDEX8_EXT
) {
693 case INTEL_TILE_NONE
:
695 intelInitStencilPointers_z24_s8(rb
);
698 intel_XTile_InitStencilPointers_z24_s8(rb
);
701 intel_YTile_InitStencilPointers_z24_s8(rb
);
707 "Unexpected _ActualFormat in intelSetSpanFunctions");