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