• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**************************************************************************
2  *
3  * Copyright 2003 VMware, Inc.
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sub license, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the
15  * next paragraph) shall be included in all copies or substantial portions
16  * of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25  *
26  **************************************************************************/
27 
28 #include <errno.h>
29 #include <time.h>
30 #include <unistd.h>
31 #include "main/glheader.h"
32 #include "main/context.h"
33 #include "main/framebuffer.h"
34 #include "main/renderbuffer.h"
35 #include "main/texobj.h"
36 #include "main/hash.h"
37 #include "main/fbobject.h"
38 #include "main/version.h"
39 #include "swrast/s_renderbuffer.h"
40 
41 #include "utils.h"
42 #include "util/xmlpool.h"
43 
44 static const __DRIconfigOptionsExtension i915_config_options = {
45    .base = { __DRI_CONFIG_OPTIONS, 1 },
46    .xml =
47 
48 DRI_CONF_BEGIN
49    DRI_CONF_SECTION_PERFORMANCE
50       /* Options correspond to DRI_CONF_BO_REUSE_DISABLED,
51        * DRI_CONF_BO_REUSE_ALL
52        */
53       DRI_CONF_OPT_BEGIN_V(bo_reuse, enum, 1, "0:1")
54 	 DRI_CONF_DESC_BEGIN(en, "Buffer object reuse")
55 	    DRI_CONF_ENUM(0, "Disable buffer object reuse")
56 	    DRI_CONF_ENUM(1, "Enable reuse of all sizes of buffer objects")
57 	 DRI_CONF_DESC_END
58       DRI_CONF_OPT_END
59 
60       DRI_CONF_OPT_BEGIN_B(early_z, "false")
61 	 DRI_CONF_DESC(en, "Enable early Z in classic mode (unstable, 945-only).")
62       DRI_CONF_OPT_END
63 
64       DRI_CONF_OPT_BEGIN_B(fragment_shader, "true")
65 	 DRI_CONF_DESC(en, "Enable limited ARB_fragment_shader support on 915/945.")
66       DRI_CONF_OPT_END
67 
68    DRI_CONF_SECTION_END
69    DRI_CONF_SECTION_QUALITY
70    DRI_CONF_SECTION_END
71    DRI_CONF_SECTION_DEBUG
72       DRI_CONF_NO_RAST("false")
73       DRI_CONF_ALWAYS_FLUSH_BATCH("false")
74       DRI_CONF_ALWAYS_FLUSH_CACHE("false")
75       DRI_CONF_DISABLE_THROTTLING("false")
76       DRI_CONF_FORCE_GLSL_EXTENSIONS_WARN("false")
77       DRI_CONF_DISABLE_GLSL_LINE_CONTINUATIONS("false")
78       DRI_CONF_DISABLE_BLEND_FUNC_EXTENDED("false")
79 
80       DRI_CONF_OPT_BEGIN_B(stub_occlusion_query, "false")
81 	 DRI_CONF_DESC(en, "Enable stub ARB_occlusion_query support on 915/945.")
82       DRI_CONF_OPT_END
83 
84       DRI_CONF_OPT_BEGIN_B(shader_precompile, "true")
85 	 DRI_CONF_DESC(en, "Perform code generation at shader link time.")
86       DRI_CONF_OPT_END
87    DRI_CONF_SECTION_END
88 DRI_CONF_END
89 };
90 
91 #include "intel_batchbuffer.h"
92 #include "intel_buffers.h"
93 #include "intel_bufmgr.h"
94 #include "intel_chipset.h"
95 #include "intel_fbo.h"
96 #include "intel_mipmap_tree.h"
97 #include "intel_screen.h"
98 #include "intel_tex.h"
99 #include "intel_regions.h"
100 
101 #include "i915_drm.h"
102 
103 /**
104  * For debugging purposes, this returns a time in seconds.
105  */
106 double
get_time(void)107 get_time(void)
108 {
109    struct timespec tp;
110 
111    clock_gettime(CLOCK_MONOTONIC, &tp);
112 
113    return tp.tv_sec + tp.tv_nsec / 1000000000.0;
114 }
115 
116 void
aub_dump_bmp(struct gl_context * ctx)117 aub_dump_bmp(struct gl_context *ctx)
118 {
119    struct gl_framebuffer *fb = ctx->DrawBuffer;
120 
121    for (int i = 0; i < fb->_NumColorDrawBuffers; i++) {
122       struct intel_renderbuffer *irb =
123 	 intel_renderbuffer(fb->_ColorDrawBuffers[i]);
124 
125       if (irb && irb->mt) {
126 	 enum aub_dump_bmp_format format;
127 
128 	 switch (irb->Base.Base.Format) {
129 	 case MESA_FORMAT_B8G8R8A8_UNORM:
130 	 case MESA_FORMAT_B8G8R8X8_UNORM:
131 	    format = AUB_DUMP_BMP_FORMAT_ARGB_8888;
132 	    break;
133 	 default:
134 	    continue;
135 	 }
136 
137          assert(irb->mt->region->pitch % irb->mt->region->cpp == 0);
138 	 drm_intel_gem_bo_aub_dump_bmp(irb->mt->region->bo,
139 				       irb->draw_x,
140 				       irb->draw_y,
141 				       irb->Base.Base.Width,
142 				       irb->Base.Base.Height,
143 				       format,
144 				       irb->mt->region->pitch,
145 				       0);
146       }
147    }
148 }
149 
150 static const __DRItexBufferExtension intelTexBufferExtension = {
151    .base = { __DRI_TEX_BUFFER, 3 },
152 
153    .setTexBuffer        = intelSetTexBuffer,
154    .setTexBuffer2       = intelSetTexBuffer2,
155    .releaseTexBuffer    = NULL,
156 };
157 
158 static void
intelDRI2Flush(__DRIdrawable * drawable)159 intelDRI2Flush(__DRIdrawable *drawable)
160 {
161    GET_CURRENT_CONTEXT(ctx);
162    struct intel_context *intel = intel_context(ctx);
163    if (intel == NULL)
164       return;
165 
166    INTEL_FIREVERTICES(intel);
167 
168    intel->need_throttle = true;
169 
170    if (intel->batch.used)
171       intel_batchbuffer_flush(intel);
172 
173    if (INTEL_DEBUG & DEBUG_AUB) {
174       aub_dump_bmp(ctx);
175    }
176 }
177 
178 static const struct __DRI2flushExtensionRec intelFlushExtension = {
179     .base = { __DRI2_FLUSH, 3 },
180 
181     .flush              = intelDRI2Flush,
182     .invalidate         = dri2InvalidateDrawable,
183 };
184 
185 static struct intel_image_format intel_image_formats[] = {
186    { __DRI_IMAGE_FOURCC_ARGB8888, __DRI_IMAGE_COMPONENTS_RGBA, 1,
187      { { 0, 0, 0, __DRI_IMAGE_FORMAT_ARGB8888, 4 } } },
188 
189    { __DRI_IMAGE_FOURCC_SARGB8888, __DRI_IMAGE_COMPONENTS_RGBA, 1,
190      { { 0, 0, 0, __DRI_IMAGE_FORMAT_SARGB8, 4 } } },
191 
192    { __DRI_IMAGE_FOURCC_XRGB8888, __DRI_IMAGE_COMPONENTS_RGB, 1,
193      { { 0, 0, 0, __DRI_IMAGE_FORMAT_XRGB8888, 4 }, } },
194 
195    { __DRI_IMAGE_FOURCC_YUV410, __DRI_IMAGE_COMPONENTS_Y_U_V, 3,
196      { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
197        { 1, 2, 2, __DRI_IMAGE_FORMAT_R8, 1 },
198        { 2, 2, 2, __DRI_IMAGE_FORMAT_R8, 1 } } },
199 
200    { __DRI_IMAGE_FOURCC_YUV411, __DRI_IMAGE_COMPONENTS_Y_U_V, 3,
201      { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
202        { 1, 2, 0, __DRI_IMAGE_FORMAT_R8, 1 },
203        { 2, 2, 0, __DRI_IMAGE_FORMAT_R8, 1 } } },
204 
205    { __DRI_IMAGE_FOURCC_YUV420, __DRI_IMAGE_COMPONENTS_Y_U_V, 3,
206      { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
207        { 1, 1, 1, __DRI_IMAGE_FORMAT_R8, 1 },
208        { 2, 1, 1, __DRI_IMAGE_FORMAT_R8, 1 } } },
209 
210    { __DRI_IMAGE_FOURCC_YUV422, __DRI_IMAGE_COMPONENTS_Y_U_V, 3,
211      { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
212        { 1, 1, 0, __DRI_IMAGE_FORMAT_R8, 1 },
213        { 2, 1, 0, __DRI_IMAGE_FORMAT_R8, 1 } } },
214 
215    { __DRI_IMAGE_FOURCC_YUV444, __DRI_IMAGE_COMPONENTS_Y_U_V, 3,
216      { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
217        { 1, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
218        { 2, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 } } },
219 
220    { __DRI_IMAGE_FOURCC_NV12, __DRI_IMAGE_COMPONENTS_Y_UV, 2,
221      { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
222        { 1, 1, 1, __DRI_IMAGE_FORMAT_GR88, 2 } } },
223 
224    { __DRI_IMAGE_FOURCC_NV16, __DRI_IMAGE_COMPONENTS_Y_UV, 2,
225      { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
226        { 1, 1, 0, __DRI_IMAGE_FORMAT_GR88, 2 } } },
227 
228    /* For YUYV and UYVY buffers, we set up two overlapping DRI images
229     * and treat them as planar buffers in the compositors.
230     * Plane 0 is GR88 and samples YU or YV pairs and places Y into
231     * the R component, while plane 1 is ARGB/ABGR and samples YUYV/UYVY
232     * clusters and places pairs and places U into the G component and
233     * V into A.  This lets the texture sampler interpolate the Y
234     * components correctly when sampling from plane 0, and interpolate
235     * U and V correctly when sampling from plane 1. */
236    { __DRI_IMAGE_FOURCC_YUYV, __DRI_IMAGE_COMPONENTS_Y_XUXV, 2,
237      { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88, 2 },
238        { 0, 1, 0, __DRI_IMAGE_FORMAT_ARGB8888, 4 } } },
239    { __DRI_IMAGE_FOURCC_UYVY, __DRI_IMAGE_COMPONENTS_Y_UXVX, 2,
240      { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88, 2 },
241        { 0, 1, 0, __DRI_IMAGE_FORMAT_ABGR8888, 4 } } }
242 };
243 
244 static __DRIimage *
intel_allocate_image(int dri_format,void * loaderPrivate)245 intel_allocate_image(int dri_format, void *loaderPrivate)
246 {
247     __DRIimage *image;
248 
249     image = calloc(1, sizeof *image);
250     if (image == NULL)
251 	return NULL;
252 
253     image->dri_format = dri_format;
254     image->offset = 0;
255 
256     image->format = driImageFormatToGLFormat(dri_format);
257     if (dri_format != __DRI_IMAGE_FORMAT_NONE &&
258         image->format == MESA_FORMAT_NONE) {
259        free(image);
260        return NULL;
261     }
262 
263     image->internal_format = _mesa_get_format_base_format(image->format);
264     image->data = loaderPrivate;
265 
266     return image;
267 }
268 
269 /**
270  * Sets up a DRIImage structure to point to our shared image in a region
271  */
272 static void
intel_setup_image_from_mipmap_tree(struct intel_context * intel,__DRIimage * image,struct intel_mipmap_tree * mt,GLuint level,GLuint zoffset)273 intel_setup_image_from_mipmap_tree(struct intel_context *intel, __DRIimage *image,
274                                    struct intel_mipmap_tree *mt, GLuint level,
275                                    GLuint zoffset)
276 {
277    unsigned int draw_x, draw_y;
278    uint32_t mask_x, mask_y;
279 
280    intel_miptree_check_level_layer(mt, level, zoffset);
281 
282    intel_region_get_tile_masks(mt->region, &mask_x, &mask_y);
283    intel_miptree_get_image_offset(mt, level, zoffset, &draw_x, &draw_y);
284 
285    image->width = mt->level[level].width;
286    image->height = mt->level[level].height;
287    image->tile_x = draw_x & mask_x;
288    image->tile_y = draw_y & mask_y;
289 
290    image->offset = intel_region_get_aligned_offset(mt->region,
291                                                    draw_x & ~mask_x,
292                                                    draw_y & ~mask_y);
293 
294    intel_region_reference(&image->region, mt->region);
295 }
296 
297 static void
intel_setup_image_from_dimensions(__DRIimage * image)298 intel_setup_image_from_dimensions(__DRIimage *image)
299 {
300    image->width    = image->region->width;
301    image->height   = image->region->height;
302    image->tile_x = 0;
303    image->tile_y = 0;
304 }
305 
306 static __DRIimage *
intel_create_image_from_name(__DRIscreen * screen,int width,int height,int format,int name,int pitch,void * loaderPrivate)307 intel_create_image_from_name(__DRIscreen *screen,
308 			     int width, int height, int format,
309 			     int name, int pitch, void *loaderPrivate)
310 {
311     struct intel_screen *intelScreen = screen->driverPrivate;
312     __DRIimage *image;
313     int cpp;
314 
315     image = intel_allocate_image(format, loaderPrivate);
316     if (image == NULL)
317        return NULL;
318 
319     if (image->format == MESA_FORMAT_NONE)
320        cpp = 1;
321     else
322        cpp = _mesa_get_format_bytes(image->format);
323     image->region = intel_region_alloc_for_handle(intelScreen,
324 						  cpp, width, height,
325 						  pitch * cpp, name, "image");
326     if (image->region == NULL) {
327        free(image);
328        return NULL;
329     }
330 
331     intel_setup_image_from_dimensions(image);
332 
333     return image;
334 }
335 
336 static __DRIimage *
intel_create_image_from_renderbuffer(__DRIcontext * context,int renderbuffer,void * loaderPrivate)337 intel_create_image_from_renderbuffer(__DRIcontext *context,
338 				     int renderbuffer, void *loaderPrivate)
339 {
340    __DRIimage *image;
341    struct intel_context *intel = context->driverPrivate;
342    struct gl_renderbuffer *rb;
343    struct intel_renderbuffer *irb;
344 
345    rb = _mesa_lookup_renderbuffer(&intel->ctx, renderbuffer);
346    if (!rb) {
347       _mesa_error(&intel->ctx,
348 		  GL_INVALID_OPERATION, "glRenderbufferExternalMESA");
349       return NULL;
350    }
351 
352    irb = intel_renderbuffer(rb);
353    image = calloc(1, sizeof *image);
354    if (image == NULL)
355       return NULL;
356 
357    image->internal_format = rb->InternalFormat;
358    image->format = rb->Format;
359    image->offset = 0;
360    image->data = loaderPrivate;
361    intel_region_reference(&image->region, irb->mt->region);
362    intel_setup_image_from_dimensions(image);
363    image->dri_format = driGLFormatToImageFormat(image->format);
364 
365    rb->NeedsFinishRenderTexture = true;
366    return image;
367 }
368 
369 static __DRIimage *
intel_create_image_from_texture(__DRIcontext * context,int target,unsigned texture,int zoffset,int level,unsigned * error,void * loaderPrivate)370 intel_create_image_from_texture(__DRIcontext *context, int target,
371                                 unsigned texture, int zoffset,
372                                 int level,
373                                 unsigned *error,
374                                 void *loaderPrivate)
375 {
376    __DRIimage *image;
377    struct intel_context *intel = context->driverPrivate;
378    struct gl_texture_object *obj;
379    struct intel_texture_object *iobj;
380    GLuint face = 0;
381 
382    obj = _mesa_lookup_texture(&intel->ctx, texture);
383    if (!obj || obj->Target != target) {
384       *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
385       return NULL;
386    }
387 
388    if (target == GL_TEXTURE_CUBE_MAP)
389       face = zoffset;
390 
391    _mesa_test_texobj_completeness(&intel->ctx, obj);
392    iobj = intel_texture_object(obj);
393    if (!obj->_BaseComplete || (level > 0 && !obj->_MipmapComplete)) {
394       *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
395       return NULL;
396    }
397 
398    if (level < obj->BaseLevel || level > obj->_MaxLevel) {
399       *error = __DRI_IMAGE_ERROR_BAD_MATCH;
400       return NULL;
401    }
402 
403    if (target == GL_TEXTURE_3D && obj->Image[face][level]->Depth < zoffset) {
404       *error = __DRI_IMAGE_ERROR_BAD_MATCH;
405       return NULL;
406    }
407    image = calloc(1, sizeof *image);
408    if (image == NULL) {
409       *error = __DRI_IMAGE_ERROR_BAD_ALLOC;
410       return NULL;
411    }
412 
413    image->internal_format = obj->Image[face][level]->InternalFormat;
414    image->format = obj->Image[face][level]->TexFormat;
415    image->data = loaderPrivate;
416    intel_setup_image_from_mipmap_tree(intel, image, iobj->mt, level, zoffset);
417    image->dri_format = driGLFormatToImageFormat(image->format);
418    if (image->dri_format == MESA_FORMAT_NONE) {
419       *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
420       free(image);
421       return NULL;
422    }
423 
424    *error = __DRI_IMAGE_ERROR_SUCCESS;
425    return image;
426 }
427 
428 static void
intel_destroy_image(__DRIimage * image)429 intel_destroy_image(__DRIimage *image)
430 {
431     intel_region_release(&image->region);
432     free(image);
433 }
434 
435 static __DRIimage *
intel_create_image(__DRIscreen * screen,int width,int height,int format,unsigned int use,void * loaderPrivate)436 intel_create_image(__DRIscreen *screen,
437 		   int width, int height, int format,
438 		   unsigned int use,
439 		   void *loaderPrivate)
440 {
441    __DRIimage *image;
442    struct intel_screen *intelScreen = screen->driverPrivate;
443    uint32_t tiling;
444    int cpp;
445 
446    tiling = I915_TILING_X;
447    if (use & __DRI_IMAGE_USE_CURSOR) {
448       if (width != 64 || height != 64)
449 	 return NULL;
450       tiling = I915_TILING_NONE;
451    }
452 
453    if (use & __DRI_IMAGE_USE_LINEAR)
454       tiling = I915_TILING_NONE;
455 
456    image = intel_allocate_image(format, loaderPrivate);
457    if (image == NULL)
458       return NULL;
459 
460    cpp = _mesa_get_format_bytes(image->format);
461    image->region =
462       intel_region_alloc(intelScreen, tiling, cpp, width, height, true);
463    if (image->region == NULL) {
464       free(image);
465       return NULL;
466    }
467 
468    intel_setup_image_from_dimensions(image);
469 
470    return image;
471 }
472 
473 static GLboolean
intel_query_image(__DRIimage * image,int attrib,int * value)474 intel_query_image(__DRIimage *image, int attrib, int *value)
475 {
476    switch (attrib) {
477    case __DRI_IMAGE_ATTRIB_STRIDE:
478       *value = image->region->pitch;
479       return true;
480    case __DRI_IMAGE_ATTRIB_HANDLE:
481       *value = image->region->bo->handle;
482       return true;
483    case __DRI_IMAGE_ATTRIB_NAME:
484       return intel_region_flink(image->region, (uint32_t *) value);
485    case __DRI_IMAGE_ATTRIB_FORMAT:
486       *value = image->dri_format;
487       return true;
488    case __DRI_IMAGE_ATTRIB_WIDTH:
489       *value = image->region->width;
490       return true;
491    case __DRI_IMAGE_ATTRIB_HEIGHT:
492       *value = image->region->height;
493       return true;
494    case __DRI_IMAGE_ATTRIB_COMPONENTS:
495       if (image->planar_format == NULL)
496          return false;
497       *value = image->planar_format->components;
498       return true;
499    case __DRI_IMAGE_ATTRIB_FD:
500       return !drm_intel_bo_gem_export_to_prime(image->region->bo, value);
501   default:
502       return false;
503    }
504 }
505 
506 static __DRIimage *
intel_dup_image(__DRIimage * orig_image,void * loaderPrivate)507 intel_dup_image(__DRIimage *orig_image, void *loaderPrivate)
508 {
509    __DRIimage *image;
510 
511    image = calloc(1, sizeof *image);
512    if (image == NULL)
513       return NULL;
514 
515    intel_region_reference(&image->region, orig_image->region);
516    if (image->region == NULL) {
517       free(image);
518       return NULL;
519    }
520 
521    image->internal_format = orig_image->internal_format;
522    image->planar_format   = orig_image->planar_format;
523    image->dri_format      = orig_image->dri_format;
524    image->format          = orig_image->format;
525    image->offset          = orig_image->offset;
526    image->width           = orig_image->width;
527    image->height          = orig_image->height;
528    image->tile_x          = orig_image->tile_x;
529    image->tile_y          = orig_image->tile_y;
530    image->data            = loaderPrivate;
531 
532    memcpy(image->strides, orig_image->strides, sizeof(image->strides));
533    memcpy(image->offsets, orig_image->offsets, sizeof(image->offsets));
534 
535    return image;
536 }
537 
538 static GLboolean
intel_validate_usage(__DRIimage * image,unsigned int use)539 intel_validate_usage(__DRIimage *image, unsigned int use)
540 {
541    if (use & __DRI_IMAGE_USE_CURSOR) {
542       if (image->region->width != 64 || image->region->height != 64)
543 	 return GL_FALSE;
544    }
545 
546    return GL_TRUE;
547 }
548 
549 static __DRIimage *
intel_create_image_from_names(__DRIscreen * screen,int width,int height,int fourcc,int * names,int num_names,int * strides,int * offsets,void * loaderPrivate)550 intel_create_image_from_names(__DRIscreen *screen,
551                               int width, int height, int fourcc,
552                               int *names, int num_names,
553                               int *strides, int *offsets,
554                               void *loaderPrivate)
555 {
556     struct intel_image_format *f = NULL;
557     __DRIimage *image;
558     int i, index;
559 
560     if (screen == NULL || names == NULL || num_names != 1)
561         return NULL;
562 
563     for (i = 0; i < ARRAY_SIZE(intel_image_formats); i++) {
564         if (intel_image_formats[i].fourcc == fourcc) {
565            f = &intel_image_formats[i];
566         }
567     }
568 
569     if (f == NULL)
570         return NULL;
571 
572     image = intel_create_image_from_name(screen, width, height,
573                                          __DRI_IMAGE_FORMAT_NONE,
574                                          names[0], strides[0],
575                                          loaderPrivate);
576 
577    if (image == NULL)
578       return NULL;
579 
580     image->planar_format = f;
581     for (i = 0; i < f->nplanes; i++) {
582         index = f->planes[i].buffer_index;
583         image->offsets[index] = offsets[index];
584         image->strides[index] = strides[index];
585     }
586 
587     return image;
588 }
589 
590 static __DRIimage *
intel_create_image_from_fds(__DRIscreen * screen,int width,int height,int fourcc,int * fds,int num_fds,int * strides,int * offsets,void * loaderPrivate)591 intel_create_image_from_fds(__DRIscreen *screen,
592                             int width, int height, int fourcc,
593                             int *fds, int num_fds, int *strides, int *offsets,
594                             void *loaderPrivate)
595 {
596    struct intel_screen *intelScreen = screen->driverPrivate;
597    struct intel_image_format *f = NULL;
598    __DRIimage *image;
599    int i, index;
600 
601    if (fds == NULL || num_fds != 1)
602       return NULL;
603 
604    for (i = 0; i < ARRAY_SIZE(intel_image_formats); i++) {
605       if (intel_image_formats[i].fourcc == fourcc) {
606          f = &intel_image_formats[i];
607       }
608    }
609 
610    if (f == NULL)
611       return NULL;
612 
613    image = intel_allocate_image(__DRI_IMAGE_FORMAT_NONE, loaderPrivate);
614    if (image == NULL)
615       return NULL;
616 
617    image->region = intel_region_alloc_for_fd(intelScreen,
618                                              f->planes[0].cpp, width, height, strides[0],
619                                              height * strides[0], fds[0], "image");
620    if (image->region == NULL) {
621       free(image);
622       return NULL;
623    }
624 
625    intel_setup_image_from_dimensions(image);
626 
627    image->planar_format = f;
628    for (i = 0; i < f->nplanes; i++) {
629       index = f->planes[i].buffer_index;
630       image->offsets[index] = offsets[index];
631       image->strides[index] = strides[index];
632    }
633 
634    return image;
635 }
636 
637 
638 static __DRIimage *
intel_from_planar(__DRIimage * parent,int plane,void * loaderPrivate)639 intel_from_planar(__DRIimage *parent, int plane, void *loaderPrivate)
640 {
641     int width, height, offset, stride, dri_format, index;
642     struct intel_image_format *f;
643     uint32_t mask_x, mask_y;
644     __DRIimage *image;
645 
646     if (parent == NULL || parent->planar_format == NULL)
647         return NULL;
648 
649     f = parent->planar_format;
650 
651     if (plane >= f->nplanes)
652         return NULL;
653 
654     width = parent->region->width >> f->planes[plane].width_shift;
655     height = parent->region->height >> f->planes[plane].height_shift;
656     dri_format = f->planes[plane].dri_format;
657     index = f->planes[plane].buffer_index;
658     offset = parent->offsets[index];
659     stride = parent->strides[index];
660 
661     image = intel_allocate_image(dri_format, loaderPrivate);
662     if (image == NULL)
663        return NULL;
664 
665     if (offset + height * stride > parent->region->bo->size) {
666        _mesa_warning(NULL, "intel_create_sub_image: subimage out of bounds");
667        free(image);
668        return NULL;
669     }
670 
671     image->region = calloc(sizeof(*image->region), 1);
672     if (image->region == NULL) {
673        free(image);
674        return NULL;
675     }
676 
677     image->region->cpp = _mesa_get_format_bytes(image->format);
678     image->region->width = width;
679     image->region->height = height;
680     image->region->pitch = stride;
681     image->region->refcount = 1;
682     image->region->bo = parent->region->bo;
683     drm_intel_bo_reference(image->region->bo);
684     image->region->tiling = parent->region->tiling;
685     image->offset = offset;
686     intel_setup_image_from_dimensions(image);
687 
688     intel_region_get_tile_masks(image->region, &mask_x, &mask_y);
689     if (offset & mask_x)
690        _mesa_warning(NULL,
691                      "intel_create_sub_image: offset not on tile boundary");
692 
693     return image;
694 }
695 
696 static const __DRIimageExtension intelImageExtension = {
697     .base = { __DRI_IMAGE, 7 },
698 
699     .createImageFromName                = intel_create_image_from_name,
700     .createImageFromRenderbuffer        = intel_create_image_from_renderbuffer,
701     .destroyImage                       = intel_destroy_image,
702     .createImage                        = intel_create_image,
703     .queryImage                         = intel_query_image,
704     .dupImage                           = intel_dup_image,
705     .validateUsage                      = intel_validate_usage,
706     .createImageFromNames               = intel_create_image_from_names,
707     .fromPlanar                         = intel_from_planar,
708     .createImageFromTexture             = intel_create_image_from_texture,
709     .createImageFromFds                 = intel_create_image_from_fds
710 };
711 
712 static int
i915_query_renderer_integer(__DRIscreen * psp,int param,unsigned int * value)713 i915_query_renderer_integer(__DRIscreen *psp, int param, unsigned int *value)
714 {
715    const struct intel_screen *const intelScreen =
716       (struct intel_screen *) psp->driverPrivate;
717 
718    switch (param) {
719    case __DRI2_RENDERER_VENDOR_ID:
720       value[0] = 0x8086;
721       return 0;
722    case __DRI2_RENDERER_DEVICE_ID:
723       value[0] = intelScreen->deviceID;
724       return 0;
725    case __DRI2_RENDERER_ACCELERATED:
726       value[0] = 1;
727       return 0;
728    case __DRI2_RENDERER_VIDEO_MEMORY: {
729       /* Once a batch uses more than 75% of the maximum mappable size, we
730        * assume that there's some fragmentation, and we start doing extra
731        * flushing, etc.  That's the big cliff apps will care about.
732        */
733       size_t aper_size;
734       size_t mappable_size;
735 
736       drm_intel_get_aperture_sizes(psp->fd, &mappable_size, &aper_size);
737 
738       const unsigned gpu_mappable_megabytes =
739          (aper_size / (1024 * 1024)) * 3 / 4;
740 
741       const long system_memory_pages = sysconf(_SC_PHYS_PAGES);
742       const long system_page_size = sysconf(_SC_PAGE_SIZE);
743 
744       if (system_memory_pages <= 0 || system_page_size <= 0)
745          return -1;
746 
747       const uint64_t system_memory_bytes = (uint64_t) system_memory_pages
748          * (uint64_t) system_page_size;
749 
750       const unsigned system_memory_megabytes =
751          (unsigned) (system_memory_bytes / (1024 * 1024));
752 
753       value[0] = MIN2(system_memory_megabytes, gpu_mappable_megabytes);
754       return 0;
755    }
756    case __DRI2_RENDERER_UNIFIED_MEMORY_ARCHITECTURE:
757       value[0] = 1;
758       return 0;
759    case __DRI2_RENDERER_HAS_TEXTURE_3D:
760       value[0] = 1;
761       return 0;
762    default:
763       return driQueryRendererIntegerCommon(psp, param, value);
764    }
765 
766    return -1;
767 }
768 
769 static int
i915_query_renderer_string(__DRIscreen * psp,int param,const char ** value)770 i915_query_renderer_string(__DRIscreen *psp, int param, const char **value)
771 {
772    const struct intel_screen *intelScreen =
773       (struct intel_screen *) psp->driverPrivate;
774 
775    switch (param) {
776    case __DRI2_RENDERER_VENDOR_ID:
777       value[0] = i915_vendor_string;
778       return 0;
779    case __DRI2_RENDERER_DEVICE_ID:
780       value[0] = i915_get_renderer_string(intelScreen->deviceID);
781       return 0;
782    default:
783       break;
784    }
785 
786    return -1;
787 }
788 
789 static const __DRI2rendererQueryExtension intelRendererQueryExtension = {
790    .base = { __DRI2_RENDERER_QUERY, 1 },
791 
792    .queryInteger = i915_query_renderer_integer,
793    .queryString = i915_query_renderer_string
794 };
795 
796 static const __DRIextension *intelScreenExtensions[] = {
797     &intelTexBufferExtension.base,
798     &intelFenceExtension.base,
799     &intelFlushExtension.base,
800     &intelImageExtension.base,
801     &intelRendererQueryExtension.base,
802     &dri2ConfigQueryExtension.base,
803     &dri2NoErrorExtension.base,
804     NULL
805 };
806 
807 static bool
intel_get_param(__DRIscreen * psp,int param,int * value)808 intel_get_param(__DRIscreen *psp, int param, int *value)
809 {
810    int ret;
811    struct drm_i915_getparam gp;
812 
813    memset(&gp, 0, sizeof(gp));
814    gp.param = param;
815    gp.value = value;
816 
817    ret = drmCommandWriteRead(psp->fd, DRM_I915_GETPARAM, &gp, sizeof(gp));
818    if (ret) {
819       if (ret != -EINVAL)
820 	 _mesa_warning(NULL, "drm_i915_getparam: %d", ret);
821       return false;
822    }
823 
824    return true;
825 }
826 
827 static bool
intel_get_boolean(__DRIscreen * psp,int param)828 intel_get_boolean(__DRIscreen *psp, int param)
829 {
830    int value = 0;
831    return intel_get_param(psp, param, &value) && value;
832 }
833 
834 static void
intelDestroyScreen(__DRIscreen * sPriv)835 intelDestroyScreen(__DRIscreen * sPriv)
836 {
837    struct intel_screen *intelScreen = sPriv->driverPrivate;
838 
839    dri_bufmgr_destroy(intelScreen->bufmgr);
840    driDestroyOptionInfo(&intelScreen->optionCache);
841 
842    free(intelScreen);
843    sPriv->driverPrivate = NULL;
844 }
845 
846 
847 /**
848  * This is called when we need to set up GL rendering to a new X window.
849  */
850 static GLboolean
intelCreateBuffer(__DRIscreen * driScrnPriv,__DRIdrawable * driDrawPriv,const struct gl_config * mesaVis,GLboolean isPixmap)851 intelCreateBuffer(__DRIscreen * driScrnPriv,
852                   __DRIdrawable * driDrawPriv,
853                   const struct gl_config * mesaVis, GLboolean isPixmap)
854 {
855    struct intel_renderbuffer *rb;
856    mesa_format rgbFormat;
857    struct gl_framebuffer *fb;
858 
859    if (isPixmap)
860       return false;
861 
862    fb = CALLOC_STRUCT(gl_framebuffer);
863    if (!fb)
864       return false;
865 
866    _mesa_initialize_window_framebuffer(fb, mesaVis);
867 
868    if (mesaVis->redBits == 5)
869       rgbFormat = MESA_FORMAT_B5G6R5_UNORM;
870    else if (mesaVis->sRGBCapable)
871       rgbFormat = MESA_FORMAT_B8G8R8A8_SRGB;
872    else if (mesaVis->alphaBits == 0)
873       rgbFormat = MESA_FORMAT_B8G8R8X8_UNORM;
874    else
875       rgbFormat = MESA_FORMAT_B8G8R8A8_UNORM;
876 
877    /* setup the hardware-based renderbuffers */
878    rb = intel_create_renderbuffer(rgbFormat);
879    _mesa_attach_and_own_rb(fb, BUFFER_FRONT_LEFT, &rb->Base.Base);
880 
881    if (mesaVis->doubleBufferMode) {
882       rb = intel_create_renderbuffer(rgbFormat);
883       _mesa_attach_and_own_rb(fb, BUFFER_BACK_LEFT, &rb->Base.Base);
884    }
885 
886    /*
887     * Assert here that the gl_config has an expected depth/stencil bit
888     * combination: one of d24/s8, d16/s0, d0/s0. (See intelInitScreen2(),
889     * which constructs the advertised configs.)
890     */
891    if (mesaVis->depthBits == 24) {
892       assert(mesaVis->stencilBits == 8);
893 
894       /*
895        * Use combined depth/stencil. Note that the renderbuffer is
896        * attached to two attachment points.
897        */
898       rb = intel_create_private_renderbuffer(MESA_FORMAT_Z24_UNORM_S8_UINT);
899       _mesa_attach_and_own_rb(fb, BUFFER_DEPTH, &rb->Base.Base);
900       _mesa_attach_and_reference_rb(fb, BUFFER_STENCIL, &rb->Base.Base);
901    }
902    else if (mesaVis->depthBits == 16) {
903       assert(mesaVis->stencilBits == 0);
904       rb = intel_create_private_renderbuffer(MESA_FORMAT_Z_UNORM16);
905       _mesa_attach_and_own_rb(fb, BUFFER_DEPTH, &rb->Base.Base);
906    }
907    else {
908       assert(mesaVis->depthBits == 0);
909       assert(mesaVis->stencilBits == 0);
910    }
911 
912    /* now add any/all software-based renderbuffers we may need */
913    _swrast_add_soft_renderbuffers(fb,
914                                   false, /* never sw color */
915                                   false, /* never sw depth */
916                                   false, /* never sw stencil */
917                                   mesaVis->accumRedBits > 0,
918                                   false, /* never sw alpha */
919                                   false  /* never sw aux */ );
920    driDrawPriv->driverPrivate = fb;
921 
922    return true;
923 }
924 
925 static void
intelDestroyBuffer(__DRIdrawable * driDrawPriv)926 intelDestroyBuffer(__DRIdrawable * driDrawPriv)
927 {
928     struct gl_framebuffer *fb = driDrawPriv->driverPrivate;
929 
930     _mesa_reference_framebuffer(&fb, NULL);
931 }
932 
933 /* There are probably better ways to do this, such as an
934  * init-designated function to register chipids and createcontext
935  * functions.
936  */
937 extern bool
938 i830CreateContext(int api,
939                   const struct gl_config *mesaVis,
940 		  __DRIcontext *driContextPriv,
941 		  unsigned major_version,
942 		  unsigned minor_version,
943                   uint32_t flags,
944 		  unsigned *error,
945 		  void *sharedContextPrivate);
946 
947 extern bool
948 i915CreateContext(int api,
949 		  const struct gl_config *mesaVis,
950 		  __DRIcontext *driContextPriv,
951                   unsigned major_version,
952                   unsigned minor_version,
953                   uint32_t flags,
954                   unsigned *error,
955 		  void *sharedContextPrivate);
956 
957 static GLboolean
intelCreateContext(gl_api api,const struct gl_config * mesaVis,__DRIcontext * driContextPriv,const struct __DriverContextConfig * ctx_config,unsigned * error,void * sharedContextPrivate)958 intelCreateContext(gl_api api,
959                    const struct gl_config * mesaVis,
960                    __DRIcontext * driContextPriv,
961                    const struct __DriverContextConfig *ctx_config,
962                    unsigned *error,
963                    void *sharedContextPrivate)
964 {
965    bool success = false;
966 
967    __DRIscreen *sPriv = driContextPriv->driScreenPriv;
968    struct intel_screen *intelScreen = sPriv->driverPrivate;
969 
970    if (ctx_config->flags & ~(__DRI_CTX_FLAG_DEBUG | __DRI_CTX_FLAG_NO_ERROR)) {
971       *error = __DRI_CTX_ERROR_UNKNOWN_FLAG;
972       return false;
973    }
974 
975    if (ctx_config->attribute_mask) {
976       *error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE;
977       return false;
978    }
979 
980    if (IS_GEN3(intelScreen->deviceID)) {
981       success = i915CreateContext(api, mesaVis, driContextPriv,
982                                   ctx_config->major_version,
983                                   ctx_config->minor_version,
984                                   ctx_config->flags,
985                                   error, sharedContextPrivate);
986    } else {
987       intelScreen->no_vbo = true;
988       success = i830CreateContext(api, mesaVis, driContextPriv,
989                                   ctx_config->major_version,
990                                   ctx_config->minor_version,
991                                   ctx_config->flags,
992                                   error, sharedContextPrivate);
993    }
994 
995    if (success)
996       return true;
997 
998    if (driContextPriv->driverPrivate != NULL)
999       intelDestroyContext(driContextPriv);
1000 
1001    return false;
1002 }
1003 
1004 static bool
intel_init_bufmgr(struct intel_screen * intelScreen)1005 intel_init_bufmgr(struct intel_screen *intelScreen)
1006 {
1007    __DRIscreen *spriv = intelScreen->driScrnPriv;
1008 
1009    intelScreen->no_hw = getenv("INTEL_NO_HW") != NULL;
1010 
1011    intelScreen->bufmgr = intel_bufmgr_gem_init(spriv->fd, BATCH_SZ);
1012    if (intelScreen->bufmgr == NULL) {
1013       fprintf(stderr, "[%s:%u] Error initializing buffer manager.\n",
1014 	      __func__, __LINE__);
1015       return false;
1016    }
1017 
1018    drm_intel_bufmgr_gem_enable_fenced_relocs(intelScreen->bufmgr);
1019 
1020    if (!intel_get_boolean(spriv, I915_PARAM_HAS_RELAXED_DELTA)) {
1021       fprintf(stderr, "[%s: %u] Kernel 2.6.39 required.\n", __func__, __LINE__);
1022       return false;
1023    }
1024 
1025    return true;
1026 }
1027 
1028 static bool
intel_detect_swizzling(struct intel_screen * screen)1029 intel_detect_swizzling(struct intel_screen *screen)
1030 {
1031    drm_intel_bo *buffer;
1032    unsigned long flags = 0;
1033    unsigned long aligned_pitch;
1034    uint32_t tiling = I915_TILING_X;
1035    uint32_t swizzle_mode = 0;
1036 
1037    buffer = drm_intel_bo_alloc_tiled(screen->bufmgr, "swizzle test",
1038 				     64, 64, 4,
1039 				     &tiling, &aligned_pitch, flags);
1040    if (buffer == NULL)
1041       return false;
1042 
1043    drm_intel_bo_get_tiling(buffer, &tiling, &swizzle_mode);
1044    drm_intel_bo_unreference(buffer);
1045 
1046    if (swizzle_mode == I915_BIT_6_SWIZZLE_NONE)
1047       return false;
1048    else
1049       return true;
1050 }
1051 
1052 static __DRIconfig**
intel_screen_make_configs(__DRIscreen * dri_screen)1053 intel_screen_make_configs(__DRIscreen *dri_screen)
1054 {
1055    static const mesa_format formats[] = {
1056       MESA_FORMAT_B5G6R5_UNORM,
1057       MESA_FORMAT_B8G8R8A8_UNORM,
1058       MESA_FORMAT_B8G8R8X8_UNORM
1059    };
1060 
1061    /* GLX_SWAP_COPY_OML is not supported due to page flipping. */
1062    static const GLenum back_buffer_modes[] = {
1063       __DRI_ATTRIB_SWAP_UNDEFINED, __DRI_ATTRIB_SWAP_NONE
1064    };
1065 
1066    static const uint8_t singlesample_samples[1] = {0};
1067 
1068    uint8_t depth_bits[4], stencil_bits[4];
1069    __DRIconfig **configs = NULL;
1070 
1071    /* Generate singlesample configs without accumulation buffer. */
1072    for (int i = 0; i < ARRAY_SIZE(formats); i++) {
1073       __DRIconfig **new_configs;
1074       int num_depth_stencil_bits = 2;
1075 
1076       /* Starting with DRI2 protocol version 1.1 we can request a depth/stencil
1077        * buffer that has a different number of bits per pixel than the color
1078        * buffer.
1079        */
1080       depth_bits[0] = 0;
1081       stencil_bits[0] = 0;
1082 
1083       if (formats[i] == MESA_FORMAT_B5G6R5_UNORM) {
1084          depth_bits[1] = 16;
1085          stencil_bits[1] = 0;
1086       } else {
1087          depth_bits[1] = 24;
1088          stencil_bits[1] = 8;
1089       }
1090 
1091       new_configs = driCreateConfigs(formats[i],
1092                                      depth_bits,
1093                                      stencil_bits,
1094                                      num_depth_stencil_bits,
1095                                      back_buffer_modes, 2,
1096                                      singlesample_samples, 1,
1097                                      false, false);
1098       configs = driConcatConfigs(configs, new_configs);
1099    }
1100 
1101    /* Generate the minimum possible set of configs that include an
1102     * accumulation buffer.
1103     */
1104    for (int i = 0; i < ARRAY_SIZE(formats); i++) {
1105       __DRIconfig **new_configs;
1106 
1107       if (formats[i] == MESA_FORMAT_B5G6R5_UNORM) {
1108          depth_bits[0] = 16;
1109          stencil_bits[0] = 0;
1110       } else {
1111          depth_bits[0] = 24;
1112          stencil_bits[0] = 8;
1113       }
1114 
1115       new_configs = driCreateConfigs(formats[i],
1116                                      depth_bits, stencil_bits, 1,
1117                                      back_buffer_modes, 1,
1118                                      singlesample_samples, 1,
1119                                      true, false);
1120       configs = driConcatConfigs(configs, new_configs);
1121    }
1122 
1123    if (configs == NULL) {
1124       fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
1125               __LINE__);
1126       return NULL;
1127    }
1128 
1129    return configs;
1130 }
1131 
1132 static void
set_max_gl_versions(struct intel_screen * screen)1133 set_max_gl_versions(struct intel_screen *screen)
1134 {
1135    __DRIscreen *psp = screen->driScrnPriv;
1136 
1137    switch (screen->gen) {
1138    case 3: {
1139       bool has_fragment_shader = driQueryOptionb(&screen->optionCache, "fragment_shader");
1140       bool has_occlusion_query = driQueryOptionb(&screen->optionCache, "stub_occlusion_query");
1141 
1142       psp->max_gl_core_version = 0;
1143       psp->max_gl_es1_version = 11;
1144       psp->max_gl_es2_version = 20;
1145 
1146       if (has_fragment_shader && has_occlusion_query) {
1147          psp->max_gl_compat_version = 21;
1148       } else {
1149          psp->max_gl_compat_version = 14;
1150       }
1151       break;
1152    }
1153    case 2:
1154       psp->max_gl_core_version = 0;
1155       psp->max_gl_compat_version = 13;
1156       psp->max_gl_es1_version = 11;
1157       psp->max_gl_es2_version = 0;
1158       break;
1159    default:
1160       assert(!"unrecognized intel_screen::gen");
1161       break;
1162    }
1163 }
1164 
1165 /**
1166  * This is the driver specific part of the createNewScreen entry point.
1167  * Called when using DRI2.
1168  *
1169  * \return the struct gl_config supported by this driver
1170  */
1171 static const
intelInitScreen2(__DRIscreen * psp)1172 __DRIconfig **intelInitScreen2(__DRIscreen *psp)
1173 {
1174    struct intel_screen *intelScreen;
1175 
1176    if (psp->image.loader) {
1177    } else if (psp->dri2.loader->base.version <= 2 ||
1178        psp->dri2.loader->getBuffersWithFormat == NULL) {
1179       fprintf(stderr,
1180 	      "\nERROR!  DRI2 loader with getBuffersWithFormat() "
1181 	      "support required\n");
1182       return false;
1183    }
1184 
1185    /* Allocate the private area */
1186    intelScreen = calloc(1, sizeof *intelScreen);
1187    if (!intelScreen) {
1188       fprintf(stderr, "\nERROR!  Allocating private area failed\n");
1189       return false;
1190    }
1191    /* parse information in __driConfigOptions */
1192    driParseOptionInfo(&intelScreen->optionCache, i915_config_options.xml);
1193 
1194    intelScreen->driScrnPriv = psp;
1195    psp->driverPrivate = (void *) intelScreen;
1196 
1197    if (!intel_init_bufmgr(intelScreen))
1198        return false;
1199 
1200    intelScreen->deviceID = drm_intel_bufmgr_gem_get_devid(intelScreen->bufmgr);
1201 
1202    if (IS_GEN3(intelScreen->deviceID)) {
1203       intelScreen->gen = 3;
1204    } else {
1205       intelScreen->gen = 2;
1206    }
1207 
1208    intelScreen->hw_has_swizzling = intel_detect_swizzling(intelScreen);
1209 
1210    set_max_gl_versions(intelScreen);
1211 
1212    psp->extensions = intelScreenExtensions;
1213 
1214    return (const __DRIconfig**) intel_screen_make_configs(psp);
1215 }
1216 
1217 struct intel_buffer {
1218    __DRIbuffer base;
1219    struct intel_region *region;
1220 };
1221 
1222 static __DRIbuffer *
intelAllocateBuffer(__DRIscreen * screen,unsigned attachment,unsigned format,int width,int height)1223 intelAllocateBuffer(__DRIscreen *screen,
1224 		    unsigned attachment, unsigned format,
1225 		    int width, int height)
1226 {
1227    struct intel_buffer *intelBuffer;
1228    struct intel_screen *intelScreen = screen->driverPrivate;
1229 
1230    assert(attachment == __DRI_BUFFER_FRONT_LEFT ||
1231           attachment == __DRI_BUFFER_BACK_LEFT);
1232 
1233    intelBuffer = calloc(1, sizeof *intelBuffer);
1234    if (intelBuffer == NULL)
1235       return NULL;
1236 
1237    /* The front and back buffers are color buffers, which are X tiled. */
1238    intelBuffer->region = intel_region_alloc(intelScreen,
1239                                             I915_TILING_X,
1240                                             format / 8,
1241                                             width,
1242                                             height,
1243                                             true);
1244 
1245    if (intelBuffer->region == NULL) {
1246 	   free(intelBuffer);
1247 	   return NULL;
1248    }
1249 
1250    intel_region_flink(intelBuffer->region, &intelBuffer->base.name);
1251 
1252    intelBuffer->base.attachment = attachment;
1253    intelBuffer->base.cpp = intelBuffer->region->cpp;
1254    intelBuffer->base.pitch = intelBuffer->region->pitch;
1255 
1256    return &intelBuffer->base;
1257 }
1258 
1259 static void
intelReleaseBuffer(__DRIscreen * screen,__DRIbuffer * buffer)1260 intelReleaseBuffer(__DRIscreen *screen, __DRIbuffer *buffer)
1261 {
1262    struct intel_buffer *intelBuffer = (struct intel_buffer *) buffer;
1263 
1264    intel_region_release(&intelBuffer->region);
1265    free(intelBuffer);
1266 }
1267 
1268 
1269 static const struct __DriverAPIRec i915_driver_api = {
1270    .InitScreen		 = intelInitScreen2,
1271    .DestroyScreen	 = intelDestroyScreen,
1272    .CreateContext	 = intelCreateContext,
1273    .DestroyContext	 = intelDestroyContext,
1274    .CreateBuffer	 = intelCreateBuffer,
1275    .DestroyBuffer	 = intelDestroyBuffer,
1276    .MakeCurrent		 = intelMakeCurrent,
1277    .UnbindContext	 = intelUnbindContext,
1278    .AllocateBuffer       = intelAllocateBuffer,
1279    .ReleaseBuffer        = intelReleaseBuffer
1280 };
1281 
1282 static const struct __DRIDriverVtableExtensionRec i915_vtable = {
1283    .base = { __DRI_DRIVER_VTABLE, 1 },
1284    .vtable = &i915_driver_api,
1285 };
1286 
1287 /* This is the table of extensions that the loader will dlsym() for. */
1288 static const __DRIextension *i915_driver_extensions[] = {
1289     &driCoreExtension.base,
1290     &driImageDriverExtension.base,
1291     &driDRI2Extension.base,
1292     &i915_vtable.base,
1293     &i915_config_options.base,
1294     NULL
1295 };
1296 
__driDriverGetExtensions_i915(void)1297 PUBLIC const __DRIextension **__driDriverGetExtensions_i915(void)
1298 {
1299    globalDriverAPI = &i915_driver_api;
1300 
1301    return i915_driver_extensions;
1302 }
1303