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