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