intel_fbo.c revision 9c5fdbb721147f7304faaa8960f5b64e25a8f673
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 */
59static struct gl_framebuffer *
60intel_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() */
70static void
71intel_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 */
93static void *
94intel_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 */
108static GLboolean
109intel_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
224static void
225intel_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 */
260static GLboolean
261intel_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
273static void
274intel_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() */
301static GLboolean
302intel_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
310void
311intel_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
324void
325intel_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 */
340struct intel_renderbuffer *
341intel_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 */
373static struct gl_renderbuffer *
374intel_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 */
401static void
402intel_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 */
417static void
418intel_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
431static GLboolean
432intel_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 */
491static struct intel_renderbuffer *
492intel_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
515static void
516intel_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 */
545uint32_t
546intel_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 */
577static void
578intel_render_texture(struct gl_context * ctx,
579                     struct gl_framebuffer *fb,
580                     struct gl_renderbuffer_attachment *att)
581{
582   struct gl_texture_image *image = _mesa_get_attachment_teximage(att);
583   struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer);
584   struct intel_texture_image *intel_image = intel_texture_image(image);
585
586   (void) fb;
587
588   if (!intel_image->mt) {
589      /* Fallback on drawing to a texture that doesn't have a miptree
590       * (has a border, width/height 0, etc.)
591       */
592      _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
593      _swrast_render_texture(ctx, fb, att);
594      return;
595   }
596   else if (!irb) {
597      irb = intel_wrap_texture(ctx, image);
598      if (irb) {
599         /* bind the wrapper to the attachment point */
600         _mesa_reference_renderbuffer(&att->Renderbuffer, &irb->Base);
601      }
602      else {
603         /* fallback to software rendering */
604         _swrast_render_texture(ctx, fb, att);
605         return;
606      }
607   }
608
609   if (!intel_update_wrapper(ctx, irb, image)) {
610       _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
611       _swrast_render_texture(ctx, fb, att);
612       return;
613   }
614
615   DBG("Begin render texture tid %lx tex=%u w=%d h=%d refcount=%d\n",
616       _glthread_GetID(),
617       att->Texture->Name, image->Width, image->Height,
618       irb->Base.RefCount);
619
620   intel_renderbuffer_set_draw_offset(irb, intel_image, att->Zoffset);
621   intel_image->used_as_render_target = GL_TRUE;
622
623#ifndef I915
624   if (!brw_context(ctx)->has_surface_tile_offset &&
625       (irb->draw_offset & 4095) != 0) {
626      /* Original gen4 hardware couldn't draw to a non-tile-aligned
627       * destination in a miptree unless you actually setup your
628       * renderbuffer as a miptree and used the fragile
629       * lod/array_index/etc. controls to select the image.  So,
630       * instead, we just make a new single-level miptree and render
631       * into that.
632       */
633      struct intel_context *intel = intel_context(ctx);
634      struct intel_mipmap_tree *old_mt = intel_image->mt;
635      struct intel_mipmap_tree *new_mt;
636      int comp_byte = 0, texel_bytes;
637
638      if (_mesa_is_format_compressed(intel_image->base.TexFormat))
639	 comp_byte = intel_compressed_num_bytes(intel_image->base.TexFormat);
640
641      texel_bytes = _mesa_get_format_bytes(intel_image->base.TexFormat);
642
643      new_mt = intel_miptree_create(intel, image->TexObject->Target,
644				    intel_image->base.TexFormat,
645				    intel_image->level,
646				    intel_image->level,
647				    intel_image->base.Width,
648				    intel_image->base.Height,
649				    intel_image->base.Depth,
650				    texel_bytes, comp_byte, GL_TRUE);
651
652      intel_miptree_image_copy(intel,
653                               new_mt,
654                               intel_image->face,
655			       intel_image->level,
656			       old_mt);
657
658      intel_miptree_release(intel, &intel_image->mt);
659      intel_image->mt = new_mt;
660      intel_renderbuffer_set_draw_offset(irb, intel_image, att->Zoffset);
661
662      intel_region_release(&irb->region);
663      intel_region_reference(&irb->region, intel_image->mt->region);
664   }
665#endif
666   /* update drawing region, etc */
667   intel_draw_buffer(ctx, fb);
668}
669
670
671/**
672 * Called by Mesa when rendering to a texture is done.
673 */
674static void
675intel_finish_render_texture(struct gl_context * ctx,
676                            struct gl_renderbuffer_attachment *att)
677{
678   struct intel_context *intel = intel_context(ctx);
679   struct gl_texture_object *tex_obj = att->Texture;
680   struct gl_texture_image *image =
681      tex_obj->Image[att->CubeMapFace][att->TextureLevel];
682   struct intel_texture_image *intel_image = intel_texture_image(image);
683
684   DBG("Finish render texture tid %lx tex=%u\n",
685       _glthread_GetID(), att->Texture->Name);
686
687   /* Flag that this image may now be validated into the object's miptree. */
688   if (intel_image)
689      intel_image->used_as_render_target = GL_FALSE;
690
691   /* Since we've (probably) rendered to the texture and will (likely) use
692    * it in the texture domain later on in this batchbuffer, flush the
693    * batch.  Once again, we wish for a domain tracker in libdrm to cover
694    * usage inside of a batchbuffer like GEM does in the kernel.
695    */
696   intel_batchbuffer_emit_mi_flush(intel);
697}
698
699/**
700 * Do additional "completeness" testing of a framebuffer object.
701 */
702static void
703intel_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
704{
705   struct intel_context *intel = intel_context(ctx);
706   const struct intel_renderbuffer *depthRb =
707      intel_get_renderbuffer(fb, BUFFER_DEPTH);
708   const struct intel_renderbuffer *stencilRb =
709      intel_get_renderbuffer(fb, BUFFER_STENCIL);
710   int i;
711
712   /*
713    * The depth and stencil renderbuffers are the same renderbuffer or wrap
714    * the same texture.
715    */
716   bool depth_stencil_are_same;
717   if (depthRb && stencilRb && depthRb == stencilRb)
718      depth_stencil_are_same = true;
719   else if (depthRb && stencilRb && depthRb != stencilRb
720	    && (fb->Attachment[BUFFER_DEPTH].Type == GL_TEXTURE)
721	    && (fb->Attachment[BUFFER_STENCIL].Type == GL_TEXTURE)
722	    && (fb->Attachment[BUFFER_DEPTH].Texture->Name
723		== fb->Attachment[BUFFER_STENCIL].Texture->Name))
724      depth_stencil_are_same = true;
725   else
726      depth_stencil_are_same = false;
727
728   bool fb_has_combined_depth_stencil_format =
729     (depthRb && depthRb->Base.Format == MESA_FORMAT_S8_Z24) ||
730     (stencilRb && stencilRb->Base.Format == MESA_FORMAT_S8_Z24);
731
732   bool fb_has_hiz = intel_framebuffer_has_hiz(fb);
733
734   if ((intel->must_use_separate_stencil || fb_has_hiz)
735	 && (depth_stencil_are_same || fb_has_combined_depth_stencil_format)) {
736      fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
737   } else if (!intel->has_separate_stencil && depthRb && stencilRb && !depth_stencil_are_same) {
738      fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
739   }
740
741   for (i = 0; i < Elements(fb->Attachment); i++) {
742      struct gl_renderbuffer *rb;
743      struct intel_renderbuffer *irb;
744
745      if (fb->Attachment[i].Type == GL_NONE)
746	 continue;
747
748      /* A supported attachment will have a Renderbuffer set either
749       * from being a Renderbuffer or being a texture that got the
750       * intel_wrap_texture() treatment.
751       */
752      rb = fb->Attachment[i].Renderbuffer;
753      if (rb == NULL) {
754	 DBG("attachment without renderbuffer\n");
755	 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
756	 continue;
757      }
758
759      irb = intel_renderbuffer(rb);
760      if (irb == NULL) {
761	 DBG("software rendering renderbuffer\n");
762	 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
763	 continue;
764      }
765
766      if (!intel_span_supports_format(irb->Base.Format) ||
767	  !intel->vtbl.render_target_supported(irb->Base.Format)) {
768	 DBG("Unsupported texture/renderbuffer format attached: %s\n",
769	     _mesa_get_format_name(irb->Base.Format));
770	 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
771      }
772   }
773}
774
775/**
776 * Try to do a glBlitFramebuffer using glCopyTexSubImage2D
777 * We can do this when the dst renderbuffer is actually a texture and
778 * there is no scaling, mirroring or scissoring.
779 *
780 * \return new buffer mask indicating the buffers left to blit using the
781 *         normal path.
782 */
783static GLbitfield
784intel_blit_framebuffer_copy_tex_sub_image(struct gl_context *ctx,
785                                          GLint srcX0, GLint srcY0,
786                                          GLint srcX1, GLint srcY1,
787                                          GLint dstX0, GLint dstY0,
788                                          GLint dstX1, GLint dstY1,
789                                          GLbitfield mask, GLenum filter)
790{
791   if (mask & GL_COLOR_BUFFER_BIT) {
792      const struct gl_framebuffer *drawFb = ctx->DrawBuffer;
793      const struct gl_framebuffer *readFb = ctx->ReadBuffer;
794      const struct gl_renderbuffer_attachment *drawAtt =
795         &drawFb->Attachment[drawFb->_ColorDrawBufferIndexes[0]];
796
797      /* If the source and destination are the same size with no
798         mirroring, the rectangles are within the size of the
799         texture and there is no scissor then we can use
800         glCopyTexSubimage2D to implement the blit. This will end
801         up as a fast hardware blit on some drivers */
802      if (drawAtt && drawAtt->Texture &&
803          srcX0 - srcX1 == dstX0 - dstX1 &&
804          srcY0 - srcY1 == dstY0 - dstY1 &&
805          srcX1 >= srcX0 &&
806          srcY1 >= srcY0 &&
807          srcX0 >= 0 && srcX1 <= readFb->Width &&
808          srcY0 >= 0 && srcY1 <= readFb->Height &&
809          dstX0 >= 0 && dstX1 <= drawFb->Width &&
810          dstY0 >= 0 && dstY1 <= drawFb->Height &&
811          !ctx->Scissor.Enabled) {
812         const struct gl_texture_object *texObj = drawAtt->Texture;
813         const GLuint dstLevel = drawAtt->TextureLevel;
814         const GLenum target = texObj->Target;
815
816         struct gl_texture_image *texImage =
817            _mesa_select_tex_image(ctx, texObj, target, dstLevel);
818         GLenum internalFormat = texImage->InternalFormat;
819
820         if (intel_copy_texsubimage(intel_context(ctx), target,
821                                    intel_texture_image(texImage),
822                                    internalFormat,
823                                    dstX0, dstY0,
824                                    srcX0, srcY0,
825                                    srcX1 - srcX0, /* width */
826                                    srcY1 - srcY0))
827            mask &= ~GL_COLOR_BUFFER_BIT;
828      }
829   }
830
831   return mask;
832}
833
834static void
835intel_blit_framebuffer(struct gl_context *ctx,
836                       GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
837                       GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
838                       GLbitfield mask, GLenum filter)
839{
840   /* Try faster, glCopyTexSubImage2D approach first which uses the BLT. */
841   mask = intel_blit_framebuffer_copy_tex_sub_image(ctx,
842                                                    srcX0, srcY0, srcX1, srcY1,
843                                                    dstX0, dstY0, dstX1, dstY1,
844                                                    mask, filter);
845   if (mask == 0x0)
846      return;
847
848   _mesa_meta_BlitFramebuffer(ctx,
849                              srcX0, srcY0, srcX1, srcY1,
850                              dstX0, dstY0, dstX1, dstY1,
851                              mask, filter);
852}
853
854/**
855 * Do one-time context initializations related to GL_EXT_framebuffer_object.
856 * Hook in device driver functions.
857 */
858void
859intel_fbo_init(struct intel_context *intel)
860{
861   intel->ctx.Driver.NewFramebuffer = intel_new_framebuffer;
862   intel->ctx.Driver.NewRenderbuffer = intel_new_renderbuffer;
863   intel->ctx.Driver.BindFramebuffer = intel_bind_framebuffer;
864   intel->ctx.Driver.FramebufferRenderbuffer = intel_framebuffer_renderbuffer;
865   intel->ctx.Driver.RenderTexture = intel_render_texture;
866   intel->ctx.Driver.FinishRenderTexture = intel_finish_render_texture;
867   intel->ctx.Driver.ResizeBuffers = intel_resize_buffers;
868   intel->ctx.Driver.ValidateFramebuffer = intel_validate_framebuffer;
869   intel->ctx.Driver.BlitFramebuffer = intel_blit_framebuffer;
870
871#if FEATURE_OES_EGL_image
872   intel->ctx.Driver.EGLImageTargetRenderbufferStorage =
873      intel_image_target_renderbuffer_storage;
874#endif
875}
876