Merge branch 'mesa_7_7_branch'
[mesa.git] / src / mesa / drivers / dri / radeon / radeon_fbo.c
1 /**************************************************************************
2 *
3 * Copyright 2008 Red Hat Inc.
4 * All Rights Reserved.
5 *
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:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
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.
25 *
26 **************************************************************************/
27
28
29 #include "main/imports.h"
30 #include "main/macros.h"
31 #include "main/mtypes.h"
32 #include "main/fbobject.h"
33 #include "main/framebuffer.h"
34 #include "main/renderbuffer.h"
35 #include "main/context.h"
36 #include "main/texrender.h"
37 #include "drivers/common/meta.h"
38
39 #include "radeon_common.h"
40 #include "radeon_mipmap_tree.h"
41
42 #define FILE_DEBUG_FLAG RADEON_TEXTURE
43 #define DBG(...) do { \
44 if (RADEON_DEBUG & FILE_DEBUG_FLAG) \
45 _mesa_printf(__VA_ARGS__); \
46 } while(0)
47
48 static struct gl_framebuffer *
49 radeon_new_framebuffer(GLcontext *ctx, GLuint name)
50 {
51 return _mesa_new_framebuffer(ctx, name);
52 }
53
54 static void
55 radeon_delete_renderbuffer(struct gl_renderbuffer *rb)
56 {
57 struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
58
59 ASSERT(rrb);
60
61 if (rrb && rrb->bo) {
62 radeon_bo_unref(rrb->bo);
63 }
64 _mesa_free(rrb);
65 }
66
67 static void *
68 radeon_get_pointer(GLcontext *ctx, struct gl_renderbuffer *rb,
69 GLint x, GLint y)
70 {
71 return NULL;
72 }
73
74 /**
75 * Called via glRenderbufferStorageEXT() to set the format and allocate
76 * storage for a user-created renderbuffer.
77 */
78 static GLboolean
79 radeon_alloc_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
80 GLenum internalFormat,
81 GLuint width, GLuint height)
82 {
83 struct radeon_context *radeon = RADEON_CONTEXT(ctx);
84 struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
85 GLboolean software_buffer = GL_FALSE;
86 int cpp;
87
88 ASSERT(rb->Name != 0);
89 switch (internalFormat) {
90 case GL_R3_G3_B2:
91 case GL_RGB4:
92 case GL_RGB5:
93 rb->Format = _dri_texformat_rgb565;
94 rb->DataType = GL_UNSIGNED_BYTE;
95 cpp = 2;
96 break;
97 case GL_RGB:
98 case GL_RGB8:
99 case GL_RGB10:
100 case GL_RGB12:
101 case GL_RGB16:
102 rb->Format = _dri_texformat_argb8888;
103 rb->DataType = GL_UNSIGNED_BYTE;
104 cpp = 4;
105 break;
106 case GL_RGBA:
107 case GL_RGBA2:
108 case GL_RGBA4:
109 case GL_RGB5_A1:
110 case GL_RGBA8:
111 case GL_RGB10_A2:
112 case GL_RGBA12:
113 case GL_RGBA16:
114 rb->Format = _dri_texformat_argb8888;
115 rb->DataType = GL_UNSIGNED_BYTE;
116 cpp = 4;
117 break;
118 case GL_STENCIL_INDEX:
119 case GL_STENCIL_INDEX1_EXT:
120 case GL_STENCIL_INDEX4_EXT:
121 case GL_STENCIL_INDEX8_EXT:
122 case GL_STENCIL_INDEX16_EXT:
123 /* alloc a depth+stencil buffer */
124 rb->Format = MESA_FORMAT_S8_Z24;
125 rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
126 cpp = 4;
127 break;
128 case GL_DEPTH_COMPONENT16:
129 rb->Format = MESA_FORMAT_Z16;
130 rb->DataType = GL_UNSIGNED_SHORT;
131 cpp = 2;
132 break;
133 case GL_DEPTH_COMPONENT:
134 case GL_DEPTH_COMPONENT24:
135 case GL_DEPTH_COMPONENT32:
136 rb->Format = MESA_FORMAT_X8_Z24;
137 rb->DataType = GL_UNSIGNED_INT;
138 cpp = 4;
139 break;
140 case GL_DEPTH_STENCIL_EXT:
141 case GL_DEPTH24_STENCIL8_EXT:
142 rb->Format = MESA_FORMAT_S8_Z24;
143 rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
144 cpp = 4;
145 break;
146 default:
147 _mesa_problem(ctx,
148 "Unexpected format in radeon_alloc_renderbuffer_storage");
149 return GL_FALSE;
150 }
151
152 rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat);
153
154 if (ctx->Driver.Flush)
155 ctx->Driver.Flush(ctx); /* +r6/r7 */
156
157 if (rrb->bo)
158 radeon_bo_unref(rrb->bo);
159
160
161 if (software_buffer) {
162 return _mesa_soft_renderbuffer_storage(ctx, rb, internalFormat,
163 width, height);
164 }
165 else {
166 uint32_t size;
167 uint32_t pitch = ((cpp * width + 63) & ~63) / cpp;
168
169 if (RADEON_DEBUG & RADEON_MEMORY)
170 fprintf(stderr,"Allocating %d x %d radeon RBO (pitch %d)\n", width,
171 height, pitch);
172
173 size = pitch * height * cpp;
174 rrb->pitch = pitch * cpp;
175 rrb->cpp = cpp;
176 rrb->bo = radeon_bo_open(radeon->radeonScreen->bom,
177 0,
178 size,
179 0,
180 RADEON_GEM_DOMAIN_VRAM,
181 0);
182 rb->Width = width;
183 rb->Height = height;
184 return GL_TRUE;
185 }
186
187 }
188
189
190 /**
191 * Called for each hardware renderbuffer when a _window_ is resized.
192 * Just update fields.
193 * Not used for user-created renderbuffers!
194 */
195 static GLboolean
196 radeon_alloc_window_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
197 GLenum internalFormat, GLuint width, GLuint height)
198 {
199 ASSERT(rb->Name == 0);
200 rb->Width = width;
201 rb->Height = height;
202 rb->InternalFormat = internalFormat;
203
204 return GL_TRUE;
205 }
206
207
208 static void
209 radeon_resize_buffers(GLcontext *ctx, struct gl_framebuffer *fb,
210 GLuint width, GLuint height)
211 {
212 struct radeon_framebuffer *radeon_fb = (struct radeon_framebuffer*)fb;
213 int i;
214
215 _mesa_resize_framebuffer(ctx, fb, width, height);
216
217 fb->Initialized = GL_TRUE; /* XXX remove someday */
218
219 if (fb->Name != 0) {
220 return;
221 }
222
223 /* Make sure all window system renderbuffers are up to date */
224 for (i = 0; i < 2; i++) {
225 struct gl_renderbuffer *rb = &radeon_fb->color_rb[i]->base;
226
227 /* only resize if size is changing */
228 if (rb && (rb->Width != width || rb->Height != height)) {
229 rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height);
230 }
231 }
232 }
233
234
235 /** Dummy function for gl_renderbuffer::AllocStorage() */
236 static GLboolean
237 radeon_nop_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
238 GLenum internalFormat, GLuint width, GLuint height)
239 {
240 _mesa_problem(ctx, "radeon_op_alloc_storage should never be called.");
241 return GL_FALSE;
242 }
243
244
245 /**
246 * Create a renderbuffer for a window's color, depth and/or stencil buffer.
247 * Not used for user-created renderbuffers.
248 */
249 struct radeon_renderbuffer *
250 radeon_create_renderbuffer(gl_format format, __DRIdrawable *driDrawPriv)
251 {
252 struct radeon_renderbuffer *rrb;
253
254 rrb = CALLOC_STRUCT(radeon_renderbuffer);
255 if (!rrb)
256 return NULL;
257
258 _mesa_init_renderbuffer(&rrb->base, 0);
259 rrb->base.ClassID = RADEON_RB_CLASS;
260
261 rrb->base.Format = format;
262
263 switch (format) {
264 case MESA_FORMAT_RGB565:
265 assert(_mesa_little_endian());
266 rrb->base.DataType = GL_UNSIGNED_BYTE;
267 rrb->base._BaseFormat = GL_RGB;
268 break;
269 case MESA_FORMAT_RGB565_REV:
270 assert(!_mesa_little_endian());
271 rrb->base.DataType = GL_UNSIGNED_BYTE;
272 rrb->base._BaseFormat = GL_RGB;
273 break;
274 case MESA_FORMAT_XRGB8888:
275 assert(_mesa_little_endian());
276 rrb->base.DataType = GL_UNSIGNED_BYTE;
277 rrb->base._BaseFormat = GL_RGB;
278 break;
279 case MESA_FORMAT_XRGB8888_REV:
280 assert(!_mesa_little_endian());
281 rrb->base.DataType = GL_UNSIGNED_BYTE;
282 rrb->base._BaseFormat = GL_RGB;
283 break;
284 case MESA_FORMAT_ARGB8888:
285 assert(_mesa_little_endian());
286 rrb->base.DataType = GL_UNSIGNED_BYTE;
287 rrb->base._BaseFormat = GL_RGBA;
288 break;
289 case MESA_FORMAT_ARGB8888_REV:
290 assert(!_mesa_little_endian());
291 rrb->base.DataType = GL_UNSIGNED_BYTE;
292 rrb->base._BaseFormat = GL_RGBA;
293 break;
294 case MESA_FORMAT_S8:
295 rrb->base.DataType = GL_UNSIGNED_BYTE;
296 rrb->base._BaseFormat = GL_STENCIL_INDEX;
297 break;
298 case MESA_FORMAT_Z16:
299 rrb->base.DataType = GL_UNSIGNED_SHORT;
300 rrb->base._BaseFormat = GL_DEPTH_COMPONENT;
301 break;
302 case MESA_FORMAT_X8_Z24:
303 rrb->base.DataType = GL_UNSIGNED_INT;
304 rrb->base._BaseFormat = GL_DEPTH_COMPONENT;
305 break;
306 case MESA_FORMAT_S8_Z24:
307 rrb->base.DataType = GL_UNSIGNED_INT_24_8_EXT;
308 rrb->base._BaseFormat = GL_DEPTH_STENCIL;
309 break;
310 default:
311 fprintf(stderr, "%s: Unknown format %s\n",
312 __FUNCTION__, _mesa_get_format_name(format));
313 _mesa_delete_renderbuffer(&rrb->base);
314 return NULL;
315 }
316
317 rrb->dPriv = driDrawPriv;
318 rrb->base.InternalFormat = _mesa_get_format_base_format(format);
319
320 rrb->base.Delete = radeon_delete_renderbuffer;
321 rrb->base.AllocStorage = radeon_alloc_window_storage;
322 rrb->base.GetPointer = radeon_get_pointer;
323
324 rrb->bo = NULL;
325 return rrb;
326 }
327
328 static struct gl_renderbuffer *
329 radeon_new_renderbuffer(GLcontext * ctx, GLuint name)
330 {
331 struct radeon_renderbuffer *rrb;
332
333 rrb = CALLOC_STRUCT(radeon_renderbuffer);
334 if (!rrb)
335 return NULL;
336
337 _mesa_init_renderbuffer(&rrb->base, name);
338 rrb->base.ClassID = RADEON_RB_CLASS;
339
340 rrb->base.Delete = radeon_delete_renderbuffer;
341 rrb->base.AllocStorage = radeon_alloc_renderbuffer_storage;
342 rrb->base.GetPointer = radeon_get_pointer;
343
344 return &rrb->base;
345 }
346
347 static void
348 radeon_bind_framebuffer(GLcontext * ctx, GLenum target,
349 struct gl_framebuffer *fb, struct gl_framebuffer *fbread)
350 {
351 if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) {
352 radeon_draw_buffer(ctx, fb);
353 }
354 else {
355 /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */
356 }
357 }
358
359 static void
360 radeon_framebuffer_renderbuffer(GLcontext * ctx,
361 struct gl_framebuffer *fb,
362 GLenum attachment, struct gl_renderbuffer *rb)
363 {
364
365 if (ctx->Driver.Flush)
366 ctx->Driver.Flush(ctx); /* +r6/r7 */
367
368 _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
369 radeon_draw_buffer(ctx, fb);
370 }
371
372
373 /* TODO: According to EXT_fbo spec internal format of texture image
374 * once set during glTexImage call, should be preserved when
375 * attaching image to renderbuffer. When HW doesn't support
376 * rendering to format of attached image, set framebuffer
377 * completeness accordingly in radeon_validate_framebuffer (issue #79).
378 */
379 static GLboolean
380 radeon_update_wrapper(GLcontext *ctx, struct radeon_renderbuffer *rrb,
381 struct gl_texture_image *texImage)
382 {
383 int retry = 0;
384 gl_format texFormat;
385
386 restart:
387 if (texImage->TexFormat == _dri_texformat_argb8888) {
388 rrb->base.DataType = GL_UNSIGNED_BYTE;
389 DBG("Render to RGBA8 texture OK\n");
390 }
391 else if (texImage->TexFormat == _dri_texformat_rgb565) {
392 rrb->base.DataType = GL_UNSIGNED_BYTE;
393 DBG("Render to RGB5 texture OK\n");
394 }
395 else if (texImage->TexFormat == _dri_texformat_argb1555) {
396 rrb->base.DataType = GL_UNSIGNED_BYTE;
397 DBG("Render to ARGB1555 texture OK\n");
398 }
399 else if (texImage->TexFormat == _dri_texformat_argb4444) {
400 rrb->base.DataType = GL_UNSIGNED_BYTE;
401 DBG("Render to ARGB4444 texture OK\n");
402 }
403 else if (texImage->TexFormat == MESA_FORMAT_Z16) {
404 rrb->base.DataType = GL_UNSIGNED_SHORT;
405 DBG("Render to DEPTH16 texture OK\n");
406 }
407 else if (texImage->TexFormat == MESA_FORMAT_S8_Z24) {
408 rrb->base.DataType = GL_UNSIGNED_INT_24_8_EXT;
409 DBG("Render to DEPTH_STENCIL texture OK\n");
410 }
411 else {
412 /* try redoing the FBO */
413 if (retry == 1) {
414 DBG("Render to texture BAD FORMAT %d\n",
415 texImage->TexFormat);
416 return GL_FALSE;
417 }
418 /* XXX why is the tex format being set here?
419 * I think this can be removed.
420 */
421 texImage->TexFormat = radeonChooseTextureFormat(ctx, texImage->InternalFormat, 0,
422 _mesa_get_format_datatype(texImage->TexFormat),
423 1);
424
425 retry++;
426 goto restart;
427 }
428
429 texFormat = texImage->TexFormat;
430
431 rrb->base.Format = texFormat;
432
433 rrb->cpp = _mesa_get_format_bytes(texFormat);
434 rrb->pitch = texImage->Width * rrb->cpp;
435 rrb->base.InternalFormat = texImage->InternalFormat;
436 rrb->base._BaseFormat = _mesa_base_fbo_format(ctx, rrb->base.InternalFormat);
437
438 rrb->base.Width = texImage->Width;
439 rrb->base.Height = texImage->Height;
440
441 rrb->base.Delete = radeon_delete_renderbuffer;
442 rrb->base.AllocStorage = radeon_nop_alloc_storage;
443
444 return GL_TRUE;
445 }
446
447
448 static struct radeon_renderbuffer *
449 radeon_wrap_texture(GLcontext * ctx, struct gl_texture_image *texImage)
450 {
451 const GLuint name = ~0; /* not significant, but distinct for debugging */
452 struct radeon_renderbuffer *rrb;
453
454 /* make an radeon_renderbuffer to wrap the texture image */
455 rrb = CALLOC_STRUCT(radeon_renderbuffer);
456 if (!rrb) {
457 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture");
458 return NULL;
459 }
460
461 _mesa_init_renderbuffer(&rrb->base, name);
462 rrb->base.ClassID = RADEON_RB_CLASS;
463
464 if (!radeon_update_wrapper(ctx, rrb, texImage)) {
465 _mesa_free(rrb);
466 return NULL;
467 }
468
469 return rrb;
470
471 }
472 static void
473 radeon_render_texture(GLcontext * ctx,
474 struct gl_framebuffer *fb,
475 struct gl_renderbuffer_attachment *att)
476 {
477 struct gl_texture_image *newImage
478 = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
479 struct radeon_renderbuffer *rrb = radeon_renderbuffer(att->Renderbuffer);
480 radeon_texture_image *radeon_image;
481 GLuint imageOffset;
482
483 (void) fb;
484
485 ASSERT(newImage);
486
487 if (newImage->Border != 0) {
488 /* Fallback on drawing to a texture with a border, which won't have a
489 * miptree.
490 */
491 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
492 _mesa_render_texture(ctx, fb, att);
493 return;
494 }
495 else if (!rrb) {
496 rrb = radeon_wrap_texture(ctx, newImage);
497 if (rrb) {
498 /* bind the wrapper to the attachment point */
499 _mesa_reference_renderbuffer(&att->Renderbuffer, &rrb->base);
500 }
501 else {
502 /* fallback to software rendering */
503 _mesa_render_texture(ctx, fb, att);
504 return;
505 }
506 }
507
508 if (!radeon_update_wrapper(ctx, rrb, newImage)) {
509 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
510 _mesa_render_texture(ctx, fb, att);
511 return;
512 }
513
514 DBG("Begin render texture tid %x tex=%u w=%d h=%d refcount=%d\n",
515 _glthread_GetID(),
516 att->Texture->Name, newImage->Width, newImage->Height,
517 rrb->base.RefCount);
518
519 /* point the renderbufer's region to the texture image region */
520 radeon_image = (radeon_texture_image *)newImage;
521 if (rrb->bo != radeon_image->mt->bo) {
522 if (rrb->bo)
523 radeon_bo_unref(rrb->bo);
524 rrb->bo = radeon_image->mt->bo;
525 radeon_bo_ref(rrb->bo);
526 }
527
528 /* compute offset of the particular 2D image within the texture region */
529 imageOffset = radeon_miptree_image_offset(radeon_image->mt,
530 att->CubeMapFace,
531 att->TextureLevel);
532
533 if (att->Texture->Target == GL_TEXTURE_3D) {
534 imageOffset += radeon_image->mt->levels[att->TextureLevel].rowstride *
535 radeon_image->mt->levels[att->TextureLevel].height *
536 att->Zoffset;
537 }
538
539 /* store that offset in the region, along with the correct pitch for
540 * the image we are rendering to */
541 rrb->draw_offset = imageOffset;
542 rrb->pitch = radeon_image->mt->levels[att->TextureLevel].rowstride;
543
544 /* update drawing region, etc */
545 radeon_draw_buffer(ctx, fb);
546 }
547
548 static void
549 radeon_finish_render_texture(GLcontext * ctx,
550 struct gl_renderbuffer_attachment *att)
551 {
552
553 }
554 static void
555 radeon_validate_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb)
556 {
557 }
558
559 void radeon_fbo_init(struct radeon_context *radeon)
560 {
561 radeon->glCtx->Driver.NewFramebuffer = radeon_new_framebuffer;
562 radeon->glCtx->Driver.NewRenderbuffer = radeon_new_renderbuffer;
563 radeon->glCtx->Driver.BindFramebuffer = radeon_bind_framebuffer;
564 radeon->glCtx->Driver.FramebufferRenderbuffer = radeon_framebuffer_renderbuffer;
565 radeon->glCtx->Driver.RenderTexture = radeon_render_texture;
566 radeon->glCtx->Driver.FinishRenderTexture = radeon_finish_render_texture;
567 radeon->glCtx->Driver.ResizeBuffers = radeon_resize_buffers;
568 radeon->glCtx->Driver.ValidateFramebuffer = radeon_validate_framebuffer;
569 radeon->glCtx->Driver.BlitFramebuffer = _mesa_meta_BlitFramebuffer;
570 }
571
572
573 void radeon_renderbuffer_set_bo(struct radeon_renderbuffer *rb,
574 struct radeon_bo *bo)
575 {
576 struct radeon_bo *old;
577 old = rb->bo;
578 rb->bo = bo;
579 radeon_bo_ref(bo);
580 if (old)
581 radeon_bo_unref(old);
582 }