bd35ac5c1e781e5990a79bf59ea5fe66059f2b48
[mesa.git] / src / mesa / drivers / dri / intel / intel_fbo.c
1 /**************************************************************************
2 *
3 * Copyright 2006 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 #include "main/imports.h"
30 #include "main/macros.h"
31 #include "main/mfeatures.h"
32 #include "main/mtypes.h"
33 #include "main/fbobject.h"
34 #include "main/framebuffer.h"
35 #include "main/renderbuffer.h"
36 #include "main/context.h"
37 #include "main/teximage.h"
38 #include "swrast/swrast.h"
39 #include "drivers/common/meta.h"
40
41 #include "intel_context.h"
42 #include "intel_batchbuffer.h"
43 #include "intel_buffers.h"
44 #include "intel_fbo.h"
45 #include "intel_mipmap_tree.h"
46 #include "intel_regions.h"
47 #include "intel_tex.h"
48 #include "intel_span.h"
49 #ifndef I915
50 #include "brw_context.h"
51 #endif
52
53 #define FILE_DEBUG_FLAG DEBUG_FBO
54
55
56 /**
57 * Create a new framebuffer object.
58 */
59 static struct gl_framebuffer *
60 intel_new_framebuffer(struct gl_context * ctx, GLuint name)
61 {
62 /* Only drawable state in intel_framebuffer at this time, just use Mesa's
63 * class
64 */
65 return _mesa_new_framebuffer(ctx, name);
66 }
67
68
69 /** Called by gl_renderbuffer::Delete() */
70 static void
71 intel_delete_renderbuffer(struct gl_renderbuffer *rb)
72 {
73 struct intel_renderbuffer *irb = intel_renderbuffer(rb);
74
75 ASSERT(irb);
76
77 intel_region_release(&irb->region);
78 intel_region_release(&irb->hiz_region);
79
80 _mesa_reference_renderbuffer(&irb->wrapped_depth, NULL);
81 _mesa_reference_renderbuffer(&irb->wrapped_stencil, NULL);
82
83 free(irb);
84 }
85
86
87 /**
88 * Return a pointer to a specific pixel in a renderbuffer.
89 */
90 static void *
91 intel_get_pointer(struct gl_context * ctx, struct gl_renderbuffer *rb,
92 GLint x, GLint y)
93 {
94 /* By returning NULL we force all software rendering to go through
95 * the span routines.
96 */
97 return NULL;
98 }
99
100
101 /**
102 * Called via glRenderbufferStorageEXT() to set the format and allocate
103 * storage for a user-created renderbuffer.
104 */
105 GLboolean
106 intel_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
107 GLenum internalFormat,
108 GLuint width, GLuint height)
109 {
110 struct intel_context *intel = intel_context(ctx);
111 struct intel_renderbuffer *irb = intel_renderbuffer(rb);
112 int cpp, tiling;
113
114 ASSERT(rb->Name != 0);
115
116 switch (internalFormat) {
117 default:
118 /* Use the same format-choice logic as for textures.
119 * Renderbuffers aren't any different from textures for us,
120 * except they're less useful because you can't texture with
121 * them.
122 */
123 rb->Format = intel->ctx.Driver.ChooseTextureFormat(ctx, internalFormat,
124 GL_NONE, GL_NONE);
125 break;
126 case GL_STENCIL_INDEX:
127 case GL_STENCIL_INDEX1_EXT:
128 case GL_STENCIL_INDEX4_EXT:
129 case GL_STENCIL_INDEX8_EXT:
130 case GL_STENCIL_INDEX16_EXT:
131 /* These aren't actual texture formats, so force them here. */
132 if (intel->has_separate_stencil) {
133 rb->Format = MESA_FORMAT_S8;
134 } else {
135 assert(!intel->must_use_separate_stencil);
136 rb->Format = MESA_FORMAT_S8_Z24;
137 }
138 break;
139 }
140
141 rb->Width = width;
142 rb->Height = height;
143 rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat);
144 rb->DataType = intel_mesa_format_to_rb_datatype(rb->Format);
145 cpp = _mesa_get_format_bytes(rb->Format);
146
147 intel_flush(ctx);
148
149 /* free old region */
150 if (irb->region) {
151 intel_region_release(&irb->region);
152 }
153 if (irb->hiz_region) {
154 intel_region_release(&irb->hiz_region);
155 }
156
157 /* allocate new memory region/renderbuffer */
158
159 /* alloc hardware renderbuffer */
160 DBG("Allocating %d x %d Intel RBO\n", width, height);
161
162 tiling = I915_TILING_NONE;
163 if (intel->use_texture_tiling) {
164 GLenum base_format = _mesa_get_format_base_format(rb->Format);
165
166 if (intel->gen >= 4 && (base_format == GL_DEPTH_COMPONENT ||
167 base_format == GL_STENCIL_INDEX ||
168 base_format == GL_DEPTH_STENCIL))
169 tiling = I915_TILING_Y;
170 else
171 tiling = I915_TILING_X;
172 }
173
174 if (irb->Base.Format == MESA_FORMAT_S8) {
175 /*
176 * The stencil buffer is W tiled. However, we request from the kernel a
177 * non-tiled buffer because the GTT is incapable of W fencing.
178 *
179 * The stencil buffer has quirky pitch requirements. From Vol 2a,
180 * 11.5.6.2.1 3DSTATE_STENCIL_BUFFER, field "Surface Pitch":
181 * The pitch must be set to 2x the value computed based on width, as
182 * the stencil buffer is stored with two rows interleaved.
183 * To accomplish this, we resort to the nasty hack of doubling the drm
184 * region's cpp and halving its height.
185 *
186 * If we neglect to double the pitch, then render corruption occurs.
187 */
188 irb->region = intel_region_alloc(intel->intelScreen,
189 I915_TILING_NONE,
190 cpp * 2,
191 ALIGN(width, 64),
192 ALIGN((height + 1) / 2, 64),
193 GL_TRUE);
194 if (!irb->region)
195 return false;
196
197 } else if (irb->Base.Format == MESA_FORMAT_S8_Z24
198 && intel->must_use_separate_stencil) {
199
200 bool ok = true;
201 struct gl_renderbuffer *depth_rb;
202 struct gl_renderbuffer *stencil_rb;
203
204 depth_rb = intel_create_wrapped_renderbuffer(ctx, width, height,
205 MESA_FORMAT_X8_Z24);
206 stencil_rb = intel_create_wrapped_renderbuffer(ctx, width, height,
207 MESA_FORMAT_S8);
208 ok = depth_rb && stencil_rb;
209 ok = ok && intel_alloc_renderbuffer_storage(ctx, depth_rb,
210 depth_rb->InternalFormat,
211 width, height);
212 ok = ok && intel_alloc_renderbuffer_storage(ctx, stencil_rb,
213 stencil_rb->InternalFormat,
214 width, height);
215
216 if (!ok) {
217 if (depth_rb) {
218 intel_delete_renderbuffer(depth_rb);
219 }
220 if (stencil_rb) {
221 intel_delete_renderbuffer(stencil_rb);
222 }
223 return false;
224 }
225
226 depth_rb->Wrapped = rb;
227 stencil_rb->Wrapped = rb;
228 _mesa_reference_renderbuffer(&irb->wrapped_depth, depth_rb);
229 _mesa_reference_renderbuffer(&irb->wrapped_stencil, stencil_rb);
230
231 } else {
232 irb->region = intel_region_alloc(intel->intelScreen, tiling, cpp,
233 width, height, GL_TRUE);
234 if (!irb->region)
235 return false;
236
237 if (intel->vtbl.is_hiz_depth_format(intel, rb->Format)) {
238 irb->hiz_region = intel_region_alloc(intel->intelScreen,
239 I915_TILING_Y,
240 irb->region->cpp,
241 irb->region->width,
242 irb->region->height,
243 GL_TRUE);
244 if (!irb->hiz_region) {
245 intel_region_release(&irb->region);
246 return false;
247 }
248 }
249 }
250
251 return GL_TRUE;
252 }
253
254
255 #if FEATURE_OES_EGL_image
256 static void
257 intel_image_target_renderbuffer_storage(struct gl_context *ctx,
258 struct gl_renderbuffer *rb,
259 void *image_handle)
260 {
261 struct intel_context *intel = intel_context(ctx);
262 struct intel_renderbuffer *irb;
263 __DRIscreen *screen;
264 __DRIimage *image;
265
266 screen = intel->intelScreen->driScrnPriv;
267 image = screen->dri2.image->lookupEGLImage(screen, image_handle,
268 screen->loaderPrivate);
269 if (image == NULL)
270 return;
271
272 /* __DRIimage is opaque to the core so it has to be checked here */
273 switch (image->format) {
274 case MESA_FORMAT_RGBA8888_REV:
275 _mesa_error(&intel->ctx, GL_INVALID_OPERATION,
276 "glEGLImageTargetRenderbufferStorage(unsupported image format");
277 return;
278 break;
279 default:
280 break;
281 }
282
283 irb = intel_renderbuffer(rb);
284 intel_region_reference(&irb->region, image->region);
285
286 rb->InternalFormat = image->internal_format;
287 rb->Width = image->region->width;
288 rb->Height = image->region->height;
289 rb->Format = image->format;
290 rb->DataType = image->data_type;
291 rb->_BaseFormat = _mesa_base_fbo_format(&intel->ctx,
292 image->internal_format);
293 }
294 #endif
295
296 /**
297 * Called for each hardware renderbuffer when a _window_ is resized.
298 * Just update fields.
299 * Not used for user-created renderbuffers!
300 */
301 static GLboolean
302 intel_alloc_window_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
303 GLenum internalFormat, GLuint width, GLuint height)
304 {
305 ASSERT(rb->Name == 0);
306 rb->Width = width;
307 rb->Height = height;
308 rb->InternalFormat = internalFormat;
309
310 return GL_TRUE;
311 }
312
313
314 static void
315 intel_resize_buffers(struct gl_context *ctx, struct gl_framebuffer *fb,
316 GLuint width, GLuint height)
317 {
318 int i;
319
320 _mesa_resize_framebuffer(ctx, fb, width, height);
321
322 fb->Initialized = GL_TRUE; /* XXX remove someday */
323
324 if (fb->Name != 0) {
325 return;
326 }
327
328
329 /* Make sure all window system renderbuffers are up to date */
330 for (i = BUFFER_FRONT_LEFT; i <= BUFFER_BACK_RIGHT; i++) {
331 struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer;
332
333 /* only resize if size is changing */
334 if (rb && (rb->Width != width || rb->Height != height)) {
335 rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height);
336 }
337 }
338 }
339
340
341 /** Dummy function for gl_renderbuffer::AllocStorage() */
342 static GLboolean
343 intel_nop_alloc_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
344 GLenum internalFormat, GLuint width, GLuint height)
345 {
346 _mesa_problem(ctx, "intel_op_alloc_storage should never be called.");
347 return GL_FALSE;
348 }
349
350 /**
351 * Create a new intel_renderbuffer which corresponds to an on-screen window,
352 * not a user-created renderbuffer.
353 */
354 struct intel_renderbuffer *
355 intel_create_renderbuffer(gl_format format)
356 {
357 GET_CURRENT_CONTEXT(ctx);
358
359 struct intel_renderbuffer *irb;
360
361 irb = CALLOC_STRUCT(intel_renderbuffer);
362 if (!irb) {
363 _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer");
364 return NULL;
365 }
366
367 _mesa_init_renderbuffer(&irb->Base, 0);
368 irb->Base.ClassID = INTEL_RB_CLASS;
369 irb->Base._BaseFormat = _mesa_get_format_base_format(format);
370 irb->Base.Format = format;
371 irb->Base.InternalFormat = irb->Base._BaseFormat;
372 irb->Base.DataType = intel_mesa_format_to_rb_datatype(format);
373
374 /* intel-specific methods */
375 irb->Base.Delete = intel_delete_renderbuffer;
376 irb->Base.AllocStorage = intel_alloc_window_storage;
377 irb->Base.GetPointer = intel_get_pointer;
378
379 return irb;
380 }
381
382
383 struct gl_renderbuffer*
384 intel_create_wrapped_renderbuffer(struct gl_context * ctx,
385 int width, int height,
386 gl_format format)
387 {
388 /*
389 * The name here is irrelevant, as long as its nonzero, because the
390 * renderbuffer never gets entered into Mesa's renderbuffer hash table.
391 */
392 GLuint name = ~0;
393
394 struct intel_renderbuffer *irb = CALLOC_STRUCT(intel_renderbuffer);
395 if (!irb) {
396 _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer");
397 return NULL;
398 }
399
400 struct gl_renderbuffer *rb = &irb->Base;
401 _mesa_init_renderbuffer(rb, name);
402 rb->ClassID = INTEL_RB_CLASS;
403 rb->_BaseFormat = _mesa_get_format_base_format(format);
404 rb->Format = format;
405 rb->InternalFormat = rb->_BaseFormat;
406 rb->DataType = intel_mesa_format_to_rb_datatype(format);
407 rb->Width = width;
408 rb->Height = height;
409
410 return rb;
411 }
412
413
414 /**
415 * Create a new renderbuffer object.
416 * Typically called via glBindRenderbufferEXT().
417 */
418 static struct gl_renderbuffer *
419 intel_new_renderbuffer(struct gl_context * ctx, GLuint name)
420 {
421 /*struct intel_context *intel = intel_context(ctx); */
422 struct intel_renderbuffer *irb;
423
424 irb = CALLOC_STRUCT(intel_renderbuffer);
425 if (!irb) {
426 _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer");
427 return NULL;
428 }
429
430 _mesa_init_renderbuffer(&irb->Base, name);
431 irb->Base.ClassID = INTEL_RB_CLASS;
432
433 /* intel-specific methods */
434 irb->Base.Delete = intel_delete_renderbuffer;
435 irb->Base.AllocStorage = intel_alloc_renderbuffer_storage;
436 irb->Base.GetPointer = intel_get_pointer;
437 /* span routines set in alloc_storage function */
438
439 return &irb->Base;
440 }
441
442
443 /**
444 * Called via glBindFramebufferEXT().
445 */
446 static void
447 intel_bind_framebuffer(struct gl_context * ctx, GLenum target,
448 struct gl_framebuffer *fb, struct gl_framebuffer *fbread)
449 {
450 if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) {
451 intel_draw_buffer(ctx);
452 }
453 else {
454 /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */
455 }
456 }
457
458
459 /**
460 * Called via glFramebufferRenderbufferEXT().
461 */
462 static void
463 intel_framebuffer_renderbuffer(struct gl_context * ctx,
464 struct gl_framebuffer *fb,
465 GLenum attachment, struct gl_renderbuffer *rb)
466 {
467 DBG("Intel FramebufferRenderbuffer %u %u\n", fb->Name, rb ? rb->Name : 0);
468
469 intel_flush(ctx);
470
471 _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
472 intel_draw_buffer(ctx);
473 }
474
475 static bool
476 intel_update_tex_wrapper_regions(struct intel_context *intel,
477 struct intel_renderbuffer *irb,
478 struct intel_texture_image *intel_image);
479
480 static GLboolean
481 intel_update_wrapper(struct gl_context *ctx, struct intel_renderbuffer *irb,
482 struct gl_texture_image *texImage)
483 {
484 struct intel_context *intel = intel_context(ctx);
485 struct intel_texture_image *intel_image = intel_texture_image(texImage);
486
487 if (!intel_span_supports_format(texImage->TexFormat)) {
488 DBG("Render to texture BAD FORMAT %s\n",
489 _mesa_get_format_name(texImage->TexFormat));
490 return GL_FALSE;
491 } else {
492 DBG("Render to texture %s\n", _mesa_get_format_name(texImage->TexFormat));
493 }
494
495 irb->Base.Format = texImage->TexFormat;
496 irb->Base.DataType = intel_mesa_format_to_rb_datatype(texImage->TexFormat);
497 irb->Base.InternalFormat = texImage->InternalFormat;
498 irb->Base._BaseFormat = _mesa_base_tex_format(ctx, irb->Base.InternalFormat);
499 irb->Base.Width = texImage->Width;
500 irb->Base.Height = texImage->Height;
501
502 irb->Base.Delete = intel_delete_renderbuffer;
503 irb->Base.AllocStorage = intel_nop_alloc_storage;
504
505 if (intel_image->stencil_rb) {
506 /* The tex image has packed depth/stencil format, but is using separate
507 * stencil. */
508
509 bool ok;
510 struct intel_renderbuffer *depth_irb =
511 intel_renderbuffer(intel_image->depth_rb);
512
513 /* Update the hiz region if necessary. */
514 ok = intel_update_tex_wrapper_regions(intel, depth_irb, intel_image);
515 if (!ok) {
516 return false;
517 }
518
519 /* The tex image shares its embedded depth and stencil renderbuffers with
520 * the renderbuffer wrapper. */
521 if (irb->wrapped_depth != intel_image->depth_rb) {
522 _mesa_reference_renderbuffer(&irb->wrapped_depth,
523 intel_image->depth_rb);
524 }
525 if (irb->wrapped_stencil != intel_image->stencil_rb) {
526 _mesa_reference_renderbuffer(&irb->wrapped_stencil,
527 intel_image->stencil_rb);
528 }
529
530 return true;
531
532 } else {
533 return intel_update_tex_wrapper_regions(intel, irb, intel_image);
534 }
535 }
536
537 /**
538 * FIXME: The handling of the hiz region is broken for mipmapped depth textures
539 * FIXME: because intel_finalize_mipmap_tree is unaware of it.
540 */
541 static bool
542 intel_update_tex_wrapper_regions(struct intel_context *intel,
543 struct intel_renderbuffer *irb,
544 struct intel_texture_image *intel_image)
545 {
546 struct gl_renderbuffer *rb = &irb->Base;
547
548 /* Point the renderbuffer's region to the texture's region. */
549 if (irb->region != intel_image->mt->region) {
550 intel_region_reference(&irb->region, intel_image->mt->region);
551 }
552
553 /* Allocate the texture's hiz region if necessary. */
554 if (intel->vtbl.is_hiz_depth_format(intel, rb->Format)
555 && !intel_image->mt->hiz_region) {
556 intel_image->mt->hiz_region =
557 intel_region_alloc(intel->intelScreen,
558 I915_TILING_Y,
559 _mesa_get_format_bytes(rb->Format),
560 rb->Width,
561 rb->Height,
562 GL_TRUE);
563 if (!intel_image->mt->hiz_region)
564 return GL_FALSE;
565 }
566
567 /* Point the renderbuffer's hiz region to the texture's hiz region. */
568 if (irb->hiz_region != intel_image->mt->hiz_region) {
569 intel_region_reference(&irb->hiz_region, intel_image->mt->hiz_region);
570 }
571
572 return GL_TRUE;
573 }
574
575
576 /**
577 * When glFramebufferTexture[123]D is called this function sets up the
578 * gl_renderbuffer wrapper around the texture image.
579 * This will have the region info needed for hardware rendering.
580 */
581 static struct intel_renderbuffer *
582 intel_wrap_texture(struct gl_context * ctx, struct gl_texture_image *texImage)
583 {
584 const GLuint name = ~0; /* not significant, but distinct for debugging */
585 struct intel_renderbuffer *irb;
586
587 /* make an intel_renderbuffer to wrap the texture image */
588 irb = CALLOC_STRUCT(intel_renderbuffer);
589 if (!irb) {
590 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture");
591 return NULL;
592 }
593
594 _mesa_init_renderbuffer(&irb->Base, name);
595 irb->Base.ClassID = INTEL_RB_CLASS;
596
597 if (!intel_update_wrapper(ctx, irb, texImage)) {
598 free(irb);
599 return NULL;
600 }
601
602 return irb;
603 }
604
605 void
606 intel_renderbuffer_set_draw_offset(struct intel_renderbuffer *irb,
607 struct intel_texture_image *intel_image,
608 int zoffset)
609 {
610 unsigned int dst_x, dst_y;
611
612 /* compute offset of the particular 2D image within the texture region */
613 intel_miptree_get_image_offset(intel_image->mt,
614 intel_image->base.Level,
615 intel_image->base.Face,
616 zoffset,
617 &dst_x, &dst_y);
618
619 irb->draw_x = dst_x;
620 irb->draw_y = dst_y;
621 }
622
623 /**
624 * Rendering to tiled buffers requires that the base address of the
625 * buffer be aligned to a page boundary. We generally render to
626 * textures by pointing the surface at the mipmap image level, which
627 * may not be aligned to a tile boundary.
628 *
629 * This function returns an appropriately-aligned base offset
630 * according to the tiling restrictions, plus any required x/y offset
631 * from there.
632 */
633 uint32_t
634 intel_renderbuffer_tile_offsets(struct intel_renderbuffer *irb,
635 uint32_t *tile_x,
636 uint32_t *tile_y)
637 {
638 int cpp = irb->region->cpp;
639 uint32_t pitch = irb->region->pitch * cpp;
640
641 if (irb->region->tiling == I915_TILING_NONE) {
642 *tile_x = 0;
643 *tile_y = 0;
644 return irb->draw_x * cpp + irb->draw_y * pitch;
645 } else if (irb->region->tiling == I915_TILING_X) {
646 *tile_x = irb->draw_x % (512 / cpp);
647 *tile_y = irb->draw_y % 8;
648 return ((irb->draw_y / 8) * (8 * pitch) +
649 (irb->draw_x - *tile_x) / (512 / cpp) * 4096);
650 } else {
651 assert(irb->region->tiling == I915_TILING_Y);
652 *tile_x = irb->draw_x % (128 / cpp);
653 *tile_y = irb->draw_y % 32;
654 return ((irb->draw_y / 32) * (32 * pitch) +
655 (irb->draw_x - *tile_x) / (128 / cpp) * 4096);
656 }
657 }
658
659 #ifndef I915
660 static bool
661 need_tile_offset_workaround(struct brw_context *brw,
662 struct intel_renderbuffer *irb)
663 {
664 uint32_t tile_x, tile_y;
665
666 if (brw->has_surface_tile_offset)
667 return false;
668
669 intel_renderbuffer_tile_offsets(irb, &tile_x, &tile_y);
670
671 return tile_x != 0 || tile_y != 0;
672 }
673 #endif
674
675 /**
676 * Called by glFramebufferTexture[123]DEXT() (and other places) to
677 * prepare for rendering into texture memory. This might be called
678 * many times to choose different texture levels, cube faces, etc
679 * before intel_finish_render_texture() is ever called.
680 */
681 static void
682 intel_render_texture(struct gl_context * ctx,
683 struct gl_framebuffer *fb,
684 struct gl_renderbuffer_attachment *att)
685 {
686 struct gl_texture_image *image = _mesa_get_attachment_teximage(att);
687 struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer);
688 struct intel_texture_image *intel_image = intel_texture_image(image);
689
690 (void) fb;
691
692 if (!intel_image->mt) {
693 /* Fallback on drawing to a texture that doesn't have a miptree
694 * (has a border, width/height 0, etc.)
695 */
696 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
697 _swrast_render_texture(ctx, fb, att);
698 return;
699 }
700 else if (!irb) {
701 irb = intel_wrap_texture(ctx, image);
702 if (irb) {
703 /* bind the wrapper to the attachment point */
704 _mesa_reference_renderbuffer(&att->Renderbuffer, &irb->Base);
705 }
706 else {
707 /* fallback to software rendering */
708 _swrast_render_texture(ctx, fb, att);
709 return;
710 }
711 }
712
713 if (!intel_update_wrapper(ctx, irb, image)) {
714 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
715 _swrast_render_texture(ctx, fb, att);
716 return;
717 }
718
719 DBG("Begin render texture tid %lx tex=%u w=%d h=%d refcount=%d\n",
720 _glthread_GetID(),
721 att->Texture->Name, image->Width, image->Height,
722 irb->Base.RefCount);
723
724 intel_renderbuffer_set_draw_offset(irb, intel_image, att->Zoffset);
725 intel_image->used_as_render_target = GL_TRUE;
726
727 #ifndef I915
728 if (need_tile_offset_workaround(brw_context(ctx), irb)) {
729 /* Original gen4 hardware couldn't draw to a non-tile-aligned
730 * destination in a miptree unless you actually setup your
731 * renderbuffer as a miptree and used the fragile
732 * lod/array_index/etc. controls to select the image. So,
733 * instead, we just make a new single-level miptree and render
734 * into that.
735 */
736 struct intel_context *intel = intel_context(ctx);
737 struct intel_mipmap_tree *old_mt = intel_image->mt;
738 struct intel_mipmap_tree *new_mt;
739
740 new_mt = intel_miptree_create(intel, image->TexObject->Target,
741 intel_image->base.TexFormat,
742 intel_image->base.Level,
743 intel_image->base.Level,
744 intel_image->base.Width,
745 intel_image->base.Height,
746 intel_image->base.Depth,
747 GL_TRUE);
748
749 intel_miptree_image_copy(intel,
750 new_mt,
751 intel_image->base.Face,
752 intel_image->base.Level,
753 old_mt);
754
755 intel_miptree_release(intel, &intel_image->mt);
756 intel_image->mt = new_mt;
757 intel_renderbuffer_set_draw_offset(irb, intel_image, att->Zoffset);
758
759 intel_region_reference(&irb->region, intel_image->mt->region);
760 }
761 #endif
762 /* update drawing region, etc */
763 intel_draw_buffer(ctx);
764 }
765
766
767 /**
768 * Called by Mesa when rendering to a texture is done.
769 */
770 static void
771 intel_finish_render_texture(struct gl_context * ctx,
772 struct gl_renderbuffer_attachment *att)
773 {
774 struct intel_context *intel = intel_context(ctx);
775 struct gl_texture_object *tex_obj = att->Texture;
776 struct gl_texture_image *image =
777 tex_obj->Image[att->CubeMapFace][att->TextureLevel];
778 struct intel_texture_image *intel_image = intel_texture_image(image);
779
780 DBG("Finish render texture tid %lx tex=%u\n",
781 _glthread_GetID(), att->Texture->Name);
782
783 /* Flag that this image may now be validated into the object's miptree. */
784 if (intel_image)
785 intel_image->used_as_render_target = GL_FALSE;
786
787 /* Since we've (probably) rendered to the texture and will (likely) use
788 * it in the texture domain later on in this batchbuffer, flush the
789 * batch. Once again, we wish for a domain tracker in libdrm to cover
790 * usage inside of a batchbuffer like GEM does in the kernel.
791 */
792 intel_batchbuffer_emit_mi_flush(intel);
793 }
794
795 /**
796 * Do additional "completeness" testing of a framebuffer object.
797 */
798 static void
799 intel_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
800 {
801 struct intel_context *intel = intel_context(ctx);
802 const struct intel_renderbuffer *depthRb =
803 intel_get_renderbuffer(fb, BUFFER_DEPTH);
804 const struct intel_renderbuffer *stencilRb =
805 intel_get_renderbuffer(fb, BUFFER_STENCIL);
806 int i;
807
808 /*
809 * The depth and stencil renderbuffers are the same renderbuffer or wrap
810 * the same texture.
811 */
812 if (depthRb && stencilRb) {
813 bool depth_stencil_are_same;
814 if (depthRb == stencilRb)
815 depth_stencil_are_same = true;
816 else if ((fb->Attachment[BUFFER_DEPTH].Type == GL_TEXTURE) &&
817 (fb->Attachment[BUFFER_STENCIL].Type == GL_TEXTURE) &&
818 (fb->Attachment[BUFFER_DEPTH].Texture->Name ==
819 fb->Attachment[BUFFER_STENCIL].Texture->Name))
820 depth_stencil_are_same = true;
821 else
822 depth_stencil_are_same = false;
823
824 if (!intel->has_separate_stencil && !depth_stencil_are_same) {
825 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
826 }
827 }
828
829 for (i = 0; i < Elements(fb->Attachment); i++) {
830 struct gl_renderbuffer *rb;
831 struct intel_renderbuffer *irb;
832
833 if (fb->Attachment[i].Type == GL_NONE)
834 continue;
835
836 /* A supported attachment will have a Renderbuffer set either
837 * from being a Renderbuffer or being a texture that got the
838 * intel_wrap_texture() treatment.
839 */
840 rb = fb->Attachment[i].Renderbuffer;
841 if (rb == NULL) {
842 DBG("attachment without renderbuffer\n");
843 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
844 continue;
845 }
846
847 irb = intel_renderbuffer(rb);
848 if (irb == NULL) {
849 DBG("software rendering renderbuffer\n");
850 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
851 continue;
852 }
853
854 if (!intel_span_supports_format(irb->Base.Format) ||
855 !intel->vtbl.render_target_supported(irb->Base.Format)) {
856 DBG("Unsupported texture/renderbuffer format attached: %s\n",
857 _mesa_get_format_name(irb->Base.Format));
858 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
859 }
860 }
861 }
862
863 /**
864 * Try to do a glBlitFramebuffer using glCopyTexSubImage2D
865 * We can do this when the dst renderbuffer is actually a texture and
866 * there is no scaling, mirroring or scissoring.
867 *
868 * \return new buffer mask indicating the buffers left to blit using the
869 * normal path.
870 */
871 static GLbitfield
872 intel_blit_framebuffer_copy_tex_sub_image(struct gl_context *ctx,
873 GLint srcX0, GLint srcY0,
874 GLint srcX1, GLint srcY1,
875 GLint dstX0, GLint dstY0,
876 GLint dstX1, GLint dstY1,
877 GLbitfield mask, GLenum filter)
878 {
879 if (mask & GL_COLOR_BUFFER_BIT) {
880 const struct gl_framebuffer *drawFb = ctx->DrawBuffer;
881 const struct gl_framebuffer *readFb = ctx->ReadBuffer;
882 const struct gl_renderbuffer_attachment *drawAtt =
883 &drawFb->Attachment[drawFb->_ColorDrawBufferIndexes[0]];
884
885 /* If the source and destination are the same size with no
886 mirroring, the rectangles are within the size of the
887 texture and there is no scissor then we can use
888 glCopyTexSubimage2D to implement the blit. This will end
889 up as a fast hardware blit on some drivers */
890 if (drawAtt && drawAtt->Texture &&
891 srcX0 - srcX1 == dstX0 - dstX1 &&
892 srcY0 - srcY1 == dstY0 - dstY1 &&
893 srcX1 >= srcX0 &&
894 srcY1 >= srcY0 &&
895 srcX0 >= 0 && srcX1 <= readFb->Width &&
896 srcY0 >= 0 && srcY1 <= readFb->Height &&
897 dstX0 >= 0 && dstX1 <= drawFb->Width &&
898 dstY0 >= 0 && dstY1 <= drawFb->Height &&
899 !ctx->Scissor.Enabled) {
900 const struct gl_texture_object *texObj = drawAtt->Texture;
901 const GLuint dstLevel = drawAtt->TextureLevel;
902 const GLenum target = texObj->Target;
903
904 struct gl_texture_image *texImage =
905 _mesa_select_tex_image(ctx, texObj, target, dstLevel);
906 GLenum internalFormat = texImage->InternalFormat;
907
908 if (intel_copy_texsubimage(intel_context(ctx), target,
909 intel_texture_image(texImage),
910 internalFormat,
911 dstX0, dstY0,
912 srcX0, srcY0,
913 srcX1 - srcX0, /* width */
914 srcY1 - srcY0))
915 mask &= ~GL_COLOR_BUFFER_BIT;
916 }
917 }
918
919 return mask;
920 }
921
922 static void
923 intel_blit_framebuffer(struct gl_context *ctx,
924 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
925 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
926 GLbitfield mask, GLenum filter)
927 {
928 /* Try faster, glCopyTexSubImage2D approach first which uses the BLT. */
929 mask = intel_blit_framebuffer_copy_tex_sub_image(ctx,
930 srcX0, srcY0, srcX1, srcY1,
931 dstX0, dstY0, dstX1, dstY1,
932 mask, filter);
933 if (mask == 0x0)
934 return;
935
936 _mesa_meta_BlitFramebuffer(ctx,
937 srcX0, srcY0, srcX1, srcY1,
938 dstX0, dstY0, dstX1, dstY1,
939 mask, filter);
940 }
941
942 /**
943 * Do one-time context initializations related to GL_EXT_framebuffer_object.
944 * Hook in device driver functions.
945 */
946 void
947 intel_fbo_init(struct intel_context *intel)
948 {
949 intel->ctx.Driver.NewFramebuffer = intel_new_framebuffer;
950 intel->ctx.Driver.NewRenderbuffer = intel_new_renderbuffer;
951 intel->ctx.Driver.BindFramebuffer = intel_bind_framebuffer;
952 intel->ctx.Driver.FramebufferRenderbuffer = intel_framebuffer_renderbuffer;
953 intel->ctx.Driver.RenderTexture = intel_render_texture;
954 intel->ctx.Driver.FinishRenderTexture = intel_finish_render_texture;
955 intel->ctx.Driver.ResizeBuffers = intel_resize_buffers;
956 intel->ctx.Driver.ValidateFramebuffer = intel_validate_framebuffer;
957 intel->ctx.Driver.BlitFramebuffer = intel_blit_framebuffer;
958
959 #if FEATURE_OES_EGL_image
960 intel->ctx.Driver.EGLImageTargetRenderbufferStorage =
961 intel_image_target_renderbuffer_storage;
962 #endif
963 }