gallium: Permit surface_copy and surface_fill to be NULL.
[mesa.git] / src / mesa / state_tracker / st_cb_fbo.c
1 /**************************************************************************
2 *
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
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 /**
30 * Framebuffer/renderbuffer functions.
31 *
32 * \author Brian Paul
33 */
34
35
36 #include "main/imports.h"
37 #include "main/context.h"
38 #include "main/fbobject.h"
39 #include "main/framebuffer.h"
40 #include "main/renderbuffer.h"
41
42 #include "pipe/p_context.h"
43 #include "pipe/p_defines.h"
44 #include "pipe/p_screen.h"
45 #include "st_context.h"
46 #include "st_cb_fbo.h"
47 #include "st_cb_texture.h"
48 #include "st_format.h"
49 #include "st_public.h"
50 #include "st_texture.h"
51
52 #include "util/u_rect.h"
53
54
55 /**
56 * Compute the renderbuffer's Red/Green/EtcBit fields from the pipe format.
57 */
58 static int
59 init_renderbuffer_bits(struct st_renderbuffer *strb,
60 enum pipe_format pipeFormat)
61 {
62 struct pipe_format_info info;
63
64 if (!st_get_format_info( pipeFormat, &info )) {
65 assert( 0 );
66 }
67
68 strb->Base._ActualFormat = info.base_format;
69 strb->Base.RedBits = info.red_bits;
70 strb->Base.GreenBits = info.green_bits;
71 strb->Base.BlueBits = info.blue_bits;
72 strb->Base.AlphaBits = info.alpha_bits;
73 strb->Base.DepthBits = info.depth_bits;
74 strb->Base.StencilBits = info.stencil_bits;
75 strb->Base.DataType = st_format_datatype(pipeFormat);
76
77 return info.size;
78 }
79
80 /**
81 * gl_renderbuffer::AllocStorage()
82 * This is called to allocate the original drawing surface, and
83 * during window resize.
84 */
85 static GLboolean
86 st_renderbuffer_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
87 GLenum internalFormat,
88 GLuint width, GLuint height)
89 {
90 struct pipe_context *pipe = ctx->st->pipe;
91 struct st_renderbuffer *strb = st_renderbuffer(rb);
92 enum pipe_format format;
93
94 if (strb->format != PIPE_FORMAT_NONE)
95 format = strb->format;
96 else
97 format = st_choose_renderbuffer_format(pipe->screen, internalFormat);
98
99 /* init renderbuffer fields */
100 strb->Base.Width = width;
101 strb->Base.Height = height;
102 init_renderbuffer_bits(strb, format);
103
104 strb->defined = GL_FALSE; /* undefined contents now */
105
106 if(strb->software) {
107 struct pipe_format_block block;
108 size_t size;
109
110 _mesa_free(strb->data);
111
112 assert(strb->format != PIPE_FORMAT_NONE);
113 pf_get_block(strb->format, &block);
114
115 strb->stride = pf_get_stride(&block, width);
116 size = pf_get_2d_size(&block, strb->stride, height);
117
118 strb->data = _mesa_malloc(size);
119
120 return strb->data != NULL;
121 }
122 else {
123 struct pipe_texture template;
124 unsigned surface_usage;
125
126 /* Free the old surface and texture
127 */
128 pipe_surface_reference( &strb->surface, NULL );
129 pipe_texture_reference( &strb->texture, NULL );
130
131 /* Setup new texture template.
132 */
133 memset(&template, 0, sizeof(template));
134 template.target = PIPE_TEXTURE_2D;
135 template.format = format;
136 pf_get_block(format, &template.block);
137 template.width[0] = width;
138 template.height[0] = height;
139 template.depth[0] = 1;
140 template.last_level = 0;
141 template.nr_samples = rb->NumSamples;
142 if (pf_is_depth_stencil(format)) {
143 template.tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL;
144 }
145 else {
146 template.tex_usage = (PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
147 PIPE_TEXTURE_USAGE_RENDER_TARGET);
148 }
149
150 /* Probably need dedicated flags for surface usage too:
151 */
152 surface_usage = (PIPE_BUFFER_USAGE_GPU_READ |
153 PIPE_BUFFER_USAGE_GPU_WRITE);
154 #if 0
155 PIPE_BUFFER_USAGE_CPU_READ |
156 PIPE_BUFFER_USAGE_CPU_WRITE);
157 #endif
158
159 strb->texture = pipe->screen->texture_create( pipe->screen,
160 &template );
161
162 if (!strb->texture)
163 return FALSE;
164
165 strb->surface = pipe->screen->get_tex_surface( pipe->screen,
166 strb->texture,
167 0, 0, 0,
168 surface_usage );
169 if (strb->surface) {
170 assert(strb->surface->texture);
171 assert(strb->surface->format);
172 assert(strb->surface->width == width);
173 assert(strb->surface->height == height);
174 }
175
176 return strb->surface != NULL;
177 }
178 }
179
180
181 /**
182 * gl_renderbuffer::Delete()
183 */
184 static void
185 st_renderbuffer_delete(struct gl_renderbuffer *rb)
186 {
187 struct st_renderbuffer *strb = st_renderbuffer(rb);
188 ASSERT(strb);
189 pipe_surface_reference(&strb->surface, NULL);
190 pipe_texture_reference(&strb->texture, NULL);
191 _mesa_free(strb->data);
192 _mesa_free(strb);
193 }
194
195
196 /**
197 * gl_renderbuffer::GetPointer()
198 */
199 static void *
200 null_get_pointer(GLcontext * ctx, struct gl_renderbuffer *rb,
201 GLint x, GLint y)
202 {
203 /* By returning NULL we force all software rendering to go through
204 * the span routines.
205 */
206 #if 0
207 assert(0); /* Should never get called with softpipe */
208 #endif
209 return NULL;
210 }
211
212
213 /**
214 * Called via ctx->Driver.NewFramebuffer()
215 */
216 static struct gl_framebuffer *
217 st_new_framebuffer(GLcontext *ctx, GLuint name)
218 {
219 /* XXX not sure we need to subclass gl_framebuffer for pipe */
220 return _mesa_new_framebuffer(ctx, name);
221 }
222
223
224 /**
225 * Called via ctx->Driver.NewRenderbuffer()
226 */
227 static struct gl_renderbuffer *
228 st_new_renderbuffer(GLcontext *ctx, GLuint name)
229 {
230 struct st_renderbuffer *strb = ST_CALLOC_STRUCT(st_renderbuffer);
231 if (strb) {
232 _mesa_init_renderbuffer(&strb->Base, name);
233 strb->Base.Delete = st_renderbuffer_delete;
234 strb->Base.AllocStorage = st_renderbuffer_alloc_storage;
235 strb->Base.GetPointer = null_get_pointer;
236 strb->format = PIPE_FORMAT_NONE;
237 return &strb->Base;
238 }
239 return NULL;
240 }
241
242
243 /**
244 * Allocate a renderbuffer for a an on-screen window (not a user-created
245 * renderbuffer). The window system code determines the format.
246 */
247 struct gl_renderbuffer *
248 st_new_renderbuffer_fb(enum pipe_format format, int samples, boolean sw)
249 {
250 struct st_renderbuffer *strb;
251
252 strb = ST_CALLOC_STRUCT(st_renderbuffer);
253 if (!strb) {
254 _mesa_error(NULL, GL_OUT_OF_MEMORY, "creating renderbuffer");
255 return NULL;
256 }
257
258 _mesa_init_renderbuffer(&strb->Base, 0);
259 strb->Base.ClassID = 0x4242; /* just a unique value */
260 strb->Base.NumSamples = samples;
261 strb->format = format;
262 init_renderbuffer_bits(strb, format);
263 strb->software = sw;
264
265 switch (format) {
266 case PIPE_FORMAT_A8R8G8B8_UNORM:
267 case PIPE_FORMAT_B8G8R8A8_UNORM:
268 case PIPE_FORMAT_X8R8G8B8_UNORM:
269 case PIPE_FORMAT_B8G8R8X8_UNORM:
270 case PIPE_FORMAT_A1R5G5B5_UNORM:
271 case PIPE_FORMAT_A4R4G4B4_UNORM:
272 case PIPE_FORMAT_R5G6B5_UNORM:
273 strb->Base.InternalFormat = GL_RGBA;
274 strb->Base._BaseFormat = GL_RGBA;
275 break;
276 case PIPE_FORMAT_Z16_UNORM:
277 strb->Base.InternalFormat = GL_DEPTH_COMPONENT16;
278 strb->Base._BaseFormat = GL_DEPTH_COMPONENT;
279 break;
280 case PIPE_FORMAT_Z32_UNORM:
281 strb->Base.InternalFormat = GL_DEPTH_COMPONENT32;
282 strb->Base._BaseFormat = GL_DEPTH_COMPONENT;
283 break;
284 case PIPE_FORMAT_S8Z24_UNORM:
285 case PIPE_FORMAT_Z24S8_UNORM:
286 case PIPE_FORMAT_X8Z24_UNORM:
287 case PIPE_FORMAT_Z24X8_UNORM:
288 strb->Base.InternalFormat = GL_DEPTH24_STENCIL8_EXT;
289 strb->Base._BaseFormat = GL_DEPTH_STENCIL_EXT;
290 break;
291 case PIPE_FORMAT_S8_UNORM:
292 strb->Base.InternalFormat = GL_STENCIL_INDEX8_EXT;
293 strb->Base._BaseFormat = GL_STENCIL_INDEX;
294 break;
295 case PIPE_FORMAT_R16G16B16A16_SNORM:
296 strb->Base.InternalFormat = GL_RGBA16;
297 strb->Base._BaseFormat = GL_RGBA;
298 break;
299 default:
300 _mesa_problem(NULL,
301 "Unexpected format in st_new_renderbuffer_fb");
302 _mesa_free(strb);
303 return NULL;
304 }
305
306 /* st-specific methods */
307 strb->Base.Delete = st_renderbuffer_delete;
308 strb->Base.AllocStorage = st_renderbuffer_alloc_storage;
309 strb->Base.GetPointer = null_get_pointer;
310
311 /* surface is allocated in st_renderbuffer_alloc_storage() */
312 strb->surface = NULL;
313
314 return &strb->Base;
315 }
316
317
318
319
320 /**
321 * Called via ctx->Driver.BindFramebufferEXT().
322 */
323 static void
324 st_bind_framebuffer(GLcontext *ctx, GLenum target,
325 struct gl_framebuffer *fb, struct gl_framebuffer *fbread)
326 {
327
328 }
329
330 /**
331 * Called by ctx->Driver.FramebufferRenderbuffer
332 */
333 static void
334 st_framebuffer_renderbuffer(GLcontext *ctx,
335 struct gl_framebuffer *fb,
336 GLenum attachment,
337 struct gl_renderbuffer *rb)
338 {
339 /* XXX no need for derivation? */
340 _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
341 }
342
343
344 /**
345 * Called by ctx->Driver.RenderTexture
346 */
347 static void
348 st_render_texture(GLcontext *ctx,
349 struct gl_framebuffer *fb,
350 struct gl_renderbuffer_attachment *att)
351 {
352 struct pipe_screen *screen = ctx->st->pipe->screen;
353 struct st_renderbuffer *strb;
354 struct gl_renderbuffer *rb;
355 struct pipe_texture *pt = st_get_texobj_texture(att->Texture);
356 struct st_texture_object *stObj;
357 const struct gl_texture_image *texImage =
358 att->Texture->Image[att->CubeMapFace][att->TextureLevel];
359
360 if (!pt)
361 return;
362
363 /* create new renderbuffer which wraps the texture image */
364 rb = st_new_renderbuffer(ctx, 0);
365 if (!rb) {
366 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture()");
367 return;
368 }
369
370 _mesa_reference_renderbuffer(&att->Renderbuffer, rb);
371 assert(rb->RefCount == 1);
372 rb->AllocStorage = NULL; /* should not get called */
373 strb = st_renderbuffer(rb);
374
375 assert(strb->Base.RefCount > 0);
376
377 /* get the texture for the texture object */
378 stObj = st_texture_object(att->Texture);
379
380 /* point renderbuffer at texobject */
381 strb->rtt = stObj;
382 strb->rtt_level = att->TextureLevel;
383 strb->rtt_face = att->CubeMapFace;
384 strb->rtt_slice = att->Zoffset;
385
386 rb->Width = texImage->Width2;
387 rb->Height = texImage->Height2;
388 rb->_BaseFormat = texImage->_BaseFormat;
389 /*printf("***** render to texture level %d: %d x %d\n", att->TextureLevel, rb->Width, rb->Height);*/
390
391 /*printf("***** pipe texture %d x %d\n", pt->width[0], pt->height[0]);*/
392
393 pipe_texture_reference( &strb->texture, pt );
394
395 pipe_surface_reference(&strb->surface, NULL);
396
397 /* new surface for rendering into the texture */
398 strb->surface = screen->get_tex_surface(screen,
399 strb->texture,
400 strb->rtt_face,
401 strb->rtt_level,
402 strb->rtt_slice,
403 PIPE_BUFFER_USAGE_GPU_READ |
404 PIPE_BUFFER_USAGE_GPU_WRITE);
405
406 init_renderbuffer_bits(strb, pt->format);
407
408 /*
409 printf("RENDER TO TEXTURE obj=%p pt=%p surf=%p %d x %d\n",
410 att->Texture, pt, strb->surface, rb->Width, rb->Height);
411 */
412
413 /* Invalidate buffer state so that the pipe's framebuffer state
414 * gets updated.
415 * That's where the new renderbuffer (which we just created) gets
416 * passed to the pipe as a (color/depth) render target.
417 */
418 st_invalidate_state(ctx, _NEW_BUFFERS);
419 }
420
421
422 /**
423 * Called via ctx->Driver.FinishRenderTexture.
424 */
425 static void
426 st_finish_render_texture(GLcontext *ctx,
427 struct gl_renderbuffer_attachment *att)
428 {
429 struct st_renderbuffer *strb = st_renderbuffer(att->Renderbuffer);
430
431 if (!strb)
432 return;
433
434 st_flush( ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL );
435
436 if (strb->surface)
437 pipe_surface_reference( &strb->surface, NULL );
438
439 strb->rtt = NULL;
440
441 /*
442 printf("FINISH RENDER TO TEXTURE surf=%p\n", strb->surface);
443 */
444
445 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
446
447 /* restore previous framebuffer state */
448 st_invalidate_state(ctx, _NEW_BUFFERS);
449 }
450
451
452 /**
453 * Validate a renderbuffer attachment for a particular usage.
454 */
455
456 static GLboolean
457 st_validate_attachment(struct pipe_screen *screen,
458 const struct gl_renderbuffer_attachment *att,
459 GLuint usage)
460 {
461 const struct st_texture_object *stObj =
462 st_texture_object(att->Texture);
463
464 /**
465 * Only validate texture attachments for now, since
466 * st_renderbuffer_alloc_storage makes sure that
467 * the format is supported.
468 */
469
470 if (att->Type != GL_TEXTURE)
471 return GL_TRUE;
472
473 if (!stObj)
474 return GL_FALSE;
475
476 return screen->is_format_supported(screen, stObj->pt->format,
477 PIPE_TEXTURE_2D,
478 usage, 0);
479 }
480
481 /**
482 * Check that the framebuffer configuration is valid in terms of what
483 * the driver can support.
484 *
485 * For Gallium we only supports combined Z+stencil, not separate buffers.
486 */
487 static void
488 st_validate_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb)
489 {
490 struct pipe_screen *screen = ctx->st->pipe->screen;
491 const struct gl_renderbuffer *depthRb =
492 fb->Attachment[BUFFER_DEPTH].Renderbuffer;
493 const struct gl_renderbuffer *stencilRb =
494 fb->Attachment[BUFFER_STENCIL].Renderbuffer;
495 GLuint i;
496
497 if (stencilRb && depthRb && stencilRb != depthRb) {
498 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
499 return;
500 }
501
502 if (!st_validate_attachment(screen,
503 &fb->Attachment[BUFFER_DEPTH],
504 PIPE_TEXTURE_USAGE_DEPTH_STENCIL)) {
505 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
506 return;
507 }
508 if (!st_validate_attachment(screen,
509 &fb->Attachment[BUFFER_STENCIL],
510 PIPE_TEXTURE_USAGE_DEPTH_STENCIL)) {
511 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
512 return;
513 }
514 for (i = 0; i < ctx->Const.MaxColorAttachments; i++) {
515 if (!st_validate_attachment(screen,
516 &fb->Attachment[BUFFER_COLOR0 + i],
517 PIPE_TEXTURE_USAGE_RENDER_TARGET)) {
518 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
519 return;
520 }
521 }
522 }
523
524
525 /**
526 * Copy back color buffer to front color buffer.
527 */
528 static void
529 copy_back_to_front(struct st_context *st,
530 struct gl_framebuffer *fb,
531 gl_buffer_index frontIndex,
532 gl_buffer_index backIndex)
533
534 {
535 struct st_framebuffer *stfb = (struct st_framebuffer *) fb;
536 struct pipe_surface *surf_front, *surf_back;
537
538 (void) st_get_framebuffer_surface(stfb, frontIndex, &surf_front);
539 (void) st_get_framebuffer_surface(stfb, backIndex, &surf_back);
540
541 if (surf_front && surf_back) {
542 if (st->pipe->surface_copy) {
543 st->pipe->surface_copy(st->pipe,
544 surf_front, 0, 0, /* dest */
545 surf_back, 0, 0, /* src */
546 fb->Width, fb->Height);
547 } else {
548 util_surface_copy(st->pipe, FALSE,
549 surf_front, 0, 0,
550 surf_back, 0, 0,
551 fb->Width, fb->Height);
552 }
553 }
554 }
555
556
557 /**
558 * Check if we're drawing into, or read from, a front color buffer. If the
559 * front buffer is missing, create it now.
560 *
561 * The back color buffer must exist since we'll use its format/samples info
562 * for creating the front buffer.
563 *
564 * \param frontIndex either BUFFER_FRONT_LEFT or BUFFER_FRONT_RIGHT
565 * \param backIndex either BUFFER_BACK_LEFT or BUFFER_BACK_RIGHT
566 */
567 static void
568 check_create_front_buffer(GLcontext *ctx, struct gl_framebuffer *fb,
569 gl_buffer_index frontIndex,
570 gl_buffer_index backIndex)
571 {
572 if (fb->Attachment[frontIndex].Renderbuffer == NULL) {
573 GLboolean create = GL_FALSE;
574
575 /* check if drawing to or reading from front buffer */
576 if (fb->_ColorReadBufferIndex == frontIndex) {
577 create = GL_TRUE;
578 }
579 else {
580 GLuint b;
581 for (b = 0; b < fb->_NumColorDrawBuffers; b++) {
582 if (fb->_ColorDrawBufferIndexes[b] == frontIndex) {
583 create = GL_TRUE;
584 break;
585 }
586 }
587 }
588
589 if (create) {
590 struct st_renderbuffer *back;
591 struct gl_renderbuffer *front;
592 enum pipe_format colorFormat;
593 uint samples;
594
595 if (0)
596 _mesa_debug(ctx, "Allocate new front buffer\n");
597
598 /* get back renderbuffer info */
599 back = st_renderbuffer(fb->Attachment[backIndex].Renderbuffer);
600 colorFormat = back->format;
601 samples = back->Base.NumSamples;
602
603 /* create front renderbuffer */
604 front = st_new_renderbuffer_fb(colorFormat, samples, FALSE);
605 _mesa_add_renderbuffer(fb, frontIndex, front);
606
607 /* alloc texture/surface for new front buffer */
608 front->AllocStorage(ctx, front, front->InternalFormat,
609 fb->Width, fb->Height);
610
611 /* initialize the front color buffer contents by copying
612 * the back buffer.
613 */
614 copy_back_to_front(ctx->st, fb, frontIndex, backIndex);
615 }
616 }
617 }
618
619
620 /**
621 * If front left/right color buffers are missing, create them now.
622 */
623 static void
624 check_create_front_buffers(GLcontext *ctx, struct gl_framebuffer *fb)
625 {
626 /* check if we need to create the front left buffer now */
627 check_create_front_buffer(ctx, fb, BUFFER_FRONT_LEFT, BUFFER_BACK_LEFT);
628
629 if (fb->Visual.stereoMode) {
630 check_create_front_buffer(ctx, fb, BUFFER_FRONT_RIGHT, BUFFER_BACK_RIGHT);
631 }
632
633 st_invalidate_state(ctx, _NEW_BUFFERS);
634 }
635
636
637 /**
638 * Called via glDrawBuffer.
639 */
640 static void
641 st_DrawBuffers(GLcontext *ctx, GLsizei count, const GLenum *buffers)
642 {
643 (void) count;
644 (void) buffers;
645 check_create_front_buffers(ctx, ctx->DrawBuffer);
646 }
647
648
649 /**
650 * Called via glReadBuffer.
651 */
652 static void
653 st_ReadBuffer(GLcontext *ctx, GLenum buffer)
654 {
655 (void) buffer;
656 check_create_front_buffers(ctx, ctx->ReadBuffer);
657 }
658
659
660 void st_init_fbo_functions(struct dd_function_table *functions)
661 {
662 functions->NewFramebuffer = st_new_framebuffer;
663 functions->NewRenderbuffer = st_new_renderbuffer;
664 functions->BindFramebuffer = st_bind_framebuffer;
665 functions->FramebufferRenderbuffer = st_framebuffer_renderbuffer;
666 functions->RenderTexture = st_render_texture;
667 functions->FinishRenderTexture = st_finish_render_texture;
668 functions->ValidateFramebuffer = st_validate_framebuffer;
669 /* no longer needed by core Mesa, drivers handle resizes...
670 functions->ResizeBuffers = st_resize_buffers;
671 */
672
673 functions->DrawBuffers = st_DrawBuffers;
674 functions->ReadBuffer = st_ReadBuffer;
675 }