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