OSDN Git Service

intel: plug in stub intel_validate_framebuffer() function
[android-x86/external-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/mtypes.h"
31 #include "main/fbobject.h"
32 #include "main/framebuffer.h"
33 #include "main/renderbuffer.h"
34 #include "main/context.h"
35 #include "main/texformat.h"
36 #include "main/texrender.h"
37
38 #include "intel_context.h"
39 #include "intel_buffers.h"
40 #include "intel_depthstencil.h"
41 #include "intel_fbo.h"
42 #include "intel_mipmap_tree.h"
43 #include "intel_regions.h"
44 #include "intel_span.h"
45
46
47 #define FILE_DEBUG_FLAG DEBUG_FBO
48
49
50 /**
51  * Create a new framebuffer object.
52  */
53 static struct gl_framebuffer *
54 intel_new_framebuffer(GLcontext * ctx, GLuint name)
55 {
56    /* Only drawable state in intel_framebuffer at this time, just use Mesa's
57     * class
58     */
59    return _mesa_new_framebuffer(ctx, name);
60 }
61
62
63 static void
64 intel_delete_renderbuffer(struct gl_renderbuffer *rb)
65 {
66    GET_CURRENT_CONTEXT(ctx);
67    struct intel_context *intel = intel_context(ctx);
68    struct intel_renderbuffer *irb = intel_renderbuffer(rb);
69
70    ASSERT(irb);
71
72    if (irb->PairedStencil || irb->PairedDepth) {
73       intel_unpair_depth_stencil(ctx, irb);
74    }
75
76    if (irb->span_cache != NULL)
77       _mesa_free(irb->span_cache);
78
79    if (intel && irb->region) {
80       intel_region_release(&irb->region);
81    }
82
83    _mesa_free(irb);
84 }
85
86
87
88 /**
89  * Return a pointer to a specific pixel in a renderbuffer.
90  */
91 static void *
92 intel_get_pointer(GLcontext * ctx, struct gl_renderbuffer *rb,
93                   GLint x, GLint y)
94 {
95    /* By returning NULL we force all software rendering to go through
96     * the span routines.
97     */
98    return NULL;
99 }
100
101
102
103 /**
104  * Called via glRenderbufferStorageEXT() to set the format and allocate
105  * storage for a user-created renderbuffer.
106  */
107 static GLboolean
108 intel_alloc_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
109                                  GLenum internalFormat,
110                                  GLuint width, GLuint height)
111 {
112    struct intel_context *intel = intel_context(ctx);
113    struct intel_renderbuffer *irb = intel_renderbuffer(rb);
114    GLboolean softwareBuffer = GL_FALSE;
115    int cpp;
116
117    ASSERT(rb->Name != 0);
118
119    switch (internalFormat) {
120    case GL_R3_G3_B2:
121    case GL_RGB4:
122    case GL_RGB5:
123       rb->_ActualFormat = GL_RGB5;
124       rb->DataType = GL_UNSIGNED_BYTE;
125       rb->RedBits = 5;
126       rb->GreenBits = 6;
127       rb->BlueBits = 5;
128       cpp = 2;
129       break;
130    case GL_RGB:
131    case GL_RGB8:
132    case GL_RGB10:
133    case GL_RGB12:
134    case GL_RGB16:
135       rb->_ActualFormat = GL_RGB8;
136       rb->DataType = GL_UNSIGNED_BYTE;
137       rb->RedBits = 8;
138       rb->GreenBits = 8;
139       rb->BlueBits = 8;
140       rb->AlphaBits = 0;
141       cpp = 4;
142       break;
143    case GL_RGBA:
144    case GL_RGBA2:
145    case GL_RGBA4:
146    case GL_RGB5_A1:
147    case GL_RGBA8:
148    case GL_RGB10_A2:
149    case GL_RGBA12:
150    case GL_RGBA16:
151       rb->_ActualFormat = GL_RGBA8;
152       rb->DataType = GL_UNSIGNED_BYTE;
153       rb->RedBits = 8;
154       rb->GreenBits = 8;
155       rb->BlueBits = 8;
156       rb->AlphaBits = 8;
157       cpp = 4;
158       break;
159    case GL_STENCIL_INDEX:
160    case GL_STENCIL_INDEX1_EXT:
161    case GL_STENCIL_INDEX4_EXT:
162    case GL_STENCIL_INDEX8_EXT:
163    case GL_STENCIL_INDEX16_EXT:
164       /* alloc a depth+stencil buffer */
165       rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
166       rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
167       rb->StencilBits = 8;
168       cpp = 4;
169       break;
170    case GL_DEPTH_COMPONENT16:
171 #if 0
172       rb->_ActualFormat = GL_DEPTH_COMPONENT16;
173       rb->DataType = GL_UNSIGNED_SHORT;
174       rb->DepthBits = 16;
175       cpp = 2;
176       break;
177 #else
178       /* fall-through.
179        * 16bpp depth renderbuffer can't be paired with a stencil buffer so
180        * always used combined depth/stencil format.
181        */
182 #endif
183    case GL_DEPTH_COMPONENT:
184    case GL_DEPTH_COMPONENT24:
185    case GL_DEPTH_COMPONENT32:
186       rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
187       rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
188       rb->DepthBits = 24;
189       cpp = 4;
190       break;
191    case GL_DEPTH_STENCIL_EXT:
192    case GL_DEPTH24_STENCIL8_EXT:
193       rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
194       rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
195       rb->DepthBits = 24;
196       rb->StencilBits = 8;
197       cpp = 4;
198       break;
199    default:
200       _mesa_problem(ctx,
201                     "Unexpected format in intel_alloc_renderbuffer_storage");
202       return GL_FALSE;
203    }
204
205    intelFlush(ctx);
206
207    /* free old region */
208    if (irb->region) {
209       intel_region_release(&irb->region);
210    }
211
212    /* allocate new memory region/renderbuffer */
213    if (softwareBuffer) {
214       return _mesa_soft_renderbuffer_storage(ctx, rb, internalFormat,
215                                              width, height);
216    }
217    else {
218       /* Choose a pitch to match hardware requirements:
219        */
220       GLuint pitch = ((cpp * width + 63) & ~63) / cpp;
221
222       /* alloc hardware renderbuffer */
223       DBG("Allocating %d x %d Intel RBO (pitch %d)\n", width,
224           height, pitch);
225
226       irb->region = intel_region_alloc(intel, cpp, width, height, pitch);
227       if (!irb->region)
228          return GL_FALSE;       /* out of memory? */
229
230       ASSERT(irb->region->buffer);
231
232       rb->Width = width;
233       rb->Height = height;
234
235       return GL_TRUE;
236    }
237 }
238
239
240
241 /**
242  * Called for each hardware renderbuffer when a _window_ is resized.
243  * Just update fields.
244  * Not used for user-created renderbuffers!
245  */
246 static GLboolean
247 intel_alloc_window_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
248                            GLenum internalFormat, GLuint width, GLuint height)
249 {
250    ASSERT(rb->Name == 0);
251    rb->Width = width;
252    rb->Height = height;
253    rb->_ActualFormat = internalFormat;
254
255    return GL_TRUE;
256 }
257
258 static void
259 intel_resize_buffers(GLcontext *ctx, struct gl_framebuffer *fb,
260                      GLuint width, GLuint height)
261 {
262    struct intel_framebuffer *intel_fb = (struct intel_framebuffer*)fb;
263    int i;
264
265    _mesa_resize_framebuffer(ctx, fb, width, height);
266
267    fb->Initialized = GL_TRUE; /* XXX remove someday */
268
269    if (fb->Name != 0) {
270       return;
271    }
272
273    /* Make sure all window system renderbuffers are up to date */
274    for (i = 0; i < 2; i++) {
275       struct gl_renderbuffer *rb = &intel_fb->color_rb[i]->Base;
276
277       /* only resize if size is changing */
278       if (rb && (rb->Width != width || rb->Height != height)) {
279          rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height);
280       }
281    }
282 }
283
284 static GLboolean
285 intel_nop_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
286                         GLenum internalFormat, GLuint width, GLuint height)
287 {
288    _mesa_problem(ctx, "intel_op_alloc_storage should never be called.");
289    return GL_FALSE;
290 }
291
292
293 void
294 intel_renderbuffer_set_region(struct intel_renderbuffer *rb,
295                               struct intel_region *region)
296 {
297    struct intel_region *old;
298
299    old = rb->region;
300    rb->region = NULL;
301    intel_region_reference(&rb->region, region);
302    intel_region_release(&old);
303
304    rb->pfPitch = region->pitch;
305 }
306
307 /**
308  * Create a new intel_renderbuffer which corresponds to an on-screen window,
309  * not a user-created renderbuffer.
310  */
311 struct intel_renderbuffer *
312 intel_create_renderbuffer(GLenum intFormat)
313 {
314    GET_CURRENT_CONTEXT(ctx);
315
316    struct intel_renderbuffer *irb;
317    const GLuint name = 0;
318
319    irb = CALLOC_STRUCT(intel_renderbuffer);
320    if (!irb) {
321       _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer");
322       return NULL;
323    }
324
325    _mesa_init_renderbuffer(&irb->Base, name);
326    irb->Base.ClassID = INTEL_RB_CLASS;
327
328    switch (intFormat) {
329    case GL_RGB5:
330       irb->Base._ActualFormat = GL_RGB5;
331       irb->Base._BaseFormat = GL_RGBA;
332       irb->Base.RedBits = 5;
333       irb->Base.GreenBits = 6;
334       irb->Base.BlueBits = 5;
335       irb->Base.DataType = GL_UNSIGNED_BYTE;
336       break;
337    case GL_RGBA8:
338       irb->Base._ActualFormat = GL_RGBA8;
339       irb->Base._BaseFormat = GL_RGBA;
340       irb->Base.RedBits = 8;
341       irb->Base.GreenBits = 8;
342       irb->Base.BlueBits = 8;
343       irb->Base.AlphaBits = 8;
344       irb->Base.DataType = GL_UNSIGNED_BYTE;
345       break;
346    case GL_STENCIL_INDEX8_EXT:
347       irb->Base._ActualFormat = GL_STENCIL_INDEX8_EXT;
348       irb->Base._BaseFormat = GL_STENCIL_INDEX;
349       irb->Base.StencilBits = 8;
350       irb->Base.DataType = GL_UNSIGNED_BYTE;
351       break;
352    case GL_DEPTH_COMPONENT16:
353       irb->Base._ActualFormat = GL_DEPTH_COMPONENT16;
354       irb->Base._BaseFormat = GL_DEPTH_COMPONENT;
355       irb->Base.DepthBits = 16;
356       irb->Base.DataType = GL_UNSIGNED_SHORT;
357       break;
358    case GL_DEPTH_COMPONENT24:
359       irb->Base._ActualFormat = GL_DEPTH24_STENCIL8_EXT;
360       irb->Base._BaseFormat = GL_DEPTH_COMPONENT;
361       irb->Base.DepthBits = 24;
362       irb->Base.DataType = GL_UNSIGNED_INT;
363       break;
364    case GL_DEPTH24_STENCIL8_EXT:
365       irb->Base._ActualFormat = GL_DEPTH24_STENCIL8_EXT;
366       irb->Base._BaseFormat = GL_DEPTH_STENCIL_EXT;
367       irb->Base.DepthBits = 24;
368       irb->Base.StencilBits = 8;
369       irb->Base.DataType = GL_UNSIGNED_INT_24_8_EXT;
370       break;
371    default:
372       _mesa_problem(NULL,
373                     "Unexpected intFormat in intel_create_renderbuffer");
374       return NULL;
375    }
376
377    irb->Base.InternalFormat = intFormat;
378
379    /* intel-specific methods */
380    irb->Base.Delete = intel_delete_renderbuffer;
381    irb->Base.AllocStorage = intel_alloc_window_storage;
382    irb->Base.GetPointer = intel_get_pointer;
383
384    return irb;
385 }
386
387
388 /**
389  * Create a new renderbuffer object.
390  * Typically called via glBindRenderbufferEXT().
391  */
392 static struct gl_renderbuffer *
393 intel_new_renderbuffer(GLcontext * ctx, GLuint name)
394 {
395    /*struct intel_context *intel = intel_context(ctx); */
396    struct intel_renderbuffer *irb;
397
398    irb = CALLOC_STRUCT(intel_renderbuffer);
399    if (!irb) {
400       _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer");
401       return NULL;
402    }
403
404    _mesa_init_renderbuffer(&irb->Base, name);
405    irb->Base.ClassID = INTEL_RB_CLASS;
406
407    /* intel-specific methods */
408    irb->Base.Delete = intel_delete_renderbuffer;
409    irb->Base.AllocStorage = intel_alloc_renderbuffer_storage;
410    irb->Base.GetPointer = intel_get_pointer;
411    /* span routines set in alloc_storage function */
412
413    return &irb->Base;
414 }
415
416
417 /**
418  * Called via glBindFramebufferEXT().
419  */
420 static void
421 intel_bind_framebuffer(GLcontext * ctx, GLenum target,
422                        struct gl_framebuffer *fb, struct gl_framebuffer *fbread)
423 {
424    if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) {
425       intel_draw_buffer(ctx, fb);
426       /* Integer depth range depends on depth buffer bits */
427       if (ctx->Driver.DepthRange != NULL)
428          ctx->Driver.DepthRange(ctx, ctx->Viewport.Near, ctx->Viewport.Far);
429    }
430    else {
431       /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */
432    }
433 }
434
435
436 /**
437  * Called via glFramebufferRenderbufferEXT().
438  */
439 static void
440 intel_framebuffer_renderbuffer(GLcontext * ctx,
441                                struct gl_framebuffer *fb,
442                                GLenum attachment, struct gl_renderbuffer *rb)
443 {
444    DBG("Intel FramebufferRenderbuffer %u %u\n", fb->Name, rb ? rb->Name : 0);
445
446    intelFlush(ctx);
447
448    _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
449    intel_draw_buffer(ctx, fb);
450 }
451
452 static GLboolean
453 intel_update_wrapper(GLcontext *ctx, struct intel_renderbuffer *irb, 
454                      struct gl_texture_image *texImage)
455 {
456    if (texImage->TexFormat == &_mesa_texformat_argb8888) {
457       irb->Base._ActualFormat = GL_RGBA8;
458       irb->Base._BaseFormat = GL_RGBA;
459       irb->Base.DataType = GL_UNSIGNED_BYTE;
460       DBG("Render to RGBA8 texture OK\n");
461    }
462    else if (texImage->TexFormat == &_mesa_texformat_rgb565) {
463       irb->Base._ActualFormat = GL_RGB5;
464       irb->Base._BaseFormat = GL_RGB;
465       irb->Base.DataType = GL_UNSIGNED_SHORT;
466       DBG("Render to RGB5 texture OK\n");
467    }
468    else if (texImage->TexFormat == &_mesa_texformat_z16) {
469       irb->Base._ActualFormat = GL_DEPTH_COMPONENT16;
470       irb->Base._BaseFormat = GL_DEPTH_COMPONENT;
471       irb->Base.DataType = GL_UNSIGNED_SHORT;
472       DBG("Render to DEPTH16 texture OK\n");
473    }
474    else if (texImage->TexFormat == &_mesa_texformat_s8_z24) {
475       irb->Base._ActualFormat = GL_DEPTH24_STENCIL8_EXT;
476       irb->Base._BaseFormat = GL_DEPTH_STENCIL_EXT;
477       irb->Base.DataType = GL_UNSIGNED_INT_24_8_EXT;
478       DBG("Render to DEPTH_STENCIL texture OK\n");
479    }
480    else {
481       DBG("Render to texture BAD FORMAT %d\n",
482           texImage->TexFormat->MesaFormat);
483       return GL_FALSE;
484    }
485
486    irb->Base.InternalFormat = irb->Base._ActualFormat;
487    irb->Base.Width = texImage->Width;
488    irb->Base.Height = texImage->Height;
489    irb->Base.RedBits = texImage->TexFormat->RedBits;
490    irb->Base.GreenBits = texImage->TexFormat->GreenBits;
491    irb->Base.BlueBits = texImage->TexFormat->BlueBits;
492    irb->Base.AlphaBits = texImage->TexFormat->AlphaBits;
493    irb->Base.DepthBits = texImage->TexFormat->DepthBits;
494
495    irb->Base.Delete = intel_delete_renderbuffer;
496    irb->Base.AllocStorage = intel_nop_alloc_storage;
497
498    irb->RenderToTexture = GL_TRUE;
499
500    return GL_TRUE;
501 }
502
503 /**
504  * When glFramebufferTexture[123]D is called this function sets up the
505  * gl_renderbuffer wrapper around the texture image.
506  * This will have the region info needed for hardware rendering.
507  */
508 static struct intel_renderbuffer *
509 intel_wrap_texture(GLcontext * ctx, struct gl_texture_image *texImage)
510 {
511    const GLuint name = ~0;      /* not significant, but distinct for debugging */
512    struct intel_renderbuffer *irb;
513
514    /* make an intel_renderbuffer to wrap the texture image */
515    irb = CALLOC_STRUCT(intel_renderbuffer);
516    if (!irb) {
517       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture");
518       return NULL;
519    }
520
521    _mesa_init_renderbuffer(&irb->Base, name);
522    irb->Base.ClassID = INTEL_RB_CLASS;
523
524    if (!intel_update_wrapper(ctx, irb, texImage)) {
525       _mesa_free(irb);
526       return NULL;
527    }
528
529    return irb;
530 }
531
532
533 /**
534  * Called by glFramebufferTexture[123]DEXT() (and other places) to
535  * prepare for rendering into texture memory.  This might be called
536  * many times to choose different texture levels, cube faces, etc
537  * before intel_finish_render_texture() is ever called.
538  */
539 static void
540 intel_render_texture(GLcontext * ctx,
541                      struct gl_framebuffer *fb,
542                      struct gl_renderbuffer_attachment *att)
543 {
544    struct gl_texture_image *newImage
545       = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
546    struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer);
547    struct intel_texture_image *intel_image;
548    GLuint imageOffset;
549
550    (void) fb;
551
552    ASSERT(newImage);
553
554    if (newImage->Border != 0) {
555       /* Fallback on drawing to a texture with a border, which won't have a
556        * miptree.
557        */
558        _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
559        _mesa_render_texture(ctx, fb, att);
560        return;
561    } else if (!irb) {
562       irb = intel_wrap_texture(ctx, newImage);
563       if (irb) {
564          /* bind the wrapper to the attachment point */
565          _mesa_reference_renderbuffer(&att->Renderbuffer, &irb->Base);
566       }
567       else {
568          /* fallback to software rendering */
569          _mesa_render_texture(ctx, fb, att);
570          return;
571       }
572    } if (!intel_update_wrapper(ctx, irb, newImage)) {
573        _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
574        _mesa_render_texture(ctx, fb, att);
575        return;
576    }
577
578    DBG("Begin render texture tid %x tex=%u w=%d h=%d refcount=%d\n",
579        _glthread_GetID(),
580        att->Texture->Name, newImage->Width, newImage->Height,
581        irb->Base.RefCount);
582
583    /* point the renderbufer's region to the texture image region */
584    intel_image = intel_texture_image(newImage);
585    if (irb->region != intel_image->mt->region) {
586       if (irb->region)
587          intel_region_release(&irb->region);
588       intel_region_reference(&irb->region, intel_image->mt->region);
589    }
590
591    /* compute offset of the particular 2D image within the texture region */
592    imageOffset = intel_miptree_image_offset(intel_image->mt,
593                                             att->CubeMapFace,
594                                             att->TextureLevel);
595
596    if (att->Texture->Target == GL_TEXTURE_3D) {
597       const GLuint *offsets = intel_miptree_depth_offsets(intel_image->mt,
598                                                           att->TextureLevel);
599       imageOffset += offsets[att->Zoffset];
600    }
601
602    /* store that offset in the region */
603    intel_image->mt->region->draw_offset = imageOffset;
604
605    /* update drawing region, etc */
606    intel_draw_buffer(ctx, fb);
607 }
608
609
610 /**
611  * Called by Mesa when rendering to a texture is done.
612  */
613 static void
614 intel_finish_render_texture(GLcontext * ctx,
615                             struct gl_renderbuffer_attachment *att)
616 {
617    struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer);
618
619    DBG("End render texture (tid %x) tex %u\n", _glthread_GetID(), att->Texture->Name);
620
621    if (irb) {
622       /* just release the region */
623       intel_region_release(&irb->region);
624    }
625    else if (att->Renderbuffer) {
626       /* software fallback */
627       _mesa_finish_render_texture(ctx, att);
628       /* XXX FBO: Need to unmap the buffer (or in intelSpanRenderStart???) */
629    }
630 }
631
632
633 /**
634  * Do additional "completeness" testing of a framebuffer object.
635  */
636 static void
637 intel_validate_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb)
638 {
639    /* no-op for now.
640     * Eventually: examine the renderbuffers/textures and make sure it's
641     * supported by the hw.
642     */
643 }
644
645
646 /**
647  * Do one-time context initializations related to GL_EXT_framebuffer_object.
648  * Hook in device driver functions.
649  */
650 void
651 intel_fbo_init(struct intel_context *intel)
652 {
653    intel->ctx.Driver.NewFramebuffer = intel_new_framebuffer;
654    intel->ctx.Driver.NewRenderbuffer = intel_new_renderbuffer;
655    intel->ctx.Driver.BindFramebuffer = intel_bind_framebuffer;
656    intel->ctx.Driver.FramebufferRenderbuffer = intel_framebuffer_renderbuffer;
657    intel->ctx.Driver.RenderTexture = intel_render_texture;
658    intel->ctx.Driver.FinishRenderTexture = intel_finish_render_texture;
659    intel->ctx.Driver.ResizeBuffers = intel_resize_buffers;
660    intel->ctx.Driver.ValidateFramebuffer = intel_validate_framebuffer;
661 }