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