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