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