OSDN Git Service

mesa: remove outdated version lines in comments
[android-x86/external-mesa.git] / src / gallium / state_trackers / dri / drm / dri2.c
1 /*
2  * Mesa 3-D graphics library
3  *
4  * Copyright 2009, VMware, Inc.
5  * All Rights Reserved.
6  * Copyright (C) 2010 LunarG Inc.
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a
9  * copy of this software and associated documentation files (the "Software"),
10  * to deal in the Software without restriction, including without limitation
11  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12  * and/or sell copies of the Software, and to permit persons to whom the
13  * Software is furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included
16  * in all copies or substantial portions 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 MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24  * OTHER DEALINGS IN THE SOFTWARE.
25  *
26  * Authors:
27  *    Keith Whitwell <keithw@vmware.com> Jakob Bornecrantz
28  *    <wallbraker@gmail.com> Chia-I Wu <olv@lunarg.com>
29  */
30
31 #include "util/u_memory.h"
32 #include "util/u_inlines.h"
33 #include "util/u_format.h"
34 #include "util/u_debug.h"
35 #include "state_tracker/drm_driver.h"
36
37 #include "dri_screen.h"
38 #include "dri_context.h"
39 #include "dri_drawable.h"
40 #include "dri2_buffer.h"
41
42 /**
43  * DRI2 flush extension.
44  */
45 static void
46 dri2_flush_drawable(__DRIdrawable *dPriv)
47 {
48    dri_flush(dPriv->driContextPriv, dPriv, __DRI2_FLUSH_DRAWABLE, 0);
49 }
50
51 static void
52 dri2_invalidate_drawable(__DRIdrawable *dPriv)
53 {
54    struct dri_drawable *drawable = dri_drawable(dPriv);
55
56    dri2InvalidateDrawable(dPriv);
57    drawable->dPriv->lastStamp = drawable->dPriv->dri2.stamp;
58
59    p_atomic_inc(&drawable->base.stamp);
60 }
61
62 static const __DRI2flushExtension dri2FlushExtension = {
63     { __DRI2_FLUSH, __DRI2_FLUSH_VERSION },
64     dri2_flush_drawable,
65     dri2_invalidate_drawable,
66     dri_flush,
67 };
68
69 /**
70  * Retrieve __DRIbuffer from the DRI loader.
71  */
72 static __DRIbuffer *
73 dri2_drawable_get_buffers(struct dri_drawable *drawable,
74                           const enum st_attachment_type *atts,
75                           unsigned *count)
76 {
77    __DRIdrawable *dri_drawable = drawable->dPriv;
78    struct __DRIdri2LoaderExtensionRec *loader = drawable->sPriv->dri2.loader;
79    boolean with_format;
80    __DRIbuffer *buffers;
81    int num_buffers;
82    unsigned attachments[10];
83    unsigned num_attachments, i;
84
85    assert(loader);
86    with_format = dri_with_format(drawable->sPriv);
87
88    num_attachments = 0;
89
90    /* for Xserver 1.6.0 (DRI2 version 1) we always need to ask for the front */
91    if (!with_format)
92       attachments[num_attachments++] = __DRI_BUFFER_FRONT_LEFT;
93
94    for (i = 0; i < *count; i++) {
95       enum pipe_format format;
96       unsigned bind;
97       int att, depth;
98
99       dri_drawable_get_format(drawable, atts[i], &format, &bind);
100       if (format == PIPE_FORMAT_NONE)
101          continue;
102
103       switch (atts[i]) {
104       case ST_ATTACHMENT_FRONT_LEFT:
105          /* already added */
106          if (!with_format)
107             continue;
108          att = __DRI_BUFFER_FRONT_LEFT;
109          break;
110       case ST_ATTACHMENT_BACK_LEFT:
111          att = __DRI_BUFFER_BACK_LEFT;
112          break;
113       case ST_ATTACHMENT_FRONT_RIGHT:
114          att = __DRI_BUFFER_FRONT_RIGHT;
115          break;
116       case ST_ATTACHMENT_BACK_RIGHT:
117          att = __DRI_BUFFER_BACK_RIGHT;
118          break;
119       default:
120          continue;
121       }
122
123       /*
124        * In this switch statement we must support all formats that
125        * may occur as the stvis->color_format.
126        */
127       switch(format) {
128       case PIPE_FORMAT_B8G8R8A8_UNORM:
129          depth = 32;
130          break;
131       case PIPE_FORMAT_B8G8R8X8_UNORM:
132          depth = 24;
133          break;
134       case PIPE_FORMAT_B5G6R5_UNORM:
135          depth = 16;
136          break;
137       default:
138          depth = util_format_get_blocksizebits(format);
139          assert(!"Unexpected format in dri2_drawable_get_buffers()");
140       }
141
142       attachments[num_attachments++] = att;
143       if (with_format) {
144          attachments[num_attachments++] = depth;
145       }
146    }
147
148    if (with_format) {
149       num_attachments /= 2;
150       buffers = loader->getBuffersWithFormat(dri_drawable,
151             &dri_drawable->w, &dri_drawable->h,
152             attachments, num_attachments,
153             &num_buffers, dri_drawable->loaderPrivate);
154    }
155    else {
156       buffers = loader->getBuffers(dri_drawable,
157             &dri_drawable->w, &dri_drawable->h,
158             attachments, num_attachments,
159             &num_buffers, dri_drawable->loaderPrivate);
160    }
161
162    if (buffers)
163       *count = num_buffers;
164
165    return buffers;
166 }
167
168 /**
169  * Process __DRIbuffer and convert them into pipe_resources.
170  */
171 static void
172 dri2_drawable_process_buffers(struct dri_drawable *drawable,
173                               __DRIbuffer *buffers, unsigned buffer_count,
174                               const enum st_attachment_type *atts,
175                               unsigned att_count)
176 {
177    struct dri_screen *screen = dri_screen(drawable->sPriv);
178    __DRIdrawable *dri_drawable = drawable->dPriv;
179    struct pipe_resource templ;
180    struct winsys_handle whandle;
181    boolean alloc_depthstencil = FALSE;
182    unsigned i, bind;
183
184    if (drawable->old_num == buffer_count &&
185        drawable->old_w == dri_drawable->w &&
186        drawable->old_h == dri_drawable->h &&
187        memcmp(drawable->old, buffers, sizeof(__DRIbuffer) * buffer_count) == 0)
188       return;
189
190    for (i = 0; i < ST_ATTACHMENT_COUNT; i++)
191       pipe_resource_reference(&drawable->textures[i], NULL);
192    for (i = 0; i < ST_ATTACHMENT_COUNT; i++)
193       pipe_resource_reference(&drawable->msaa_textures[i], NULL);
194
195    memset(&templ, 0, sizeof(templ));
196    templ.target = screen->target;
197    templ.last_level = 0;
198    templ.width0 = dri_drawable->w;
199    templ.height0 = dri_drawable->h;
200    templ.depth0 = 1;
201    templ.array_size = 1;
202
203    memset(&whandle, 0, sizeof(whandle));
204
205    /* Process DRI-provided buffers and get pipe_resources. */
206    for (i = 0; i < buffer_count; i++) {
207       __DRIbuffer *buf = &buffers[i];
208       enum st_attachment_type statt;
209       enum pipe_format format;
210
211       switch (buf->attachment) {
212       case __DRI_BUFFER_FRONT_LEFT:
213          if (!screen->auto_fake_front) {
214             continue; /* invalid attachment */
215          }
216          /* fallthrough */
217       case __DRI_BUFFER_FAKE_FRONT_LEFT:
218          statt = ST_ATTACHMENT_FRONT_LEFT;
219          break;
220       case __DRI_BUFFER_BACK_LEFT:
221          statt = ST_ATTACHMENT_BACK_LEFT;
222          break;
223       default:
224          continue; /* invalid attachment */
225       }
226
227       dri_drawable_get_format(drawable, statt, &format, &bind);
228       if (format == PIPE_FORMAT_NONE)
229          continue;
230
231       templ.format = format;
232       templ.bind = bind;
233       whandle.handle = buf->name;
234       whandle.stride = buf->pitch;
235
236       drawable->textures[statt] =
237          screen->base.screen->resource_from_handle(screen->base.screen,
238                &templ, &whandle);
239       assert(drawable->textures[statt]);
240    }
241
242    /* Allocate private MSAA colorbuffers. */
243    if (drawable->stvis.samples > 1) {
244       for (i = 0; i < att_count; i++) {
245          enum st_attachment_type att = atts[i];
246
247          if (drawable->textures[att]) {
248             templ.format = drawable->textures[att]->format;
249             templ.bind = drawable->textures[att]->bind;
250             templ.nr_samples = drawable->stvis.samples;
251
252             drawable->msaa_textures[att] =
253                screen->base.screen->resource_create(screen->base.screen,
254                                                     &templ);
255             assert(drawable->msaa_textures[att]);
256          }
257       }
258    }
259
260    /* See if we need a depth-stencil buffer. */
261    for (i = 0; i < att_count; i++) {
262       if (atts[i] == ST_ATTACHMENT_DEPTH_STENCIL) {
263          alloc_depthstencil = TRUE;
264          break;
265       }
266    }
267
268    /* Allocate a private depth-stencil buffer. */
269    if (alloc_depthstencil) {
270       enum pipe_format format;
271       unsigned bind;
272
273       dri_drawable_get_format(drawable, ST_ATTACHMENT_DEPTH_STENCIL,
274                               &format, &bind);
275       if (format) {
276          templ.format = format;
277          templ.bind = bind;
278
279          if (drawable->stvis.samples > 1) {
280             templ.nr_samples = drawable->stvis.samples;
281             drawable->msaa_textures[ST_ATTACHMENT_DEPTH_STENCIL] =
282                screen->base.screen->resource_create(screen->base.screen,
283                                                     &templ);
284             assert(drawable->msaa_textures[ST_ATTACHMENT_DEPTH_STENCIL]);
285          }
286          else {
287             templ.nr_samples = 0;
288             drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL] =
289                screen->base.screen->resource_create(screen->base.screen,
290                                                     &templ);
291             assert(drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]);
292          }
293       }
294    }
295
296    drawable->old_num = buffer_count;
297    drawable->old_w = dri_drawable->w;
298    drawable->old_h = dri_drawable->h;
299    memcpy(drawable->old, buffers, sizeof(__DRIbuffer) * buffer_count);
300 }
301
302 static __DRIbuffer *
303 dri2_allocate_buffer(__DRIscreen *sPriv,
304                      unsigned attachment, unsigned format,
305                      int width, int height)
306 {
307    struct dri_screen *screen = dri_screen(sPriv);
308    struct dri2_buffer *buffer;
309    struct pipe_resource templ;
310    enum pipe_format pf;
311    unsigned bind = 0;
312    struct winsys_handle whandle;
313
314    switch (attachment) {
315       case __DRI_BUFFER_FRONT_LEFT:
316       case __DRI_BUFFER_FAKE_FRONT_LEFT:
317          bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
318          break;
319       case __DRI_BUFFER_BACK_LEFT:
320          bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
321          break;
322       case __DRI_BUFFER_DEPTH:
323       case __DRI_BUFFER_DEPTH_STENCIL:
324       case __DRI_BUFFER_STENCIL:
325             bind = PIPE_BIND_DEPTH_STENCIL; /* XXX sampler? */
326          break;
327    }
328
329    /* because we get the handle and stride */
330    bind |= PIPE_BIND_SHARED;
331
332    switch (format) {
333       case 32:
334          pf = PIPE_FORMAT_B8G8R8A8_UNORM;
335          break;
336       case 24:
337          pf = PIPE_FORMAT_B8G8R8X8_UNORM;
338          break;
339       case 16:
340          pf = PIPE_FORMAT_Z16_UNORM;
341          break;
342       default:
343          return NULL;
344    }
345
346    buffer = CALLOC_STRUCT(dri2_buffer);
347    if (!buffer)
348       return NULL;
349
350    memset(&templ, 0, sizeof(templ));
351    templ.bind = bind;
352    templ.format = pf;
353    templ.target = PIPE_TEXTURE_2D;
354    templ.last_level = 0;
355    templ.width0 = width;
356    templ.height0 = height;
357    templ.depth0 = 1;
358    templ.array_size = 1;
359
360    buffer->resource =
361       screen->base.screen->resource_create(screen->base.screen, &templ);
362    if (!buffer->resource) {
363       FREE(buffer);
364       return NULL;
365    }
366
367    memset(&whandle, 0, sizeof(whandle));
368    whandle.type = DRM_API_HANDLE_TYPE_SHARED;
369    screen->base.screen->resource_get_handle(screen->base.screen,
370          buffer->resource, &whandle);
371
372    buffer->base.attachment = attachment;
373    buffer->base.name = whandle.handle;
374    buffer->base.cpp = util_format_get_blocksize(pf);
375    buffer->base.pitch = whandle.stride;
376
377    return &buffer->base;
378 }
379
380 static void
381 dri2_release_buffer(__DRIscreen *sPriv, __DRIbuffer *bPriv)
382 {
383    struct dri2_buffer *buffer = dri2_buffer(bPriv);
384
385    pipe_resource_reference(&buffer->resource, NULL);
386    FREE(buffer);
387 }
388
389 /*
390  * Backend functions for st_framebuffer interface.
391  */
392
393 static void
394 dri2_allocate_textures(struct dri_drawable *drawable,
395                        const enum st_attachment_type *statts,
396                        unsigned statts_count)
397 {
398    __DRIbuffer *buffers;
399    unsigned num_buffers = statts_count;
400
401    buffers = dri2_drawable_get_buffers(drawable, statts, &num_buffers);
402    if (buffers)
403       dri2_drawable_process_buffers(drawable, buffers, num_buffers,
404                                     statts, statts_count);
405 }
406
407 static void
408 dri2_flush_frontbuffer(struct dri_context *ctx,
409                        struct dri_drawable *drawable,
410                        enum st_attachment_type statt)
411 {
412    __DRIdrawable *dri_drawable = drawable->dPriv;
413    struct __DRIdri2LoaderExtensionRec *loader = drawable->sPriv->dri2.loader;
414
415    if (statt != ST_ATTACHMENT_FRONT_LEFT)
416       return;
417
418    if (drawable->stvis.samples > 1) {
419       struct pipe_context *pipe = ctx->st->pipe;
420
421       dri_msaa_resolve(ctx, drawable, ST_ATTACHMENT_FRONT_LEFT);
422       pipe->flush(pipe, NULL, 0);
423    }
424
425    if (loader->flushFrontBuffer) {
426       loader->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate);
427    }
428 }
429
430 static void
431 dri2_update_tex_buffer(struct dri_drawable *drawable,
432                        struct dri_context *ctx,
433                        struct pipe_resource *res)
434 {
435    /* no-op */
436 }
437
438 static __DRIimage *
439 dri2_lookup_egl_image(struct dri_screen *screen, void *handle)
440 {
441    __DRIimageLookupExtension *loader = screen->sPriv->dri2.image;
442    __DRIimage *img;
443
444    if (!loader->lookupEGLImage)
445       return NULL;
446
447    img = loader->lookupEGLImage(screen->sPriv,
448                                 handle, screen->sPriv->loaderPrivate);
449
450    return img;
451 }
452
453 static __DRIimage *
454 dri2_create_image_from_name(__DRIscreen *_screen,
455                             int width, int height, int format,
456                             int name, int pitch, void *loaderPrivate)
457 {
458    struct dri_screen *screen = dri_screen(_screen);
459    __DRIimage *img;
460    struct pipe_resource templ;
461    struct winsys_handle whandle;
462    unsigned tex_usage;
463    enum pipe_format pf;
464
465    tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
466
467    switch (format) {
468    case __DRI_IMAGE_FORMAT_RGB565:
469       pf = PIPE_FORMAT_B5G6R5_UNORM;
470       break;
471    case __DRI_IMAGE_FORMAT_XRGB8888:
472       pf = PIPE_FORMAT_B8G8R8X8_UNORM;
473       break;
474    case __DRI_IMAGE_FORMAT_ARGB8888:
475       pf = PIPE_FORMAT_B8G8R8A8_UNORM;
476       break;
477    case __DRI_IMAGE_FORMAT_ABGR8888:
478       pf = PIPE_FORMAT_R8G8B8A8_UNORM;
479       break;
480    default:
481       pf = PIPE_FORMAT_NONE;
482       break;
483    }
484    if (pf == PIPE_FORMAT_NONE)
485       return NULL;
486
487    img = CALLOC_STRUCT(__DRIimageRec);
488    if (!img)
489       return NULL;
490
491    memset(&templ, 0, sizeof(templ));
492    templ.bind = tex_usage;
493    templ.format = pf;
494    templ.target = screen->target;
495    templ.last_level = 0;
496    templ.width0 = width;
497    templ.height0 = height;
498    templ.depth0 = 1;
499    templ.array_size = 1;
500
501    memset(&whandle, 0, sizeof(whandle));
502    whandle.handle = name;
503    whandle.stride = pitch * util_format_get_blocksize(pf);
504
505    img->texture = screen->base.screen->resource_from_handle(screen->base.screen,
506          &templ, &whandle);
507    if (!img->texture) {
508       FREE(img);
509       return NULL;
510    }
511
512    img->level = 0;
513    img->layer = 0;
514    img->dri_format = format;
515    img->loader_private = loaderPrivate;
516
517    return img;
518 }
519
520 static __DRIimage *
521 dri2_create_image_from_renderbuffer(__DRIcontext *context,
522                                     int renderbuffer, void *loaderPrivate)
523 {
524    struct dri_context *ctx = dri_context(context);
525
526    if (!ctx->st->get_resource_for_egl_image)
527       return NULL;
528
529    /* TODO */
530    return NULL;
531 }
532
533 static __DRIimage *
534 dri2_create_image(__DRIscreen *_screen,
535                    int width, int height, int format,
536                    unsigned int use, void *loaderPrivate)
537 {
538    struct dri_screen *screen = dri_screen(_screen);
539    __DRIimage *img;
540    struct pipe_resource templ;
541    unsigned tex_usage;
542    enum pipe_format pf;
543
544    tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
545    if (use & __DRI_IMAGE_USE_SCANOUT)
546       tex_usage |= PIPE_BIND_SCANOUT;
547    if (use & __DRI_IMAGE_USE_SHARE)
548       tex_usage |= PIPE_BIND_SHARED;
549    if (use & __DRI_IMAGE_USE_CURSOR) {
550       if (width != 64 || height != 64)
551          return NULL;
552       tex_usage |= PIPE_BIND_CURSOR;
553    }
554
555    switch (format) {
556    case __DRI_IMAGE_FORMAT_RGB565:
557       pf = PIPE_FORMAT_B5G6R5_UNORM;
558       break;
559    case __DRI_IMAGE_FORMAT_XRGB8888:
560       pf = PIPE_FORMAT_B8G8R8X8_UNORM;
561       break;
562    case __DRI_IMAGE_FORMAT_ARGB8888:
563       pf = PIPE_FORMAT_B8G8R8A8_UNORM;
564       break;
565    case __DRI_IMAGE_FORMAT_ABGR8888:
566       pf = PIPE_FORMAT_R8G8B8A8_UNORM;
567       break;
568    default:
569       pf = PIPE_FORMAT_NONE;
570       break;
571    }
572    if (pf == PIPE_FORMAT_NONE)
573       return NULL;
574
575    img = CALLOC_STRUCT(__DRIimageRec);
576    if (!img)
577       return NULL;
578
579    memset(&templ, 0, sizeof(templ));
580    templ.bind = tex_usage;
581    templ.format = pf;
582    templ.target = PIPE_TEXTURE_2D;
583    templ.last_level = 0;
584    templ.width0 = width;
585    templ.height0 = height;
586    templ.depth0 = 1;
587    templ.array_size = 1;
588
589    img->texture = screen->base.screen->resource_create(screen->base.screen, &templ);
590    if (!img->texture) {
591       FREE(img);
592       return NULL;
593    }
594
595    img->level = 0;
596    img->layer = 0;
597    img->dri_format = format;
598    img->dri_components = 0;
599
600    img->loader_private = loaderPrivate;
601    return img;
602 }
603
604 static GLboolean
605 dri2_query_image(__DRIimage *image, int attrib, int *value)
606 {
607    struct winsys_handle whandle;
608    memset(&whandle, 0, sizeof(whandle));
609
610    switch (attrib) {
611    case __DRI_IMAGE_ATTRIB_STRIDE:
612       image->texture->screen->resource_get_handle(image->texture->screen,
613             image->texture, &whandle);
614       *value = whandle.stride;
615       return GL_TRUE;
616    case __DRI_IMAGE_ATTRIB_HANDLE:
617       whandle.type = DRM_API_HANDLE_TYPE_KMS;
618       image->texture->screen->resource_get_handle(image->texture->screen,
619          image->texture, &whandle);
620       *value = whandle.handle;
621       return GL_TRUE;
622    case __DRI_IMAGE_ATTRIB_NAME:
623       whandle.type = DRM_API_HANDLE_TYPE_SHARED;
624       image->texture->screen->resource_get_handle(image->texture->screen,
625          image->texture, &whandle);
626       *value = whandle.handle;
627       return GL_TRUE;
628    case __DRI_IMAGE_ATTRIB_FORMAT:
629       *value = image->dri_format;
630       return GL_TRUE;
631    case __DRI_IMAGE_ATTRIB_WIDTH:
632       *value = image->texture->width0;
633       return GL_TRUE;
634    case __DRI_IMAGE_ATTRIB_HEIGHT:
635       *value = image->texture->height0;
636       return GL_TRUE;
637    case __DRI_IMAGE_ATTRIB_COMPONENTS:
638       if (image->dri_components == 0)
639          return GL_FALSE;
640       *value = image->dri_components;
641       return GL_TRUE;
642    default:
643       return GL_FALSE;
644    }
645 }
646
647 static __DRIimage *
648 dri2_dup_image(__DRIimage *image, void *loaderPrivate)
649 {
650    __DRIimage *img;
651
652    img = CALLOC_STRUCT(__DRIimageRec);
653    if (!img)
654       return NULL;
655
656    img->texture = NULL;
657    pipe_resource_reference(&img->texture, image->texture);
658    img->level = image->level;
659    img->layer = image->layer;
660    /* This should be 0 for sub images, but dup is also used for base images. */
661    img->dri_components = image->dri_components;
662    img->loader_private = loaderPrivate;
663
664    return img;
665 }
666
667 static GLboolean
668 dri2_validate_usage(__DRIimage *image, unsigned int use)
669 {
670    /*
671     * Gallium drivers are bad at adding usages to the resources
672     * once opened again in another process, which is the main use
673     * case for this, so we have to lie.
674     */
675    if (image != NULL)
676       return GL_TRUE;
677    else
678       return GL_FALSE;
679 }
680
681 static __DRIimage *
682 dri2_from_names(__DRIscreen *screen, int width, int height, int format,
683                 int *names, int num_names, int *strides, int *offsets,
684                 void *loaderPrivate)
685 {
686    __DRIimage *img;
687    int stride, dri_components;
688
689    if (num_names != 1)
690       return NULL;
691    if (offsets[0] != 0)
692       return NULL;
693
694    switch(format) {
695    case __DRI_IMAGE_FOURCC_RGB565:
696       format = __DRI_IMAGE_FORMAT_RGB565;
697       dri_components = __DRI_IMAGE_COMPONENTS_RGB;
698       break;
699    case __DRI_IMAGE_FOURCC_ARGB8888:
700       format = __DRI_IMAGE_FORMAT_ARGB8888;
701       dri_components = __DRI_IMAGE_COMPONENTS_RGBA;
702       break;
703    case __DRI_IMAGE_FOURCC_XRGB8888:
704       format = __DRI_IMAGE_FORMAT_XRGB8888;
705       dri_components = __DRI_IMAGE_COMPONENTS_RGB;
706       break;
707    case __DRI_IMAGE_FOURCC_ABGR8888:
708       format = __DRI_IMAGE_FORMAT_ABGR8888;
709       dri_components = __DRI_IMAGE_COMPONENTS_RGBA;
710       break;
711    case __DRI_IMAGE_FOURCC_XBGR8888:
712       format = __DRI_IMAGE_FORMAT_XBGR8888;
713       dri_components = __DRI_IMAGE_COMPONENTS_RGB;
714       break;
715    default:
716       return NULL;
717    }
718
719    /* Strides are in bytes not pixels. */
720    stride = strides[0] /4;
721
722    img = dri2_create_image_from_name(screen, width, height, format,
723                                      names[0], stride, loaderPrivate);
724    if (img == NULL)
725       return NULL;
726
727    img->dri_components = dri_components;
728    return img;
729 }
730
731 static __DRIimage *
732 dri2_from_planar(__DRIimage *image, int plane, void *loaderPrivate)
733 {
734    __DRIimage *img;
735
736    if (plane != 0)
737       return NULL;
738
739    if (image->dri_components == 0)
740       return NULL;
741
742    img = dri2_dup_image(image, loaderPrivate);
743    if (img == NULL)
744       return NULL;
745
746    /* set this to 0 for sub images. */
747    img->dri_components = 0;
748    return img;
749 }
750
751 static void
752 dri2_destroy_image(__DRIimage *img)
753 {
754    pipe_resource_reference(&img->texture, NULL);
755    FREE(img);
756 }
757
758 static struct __DRIimageExtensionRec dri2ImageExtension = {
759     { __DRI_IMAGE, 5 },
760     dri2_create_image_from_name,
761     dri2_create_image_from_renderbuffer,
762     dri2_destroy_image,
763     dri2_create_image,
764     dri2_query_image,
765     dri2_dup_image,
766     dri2_validate_usage,
767     dri2_from_names,
768     dri2_from_planar,
769 };
770
771 /*
772  * Backend function init_screen.
773  */
774
775 static const __DRIextension *dri_screen_extensions[] = {
776    &driTexBufferExtension.base,
777    &dri2FlushExtension.base,
778    &dri2ImageExtension.base,
779    &dri2ConfigQueryExtension.base,
780    &dri2ThrottleExtension.base,
781    NULL
782 };
783
784 /**
785  * This is the driver specific part of the createNewScreen entry point.
786  *
787  * Returns the struct gl_config supported by this driver.
788  */
789 static const __DRIconfig **
790 dri2_init_screen(__DRIscreen * sPriv)
791 {
792    const __DRIconfig **configs;
793    struct dri_screen *screen;
794    struct pipe_screen *pscreen;
795    const struct drm_conf_ret *throttle_ret = NULL;
796
797    screen = CALLOC_STRUCT(dri_screen);
798    if (!screen)
799       return NULL;
800
801    screen->sPriv = sPriv;
802    screen->fd = sPriv->fd;
803
804    sPriv->driverPrivate = (void *)screen;
805
806    pscreen = driver_descriptor.create_screen(screen->fd);
807    if (driver_descriptor.configuration)
808       throttle_ret = driver_descriptor.configuration(DRM_CONF_THROTTLE);
809
810    if (throttle_ret && throttle_ret->val.val_int != -1) {
811       screen->throttling_enabled = TRUE;
812       screen->default_throttle_frames = throttle_ret->val.val_int;
813    }
814
815    sPriv->extensions = dri_screen_extensions;
816
817    /* dri_init_screen_helper checks pscreen for us */
818
819    configs = dri_init_screen_helper(screen, pscreen);
820    if (!configs)
821       goto fail;
822
823    sPriv->api_mask = 0;
824    if (screen->st_api->profile_mask & ST_PROFILE_DEFAULT_MASK)
825       sPriv->api_mask |= 1 << __DRI_API_OPENGL;
826    if (screen->st_api->profile_mask & ST_PROFILE_OPENGL_ES1_MASK)
827       sPriv->api_mask |= 1 << __DRI_API_GLES;
828    if (screen->st_api->profile_mask & ST_PROFILE_OPENGL_ES2_MASK)
829       sPriv->api_mask |= 1 << __DRI_API_GLES2;
830
831    screen->auto_fake_front = dri_with_format(sPriv);
832    screen->broken_invalidate = !sPriv->dri2.useInvalidate;
833    screen->lookup_egl_image = dri2_lookup_egl_image;
834
835    return configs;
836 fail:
837    dri_destroy_screen_helper(screen);
838    FREE(screen);
839    return NULL;
840 }
841
842 static boolean
843 dri2_create_buffer(__DRIscreen * sPriv,
844                    __DRIdrawable * dPriv,
845                    const struct gl_config * visual, boolean isPixmap)
846 {
847    struct dri_drawable *drawable = NULL;
848
849    if (!dri_create_buffer(sPriv, dPriv, visual, isPixmap))
850       return FALSE;
851
852    drawable = dPriv->driverPrivate;
853
854    drawable->allocate_textures = dri2_allocate_textures;
855    drawable->flush_frontbuffer = dri2_flush_frontbuffer;
856    drawable->update_tex_buffer = dri2_update_tex_buffer;
857
858    return TRUE;
859 }
860
861 /**
862  * DRI driver virtual function table.
863  *
864  * DRI versions differ in their implementation of init_screen and swap_buffers.
865  */
866 const struct __DriverAPIRec driDriverAPI = {
867    .InitScreen = dri2_init_screen,
868    .DestroyScreen = dri_destroy_screen,
869    .CreateContext = dri_create_context,
870    .DestroyContext = dri_destroy_context,
871    .CreateBuffer = dri2_create_buffer,
872    .DestroyBuffer = dri_destroy_buffer,
873    .MakeCurrent = dri_make_current,
874    .UnbindContext = dri_unbind_context,
875
876    .AllocateBuffer = dri2_allocate_buffer,
877    .ReleaseBuffer  = dri2_release_buffer,
878 };
879
880 /* This is the table of extensions that the loader will dlsym() for. */
881 PUBLIC const __DRIextension *__driDriverExtensions[] = {
882     &driCoreExtension.base,
883     &driDRI2Extension.base,
884     NULL
885 };
886
887 /* vim: set sw=3 ts=8 sts=3 expandtab: */