1 /**************************************************************************
2  *
3  * Copyright 2006 VMware, Inc.
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 VMWARE 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/macros.h"
31 #include "main/mtypes.h"
32 #include "main/fbobject.h"
33 #include "main/framebuffer.h"
34 #include "main/renderbuffer.h"
35 #include "main/context.h"
36 #include "main/teximage.h"
37 #include "main/image.h"
38 
39 #include "util/u_memory.h"
40 #include "swrast/swrast.h"
41 #include "drivers/common/meta.h"
42 
43 #include "intel_context.h"
44 #include "intel_batchbuffer.h"
45 #include "intel_buffers.h"
46 #include "intel_blit.h"
47 #include "intel_fbo.h"
48 #include "intel_mipmap_tree.h"
49 #include "intel_regions.h"
50 #include "intel_tex.h"
51 
52 #define FILE_DEBUG_FLAG DEBUG_FBO
53 
54 static struct gl_renderbuffer *
55 intel_new_renderbuffer(struct gl_context * ctx, GLuint name);
56 
57 struct intel_region*
intel_get_rb_region(struct gl_framebuffer * fb,GLuint attIndex)58 intel_get_rb_region(struct gl_framebuffer *fb, GLuint attIndex)
59 {
60    struct intel_renderbuffer *irb = intel_get_renderbuffer(fb, attIndex);
61    if (irb && irb->mt)
62       return irb->mt->region;
63    else
64       return NULL;
65 }
66 
67 /** Called by gl_renderbuffer::Delete() */
68 static void
intel_delete_renderbuffer(struct gl_context * ctx,struct gl_renderbuffer * rb)69 intel_delete_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb)
70 {
71    struct intel_renderbuffer *irb = intel_renderbuffer(rb);
72 
73    assert(irb);
74 
75    intel_miptree_release(&irb->mt);
76 
77    _mesa_delete_renderbuffer(ctx, rb);
78 }
79 
80 /**
81  * \see dd_function_table::MapRenderbuffer
82  */
83 static void
intel_map_renderbuffer(struct gl_context * ctx,struct gl_renderbuffer * rb,GLuint x,GLuint y,GLuint w,GLuint h,GLbitfield mode,GLubyte ** out_map,GLint * out_stride,bool flip_y)84 intel_map_renderbuffer(struct gl_context *ctx,
85 		       struct gl_renderbuffer *rb,
86 		       GLuint x, GLuint y, GLuint w, GLuint h,
87 		       GLbitfield mode,
88 		       GLubyte **out_map,
89 		       GLint *out_stride,
90 		       bool flip_y)
91 {
92    struct intel_context *intel = intel_context(ctx);
93    struct swrast_renderbuffer *srb = (struct swrast_renderbuffer *)rb;
94    struct intel_renderbuffer *irb = intel_renderbuffer(rb);
95    void *map;
96    int stride;
97 
98    /* driver does not support GL_FRAMEBUFFER_FLIP_Y_MESA */
99    assert((rb->Name == 0) == flip_y);
100 
101    if (srb->Buffer) {
102       /* this is a malloc'd renderbuffer (accum buffer), not an irb */
103       GLint bpp = _mesa_get_format_bytes(rb->Format);
104       GLint rowStride = srb->RowStride;
105       *out_map = (GLubyte *) srb->Buffer + y * rowStride + x * bpp;
106       *out_stride = rowStride;
107       return;
108    }
109 
110    intel_prepare_render(intel);
111 
112    /* For a window-system renderbuffer, we need to flip the mapping we receive
113     * upside-down.  So we need to ask for a rectangle on flipped vertically, and
114     * we then return a pointer to the bottom of it with a negative stride.
115     */
116    if (rb->Name == 0) {
117       y = rb->Height - y - h;
118    }
119 
120    intel_miptree_map(intel, irb->mt, irb->mt_level, irb->mt_layer,
121 		     x, y, w, h, mode, &map, &stride);
122 
123    if (rb->Name == 0) {
124       map += (h - 1) * stride;
125       stride = -stride;
126    }
127 
128    DBG("%s: rb %d (%s) mt mapped: (%d, %d) (%dx%d) -> %p/%d\n",
129        __func__, rb->Name, _mesa_get_format_name(rb->Format),
130        x, y, w, h, map, stride);
131 
132    *out_map = map;
133    *out_stride = stride;
134 }
135 
136 /**
137  * \see dd_function_table::UnmapRenderbuffer
138  */
139 static void
intel_unmap_renderbuffer(struct gl_context * ctx,struct gl_renderbuffer * rb)140 intel_unmap_renderbuffer(struct gl_context *ctx,
141 			 struct gl_renderbuffer *rb)
142 {
143    struct intel_context *intel = intel_context(ctx);
144    struct swrast_renderbuffer *srb = (struct swrast_renderbuffer *)rb;
145    struct intel_renderbuffer *irb = intel_renderbuffer(rb);
146 
147    DBG("%s: rb %d (%s)\n", __func__,
148        rb->Name, _mesa_get_format_name(rb->Format));
149 
150    if (srb->Buffer) {
151       /* this is a malloc'd renderbuffer (accum buffer) */
152       /* nothing to do */
153       return;
154    }
155 
156    intel_miptree_unmap(intel, irb->mt, irb->mt_level, irb->mt_layer);
157 }
158 
159 static mesa_format
intel_renderbuffer_format(struct gl_context * ctx,GLenum internalFormat)160 intel_renderbuffer_format(struct gl_context * ctx, GLenum internalFormat)
161 {
162    struct intel_context *intel = intel_context(ctx);
163 
164    switch (internalFormat) {
165    default:
166       /* Use the same format-choice logic as for textures.
167        * Renderbuffers aren't any different from textures for us,
168        * except they're less useful because you can't texture with
169        * them.
170        */
171       return intel->ctx.Driver.ChooseTextureFormat(ctx, GL_TEXTURE_2D,
172                                                    internalFormat,
173                                                    GL_NONE, GL_NONE);
174 
175    case GL_DEPTH_COMPONENT16:
176       return MESA_FORMAT_Z_UNORM16;
177    case GL_DEPTH_COMPONENT:
178    case GL_DEPTH_COMPONENT24:
179    case GL_DEPTH_COMPONENT32:
180       return MESA_FORMAT_Z24_UNORM_X8_UINT;
181    case GL_DEPTH_STENCIL_EXT:
182    case GL_DEPTH24_STENCIL8_EXT:
183    case GL_STENCIL_INDEX:
184    case GL_STENCIL_INDEX1_EXT:
185    case GL_STENCIL_INDEX4_EXT:
186    case GL_STENCIL_INDEX8_EXT:
187    case GL_STENCIL_INDEX16_EXT:
188       /* These aren't actual texture formats, so force them here. */
189       return MESA_FORMAT_Z24_UNORM_S8_UINT;
190    }
191 }
192 
193 static GLboolean
intel_alloc_private_renderbuffer_storage(struct gl_context * ctx,struct gl_renderbuffer * rb,GLenum internalFormat,GLuint width,GLuint height)194 intel_alloc_private_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
195                                          GLenum internalFormat,
196                                          GLuint width, GLuint height)
197 {
198    struct intel_context *intel = intel_context(ctx);
199    struct intel_renderbuffer *irb = intel_renderbuffer(rb);
200 
201    assert(rb->Format != MESA_FORMAT_NONE);
202 
203    rb->Width = width;
204    rb->Height = height;
205    rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat);
206 
207    intel_miptree_release(&irb->mt);
208 
209    DBG("%s: %s: %s (%dx%d)\n", __func__,
210        _mesa_enum_to_string(internalFormat),
211        _mesa_get_format_name(rb->Format), width, height);
212 
213    if (width == 0 || height == 0)
214       return true;
215 
216    irb->mt = intel_miptree_create_for_renderbuffer(intel, rb->Format,
217 						   width, height);
218    if (!irb->mt)
219       return false;
220 
221    return true;
222 }
223 
224 /**
225  * Called via glRenderbufferStorageEXT() to set the format and allocate
226  * storage for a user-created renderbuffer.
227  */
228 static GLboolean
intel_alloc_renderbuffer_storage(struct gl_context * ctx,struct gl_renderbuffer * rb,GLenum internalFormat,GLuint width,GLuint height)229 intel_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
230                                  GLenum internalFormat,
231                                  GLuint width, GLuint height)
232 {
233    rb->Format = intel_renderbuffer_format(ctx, internalFormat);
234    return intel_alloc_private_renderbuffer_storage(ctx, rb, internalFormat, width, height);
235 }
236 
237 static void
intel_image_target_renderbuffer_storage(struct gl_context * ctx,struct gl_renderbuffer * rb,void * image_handle)238 intel_image_target_renderbuffer_storage(struct gl_context *ctx,
239 					struct gl_renderbuffer *rb,
240 					void *image_handle)
241 {
242    struct intel_context *intel = intel_context(ctx);
243    struct intel_renderbuffer *irb;
244    __DRIscreen *screen;
245    __DRIimage *image;
246 
247    screen = intel->intelScreen->driScrnPriv;
248    image = screen->dri2.image->lookupEGLImage(screen, image_handle,
249 					      screen->loaderPrivate);
250    if (image == NULL)
251       return;
252 
253    /* __DRIimage is opaque to the core so it has to be checked here */
254    switch (image->format) {
255    case MESA_FORMAT_R8G8B8A8_UNORM:
256       _mesa_error(&intel->ctx, GL_INVALID_OPERATION,
257             "glEGLImageTargetRenderbufferStorage(unsupported image format");
258       return;
259       break;
260    default:
261       break;
262    }
263 
264    irb = intel_renderbuffer(rb);
265    intel_miptree_release(&irb->mt);
266    irb->mt = intel_miptree_create_for_bo(intel,
267                                          image->region->bo,
268                                          image->format,
269                                          image->offset,
270                                          image->region->width,
271                                          image->region->height,
272                                          image->region->pitch,
273                                          image->region->tiling);
274    if (!irb->mt)
275       return;
276 
277    rb->InternalFormat = image->internal_format;
278    rb->Width = image->region->width;
279    rb->Height = image->region->height;
280    rb->Format = image->format;
281    rb->_BaseFormat = _mesa_get_format_base_format(image->format);
282    rb->NeedsFinishRenderTexture = true;
283 }
284 
285 /**
286  * Called by _mesa_resize_framebuffer() for each hardware renderbuffer when a
287  * window system framebuffer is resized.
288  *
289  * Any actual buffer reallocations for hardware renderbuffers (which would
290  * have triggered _mesa_resize_framebuffer()) were done by
291  * intel_process_dri2_buffer().
292  */
293 static GLboolean
intel_alloc_window_storage(UNUSED struct gl_context * ctx,struct gl_renderbuffer * rb,GLenum internalFormat,GLuint width,GLuint height)294 intel_alloc_window_storage(UNUSED struct gl_context *ctx, struct gl_renderbuffer *rb,
295                            GLenum internalFormat, GLuint width, GLuint height)
296 {
297    assert(rb->Name == 0);
298    rb->Width = width;
299    rb->Height = height;
300    rb->InternalFormat = internalFormat;
301 
302    return true;
303 }
304 
305 /** Dummy function for gl_renderbuffer::AllocStorage() */
306 static GLboolean
intel_nop_alloc_storage(UNUSED struct gl_context * ctx,UNUSED struct gl_renderbuffer * rb,UNUSED GLenum internalFormat,UNUSED GLuint width,UNUSED GLuint height)307 intel_nop_alloc_storage(UNUSED struct gl_context *ctx,
308                         UNUSED struct gl_renderbuffer *rb,
309                         UNUSED GLenum internalFormat,
310                         UNUSED GLuint width, UNUSED GLuint height)
311 {
312    _mesa_problem(ctx, "intel_op_alloc_storage should never be called.");
313    return false;
314 }
315 
316 /**
317  * Create a new intel_renderbuffer which corresponds to an on-screen window,
318  * not a user-created renderbuffer.
319  */
320 struct intel_renderbuffer *
intel_create_renderbuffer(mesa_format format)321 intel_create_renderbuffer(mesa_format format)
322 {
323    struct intel_renderbuffer *irb;
324    struct gl_renderbuffer *rb;
325 
326    GET_CURRENT_CONTEXT(ctx);
327 
328    irb = CALLOC_STRUCT(intel_renderbuffer);
329    if (!irb) {
330       _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer");
331       return NULL;
332    }
333 
334    rb = &irb->Base.Base;
335 
336    _mesa_init_renderbuffer(rb, 0);
337    rb->ClassID = INTEL_RB_CLASS;
338    rb->_BaseFormat = _mesa_get_format_base_format(format);
339    rb->Format = format;
340    rb->InternalFormat = rb->_BaseFormat;
341 
342    /* intel-specific methods */
343    rb->Delete = intel_delete_renderbuffer;
344    rb->AllocStorage = intel_alloc_window_storage;
345 
346    return irb;
347 }
348 
349 /**
350  * Private window-system buffers (as opposed to ones shared with the display
351  * server created with intel_create_renderbuffer()) are most similar in their
352  * handling to user-created renderbuffers, but they have a resize handler that
353  * may be called at intel_update_renderbuffers() time.
354  */
355 struct intel_renderbuffer *
intel_create_private_renderbuffer(mesa_format format)356 intel_create_private_renderbuffer(mesa_format format)
357 {
358    struct intel_renderbuffer *irb;
359 
360    irb = intel_create_renderbuffer(format);
361    irb->Base.Base.AllocStorage = intel_alloc_private_renderbuffer_storage;
362 
363    return irb;
364 }
365 
366 /**
367  * Create a new renderbuffer object.
368  * Typically called via glBindRenderbufferEXT().
369  */
370 static struct gl_renderbuffer *
intel_new_renderbuffer(struct gl_context * ctx,GLuint name)371 intel_new_renderbuffer(struct gl_context * ctx, GLuint name)
372 {
373    /*struct intel_context *intel = intel_context(ctx); */
374    struct intel_renderbuffer *irb;
375    struct gl_renderbuffer *rb;
376 
377    irb = CALLOC_STRUCT(intel_renderbuffer);
378    if (!irb) {
379       _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer");
380       return NULL;
381    }
382 
383    rb = &irb->Base.Base;
384 
385    _mesa_init_renderbuffer(rb, name);
386    rb->ClassID = INTEL_RB_CLASS;
387 
388    /* intel-specific methods */
389    rb->Delete = intel_delete_renderbuffer;
390    rb->AllocStorage = intel_alloc_renderbuffer_storage;
391    /* span routines set in alloc_storage function */
392 
393    return rb;
394 }
395 
396 
397 /**
398  * Called via glBindFramebufferEXT().
399  */
400 static void
intel_bind_framebuffer(struct gl_context * ctx,GLenum target,UNUSED struct gl_framebuffer * fb,UNUSED struct gl_framebuffer * fbread)401 intel_bind_framebuffer(struct gl_context * ctx, GLenum target,
402                        UNUSED struct gl_framebuffer *fb,
403                        UNUSED struct gl_framebuffer *fbread)
404 {
405    if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) {
406       intel_draw_buffer(ctx);
407    }
408    else {
409       /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */
410    }
411 }
412 
413 
414 /**
415  * Called via glFramebufferRenderbufferEXT().
416  */
417 static void
intel_framebuffer_renderbuffer(struct gl_context * ctx,struct gl_framebuffer * fb,GLenum attachment,struct gl_renderbuffer * rb)418 intel_framebuffer_renderbuffer(struct gl_context * ctx,
419                                struct gl_framebuffer *fb,
420                                GLenum attachment, struct gl_renderbuffer *rb)
421 {
422    DBG("Intel FramebufferRenderbuffer %u %u\n", fb->Name, rb ? rb->Name : 0);
423 
424    _mesa_FramebufferRenderbuffer_sw(ctx, fb, attachment, rb);
425    intel_draw_buffer(ctx);
426 }
427 
428 static bool
intel_renderbuffer_update_wrapper(struct intel_renderbuffer * irb,struct gl_texture_image * image,uint32_t layer)429 intel_renderbuffer_update_wrapper(struct intel_renderbuffer *irb,
430 				  struct gl_texture_image *image,
431                                   uint32_t layer)
432 {
433    struct gl_renderbuffer *rb = &irb->Base.Base;
434    struct intel_texture_image *intel_image = intel_texture_image(image);
435    struct intel_mipmap_tree *mt = intel_image->mt;
436    int level = image->Level;
437 
438    rb->AllocStorage = intel_nop_alloc_storage;
439 
440    intel_miptree_check_level_layer(mt, level, layer);
441    irb->mt_level = level;
442    irb->mt_layer = layer;
443 
444    intel_miptree_reference(&irb->mt, mt);
445 
446    intel_renderbuffer_set_draw_offset(irb);
447 
448    return true;
449 }
450 
451 void
intel_renderbuffer_set_draw_offset(struct intel_renderbuffer * irb)452 intel_renderbuffer_set_draw_offset(struct intel_renderbuffer *irb)
453 {
454    unsigned int dst_x, dst_y;
455 
456    /* compute offset of the particular 2D image within the texture region */
457    intel_miptree_get_image_offset(irb->mt,
458 				  irb->mt_level,
459 				  irb->mt_layer,
460 				  &dst_x, &dst_y);
461 
462    irb->draw_x = dst_x;
463    irb->draw_y = dst_y;
464 }
465 
466 /**
467  * Called by glFramebufferTexture[123]DEXT() (and other places) to
468  * prepare for rendering into texture memory.  This might be called
469  * many times to choose different texture levels, cube faces, etc
470  * before intel_finish_render_texture() is ever called.
471  */
472 static void
intel_render_texture(struct gl_context * ctx,struct gl_framebuffer * fb,struct gl_renderbuffer_attachment * att)473 intel_render_texture(struct gl_context * ctx,
474                      struct gl_framebuffer *fb,
475                      struct gl_renderbuffer_attachment *att)
476 {
477    struct gl_renderbuffer *rb = att->Renderbuffer;
478    struct intel_renderbuffer *irb = intel_renderbuffer(rb);
479    struct gl_texture_image *image = rb->TexImage;
480    struct intel_texture_image *intel_image = intel_texture_image(image);
481    struct intel_mipmap_tree *mt = intel_image->mt;
482    int layer;
483 
484    (void) fb;
485 
486    if (att->CubeMapFace > 0) {
487       assert(att->Zoffset == 0);
488       layer = att->CubeMapFace;
489    } else {
490       layer = att->Zoffset;
491    }
492 
493    if (!intel_image->mt) {
494       /* Fallback on drawing to a texture that doesn't have a miptree
495        * (has a border, width/height 0, etc.)
496        */
497       _swrast_render_texture(ctx, fb, att);
498       return;
499    }
500 
501    intel_miptree_check_level_layer(mt, att->TextureLevel, layer);
502 
503    if (!intel_renderbuffer_update_wrapper(irb, image, layer)) {
504        _swrast_render_texture(ctx, fb, att);
505        return;
506    }
507 
508    DBG("Begin render %s texture tex=%u w=%d h=%d d=%d refcount=%d\n",
509        _mesa_get_format_name(image->TexFormat),
510        att->Texture->Name, image->Width, image->Height, image->Depth,
511        rb->RefCount);
512 
513    /* update drawing region, etc */
514    intel_draw_buffer(ctx);
515 }
516 
517 
518 /**
519  * Called by Mesa when rendering to a texture is done.
520  */
521 static void
intel_finish_render_texture(struct gl_context * ctx,struct gl_renderbuffer * rb)522 intel_finish_render_texture(struct gl_context * ctx, struct gl_renderbuffer *rb)
523 {
524    struct intel_context *intel = intel_context(ctx);
525 
526    DBG("Finish render %s texture\n", _mesa_get_format_name(rb->Format));
527 
528    /* Since we've (probably) rendered to the texture and will (likely) use
529     * it in the texture domain later on in this batchbuffer, flush the
530     * batch.  Once again, we wish for a domain tracker in libdrm to cover
531     * usage inside of a batchbuffer like GEM does in the kernel.
532     */
533    intel_batchbuffer_emit_mi_flush(intel);
534 }
535 
536 #define fbo_incomplete(fb, ...) do {                                          \
537       static GLuint msg_id = 0;                                               \
538       if (unlikely(ctx->Const.ContextFlags & GL_CONTEXT_FLAG_DEBUG_BIT)) {    \
539          _mesa_gl_debugf(ctx, &msg_id,                                        \
540                          MESA_DEBUG_SOURCE_API,                               \
541                          MESA_DEBUG_TYPE_OTHER,                               \
542                          MESA_DEBUG_SEVERITY_MEDIUM,                          \
543                          __VA_ARGS__);                                        \
544       }                                                                       \
545       DBG(__VA_ARGS__);                                                       \
546       fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;                               \
547    } while (0)
548 
549 /**
550  * Do additional "completeness" testing of a framebuffer object.
551  */
552 static void
intel_validate_framebuffer(struct gl_context * ctx,struct gl_framebuffer * fb)553 intel_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
554 {
555    struct intel_context *intel = intel_context(ctx);
556    struct intel_renderbuffer *depthRb =
557       intel_get_renderbuffer(fb, BUFFER_DEPTH);
558    struct intel_renderbuffer *stencilRb =
559       intel_get_renderbuffer(fb, BUFFER_STENCIL);
560    struct intel_mipmap_tree *depth_mt = NULL, *stencil_mt = NULL;
561    int i;
562 
563    DBG("%s() on fb %p (%s)\n", __func__,
564        fb, (fb == ctx->DrawBuffer ? "drawbuffer" :
565 	    (fb == ctx->ReadBuffer ? "readbuffer" : "other buffer")));
566 
567    if (depthRb)
568       depth_mt = depthRb->mt;
569    if (stencilRb)
570       stencil_mt = stencilRb->mt;
571 
572    if (depth_mt && stencil_mt) {
573       /* Make sure that the depth and stencil buffers are actually the same
574        * slice of the same miptree, since we only support packed
575        * depth/stencil.
576        */
577       if (depth_mt == stencil_mt) {
578 	 if (depthRb->mt_level != stencilRb->mt_level ||
579 	     depthRb->mt_layer != stencilRb->mt_layer) {
580 	    fbo_incomplete(fb,
581                            "FBO incomplete: depth image level/layer %d/%d != "
582                            "stencil image %d/%d\n",
583                            depthRb->mt_level,
584                            depthRb->mt_layer,
585                            stencilRb->mt_level,
586                            stencilRb->mt_layer);
587 	 }
588       } else {
589          fbo_incomplete(fb, "FBO incomplete: separate stencil unsupported\n");
590       }
591    }
592 
593    for (i = 0; i < ARRAY_SIZE(fb->Attachment); i++) {
594       struct gl_renderbuffer *rb;
595       struct intel_renderbuffer *irb;
596 
597       if (fb->Attachment[i].Type == GL_NONE)
598 	 continue;
599 
600       /* A supported attachment will have a Renderbuffer set either
601        * from being a Renderbuffer or being a texture that got the
602        * intel_wrap_texture() treatment.
603        */
604       rb = fb->Attachment[i].Renderbuffer;
605       if (rb == NULL) {
606 	 fbo_incomplete(fb, "FBO incomplete: attachment without "
607                         "renderbuffer\n");
608 	 continue;
609       }
610 
611       if (fb->Attachment[i].Type == GL_TEXTURE) {
612 	 if (rb->TexImage->Border) {
613 	    fbo_incomplete(fb, "FBO incomplete: texture with border\n");
614 	    continue;
615 	 }
616       }
617 
618       irb = intel_renderbuffer(rb);
619       if (irb == NULL) {
620 	 fbo_incomplete(fb, "FBO incomplete: software rendering "
621                         "renderbuffer\n");
622 	 continue;
623       }
624 
625       if (!intel->vtbl.render_target_supported(intel, rb)) {
626 	 fbo_incomplete(fb, "FBO incomplete: Unsupported HW "
627                         "texture/renderbuffer format attached: %s\n",
628                         _mesa_get_format_name(intel_rb_format(irb)));
629       }
630    }
631 }
632 
633 /**
634  * Try to do a glBlitFramebuffer using glCopyTexSubImage2D
635  * We can do this when the dst renderbuffer is actually a texture and
636  * there is no scaling, mirroring or scissoring.
637  *
638  * \return new buffer mask indicating the buffers left to blit using the
639  *         normal path.
640  */
641 static GLbitfield
intel_blit_framebuffer_with_blitter(struct gl_context * ctx,const struct gl_framebuffer * readFb,const struct gl_framebuffer * drawFb,GLint srcX0,GLint srcY0,GLint srcX1,GLint srcY1,GLint dstX0,GLint dstY0,GLint dstX1,GLint dstY1,GLbitfield mask)642 intel_blit_framebuffer_with_blitter(struct gl_context *ctx,
643                                     const struct gl_framebuffer *readFb,
644                                     const struct gl_framebuffer *drawFb,
645                                     GLint srcX0, GLint srcY0,
646                                     GLint srcX1, GLint srcY1,
647                                     GLint dstX0, GLint dstY0,
648                                     GLint dstX1, GLint dstY1,
649                                     GLbitfield mask)
650 {
651    struct intel_context *intel = intel_context(ctx);
652 
653    /* Sync up the state of window system buffers.  We need to do this before
654     * we go looking for the buffers.
655     */
656    intel_prepare_render(intel);
657 
658    if (mask & GL_COLOR_BUFFER_BIT) {
659       GLint i;
660       struct gl_renderbuffer *src_rb = readFb->_ColorReadBuffer;
661       struct intel_renderbuffer *src_irb = intel_renderbuffer(src_rb);
662 
663       if (!src_irb) {
664          perf_debug("glBlitFramebuffer(): missing src renderbuffer.  "
665                     "Falling back to software rendering.\n");
666          return mask;
667       }
668 
669       /* If the source and destination are the same size with no mirroring,
670        * the rectangles are within the size of the texture and there is no
671        * scissor, then we can probably use the blit engine.
672        */
673       if (!(srcX0 - srcX1 == dstX0 - dstX1 &&
674             srcY0 - srcY1 == dstY0 - dstY1 &&
675             srcX1 >= srcX0 &&
676             srcY1 >= srcY0 &&
677             srcX0 >= 0 && srcX1 <= readFb->Width &&
678             srcY0 >= 0 && srcY1 <= readFb->Height &&
679             dstX0 >= 0 && dstX1 <= drawFb->Width &&
680             dstY0 >= 0 && dstY1 <= drawFb->Height &&
681             !ctx->Scissor.EnableFlags)) {
682          perf_debug("glBlitFramebuffer(): non-1:1 blit.  "
683                     "Falling back to software rendering.\n");
684          return mask;
685       }
686 
687       /* Blit to all active draw buffers.  We don't do any pre-checking,
688        * because we assume that copying to MRTs is rare, and failure midway
689        * through copying is even more rare.  Even if it was to occur, it's
690        * safe to let meta start the copy over from scratch, because
691        * glBlitFramebuffer completely overwrites the destination pixels, and
692        * results are undefined if any destination pixels have a dependency on
693        * source pixels.
694        */
695       for (i = 0; i < drawFb->_NumColorDrawBuffers; i++) {
696          struct gl_renderbuffer *dst_rb = drawFb->_ColorDrawBuffers[i];
697          struct intel_renderbuffer *dst_irb = intel_renderbuffer(dst_rb);
698 
699          if (!dst_irb) {
700             perf_debug("glBlitFramebuffer(): missing dst renderbuffer.  "
701                        "Falling back to software rendering.\n");
702             return mask;
703          }
704 
705          mesa_format src_format = _mesa_get_srgb_format_linear(src_rb->Format);
706          mesa_format dst_format = _mesa_get_srgb_format_linear(dst_rb->Format);
707          if (src_format != dst_format) {
708             perf_debug("glBlitFramebuffer(): unsupported blit from %s to %s.  "
709                        "Falling back to software rendering.\n",
710                        _mesa_get_format_name(src_format),
711                        _mesa_get_format_name(dst_format));
712             return mask;
713          }
714 
715          if (!intel_miptree_blit(intel,
716                                  src_irb->mt,
717                                  src_irb->mt_level, src_irb->mt_layer,
718                                  srcX0, srcY0, src_rb->Name == 0,
719                                  dst_irb->mt,
720                                  dst_irb->mt_level, dst_irb->mt_layer,
721                                  dstX0, dstY0, dst_rb->Name == 0,
722                                  dstX1 - dstX0, dstY1 - dstY0, COLOR_LOGICOP_COPY)) {
723             perf_debug("glBlitFramebuffer(): unknown blit failure.  "
724                        "Falling back to software rendering.\n");
725             return mask;
726          }
727       }
728 
729       mask &= ~GL_COLOR_BUFFER_BIT;
730    }
731 
732    return mask;
733 }
734 
735 static void
intel_blit_framebuffer(struct gl_context * ctx,struct gl_framebuffer * readFb,struct gl_framebuffer * drawFb,GLint srcX0,GLint srcY0,GLint srcX1,GLint srcY1,GLint dstX0,GLint dstY0,GLint dstX1,GLint dstY1,GLbitfield mask,GLenum filter)736 intel_blit_framebuffer(struct gl_context *ctx,
737                        struct gl_framebuffer *readFb,
738                        struct gl_framebuffer *drawFb,
739                        GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
740                        GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
741                        GLbitfield mask, GLenum filter)
742 {
743    /* Try using the BLT engine. */
744    mask = intel_blit_framebuffer_with_blitter(ctx, readFb, drawFb,
745                                               srcX0, srcY0, srcX1, srcY1,
746                                               dstX0, dstY0, dstX1, dstY1,
747                                               mask);
748    if (mask == 0x0)
749       return;
750 
751 
752    _mesa_meta_and_swrast_BlitFramebuffer(ctx, readFb, drawFb,
753                                          srcX0, srcY0, srcX1, srcY1,
754                                          dstX0, dstY0, dstX1, dstY1,
755                                          mask, filter);
756 }
757 
758 /**
759  * Do one-time context initializations related to GL_EXT_framebuffer_object.
760  * Hook in device driver functions.
761  */
762 void
intel_fbo_init(struct intel_context * intel)763 intel_fbo_init(struct intel_context *intel)
764 {
765    intel->ctx.Driver.NewRenderbuffer = intel_new_renderbuffer;
766    intel->ctx.Driver.MapRenderbuffer = intel_map_renderbuffer;
767    intel->ctx.Driver.UnmapRenderbuffer = intel_unmap_renderbuffer;
768    intel->ctx.Driver.BindFramebuffer = intel_bind_framebuffer;
769    intel->ctx.Driver.FramebufferRenderbuffer = intel_framebuffer_renderbuffer;
770    intel->ctx.Driver.RenderTexture = intel_render_texture;
771    intel->ctx.Driver.FinishRenderTexture = intel_finish_render_texture;
772    intel->ctx.Driver.ValidateFramebuffer = intel_validate_framebuffer;
773    intel->ctx.Driver.BlitFramebuffer = intel_blit_framebuffer;
774    intel->ctx.Driver.EGLImageTargetRenderbufferStorage =
775       intel_image_target_renderbuffer_storage;
776 }
777