intel_fbo.c revision 39d0e3632a4ccb10f2ce6578151e854ba52d3c0e
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   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 */
99static void *
100intel_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 */
114static GLboolean
115intel_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->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat);
151   rb->DataType = intel_mesa_format_to_rb_datatype(rb->Format);
152   cpp = _mesa_get_format_bytes(rb->Format);
153
154   intel_flush(ctx);
155
156   /* free old region */
157   if (irb->region) {
158      intel_region_release(&irb->region);
159   }
160   if (irb->hiz_region) {
161      intel_region_release(&irb->hiz_region);
162   }
163
164   /* allocate new memory region/renderbuffer */
165
166   /* alloc hardware renderbuffer */
167   DBG("Allocating %d x %d Intel RBO\n", width, height);
168
169   tiling = I915_TILING_NONE;
170   if (intel->use_texture_tiling) {
171      GLenum base_format = _mesa_get_format_base_format(rb->Format);
172
173      if (intel->gen >= 4 && (base_format == GL_DEPTH_COMPONENT ||
174			      base_format == GL_STENCIL_INDEX ||
175			      base_format == GL_DEPTH_STENCIL))
176	 tiling = I915_TILING_Y;
177      else
178	 tiling = I915_TILING_X;
179   }
180
181   if (irb->Base.Format == MESA_FORMAT_S8) {
182      /*
183       * The stencil buffer has quirky pitch requirements.  From Vol 2a,
184       * 11.5.6.2.1 3DSTATE_STENCIL_BUFFER, field "Surface Pitch":
185       *    The pitch must be set to 2x the value computed based on width, as
186       *    the stencil buffer is stored with two rows interleaved.
187       * To accomplish this, we resort to the nasty hack of doubling the drm
188       * region's cpp and halving its height.
189       *
190       * If we neglect to double the pitch, then drm_intel_gem_bo_map_gtt()
191       * maps the memory incorrectly.
192       */
193      irb->region = intel_region_alloc(intel->intelScreen,
194				       I915_TILING_Y,
195				       cpp * 2,
196				       width,
197				       height / 2,
198				       GL_TRUE);
199   } else {
200      irb->region = intel_region_alloc(intel->intelScreen, tiling, cpp,
201				       width, height, GL_TRUE);
202   }
203
204   if (!irb->region)
205      return GL_FALSE;       /* out of memory? */
206
207   ASSERT(irb->region->buffer);
208
209   if (intel->vtbl.is_hiz_depth_format(intel, rb->Format)) {
210      irb->hiz_region = intel_region_alloc(intel->intelScreen,
211                                           I915_TILING_Y,
212                                           irb->region->cpp,
213                                           irb->region->width,
214                                           irb->region->height,
215                                           GL_TRUE);
216      if (!irb->hiz_region) {
217         intel_region_release(&irb->region);
218         return GL_FALSE;
219      }
220   }
221
222   rb->Width = width;
223   rb->Height = height;
224
225   return GL_TRUE;
226}
227
228
229#if FEATURE_OES_EGL_image
230static void
231intel_image_target_renderbuffer_storage(struct gl_context *ctx,
232					struct gl_renderbuffer *rb,
233					void *image_handle)
234{
235   struct intel_context *intel = intel_context(ctx);
236   struct intel_renderbuffer *irb;
237   __DRIscreen *screen;
238   __DRIimage *image;
239
240   screen = intel->intelScreen->driScrnPriv;
241   image = screen->dri2.image->lookupEGLImage(screen, image_handle,
242					      screen->loaderPrivate);
243   if (image == NULL)
244      return;
245
246   irb = intel_renderbuffer(rb);
247   if (irb->region)
248      intel_region_release(&irb->region);
249   intel_region_reference(&irb->region, image->region);
250
251   rb->InternalFormat = image->internal_format;
252   rb->Width = image->region->width;
253   rb->Height = image->region->height;
254   rb->Format = image->format;
255   rb->DataType = image->data_type;
256   rb->_BaseFormat = _mesa_base_fbo_format(&intel->ctx,
257					   image->internal_format);
258}
259#endif
260
261/**
262 * Called for each hardware renderbuffer when a _window_ is resized.
263 * Just update fields.
264 * Not used for user-created renderbuffers!
265 */
266static GLboolean
267intel_alloc_window_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
268                           GLenum internalFormat, GLuint width, GLuint height)
269{
270   ASSERT(rb->Name == 0);
271   rb->Width = width;
272   rb->Height = height;
273   rb->InternalFormat = internalFormat;
274
275   return GL_TRUE;
276}
277
278
279static void
280intel_resize_buffers(struct gl_context *ctx, struct gl_framebuffer *fb,
281		     GLuint width, GLuint height)
282{
283   int i;
284
285   _mesa_resize_framebuffer(ctx, fb, width, height);
286
287   fb->Initialized = GL_TRUE; /* XXX remove someday */
288
289   if (fb->Name != 0) {
290      return;
291   }
292
293
294   /* Make sure all window system renderbuffers are up to date */
295   for (i = BUFFER_FRONT_LEFT; i <= BUFFER_BACK_RIGHT; i++) {
296      struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer;
297
298      /* only resize if size is changing */
299      if (rb && (rb->Width != width || rb->Height != height)) {
300	 rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height);
301      }
302   }
303}
304
305
306/** Dummy function for gl_renderbuffer::AllocStorage() */
307static GLboolean
308intel_nop_alloc_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
309                        GLenum internalFormat, GLuint width, GLuint height)
310{
311   _mesa_problem(ctx, "intel_op_alloc_storage should never be called.");
312   return GL_FALSE;
313}
314
315
316void
317intel_renderbuffer_set_region(struct intel_context *intel,
318			      struct intel_renderbuffer *rb,
319			      struct intel_region *region)
320{
321   struct intel_region *old;
322
323   old = rb->region;
324   rb->region = NULL;
325   intel_region_reference(&rb->region, region);
326   intel_region_release(&old);
327}
328
329
330void
331intel_renderbuffer_set_hiz_region(struct intel_context *intel,
332				  struct intel_renderbuffer *rb,
333				  struct intel_region *region)
334{
335   struct intel_region *old = rb->hiz_region;
336   rb->hiz_region = NULL;
337   intel_region_reference(&rb->hiz_region, region);
338   intel_region_release(&old);
339}
340
341
342/**
343 * Create a new intel_renderbuffer which corresponds to an on-screen window,
344 * not a user-created renderbuffer.
345 */
346struct intel_renderbuffer *
347intel_create_renderbuffer(gl_format format)
348{
349   GET_CURRENT_CONTEXT(ctx);
350
351   struct intel_renderbuffer *irb;
352
353   irb = CALLOC_STRUCT(intel_renderbuffer);
354   if (!irb) {
355      _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer");
356      return NULL;
357   }
358
359   _mesa_init_renderbuffer(&irb->Base, 0);
360   irb->Base.ClassID = INTEL_RB_CLASS;
361   irb->Base._BaseFormat = _mesa_get_format_base_format(format);
362   irb->Base.Format = format;
363   irb->Base.InternalFormat = irb->Base._BaseFormat;
364   irb->Base.DataType = intel_mesa_format_to_rb_datatype(format);
365
366   /* intel-specific methods */
367   irb->Base.Delete = intel_delete_renderbuffer;
368   irb->Base.AllocStorage = intel_alloc_window_storage;
369   irb->Base.GetPointer = intel_get_pointer;
370
371   return irb;
372}
373
374
375/**
376 * Create a new renderbuffer object.
377 * Typically called via glBindRenderbufferEXT().
378 */
379static struct gl_renderbuffer *
380intel_new_renderbuffer(struct gl_context * ctx, GLuint name)
381{
382   /*struct intel_context *intel = intel_context(ctx); */
383   struct intel_renderbuffer *irb;
384
385   irb = CALLOC_STRUCT(intel_renderbuffer);
386   if (!irb) {
387      _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer");
388      return NULL;
389   }
390
391   _mesa_init_renderbuffer(&irb->Base, name);
392   irb->Base.ClassID = INTEL_RB_CLASS;
393
394   /* intel-specific methods */
395   irb->Base.Delete = intel_delete_renderbuffer;
396   irb->Base.AllocStorage = intel_alloc_renderbuffer_storage;
397   irb->Base.GetPointer = intel_get_pointer;
398   /* span routines set in alloc_storage function */
399
400   return &irb->Base;
401}
402
403
404/**
405 * Called via glBindFramebufferEXT().
406 */
407static void
408intel_bind_framebuffer(struct gl_context * ctx, GLenum target,
409                       struct gl_framebuffer *fb, struct gl_framebuffer *fbread)
410{
411   if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) {
412      intel_draw_buffer(ctx, fb);
413   }
414   else {
415      /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */
416   }
417}
418
419
420/**
421 * Called via glFramebufferRenderbufferEXT().
422 */
423static void
424intel_framebuffer_renderbuffer(struct gl_context * ctx,
425                               struct gl_framebuffer *fb,
426                               GLenum attachment, struct gl_renderbuffer *rb)
427{
428   DBG("Intel FramebufferRenderbuffer %u %u\n", fb->Name, rb ? rb->Name : 0);
429
430   intel_flush(ctx);
431
432   _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
433   intel_draw_buffer(ctx, fb);
434}
435
436
437static GLboolean
438intel_update_wrapper(struct gl_context *ctx, struct intel_renderbuffer *irb,
439		     struct gl_texture_image *texImage)
440{
441   struct intel_context *intel = intel_context(ctx);
442   struct intel_texture_image *intel_image = intel_texture_image(texImage);
443
444   if (!intel_span_supports_format(texImage->TexFormat)) {
445      DBG("Render to texture BAD FORMAT %s\n",
446	  _mesa_get_format_name(texImage->TexFormat));
447      return GL_FALSE;
448   } else {
449      DBG("Render to texture %s\n", _mesa_get_format_name(texImage->TexFormat));
450   }
451
452   irb->Base.Format = texImage->TexFormat;
453   irb->Base.DataType = intel_mesa_format_to_rb_datatype(texImage->TexFormat);
454   irb->Base.InternalFormat = texImage->InternalFormat;
455   irb->Base._BaseFormat = _mesa_base_tex_format(ctx, irb->Base.InternalFormat);
456   irb->Base.Width = texImage->Width;
457   irb->Base.Height = texImage->Height;
458
459   irb->Base.Delete = intel_delete_renderbuffer;
460   irb->Base.AllocStorage = intel_nop_alloc_storage;
461
462   /* Point the renderbuffer's region to the texture's region. */
463   if (irb->region != intel_image->mt->region) {
464      intel_region_release(&irb->region);
465      intel_region_reference(&irb->region, intel_image->mt->region);
466   }
467
468   /* Allocate the texture's hiz region if necessary. */
469   if (intel->vtbl.is_hiz_depth_format(intel, texImage->TexFormat)
470       && !intel_image->mt->hiz_region) {
471      intel_image->mt->hiz_region =
472         intel_region_alloc(intel->intelScreen,
473                            I915_TILING_Y,
474                            _mesa_get_format_bytes(texImage->TexFormat),
475                            texImage->Width,
476                            texImage->Height,
477                            GL_TRUE);
478      if (!intel_image->mt->hiz_region)
479         return GL_FALSE;
480   }
481
482   /* Point the renderbuffer's hiz region to the texture's hiz region. */
483   if (irb->hiz_region != intel_image->mt->hiz_region) {
484      intel_region_release(&irb->hiz_region);
485      intel_region_reference(&irb->hiz_region, intel_image->mt->hiz_region);
486   }
487
488   return GL_TRUE;
489}
490
491
492/**
493 * When glFramebufferTexture[123]D is called this function sets up the
494 * gl_renderbuffer wrapper around the texture image.
495 * This will have the region info needed for hardware rendering.
496 */
497static struct intel_renderbuffer *
498intel_wrap_texture(struct gl_context * ctx, struct gl_texture_image *texImage)
499{
500   const GLuint name = ~0;   /* not significant, but distinct for debugging */
501   struct intel_renderbuffer *irb;
502
503   /* make an intel_renderbuffer to wrap the texture image */
504   irb = CALLOC_STRUCT(intel_renderbuffer);
505   if (!irb) {
506      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture");
507      return NULL;
508   }
509
510   _mesa_init_renderbuffer(&irb->Base, name);
511   irb->Base.ClassID = INTEL_RB_CLASS;
512
513   if (!intel_update_wrapper(ctx, irb, texImage)) {
514      free(irb);
515      return NULL;
516   }
517
518   return irb;
519}
520
521static void
522intel_renderbuffer_set_draw_offset(struct intel_renderbuffer *irb,
523				   struct intel_texture_image *intel_image,
524				   int zoffset)
525{
526   struct intel_mipmap_tree *mt = intel_image->mt;
527   unsigned int dst_x, dst_y;
528
529   /* compute offset of the particular 2D image within the texture region */
530   intel_miptree_get_image_offset(intel_image->mt,
531				  intel_image->level,
532				  intel_image->face,
533				  zoffset,
534				  &dst_x, &dst_y);
535
536   irb->draw_offset = (dst_y * mt->region->pitch + dst_x) * mt->cpp;
537   irb->draw_x = dst_x;
538   irb->draw_y = dst_y;
539}
540
541/**
542 * Rendering to tiled buffers requires that the base address of the
543 * buffer be aligned to a page boundary.  We generally render to
544 * textures by pointing the surface at the mipmap image level, which
545 * may not be aligned to a tile boundary.
546 *
547 * This function returns an appropriately-aligned base offset
548 * according to the tiling restrictions, plus any required x/y offset
549 * from there.
550 */
551uint32_t
552intel_renderbuffer_tile_offsets(struct intel_renderbuffer *irb,
553				uint32_t *tile_x,
554				uint32_t *tile_y)
555{
556   int cpp = irb->region->cpp;
557   uint32_t pitch = irb->region->pitch * cpp;
558
559   if (irb->region->tiling == I915_TILING_NONE) {
560      *tile_x = 0;
561      *tile_y = 0;
562      return irb->draw_x * cpp + irb->draw_y * pitch;
563   } else if (irb->region->tiling == I915_TILING_X) {
564      *tile_x = irb->draw_x % (512 / cpp);
565      *tile_y = irb->draw_y % 8;
566      return ((irb->draw_y / 8) * (8 * pitch) +
567	      (irb->draw_x - *tile_x) / (512 / cpp) * 4096);
568   } else {
569      assert(irb->region->tiling == I915_TILING_Y);
570      *tile_x = irb->draw_x % (128 / cpp);
571      *tile_y = irb->draw_y % 32;
572      return ((irb->draw_y / 32) * (32 * pitch) +
573	      (irb->draw_x - *tile_x) / (128 / cpp) * 4096);
574   }
575}
576
577/**
578 * Called by glFramebufferTexture[123]DEXT() (and other places) to
579 * prepare for rendering into texture memory.  This might be called
580 * many times to choose different texture levels, cube faces, etc
581 * before intel_finish_render_texture() is ever called.
582 */
583static void
584intel_render_texture(struct gl_context * ctx,
585                     struct gl_framebuffer *fb,
586                     struct gl_renderbuffer_attachment *att)
587{
588   struct gl_texture_image *image = _mesa_get_attachment_teximage(att);
589   struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer);
590   struct intel_texture_image *intel_image = intel_texture_image(image);
591
592   (void) fb;
593
594   if (!intel_image->mt) {
595      /* Fallback on drawing to a texture that doesn't have a miptree
596       * (has a border, width/height 0, etc.)
597       */
598      _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
599      _swrast_render_texture(ctx, fb, att);
600      return;
601   }
602   else if (!irb) {
603      irb = intel_wrap_texture(ctx, image);
604      if (irb) {
605         /* bind the wrapper to the attachment point */
606         _mesa_reference_renderbuffer(&att->Renderbuffer, &irb->Base);
607      }
608      else {
609         /* fallback to software rendering */
610         _swrast_render_texture(ctx, fb, att);
611         return;
612      }
613   }
614
615   if (!intel_update_wrapper(ctx, irb, image)) {
616       _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
617       _swrast_render_texture(ctx, fb, att);
618       return;
619   }
620
621   DBG("Begin render texture tid %lx tex=%u w=%d h=%d refcount=%d\n",
622       _glthread_GetID(),
623       att->Texture->Name, image->Width, image->Height,
624       irb->Base.RefCount);
625
626   intel_renderbuffer_set_draw_offset(irb, intel_image, att->Zoffset);
627   intel_image->used_as_render_target = GL_TRUE;
628
629#ifndef I915
630   if (!brw_context(ctx)->has_surface_tile_offset &&
631       (irb->draw_offset & 4095) != 0) {
632      /* Original gen4 hardware couldn't draw to a non-tile-aligned
633       * destination in a miptree unless you actually setup your
634       * renderbuffer as a miptree and used the fragile
635       * lod/array_index/etc. controls to select the image.  So,
636       * instead, we just make a new single-level miptree and render
637       * into that.
638       */
639      struct intel_context *intel = intel_context(ctx);
640      struct intel_mipmap_tree *old_mt = intel_image->mt;
641      struct intel_mipmap_tree *new_mt;
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				    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