Merge remote branch 'origin/master' into pipe-video
[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 "main/texrender.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 GET_CURRENT_CONTEXT(ctx);
74 struct intel_context *intel = intel_context(ctx);
75 struct intel_renderbuffer *irb = intel_renderbuffer(rb);
76
77 ASSERT(irb);
78
79 if (intel && irb->region) {
80 intel_region_release(&irb->region);
81 }
82
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 static 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 rb->Format = MESA_FORMAT_S8_Z24;
133 break;
134 }
135
136 rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat);
137 rb->DataType = intel_mesa_format_to_rb_datatype(rb->Format);
138 cpp = _mesa_get_format_bytes(rb->Format);
139
140 intel_flush(ctx);
141
142 /* free old region */
143 if (irb->region) {
144 intel_region_release(&irb->region);
145 }
146
147 /* allocate new memory region/renderbuffer */
148
149 /* alloc hardware renderbuffer */
150 DBG("Allocating %d x %d Intel RBO\n", width, height);
151
152 tiling = I915_TILING_NONE;
153 if (intel->use_texture_tiling) {
154 GLenum base_format = _mesa_get_format_base_format(rb->Format);
155
156 if (intel->gen >= 4 && (base_format == GL_DEPTH_COMPONENT ||
157 base_format == GL_DEPTH_STENCIL))
158 tiling = I915_TILING_Y;
159 else
160 tiling = I915_TILING_X;
161 }
162
163 irb->region = intel_region_alloc(intel->intelScreen, tiling, cpp,
164 width, height, GL_TRUE);
165 if (!irb->region)
166 return GL_FALSE; /* out of memory? */
167
168 ASSERT(irb->region->buffer);
169
170 rb->Width = width;
171 rb->Height = height;
172
173 return GL_TRUE;
174 }
175
176
177 #if FEATURE_OES_EGL_image
178 static void
179 intel_image_target_renderbuffer_storage(struct gl_context *ctx,
180 struct gl_renderbuffer *rb,
181 void *image_handle)
182 {
183 struct intel_context *intel = intel_context(ctx);
184 struct intel_renderbuffer *irb;
185 __DRIscreen *screen;
186 __DRIimage *image;
187
188 screen = intel->intelScreen->driScrnPriv;
189 image = screen->dri2.image->lookupEGLImage(screen, image_handle,
190 screen->loaderPrivate);
191 if (image == NULL)
192 return;
193
194 irb = intel_renderbuffer(rb);
195 if (irb->region)
196 intel_region_release(&irb->region);
197 intel_region_reference(&irb->region, image->region);
198
199 rb->InternalFormat = image->internal_format;
200 rb->Width = image->region->width;
201 rb->Height = image->region->height;
202 rb->Format = image->format;
203 rb->DataType = image->data_type;
204 rb->_BaseFormat = _mesa_base_fbo_format(&intel->ctx,
205 image->internal_format);
206 }
207 #endif
208
209 /**
210 * Called for each hardware renderbuffer when a _window_ is resized.
211 * Just update fields.
212 * Not used for user-created renderbuffers!
213 */
214 static GLboolean
215 intel_alloc_window_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
216 GLenum internalFormat, GLuint width, GLuint height)
217 {
218 ASSERT(rb->Name == 0);
219 rb->Width = width;
220 rb->Height = height;
221 rb->InternalFormat = internalFormat;
222
223 return GL_TRUE;
224 }
225
226
227 static void
228 intel_resize_buffers(struct gl_context *ctx, struct gl_framebuffer *fb,
229 GLuint width, GLuint height)
230 {
231 int i;
232
233 _mesa_resize_framebuffer(ctx, fb, width, height);
234
235 fb->Initialized = GL_TRUE; /* XXX remove someday */
236
237 if (fb->Name != 0) {
238 return;
239 }
240
241
242 /* Make sure all window system renderbuffers are up to date */
243 for (i = BUFFER_FRONT_LEFT; i <= BUFFER_BACK_RIGHT; i++) {
244 struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer;
245
246 /* only resize if size is changing */
247 if (rb && (rb->Width != width || rb->Height != height)) {
248 rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height);
249 }
250 }
251 }
252
253
254 /** Dummy function for gl_renderbuffer::AllocStorage() */
255 static GLboolean
256 intel_nop_alloc_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
257 GLenum internalFormat, GLuint width, GLuint height)
258 {
259 _mesa_problem(ctx, "intel_op_alloc_storage should never be called.");
260 return GL_FALSE;
261 }
262
263
264 void
265 intel_renderbuffer_set_region(struct intel_context *intel,
266 struct intel_renderbuffer *rb,
267 struct intel_region *region)
268 {
269 struct intel_region *old;
270
271 old = rb->region;
272 rb->region = NULL;
273 intel_region_reference(&rb->region, region);
274 intel_region_release(&old);
275 }
276
277
278 /**
279 * Create a new intel_renderbuffer which corresponds to an on-screen window,
280 * not a user-created renderbuffer.
281 */
282 struct intel_renderbuffer *
283 intel_create_renderbuffer(gl_format format)
284 {
285 GET_CURRENT_CONTEXT(ctx);
286
287 struct intel_renderbuffer *irb;
288
289 irb = CALLOC_STRUCT(intel_renderbuffer);
290 if (!irb) {
291 _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer");
292 return NULL;
293 }
294
295 _mesa_init_renderbuffer(&irb->Base, 0);
296 irb->Base.ClassID = INTEL_RB_CLASS;
297 irb->Base._BaseFormat = _mesa_get_format_base_format(format);
298 irb->Base.Format = format;
299 irb->Base.InternalFormat = irb->Base._BaseFormat;
300 irb->Base.DataType = intel_mesa_format_to_rb_datatype(format);
301
302 /* intel-specific methods */
303 irb->Base.Delete = intel_delete_renderbuffer;
304 irb->Base.AllocStorage = intel_alloc_window_storage;
305 irb->Base.GetPointer = intel_get_pointer;
306
307 return irb;
308 }
309
310
311 /**
312 * Create a new renderbuffer object.
313 * Typically called via glBindRenderbufferEXT().
314 */
315 static struct gl_renderbuffer *
316 intel_new_renderbuffer(struct gl_context * ctx, GLuint name)
317 {
318 /*struct intel_context *intel = intel_context(ctx); */
319 struct intel_renderbuffer *irb;
320
321 irb = CALLOC_STRUCT(intel_renderbuffer);
322 if (!irb) {
323 _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer");
324 return NULL;
325 }
326
327 _mesa_init_renderbuffer(&irb->Base, name);
328 irb->Base.ClassID = INTEL_RB_CLASS;
329
330 /* intel-specific methods */
331 irb->Base.Delete = intel_delete_renderbuffer;
332 irb->Base.AllocStorage = intel_alloc_renderbuffer_storage;
333 irb->Base.GetPointer = intel_get_pointer;
334 /* span routines set in alloc_storage function */
335
336 return &irb->Base;
337 }
338
339
340 /**
341 * Called via glBindFramebufferEXT().
342 */
343 static void
344 intel_bind_framebuffer(struct gl_context * ctx, GLenum target,
345 struct gl_framebuffer *fb, struct gl_framebuffer *fbread)
346 {
347 if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) {
348 intel_draw_buffer(ctx, fb);
349 }
350 else {
351 /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */
352 }
353 }
354
355
356 /**
357 * Called via glFramebufferRenderbufferEXT().
358 */
359 static void
360 intel_framebuffer_renderbuffer(struct gl_context * ctx,
361 struct gl_framebuffer *fb,
362 GLenum attachment, struct gl_renderbuffer *rb)
363 {
364 DBG("Intel FramebufferRenderbuffer %u %u\n", fb->Name, rb ? rb->Name : 0);
365
366 intel_flush(ctx);
367
368 _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
369 intel_draw_buffer(ctx, fb);
370 }
371
372
373 static GLboolean
374 intel_update_wrapper(struct gl_context *ctx, struct intel_renderbuffer *irb,
375 struct gl_texture_image *texImage)
376 {
377 if (!intel_span_supports_format(texImage->TexFormat)) {
378 DBG("Render to texture BAD FORMAT %s\n",
379 _mesa_get_format_name(texImage->TexFormat));
380 return GL_FALSE;
381 } else {
382 DBG("Render to texture %s\n", _mesa_get_format_name(texImage->TexFormat));
383 }
384
385 irb->Base.Format = texImage->TexFormat;
386 irb->Base.DataType = intel_mesa_format_to_rb_datatype(texImage->TexFormat);
387 irb->Base.InternalFormat = texImage->InternalFormat;
388 irb->Base._BaseFormat = _mesa_base_fbo_format(ctx, irb->Base.InternalFormat);
389 irb->Base.Width = texImage->Width;
390 irb->Base.Height = texImage->Height;
391
392 irb->Base.Delete = intel_delete_renderbuffer;
393 irb->Base.AllocStorage = intel_nop_alloc_storage;
394
395 return GL_TRUE;
396 }
397
398
399 /**
400 * When glFramebufferTexture[123]D is called this function sets up the
401 * gl_renderbuffer wrapper around the texture image.
402 * This will have the region info needed for hardware rendering.
403 */
404 static struct intel_renderbuffer *
405 intel_wrap_texture(struct gl_context * ctx, struct gl_texture_image *texImage)
406 {
407 const GLuint name = ~0; /* not significant, but distinct for debugging */
408 struct intel_renderbuffer *irb;
409
410 /* make an intel_renderbuffer to wrap the texture image */
411 irb = CALLOC_STRUCT(intel_renderbuffer);
412 if (!irb) {
413 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture");
414 return NULL;
415 }
416
417 _mesa_init_renderbuffer(&irb->Base, name);
418 irb->Base.ClassID = INTEL_RB_CLASS;
419
420 if (!intel_update_wrapper(ctx, irb, texImage)) {
421 free(irb);
422 return NULL;
423 }
424
425 return irb;
426 }
427
428 static void
429 intel_set_draw_offset_for_image(struct intel_texture_image *intel_image,
430 int zoffset)
431 {
432 struct intel_mipmap_tree *mt = intel_image->mt;
433 unsigned int dst_x, dst_y;
434
435 /* compute offset of the particular 2D image within the texture region */
436 intel_miptree_get_image_offset(intel_image->mt,
437 intel_image->level,
438 intel_image->face,
439 zoffset,
440 &dst_x, &dst_y);
441
442 mt->region->draw_offset = (dst_y * mt->region->pitch + dst_x) * mt->cpp;
443 mt->region->draw_x = dst_x;
444 mt->region->draw_y = dst_y;
445 }
446
447 /**
448 * Called by glFramebufferTexture[123]DEXT() (and other places) to
449 * prepare for rendering into texture memory. This might be called
450 * many times to choose different texture levels, cube faces, etc
451 * before intel_finish_render_texture() is ever called.
452 */
453 static void
454 intel_render_texture(struct gl_context * ctx,
455 struct gl_framebuffer *fb,
456 struct gl_renderbuffer_attachment *att)
457 {
458 struct gl_texture_image *newImage
459 = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
460 struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer);
461 struct intel_texture_image *intel_image;
462
463 (void) fb;
464
465 ASSERT(newImage);
466
467 intel_image = intel_texture_image(newImage);
468 if (!intel_image->mt) {
469 /* Fallback on drawing to a texture that doesn't have a miptree
470 * (has a border, width/height 0, etc.)
471 */
472 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
473 _mesa_render_texture(ctx, fb, att);
474 return;
475 }
476 else if (!irb) {
477 irb = intel_wrap_texture(ctx, newImage);
478 if (irb) {
479 /* bind the wrapper to the attachment point */
480 _mesa_reference_renderbuffer(&att->Renderbuffer, &irb->Base);
481 }
482 else {
483 /* fallback to software rendering */
484 _mesa_render_texture(ctx, fb, att);
485 return;
486 }
487 }
488
489 if (!intel_update_wrapper(ctx, irb, newImage)) {
490 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
491 _mesa_render_texture(ctx, fb, att);
492 return;
493 }
494
495 DBG("Begin render texture tid %lx tex=%u w=%d h=%d refcount=%d\n",
496 _glthread_GetID(),
497 att->Texture->Name, newImage->Width, newImage->Height,
498 irb->Base.RefCount);
499
500 /* point the renderbufer's region to the texture image region */
501 if (irb->region != intel_image->mt->region) {
502 if (irb->region)
503 intel_region_release(&irb->region);
504 intel_region_reference(&irb->region, intel_image->mt->region);
505 }
506
507 intel_set_draw_offset_for_image(intel_image, att->Zoffset);
508 intel_image->used_as_render_target = GL_TRUE;
509
510 #ifndef I915
511 if (!brw_context(ctx)->has_surface_tile_offset &&
512 (intel_image->mt->region->draw_offset & 4095) != 0) {
513 /* Original gen4 hardware couldn't draw to a non-tile-aligned
514 * destination in a miptree unless you actually setup your
515 * renderbuffer as a miptree and used the fragile
516 * lod/array_index/etc. controls to select the image. So,
517 * instead, we just make a new single-level miptree and render
518 * into that.
519 */
520 struct intel_context *intel = intel_context(ctx);
521 struct intel_mipmap_tree *old_mt = intel_image->mt;
522 struct intel_mipmap_tree *new_mt;
523 int comp_byte = 0, texel_bytes;
524
525 if (_mesa_is_format_compressed(intel_image->base.TexFormat))
526 comp_byte = intel_compressed_num_bytes(intel_image->base.TexFormat);
527
528 texel_bytes = _mesa_get_format_bytes(intel_image->base.TexFormat);
529
530 new_mt = intel_miptree_create(intel, newImage->TexObject->Target,
531 intel_image->base._BaseFormat,
532 intel_image->base.InternalFormat,
533 intel_image->level,
534 intel_image->level,
535 intel_image->base.Width,
536 intel_image->base.Height,
537 intel_image->base.Depth,
538 texel_bytes, comp_byte, GL_TRUE);
539
540 intel_miptree_image_copy(intel,
541 new_mt,
542 intel_image->face,
543 intel_image->level,
544 old_mt);
545
546 intel_miptree_release(intel, &intel_image->mt);
547 intel_image->mt = new_mt;
548 intel_set_draw_offset_for_image(intel_image, att->Zoffset);
549
550 intel_region_release(&irb->region);
551 intel_region_reference(&irb->region, intel_image->mt->region);
552 }
553 #endif
554 /* update drawing region, etc */
555 intel_draw_buffer(ctx, fb);
556 }
557
558
559 /**
560 * Called by Mesa when rendering to a texture is done.
561 */
562 static void
563 intel_finish_render_texture(struct gl_context * ctx,
564 struct gl_renderbuffer_attachment *att)
565 {
566 struct intel_context *intel = intel_context(ctx);
567 struct gl_texture_object *tex_obj = att->Texture;
568 struct gl_texture_image *image =
569 tex_obj->Image[att->CubeMapFace][att->TextureLevel];
570 struct intel_texture_image *intel_image = intel_texture_image(image);
571
572 DBG("Finish render texture tid %lx tex=%u\n",
573 _glthread_GetID(), att->Texture->Name);
574
575 /* Flag that this image may now be validated into the object's miptree. */
576 if (intel_image)
577 intel_image->used_as_render_target = GL_FALSE;
578
579 /* Since we've (probably) rendered to the texture and will (likely) use
580 * it in the texture domain later on in this batchbuffer, flush the
581 * batch. Once again, we wish for a domain tracker in libdrm to cover
582 * usage inside of a batchbuffer like GEM does in the kernel.
583 */
584 intel_batchbuffer_emit_mi_flush(intel);
585 }
586
587 /**
588 * Do additional "completeness" testing of a framebuffer object.
589 */
590 static void
591 intel_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
592 {
593 struct intel_context *intel = intel_context(ctx);
594 const struct intel_renderbuffer *depthRb =
595 intel_get_renderbuffer(fb, BUFFER_DEPTH);
596 const struct intel_renderbuffer *stencilRb =
597 intel_get_renderbuffer(fb, BUFFER_STENCIL);
598 int i;
599
600 if (depthRb && stencilRb && stencilRb != depthRb) {
601 if (fb->Attachment[BUFFER_DEPTH].Type == GL_TEXTURE &&
602 fb->Attachment[BUFFER_STENCIL].Type == GL_TEXTURE &&
603 (fb->Attachment[BUFFER_DEPTH].Texture->Name ==
604 fb->Attachment[BUFFER_STENCIL].Texture->Name)) {
605 /* OK */
606 } else {
607 /* we only support combined depth/stencil buffers, not separate
608 * stencil buffers.
609 */
610 DBG("Only supports combined depth/stencil (found %s, %s)\n",
611 depthRb ? _mesa_get_format_name(depthRb->Base.Format): "NULL",
612 stencilRb ? _mesa_get_format_name(stencilRb->Base.Format): "NULL");
613 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
614 }
615 }
616
617 for (i = 0; i < Elements(fb->Attachment); i++) {
618 struct gl_renderbuffer *rb;
619 struct intel_renderbuffer *irb;
620
621 if (fb->Attachment[i].Type == GL_NONE)
622 continue;
623
624 /* A supported attachment will have a Renderbuffer set either
625 * from being a Renderbuffer or being a texture that got the
626 * intel_wrap_texture() treatment.
627 */
628 rb = fb->Attachment[i].Renderbuffer;
629 if (rb == NULL) {
630 DBG("attachment without renderbuffer\n");
631 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
632 continue;
633 }
634
635 irb = intel_renderbuffer(rb);
636 if (irb == NULL) {
637 DBG("software rendering renderbuffer\n");
638 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
639 continue;
640 }
641
642 if (!intel_span_supports_format(irb->Base.Format) ||
643 !intel->vtbl.render_target_supported(irb->Base.Format)) {
644 DBG("Unsupported texture/renderbuffer format attached: %s\n",
645 _mesa_get_format_name(irb->Base.Format));
646 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
647 }
648 }
649 }
650
651 /**
652 * Try to do a glBlitFramebuffer using glCopyTexSubImage2D
653 * We can do this when the dst renderbuffer is actually a texture and
654 * there is no scaling, mirroring or scissoring.
655 *
656 * \return new buffer mask indicating the buffers left to blit using the
657 * normal path.
658 */
659 static GLbitfield
660 intel_blit_framebuffer_copy_tex_sub_image(struct gl_context *ctx,
661 GLint srcX0, GLint srcY0,
662 GLint srcX1, GLint srcY1,
663 GLint dstX0, GLint dstY0,
664 GLint dstX1, GLint dstY1,
665 GLbitfield mask, GLenum filter)
666 {
667 if (mask & GL_COLOR_BUFFER_BIT) {
668 const struct gl_framebuffer *drawFb = ctx->DrawBuffer;
669 const struct gl_framebuffer *readFb = ctx->ReadBuffer;
670 const struct gl_renderbuffer_attachment *drawAtt =
671 &drawFb->Attachment[drawFb->_ColorDrawBufferIndexes[0]];
672
673 /* If the source and destination are the same size with no
674 mirroring, the rectangles are within the size of the
675 texture and there is no scissor then we can use
676 glCopyTexSubimage2D to implement the blit. This will end
677 up as a fast hardware blit on some drivers */
678 if (drawAtt && drawAtt->Texture &&
679 srcX0 - srcX1 == dstX0 - dstX1 &&
680 srcY0 - srcY1 == dstY0 - dstY1 &&
681 srcX1 >= srcX0 &&
682 srcY1 >= srcY0 &&
683 srcX0 >= 0 && srcX1 <= readFb->Width &&
684 srcY0 >= 0 && srcY1 <= readFb->Height &&
685 dstX0 >= 0 && dstX1 <= drawFb->Width &&
686 dstY0 >= 0 && dstY1 <= drawFb->Height &&
687 !ctx->Scissor.Enabled) {
688 const struct gl_texture_object *texObj = drawAtt->Texture;
689 const GLuint dstLevel = drawAtt->TextureLevel;
690 const GLenum target = texObj->Target;
691
692 struct gl_texture_image *texImage =
693 _mesa_select_tex_image(ctx, texObj, target, dstLevel);
694 GLenum internalFormat = texImage->InternalFormat;
695
696 if (intel_copy_texsubimage(intel_context(ctx), target,
697 intel_texture_image(texImage),
698 internalFormat,
699 dstX0, dstY0,
700 srcX0, srcY0,
701 srcX1 - srcX0, /* width */
702 srcY1 - srcY0))
703 mask &= ~GL_COLOR_BUFFER_BIT;
704 }
705 }
706
707 return mask;
708 }
709
710 static void
711 intel_blit_framebuffer(struct gl_context *ctx,
712 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
713 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
714 GLbitfield mask, GLenum filter)
715 {
716 /* Try faster, glCopyTexSubImage2D approach first which uses the BLT. */
717 mask = intel_blit_framebuffer_copy_tex_sub_image(ctx,
718 srcX0, srcY0, srcX1, srcY1,
719 dstX0, dstY0, dstX1, dstY1,
720 mask, filter);
721 if (mask == 0x0)
722 return;
723
724 _mesa_meta_BlitFramebuffer(ctx,
725 srcX0, srcY0, srcX1, srcY1,
726 dstX0, dstY0, dstX1, dstY1,
727 mask, filter);
728 }
729
730 /**
731 * Do one-time context initializations related to GL_EXT_framebuffer_object.
732 * Hook in device driver functions.
733 */
734 void
735 intel_fbo_init(struct intel_context *intel)
736 {
737 intel->ctx.Driver.NewFramebuffer = intel_new_framebuffer;
738 intel->ctx.Driver.NewRenderbuffer = intel_new_renderbuffer;
739 intel->ctx.Driver.BindFramebuffer = intel_bind_framebuffer;
740 intel->ctx.Driver.FramebufferRenderbuffer = intel_framebuffer_renderbuffer;
741 intel->ctx.Driver.RenderTexture = intel_render_texture;
742 intel->ctx.Driver.FinishRenderTexture = intel_finish_render_texture;
743 intel->ctx.Driver.ResizeBuffers = intel_resize_buffers;
744 intel->ctx.Driver.ValidateFramebuffer = intel_validate_framebuffer;
745 intel->ctx.Driver.BlitFramebuffer = intel_blit_framebuffer;
746
747 #if FEATURE_OES_EGL_image
748 intel->ctx.Driver.EGLImageTargetRenderbufferStorage =
749 intel_image_target_renderbuffer_storage;
750 #endif
751 }