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