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