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