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