dri2.c revision 848b8605
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 <xf86drm.h>
32#include "util/u_memory.h"
33#include "util/u_inlines.h"
34#include "util/u_format.h"
35#include "util/u_debug.h"
36#include "state_tracker/drm_driver.h"
37#include "state_tracker/st_texture.h"
38#include "state_tracker/st_context.h"
39#include "pipe-loader/pipe_loader.h"
40#include "main/texobj.h"
41
42#include "dri_screen.h"
43#include "dri_context.h"
44#include "dri_drawable.h"
45#include "dri_query_renderer.h"
46#include "dri2_buffer.h"
47
48static int convert_fourcc(int format, int *dri_components_p)
49{
50   int dri_components;
51   switch(format) {
52   case __DRI_IMAGE_FOURCC_RGB565:
53      format = __DRI_IMAGE_FORMAT_RGB565;
54      dri_components = __DRI_IMAGE_COMPONENTS_RGB;
55      break;
56   case __DRI_IMAGE_FOURCC_ARGB8888:
57      format = __DRI_IMAGE_FORMAT_ARGB8888;
58      dri_components = __DRI_IMAGE_COMPONENTS_RGBA;
59      break;
60   case __DRI_IMAGE_FOURCC_XRGB8888:
61      format = __DRI_IMAGE_FORMAT_XRGB8888;
62      dri_components = __DRI_IMAGE_COMPONENTS_RGB;
63      break;
64   case __DRI_IMAGE_FOURCC_ABGR8888:
65      format = __DRI_IMAGE_FORMAT_ABGR8888;
66      dri_components = __DRI_IMAGE_COMPONENTS_RGBA;
67      break;
68   case __DRI_IMAGE_FOURCC_XBGR8888:
69      format = __DRI_IMAGE_FORMAT_XBGR8888;
70      dri_components = __DRI_IMAGE_COMPONENTS_RGB;
71      break;
72   default:
73      return -1;
74   }
75   *dri_components_p = dri_components;
76   return format;
77}
78
79/**
80 * DRI2 flush extension.
81 */
82static void
83dri2_flush_drawable(__DRIdrawable *dPriv)
84{
85   dri_flush(dPriv->driContextPriv, dPriv, __DRI2_FLUSH_DRAWABLE, -1);
86}
87
88static void
89dri2_invalidate_drawable(__DRIdrawable *dPriv)
90{
91   struct dri_drawable *drawable = dri_drawable(dPriv);
92
93   dri2InvalidateDrawable(dPriv);
94   drawable->dPriv->lastStamp = drawable->dPriv->dri2.stamp;
95
96   p_atomic_inc(&drawable->base.stamp);
97}
98
99static const __DRI2flushExtension dri2FlushExtension = {
100    .base = { __DRI2_FLUSH, 4 },
101
102    .flush                = dri2_flush_drawable,
103    .invalidate           = dri2_invalidate_drawable,
104    .flush_with_flags     = dri_flush,
105};
106
107/**
108 * Retrieve __DRIbuffer from the DRI loader.
109 */
110static __DRIbuffer *
111dri2_drawable_get_buffers(struct dri_drawable *drawable,
112                          const enum st_attachment_type *atts,
113                          unsigned *count)
114{
115   __DRIdrawable *dri_drawable = drawable->dPriv;
116   const __DRIdri2LoaderExtension *loader = drawable->sPriv->dri2.loader;
117   boolean with_format;
118   __DRIbuffer *buffers;
119   int num_buffers;
120   unsigned attachments[10];
121   unsigned num_attachments, i;
122
123   assert(loader);
124   with_format = dri_with_format(drawable->sPriv);
125
126   num_attachments = 0;
127
128   /* for Xserver 1.6.0 (DRI2 version 1) we always need to ask for the front */
129   if (!with_format)
130      attachments[num_attachments++] = __DRI_BUFFER_FRONT_LEFT;
131
132   for (i = 0; i < *count; i++) {
133      enum pipe_format format;
134      unsigned bind;
135      int att, depth;
136
137      dri_drawable_get_format(drawable, atts[i], &format, &bind);
138      if (format == PIPE_FORMAT_NONE)
139         continue;
140
141      switch (atts[i]) {
142      case ST_ATTACHMENT_FRONT_LEFT:
143         /* already added */
144         if (!with_format)
145            continue;
146         att = __DRI_BUFFER_FRONT_LEFT;
147         break;
148      case ST_ATTACHMENT_BACK_LEFT:
149         att = __DRI_BUFFER_BACK_LEFT;
150         break;
151      case ST_ATTACHMENT_FRONT_RIGHT:
152         att = __DRI_BUFFER_FRONT_RIGHT;
153         break;
154      case ST_ATTACHMENT_BACK_RIGHT:
155         att = __DRI_BUFFER_BACK_RIGHT;
156         break;
157      default:
158         continue;
159      }
160
161      /*
162       * In this switch statement we must support all formats that
163       * may occur as the stvis->color_format.
164       */
165      switch(format) {
166      case PIPE_FORMAT_B8G8R8A8_UNORM:
167	 depth = 32;
168	 break;
169      case PIPE_FORMAT_B8G8R8X8_UNORM:
170	 depth = 24;
171	 break;
172      case PIPE_FORMAT_B5G6R5_UNORM:
173	 depth = 16;
174	 break;
175      default:
176	 depth = util_format_get_blocksizebits(format);
177	 assert(!"Unexpected format in dri2_drawable_get_buffers()");
178      }
179
180      attachments[num_attachments++] = att;
181      if (with_format) {
182         attachments[num_attachments++] = depth;
183      }
184   }
185
186   if (with_format) {
187      num_attachments /= 2;
188      buffers = loader->getBuffersWithFormat(dri_drawable,
189            &dri_drawable->w, &dri_drawable->h,
190            attachments, num_attachments,
191            &num_buffers, dri_drawable->loaderPrivate);
192   }
193   else {
194      buffers = loader->getBuffers(dri_drawable,
195            &dri_drawable->w, &dri_drawable->h,
196            attachments, num_attachments,
197            &num_buffers, dri_drawable->loaderPrivate);
198   }
199
200   if (buffers)
201      *count = num_buffers;
202
203   return buffers;
204}
205
206static bool
207dri_image_drawable_get_buffers(struct dri_drawable *drawable,
208                               struct __DRIimageList *images,
209                               const enum st_attachment_type *statts,
210                               unsigned statts_count)
211{
212   __DRIdrawable *dPriv = drawable->dPriv;
213   __DRIscreen *sPriv = drawable->sPriv;
214   unsigned int image_format = __DRI_IMAGE_FORMAT_NONE;
215   enum pipe_format pf;
216   uint32_t buffer_mask = 0;
217   unsigned i, bind;
218
219   for (i = 0; i < statts_count; i++) {
220      dri_drawable_get_format(drawable, statts[i], &pf, &bind);
221      if (pf == PIPE_FORMAT_NONE)
222         continue;
223
224      switch (statts[i]) {
225      case ST_ATTACHMENT_FRONT_LEFT:
226         buffer_mask |= __DRI_IMAGE_BUFFER_FRONT;
227         break;
228      case ST_ATTACHMENT_BACK_LEFT:
229         buffer_mask |= __DRI_IMAGE_BUFFER_BACK;
230         break;
231      default:
232         continue;
233      }
234
235      switch (pf) {
236      case PIPE_FORMAT_B5G6R5_UNORM:
237         image_format = __DRI_IMAGE_FORMAT_RGB565;
238         break;
239      case PIPE_FORMAT_B8G8R8X8_UNORM:
240         image_format = __DRI_IMAGE_FORMAT_XRGB8888;
241         break;
242      case PIPE_FORMAT_B8G8R8A8_UNORM:
243         image_format = __DRI_IMAGE_FORMAT_ARGB8888;
244         break;
245      case PIPE_FORMAT_R8G8B8A8_UNORM:
246         image_format = __DRI_IMAGE_FORMAT_ABGR8888;
247         break;
248      default:
249         image_format = __DRI_IMAGE_FORMAT_NONE;
250         break;
251      }
252   }
253
254   return (*sPriv->image.loader->getBuffers) (dPriv, image_format,
255                                       (uint32_t *) &drawable->base.stamp,
256                                       dPriv->loaderPrivate, buffer_mask,
257                                       images);
258}
259
260static __DRIbuffer *
261dri2_allocate_buffer(__DRIscreen *sPriv,
262                     unsigned attachment, unsigned format,
263                     int width, int height)
264{
265   struct dri_screen *screen = dri_screen(sPriv);
266   struct dri2_buffer *buffer;
267   struct pipe_resource templ;
268   enum pipe_format pf;
269   unsigned bind = 0;
270   struct winsys_handle whandle;
271
272   switch (attachment) {
273      case __DRI_BUFFER_FRONT_LEFT:
274      case __DRI_BUFFER_FAKE_FRONT_LEFT:
275         bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
276         break;
277      case __DRI_BUFFER_BACK_LEFT:
278         bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
279         break;
280      case __DRI_BUFFER_DEPTH:
281      case __DRI_BUFFER_DEPTH_STENCIL:
282      case __DRI_BUFFER_STENCIL:
283            bind = PIPE_BIND_DEPTH_STENCIL; /* XXX sampler? */
284         break;
285   }
286
287   /* because we get the handle and stride */
288   bind |= PIPE_BIND_SHARED;
289
290   switch (format) {
291      case 32:
292         pf = PIPE_FORMAT_B8G8R8A8_UNORM;
293         break;
294      case 24:
295         pf = PIPE_FORMAT_B8G8R8X8_UNORM;
296         break;
297      case 16:
298         pf = PIPE_FORMAT_Z16_UNORM;
299         break;
300      default:
301         return NULL;
302   }
303
304   buffer = CALLOC_STRUCT(dri2_buffer);
305   if (!buffer)
306      return NULL;
307
308   memset(&templ, 0, sizeof(templ));
309   templ.bind = bind;
310   templ.format = pf;
311   templ.target = PIPE_TEXTURE_2D;
312   templ.last_level = 0;
313   templ.width0 = width;
314   templ.height0 = height;
315   templ.depth0 = 1;
316   templ.array_size = 1;
317
318   buffer->resource =
319      screen->base.screen->resource_create(screen->base.screen, &templ);
320   if (!buffer->resource) {
321      FREE(buffer);
322      return NULL;
323   }
324
325   memset(&whandle, 0, sizeof(whandle));
326   if (screen->can_share_buffer)
327      whandle.type = DRM_API_HANDLE_TYPE_SHARED;
328   else
329      whandle.type = DRM_API_HANDLE_TYPE_KMS;
330
331   screen->base.screen->resource_get_handle(screen->base.screen,
332         buffer->resource, &whandle);
333
334   buffer->base.attachment = attachment;
335   buffer->base.name = whandle.handle;
336   buffer->base.cpp = util_format_get_blocksize(pf);
337   buffer->base.pitch = whandle.stride;
338
339   return &buffer->base;
340}
341
342static void
343dri2_release_buffer(__DRIscreen *sPriv, __DRIbuffer *bPriv)
344{
345   struct dri2_buffer *buffer = dri2_buffer(bPriv);
346
347   pipe_resource_reference(&buffer->resource, NULL);
348   FREE(buffer);
349}
350
351/*
352 * Backend functions for st_framebuffer interface.
353 */
354
355static void
356dri2_allocate_textures(struct dri_context *ctx,
357                       struct dri_drawable *drawable,
358                       const enum st_attachment_type *statts,
359                       unsigned statts_count)
360{
361   __DRIscreen *sPriv = drawable->sPriv;
362   __DRIdrawable *dri_drawable = drawable->dPriv;
363   struct dri_screen *screen = dri_screen(sPriv);
364   struct pipe_resource templ;
365   boolean alloc_depthstencil = FALSE;
366   unsigned i, j, bind;
367   const __DRIimageLoaderExtension *image = sPriv->image.loader;
368   /* Image specific variables */
369   struct __DRIimageList images;
370   /* Dri2 specific variables */
371   __DRIbuffer *buffers;
372   struct winsys_handle whandle;
373   unsigned num_buffers = statts_count;
374
375   /* First get the buffers from the loader */
376   if (image) {
377      if (!dri_image_drawable_get_buffers(drawable, &images,
378                                          statts, statts_count))
379         return;
380   }
381   else {
382      buffers = dri2_drawable_get_buffers(drawable, statts, &num_buffers);
383      if (!buffers || (drawable->old_num == num_buffers &&
384                       drawable->old_w == dri_drawable->w &&
385                       drawable->old_h == dri_drawable->h &&
386                       memcmp(drawable->old, buffers,
387                              sizeof(__DRIbuffer) * num_buffers) == 0))
388         return;
389   }
390
391   /* Second clean useless resources*/
392
393   /* See if we need a depth-stencil buffer. */
394   for (i = 0; i < statts_count; i++) {
395      if (statts[i] == ST_ATTACHMENT_DEPTH_STENCIL) {
396         alloc_depthstencil = TRUE;
397         break;
398      }
399   }
400
401   /* Delete the resources we won't need. */
402   for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
403      /* Don't delete the depth-stencil buffer, we can reuse it. */
404      if (i == ST_ATTACHMENT_DEPTH_STENCIL && alloc_depthstencil)
405         continue;
406
407      /* Flush the texture before unreferencing, so that other clients can
408       * see what the driver has rendered.
409       */
410      if (i != ST_ATTACHMENT_DEPTH_STENCIL && drawable->textures[i]) {
411         struct pipe_context *pipe = ctx->st->pipe;
412         pipe->flush_resource(pipe, drawable->textures[i]);
413      }
414
415      pipe_resource_reference(&drawable->textures[i], NULL);
416   }
417
418   if (drawable->stvis.samples > 1) {
419      for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
420         boolean del = TRUE;
421
422         /* Don't delete MSAA resources for the attachments which are enabled,
423          * we can reuse them. */
424         for (j = 0; j < statts_count; j++) {
425            if (i == statts[j]) {
426               del = FALSE;
427               break;
428            }
429         }
430
431         if (del) {
432            pipe_resource_reference(&drawable->msaa_textures[i], NULL);
433         }
434      }
435   }
436
437   /* Third use the buffers retrieved to fill the drawable info */
438
439   memset(&templ, 0, sizeof(templ));
440   templ.target = screen->target;
441   templ.last_level = 0;
442   templ.depth0 = 1;
443   templ.array_size = 1;
444
445   if (image) {
446      if (images.image_mask & __DRI_IMAGE_BUFFER_FRONT) {
447         struct pipe_resource **buf =
448            &drawable->textures[ST_ATTACHMENT_FRONT_LEFT];
449         struct pipe_resource *texture = images.front->texture;
450
451         dri_drawable->w = texture->width0;
452         dri_drawable->h = texture->height0;
453
454         pipe_resource_reference(buf, texture);
455      }
456
457      if (images.image_mask & __DRI_IMAGE_BUFFER_BACK) {
458         struct pipe_resource **buf =
459            &drawable->textures[ST_ATTACHMENT_BACK_LEFT];
460         struct pipe_resource *texture = images.back->texture;
461
462         dri_drawable->w = texture->width0;
463         dri_drawable->h = texture->height0;
464
465         pipe_resource_reference(buf, texture);
466      }
467
468      /* Note: if there is both a back and a front buffer,
469       * then they have the same size.
470       */
471      templ.width0 = dri_drawable->w;
472      templ.height0 = dri_drawable->h;
473   }
474   else {
475      memset(&whandle, 0, sizeof(whandle));
476
477      /* Process DRI-provided buffers and get pipe_resources. */
478      for (i = 0; i < num_buffers; i++) {
479         __DRIbuffer *buf = &buffers[i];
480         enum st_attachment_type statt;
481         enum pipe_format format;
482
483         switch (buf->attachment) {
484         case __DRI_BUFFER_FRONT_LEFT:
485            if (!screen->auto_fake_front) {
486               continue; /* invalid attachment */
487            }
488            /* fallthrough */
489         case __DRI_BUFFER_FAKE_FRONT_LEFT:
490            statt = ST_ATTACHMENT_FRONT_LEFT;
491            break;
492         case __DRI_BUFFER_BACK_LEFT:
493            statt = ST_ATTACHMENT_BACK_LEFT;
494            break;
495         default:
496            continue; /* invalid attachment */
497         }
498
499         dri_drawable_get_format(drawable, statt, &format, &bind);
500         if (format == PIPE_FORMAT_NONE)
501            continue;
502
503         /* dri2_drawable_get_buffers has already filled dri_drawable->w
504          * and dri_drawable->h */
505         templ.width0 = dri_drawable->w;
506         templ.height0 = dri_drawable->h;
507         templ.format = format;
508         templ.bind = bind;
509         whandle.handle = buf->name;
510         whandle.stride = buf->pitch;
511         if (screen->can_share_buffer)
512            whandle.type = DRM_API_HANDLE_TYPE_SHARED;
513         else
514            whandle.type = DRM_API_HANDLE_TYPE_KMS;
515         drawable->textures[statt] =
516            screen->base.screen->resource_from_handle(screen->base.screen,
517                  &templ, &whandle);
518         assert(drawable->textures[statt]);
519      }
520   }
521
522   /* Allocate private MSAA colorbuffers. */
523   if (drawable->stvis.samples > 1) {
524      for (i = 0; i < statts_count; i++) {
525         enum st_attachment_type statt = statts[i];
526
527         if (statt == ST_ATTACHMENT_DEPTH_STENCIL)
528            continue;
529
530         if (drawable->textures[statt]) {
531            templ.format = drawable->textures[statt]->format;
532            templ.bind = drawable->textures[statt]->bind;
533            templ.nr_samples = drawable->stvis.samples;
534
535            /* Try to reuse the resource.
536             * (the other resource parameters should be constant)
537             */
538            if (!drawable->msaa_textures[statt] ||
539                drawable->msaa_textures[statt]->width0 != templ.width0 ||
540                drawable->msaa_textures[statt]->height0 != templ.height0) {
541               /* Allocate a new one. */
542               pipe_resource_reference(&drawable->msaa_textures[statt], NULL);
543
544               drawable->msaa_textures[statt] =
545                  screen->base.screen->resource_create(screen->base.screen,
546                                                       &templ);
547               assert(drawable->msaa_textures[statt]);
548
549               /* If there are any MSAA resources, we should initialize them
550                * such that they contain the same data as the single-sample
551                * resources we just got from the X server.
552                *
553                * The reason for this is that the state tracker (and
554                * therefore the app) can access the MSAA resources only.
555                * The single-sample resources are not exposed
556                * to the state tracker.
557                *
558                */
559               dri_pipe_blit(ctx->st->pipe,
560                             drawable->msaa_textures[statt],
561                             drawable->textures[statt]);
562            }
563         }
564         else {
565            pipe_resource_reference(&drawable->msaa_textures[statt], NULL);
566         }
567      }
568   }
569
570   /* Allocate a private depth-stencil buffer. */
571   if (alloc_depthstencil) {
572      enum st_attachment_type statt = ST_ATTACHMENT_DEPTH_STENCIL;
573      struct pipe_resource **zsbuf;
574      enum pipe_format format;
575      unsigned bind;
576
577      dri_drawable_get_format(drawable, statt, &format, &bind);
578
579      if (format) {
580         templ.format = format;
581         templ.bind = bind;
582
583         if (drawable->stvis.samples > 1) {
584            templ.nr_samples = drawable->stvis.samples;
585            zsbuf = &drawable->msaa_textures[statt];
586         }
587         else {
588            templ.nr_samples = 0;
589            zsbuf = &drawable->textures[statt];
590         }
591
592         /* Try to reuse the resource.
593          * (the other resource parameters should be constant)
594          */
595         if (!*zsbuf ||
596             (*zsbuf)->width0 != templ.width0 ||
597             (*zsbuf)->height0 != templ.height0) {
598            /* Allocate a new one. */
599            pipe_resource_reference(zsbuf, NULL);
600            *zsbuf = screen->base.screen->resource_create(screen->base.screen,
601                                                          &templ);
602            assert(*zsbuf);
603         }
604      }
605      else {
606         pipe_resource_reference(&drawable->msaa_textures[statt], NULL);
607         pipe_resource_reference(&drawable->textures[statt], NULL);
608      }
609   }
610
611   /* For DRI2, we may get the same buffers again from the server.
612    * To prevent useless imports of gem names, drawable->old* is used
613    * to bypass the import if we get the same buffers. This doesn't apply
614    * to DRI3/Wayland, users of image.loader, since the buffer is managed
615    * by the client (no import), and the back buffer is going to change
616    * at every redraw.
617    */
618   if (!image) {
619      drawable->old_num = num_buffers;
620      drawable->old_w = dri_drawable->w;
621      drawable->old_h = dri_drawable->h;
622      memcpy(drawable->old, buffers, sizeof(__DRIbuffer) * num_buffers);
623   }
624}
625
626static void
627dri2_flush_frontbuffer(struct dri_context *ctx,
628                       struct dri_drawable *drawable,
629                       enum st_attachment_type statt)
630{
631   __DRIdrawable *dri_drawable = drawable->dPriv;
632   const __DRIimageLoaderExtension *image = drawable->sPriv->image.loader;
633   const __DRIdri2LoaderExtension *loader = drawable->sPriv->dri2.loader;
634   struct pipe_context *pipe = ctx->st->pipe;
635
636   if (statt != ST_ATTACHMENT_FRONT_LEFT)
637      return;
638
639   if (drawable->stvis.samples > 1) {
640      /* Resolve the front buffer. */
641      dri_pipe_blit(ctx->st->pipe,
642                    drawable->textures[ST_ATTACHMENT_FRONT_LEFT],
643                    drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT]);
644   }
645
646   if (drawable->textures[ST_ATTACHMENT_FRONT_LEFT]) {
647      pipe->flush_resource(pipe, drawable->textures[ST_ATTACHMENT_FRONT_LEFT]);
648   }
649
650   pipe->flush(pipe, NULL, 0);
651
652   if (image) {
653      image->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate);
654   }
655   else if (loader->flushFrontBuffer) {
656      loader->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate);
657   }
658}
659
660static void
661dri2_update_tex_buffer(struct dri_drawable *drawable,
662                       struct dri_context *ctx,
663                       struct pipe_resource *res)
664{
665   /* no-op */
666}
667
668static __DRIimage *
669dri2_lookup_egl_image(struct dri_screen *screen, void *handle)
670{
671   const __DRIimageLookupExtension *loader = screen->sPriv->dri2.image;
672   __DRIimage *img;
673
674   if (!loader->lookupEGLImage)
675      return NULL;
676
677   img = loader->lookupEGLImage(screen->sPriv,
678				handle, screen->sPriv->loaderPrivate);
679
680   return img;
681}
682
683static __DRIimage *
684dri2_create_image_from_winsys(__DRIscreen *_screen,
685                              int width, int height, int format,
686                              struct winsys_handle *whandle, int pitch,
687                              void *loaderPrivate)
688{
689   struct dri_screen *screen = dri_screen(_screen);
690   __DRIimage *img;
691   struct pipe_resource templ;
692   unsigned tex_usage;
693   enum pipe_format pf;
694
695   tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
696
697   switch (format) {
698   case __DRI_IMAGE_FORMAT_RGB565:
699      pf = PIPE_FORMAT_B5G6R5_UNORM;
700      break;
701   case __DRI_IMAGE_FORMAT_XRGB8888:
702      pf = PIPE_FORMAT_B8G8R8X8_UNORM;
703      break;
704   case __DRI_IMAGE_FORMAT_ARGB8888:
705      pf = PIPE_FORMAT_B8G8R8A8_UNORM;
706      break;
707   case __DRI_IMAGE_FORMAT_ABGR8888:
708      pf = PIPE_FORMAT_R8G8B8A8_UNORM;
709      break;
710   default:
711      pf = PIPE_FORMAT_NONE;
712      break;
713   }
714   if (pf == PIPE_FORMAT_NONE)
715      return NULL;
716
717   img = CALLOC_STRUCT(__DRIimageRec);
718   if (!img)
719      return NULL;
720
721   memset(&templ, 0, sizeof(templ));
722   templ.bind = tex_usage;
723   templ.format = pf;
724   templ.target = screen->target;
725   templ.last_level = 0;
726   templ.width0 = width;
727   templ.height0 = height;
728   templ.depth0 = 1;
729   templ.array_size = 1;
730
731   whandle->stride = pitch * util_format_get_blocksize(pf);
732
733   img->texture = screen->base.screen->resource_from_handle(screen->base.screen,
734         &templ, whandle);
735   if (!img->texture) {
736      FREE(img);
737      return NULL;
738   }
739
740   img->level = 0;
741   img->layer = 0;
742   img->dri_format = format;
743   img->loader_private = loaderPrivate;
744
745   return img;
746}
747
748static __DRIimage *
749dri2_create_image_from_name(__DRIscreen *_screen,
750                            int width, int height, int format,
751                            int name, int pitch, void *loaderPrivate)
752{
753   struct winsys_handle whandle;
754
755   memset(&whandle, 0, sizeof(whandle));
756   whandle.type = DRM_API_HANDLE_TYPE_SHARED;
757   whandle.handle = name;
758
759   return dri2_create_image_from_winsys(_screen, width, height, format,
760                                        &whandle, pitch, loaderPrivate);
761}
762
763static __DRIimage *
764dri2_create_image_from_fd(__DRIscreen *_screen,
765                          int width, int height, int format,
766                          int fd, int pitch, void *loaderPrivate)
767{
768   struct winsys_handle whandle;
769
770   if (fd < 0)
771      return NULL;
772
773   memset(&whandle, 0, sizeof(whandle));
774   whandle.type = DRM_API_HANDLE_TYPE_FD;
775   whandle.handle = (unsigned)fd;
776
777   return dri2_create_image_from_winsys(_screen, width, height, format,
778                                        &whandle, pitch, loaderPrivate);
779}
780
781static __DRIimage *
782dri2_create_image_from_renderbuffer(__DRIcontext *context,
783				    int renderbuffer, void *loaderPrivate)
784{
785   struct dri_context *ctx = dri_context(context);
786
787   if (!ctx->st->get_resource_for_egl_image)
788      return NULL;
789
790   /* TODO */
791   return NULL;
792}
793
794static __DRIimage *
795dri2_create_image(__DRIscreen *_screen,
796                   int width, int height, int format,
797                   unsigned int use, void *loaderPrivate)
798{
799   struct dri_screen *screen = dri_screen(_screen);
800   __DRIimage *img;
801   struct pipe_resource templ;
802   unsigned tex_usage;
803   enum pipe_format pf;
804
805   tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
806   if (use & __DRI_IMAGE_USE_SCANOUT)
807      tex_usage |= PIPE_BIND_SCANOUT;
808   if (use & __DRI_IMAGE_USE_SHARE)
809      tex_usage |= PIPE_BIND_SHARED;
810   if (use & __DRI_IMAGE_USE_LINEAR)
811      tex_usage |= PIPE_BIND_LINEAR;
812   if (use & __DRI_IMAGE_USE_CURSOR) {
813      if (width != 64 || height != 64)
814         return NULL;
815      tex_usage |= PIPE_BIND_CURSOR;
816   }
817
818   switch (format) {
819   case __DRI_IMAGE_FORMAT_RGB565:
820      pf = PIPE_FORMAT_B5G6R5_UNORM;
821      break;
822   case __DRI_IMAGE_FORMAT_XRGB8888:
823      pf = PIPE_FORMAT_B8G8R8X8_UNORM;
824      break;
825   case __DRI_IMAGE_FORMAT_ARGB8888:
826      pf = PIPE_FORMAT_B8G8R8A8_UNORM;
827      break;
828   case __DRI_IMAGE_FORMAT_ABGR8888:
829      pf = PIPE_FORMAT_R8G8B8A8_UNORM;
830      break;
831   default:
832      pf = PIPE_FORMAT_NONE;
833      break;
834   }
835   if (pf == PIPE_FORMAT_NONE)
836      return NULL;
837
838   img = CALLOC_STRUCT(__DRIimageRec);
839   if (!img)
840      return NULL;
841
842   memset(&templ, 0, sizeof(templ));
843   templ.bind = tex_usage;
844   templ.format = pf;
845   templ.target = PIPE_TEXTURE_2D;
846   templ.last_level = 0;
847   templ.width0 = width;
848   templ.height0 = height;
849   templ.depth0 = 1;
850   templ.array_size = 1;
851
852   img->texture = screen->base.screen->resource_create(screen->base.screen, &templ);
853   if (!img->texture) {
854      FREE(img);
855      return NULL;
856   }
857
858   img->level = 0;
859   img->layer = 0;
860   img->dri_format = format;
861   img->dri_components = 0;
862
863   img->loader_private = loaderPrivate;
864   return img;
865}
866
867static GLboolean
868dri2_query_image(__DRIimage *image, int attrib, int *value)
869{
870   struct winsys_handle whandle;
871   memset(&whandle, 0, sizeof(whandle));
872
873   switch (attrib) {
874   case __DRI_IMAGE_ATTRIB_STRIDE:
875      whandle.type = DRM_API_HANDLE_TYPE_KMS;
876      image->texture->screen->resource_get_handle(image->texture->screen,
877            image->texture, &whandle);
878      *value = whandle.stride;
879      return GL_TRUE;
880   case __DRI_IMAGE_ATTRIB_HANDLE:
881      whandle.type = DRM_API_HANDLE_TYPE_KMS;
882      image->texture->screen->resource_get_handle(image->texture->screen,
883         image->texture, &whandle);
884      *value = whandle.handle;
885      return GL_TRUE;
886   case __DRI_IMAGE_ATTRIB_NAME:
887      whandle.type = DRM_API_HANDLE_TYPE_SHARED;
888      image->texture->screen->resource_get_handle(image->texture->screen,
889         image->texture, &whandle);
890      *value = whandle.handle;
891      return GL_TRUE;
892   case __DRI_IMAGE_ATTRIB_FD:
893      whandle.type= DRM_API_HANDLE_TYPE_FD;
894      image->texture->screen->resource_get_handle(image->texture->screen,
895         image->texture, &whandle);
896      *value = whandle.handle;
897      return GL_TRUE;
898   case __DRI_IMAGE_ATTRIB_FORMAT:
899      *value = image->dri_format;
900      return GL_TRUE;
901   case __DRI_IMAGE_ATTRIB_WIDTH:
902      *value = image->texture->width0;
903      return GL_TRUE;
904   case __DRI_IMAGE_ATTRIB_HEIGHT:
905      *value = image->texture->height0;
906      return GL_TRUE;
907   case __DRI_IMAGE_ATTRIB_COMPONENTS:
908      if (image->dri_components == 0)
909         return GL_FALSE;
910      *value = image->dri_components;
911      return GL_TRUE;
912   default:
913      return GL_FALSE;
914   }
915}
916
917static __DRIimage *
918dri2_dup_image(__DRIimage *image, void *loaderPrivate)
919{
920   __DRIimage *img;
921
922   img = CALLOC_STRUCT(__DRIimageRec);
923   if (!img)
924      return NULL;
925
926   img->texture = NULL;
927   pipe_resource_reference(&img->texture, image->texture);
928   img->level = image->level;
929   img->layer = image->layer;
930   img->dri_format = image->dri_format;
931   /* This should be 0 for sub images, but dup is also used for base images. */
932   img->dri_components = image->dri_components;
933   img->loader_private = loaderPrivate;
934
935   return img;
936}
937
938static GLboolean
939dri2_validate_usage(__DRIimage *image, unsigned int use)
940{
941   /*
942    * Gallium drivers are bad at adding usages to the resources
943    * once opened again in another process, which is the main use
944    * case for this, so we have to lie.
945    */
946   if (image != NULL)
947      return GL_TRUE;
948   else
949      return GL_FALSE;
950}
951
952static __DRIimage *
953dri2_from_names(__DRIscreen *screen, int width, int height, int format,
954                int *names, int num_names, int *strides, int *offsets,
955                void *loaderPrivate)
956{
957   __DRIimage *img;
958   int stride, dri_components;
959
960   if (num_names != 1)
961      return NULL;
962   if (offsets[0] != 0)
963      return NULL;
964
965   format = convert_fourcc(format, &dri_components);
966   if (format == -1)
967      return NULL;
968
969   /* Strides are in bytes not pixels. */
970   stride = strides[0] /4;
971
972   img = dri2_create_image_from_name(screen, width, height, format,
973                                     names[0], stride, loaderPrivate);
974   if (img == NULL)
975      return NULL;
976
977   img->dri_components = dri_components;
978   return img;
979}
980
981static __DRIimage *
982dri2_from_planar(__DRIimage *image, int plane, void *loaderPrivate)
983{
984   __DRIimage *img;
985
986   if (plane != 0)
987      return NULL;
988
989   if (image->dri_components == 0)
990      return NULL;
991
992   img = dri2_dup_image(image, loaderPrivate);
993   if (img == NULL)
994      return NULL;
995
996   /* set this to 0 for sub images. */
997   img->dri_components = 0;
998   return img;
999}
1000
1001static __DRIimage *
1002dri2_create_from_texture(__DRIcontext *context, int target, unsigned texture,
1003                         int depth, int level, unsigned *error,
1004                         void *loaderPrivate)
1005{
1006   __DRIimage *img;
1007   struct gl_context *ctx = ((struct st_context *)dri_context(context)->st)->ctx;
1008   struct gl_texture_object *obj;
1009   struct pipe_resource *tex;
1010   GLuint face = 0;
1011
1012   obj = _mesa_lookup_texture(ctx, texture);
1013   if (!obj || obj->Target != target) {
1014      *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
1015      return NULL;
1016   }
1017
1018   tex = st_get_texobj_resource(obj);
1019   if (!tex) {
1020      *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
1021      return NULL;
1022   }
1023
1024   if (target == GL_TEXTURE_CUBE_MAP)
1025      face = depth;
1026
1027   _mesa_test_texobj_completeness(ctx, obj);
1028   if (!obj->_BaseComplete || (level > 0 && !obj->_MipmapComplete)) {
1029      *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
1030      return NULL;
1031   }
1032
1033   if (level < obj->BaseLevel || level > obj->_MaxLevel) {
1034      *error = __DRI_IMAGE_ERROR_BAD_MATCH;
1035      return NULL;
1036   }
1037
1038   if (target == GL_TEXTURE_3D && obj->Image[face][level]->Depth < depth) {
1039      *error = __DRI_IMAGE_ERROR_BAD_MATCH;
1040      return NULL;
1041   }
1042
1043   img = CALLOC_STRUCT(__DRIimageRec);
1044   if (!img) {
1045      *error = __DRI_IMAGE_ERROR_BAD_ALLOC;
1046      return NULL;
1047   }
1048
1049   img->level = level;
1050   img->layer = depth;
1051   img->dri_format = driGLFormatToImageFormat(obj->Image[face][level]->TexFormat);
1052
1053   img->loader_private = loaderPrivate;
1054
1055   if (img->dri_format == __DRI_IMAGE_FORMAT_NONE) {
1056      *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
1057      free(img);
1058      return NULL;
1059   }
1060
1061   pipe_resource_reference(&img->texture, tex);
1062
1063   *error = __DRI_IMAGE_ERROR_SUCCESS;
1064   return img;
1065}
1066
1067static __DRIimage *
1068dri2_from_fds(__DRIscreen *screen, int width, int height, int fourcc,
1069              int *fds, int num_fds, int *strides, int *offsets,
1070              void *loaderPrivate)
1071{
1072   __DRIimage *img;
1073   int format, stride, dri_components;
1074
1075   if (num_fds != 1)
1076      return NULL;
1077   if (offsets[0] != 0)
1078      return NULL;
1079
1080   format = convert_fourcc(fourcc, &dri_components);
1081   if (format == -1)
1082      return NULL;
1083
1084   /* Strides are in bytes not pixels. */
1085   stride = strides[0] /4;
1086
1087   img = dri2_create_image_from_fd(screen, width, height, format,
1088                                   fds[0], stride, loaderPrivate);
1089   if (img == NULL)
1090      return NULL;
1091
1092   img->dri_components = dri_components;
1093   return img;
1094}
1095
1096static __DRIimage *
1097dri2_from_dma_bufs(__DRIscreen *screen,
1098                   int width, int height, int fourcc,
1099                   int *fds, int num_fds,
1100                   int *strides, int *offsets,
1101                   enum __DRIYUVColorSpace yuv_color_space,
1102                   enum __DRISampleRange sample_range,
1103                   enum __DRIChromaSiting horizontal_siting,
1104                   enum __DRIChromaSiting vertical_siting,
1105                   unsigned *error,
1106                   void *loaderPrivate)
1107{
1108   __DRIimage *img;
1109   int format, stride, dri_components;
1110
1111   if (num_fds != 1 || offsets[0] != 0) {
1112      *error = __DRI_IMAGE_ERROR_BAD_MATCH;
1113      return NULL;
1114   }
1115
1116   format = convert_fourcc(fourcc, &dri_components);
1117   if (format == -1) {
1118      *error = __DRI_IMAGE_ERROR_BAD_MATCH;
1119      return NULL;
1120   }
1121
1122   /* Strides are in bytes not pixels. */
1123   stride = strides[0] /4;
1124
1125   img = dri2_create_image_from_fd(screen, width, height, format,
1126                                   fds[0], stride, loaderPrivate);
1127   if (img == NULL) {
1128      *error = __DRI_IMAGE_ERROR_BAD_ALLOC;
1129      return NULL;
1130   }
1131
1132   img->yuv_color_space = yuv_color_space;
1133   img->sample_range = sample_range;
1134   img->horizontal_siting = horizontal_siting;
1135   img->vertical_siting = vertical_siting;
1136   img->dri_components = dri_components;
1137
1138   *error = __DRI_IMAGE_ERROR_SUCCESS;
1139   return img;
1140}
1141
1142static void
1143dri2_blit_image(__DRIcontext *context, __DRIimage *dst, __DRIimage *src,
1144                int dstx0, int dsty0, int dstwidth, int dstheight,
1145                int srcx0, int srcy0, int srcwidth, int srcheight,
1146                int flush_flag)
1147{
1148   struct dri_context *ctx = dri_context(context);
1149   struct pipe_context *pipe = ctx->st->pipe;
1150   struct pipe_screen *screen;
1151   struct pipe_fence_handle *fence;
1152   struct pipe_blit_info blit;
1153
1154   if (!dst || !src)
1155      return;
1156
1157   memset(&blit, 0, sizeof(blit));
1158   blit.dst.resource = dst->texture;
1159   blit.dst.box.x = dstx0;
1160   blit.dst.box.y = dsty0;
1161   blit.dst.box.width = dstwidth;
1162   blit.dst.box.height = dstheight;
1163   blit.dst.box.depth = 1;
1164   blit.dst.format = dst->texture->format;
1165   blit.src.resource = src->texture;
1166   blit.src.box.x = srcx0;
1167   blit.src.box.y = srcy0;
1168   blit.src.box.width = srcwidth;
1169   blit.src.box.height = srcheight;
1170   blit.src.box.depth = 1;
1171   blit.src.format = src->texture->format;
1172   blit.mask = PIPE_MASK_RGBA;
1173   blit.filter = PIPE_TEX_FILTER_NEAREST;
1174
1175   pipe->blit(pipe, &blit);
1176
1177   if (flush_flag == __BLIT_FLAG_FLUSH) {
1178      pipe->flush_resource(pipe, dst->texture);
1179      ctx->st->flush(ctx->st, 0, NULL);
1180   } else if (flush_flag == __BLIT_FLAG_FINISH) {
1181      screen = dri_screen(ctx->sPriv)->base.screen;
1182      pipe->flush_resource(pipe, dst->texture);
1183      ctx->st->flush(ctx->st, 0, &fence);
1184      (void) screen->fence_finish(screen, fence, PIPE_TIMEOUT_INFINITE);
1185      screen->fence_reference(screen, &fence, NULL);
1186   }
1187}
1188
1189static void
1190dri2_destroy_image(__DRIimage *img)
1191{
1192   pipe_resource_reference(&img->texture, NULL);
1193   FREE(img);
1194}
1195
1196static int
1197dri2_get_capabilities(__DRIscreen *_screen)
1198{
1199   struct dri_screen *screen = dri_screen(_screen);
1200
1201   return (screen->can_share_buffer ? __DRI_IMAGE_CAP_GLOBAL_NAMES : 0);
1202}
1203
1204/* The extension is modified during runtime if DRI_PRIME is detected */
1205static __DRIimageExtension dri2ImageExtension = {
1206    .base = { __DRI_IMAGE, 10 },
1207
1208    .createImageFromName          = dri2_create_image_from_name,
1209    .createImageFromRenderbuffer  = dri2_create_image_from_renderbuffer,
1210    .destroyImage                 = dri2_destroy_image,
1211    .createImage                  = dri2_create_image,
1212    .queryImage                   = dri2_query_image,
1213    .dupImage                     = dri2_dup_image,
1214    .validateUsage                = dri2_validate_usage,
1215    .createImageFromNames         = dri2_from_names,
1216    .fromPlanar                   = dri2_from_planar,
1217    .createImageFromTexture       = dri2_create_from_texture,
1218    .createImageFromFds           = NULL,
1219    .createImageFromDmaBufs       = NULL,
1220    .blitImage                    = dri2_blit_image,
1221    .getCapabilities              = dri2_get_capabilities,
1222};
1223
1224/*
1225 * Backend function init_screen.
1226 */
1227
1228static const __DRIextension *dri_screen_extensions[] = {
1229   &driTexBufferExtension.base,
1230   &dri2FlushExtension.base,
1231   &dri2ImageExtension.base,
1232   &dri2RendererQueryExtension.base,
1233   &dri2ConfigQueryExtension.base,
1234   &dri2ThrottleExtension.base,
1235   NULL
1236};
1237
1238/**
1239 * This is the driver specific part of the createNewScreen entry point.
1240 *
1241 * Returns the struct gl_config supported by this driver.
1242 */
1243static const __DRIconfig **
1244dri2_init_screen(__DRIscreen * sPriv)
1245{
1246   const __DRIconfig **configs;
1247   struct dri_screen *screen;
1248   struct pipe_screen *pscreen = NULL;
1249   const struct drm_conf_ret *throttle_ret = NULL;
1250   const struct drm_conf_ret *dmabuf_ret = NULL;
1251
1252   screen = CALLOC_STRUCT(dri_screen);
1253   if (!screen)
1254      return NULL;
1255
1256   screen->sPriv = sPriv;
1257   screen->fd = sPriv->fd;
1258
1259   sPriv->driverPrivate = (void *)screen;
1260
1261#if GALLIUM_STATIC_TARGETS
1262   pscreen = dd_create_screen(screen->fd);
1263
1264   throttle_ret = dd_configuration(DRM_CONF_THROTTLE);
1265   dmabuf_ret = dd_configuration(DRM_CONF_SHARE_FD);
1266#else
1267   if (pipe_loader_drm_probe_fd(&screen->dev, screen->fd, true)) {
1268      pscreen = pipe_loader_create_screen(screen->dev, PIPE_SEARCH_DIR);
1269
1270      throttle_ret = pipe_loader_configuration(screen->dev, DRM_CONF_THROTTLE);
1271      dmabuf_ret = pipe_loader_configuration(screen->dev, DRM_CONF_SHARE_FD);
1272   }
1273#endif // GALLIUM_STATIC_TARGETS
1274
1275   if (throttle_ret && throttle_ret->val.val_int != -1) {
1276      screen->throttling_enabled = TRUE;
1277      screen->default_throttle_frames = throttle_ret->val.val_int;
1278   }
1279
1280   if (dmabuf_ret && dmabuf_ret->val.val_bool) {
1281      uint64_t cap;
1282
1283      if (drmGetCap(sPriv->fd, DRM_CAP_PRIME, &cap) == 0 &&
1284          (cap & DRM_PRIME_CAP_IMPORT)) {
1285         dri2ImageExtension.createImageFromFds = dri2_from_fds;
1286         dri2ImageExtension.createImageFromDmaBufs = dri2_from_dma_bufs;
1287      }
1288   }
1289
1290   sPriv->extensions = dri_screen_extensions;
1291
1292   /* dri_init_screen_helper checks pscreen for us */
1293
1294#if GALLIUM_STATIC_TARGETS
1295   configs = dri_init_screen_helper(screen, pscreen, dd_driver_name());
1296#else
1297   configs = dri_init_screen_helper(screen, pscreen, screen->dev->driver_name);
1298#endif // GALLIUM_STATIC_TARGETS
1299   if (!configs)
1300      goto fail;
1301
1302   screen->can_share_buffer = true;
1303   screen->auto_fake_front = dri_with_format(sPriv);
1304   screen->broken_invalidate = !sPriv->dri2.useInvalidate;
1305   screen->lookup_egl_image = dri2_lookup_egl_image;
1306
1307   return configs;
1308fail:
1309   dri_destroy_screen_helper(screen);
1310#if !GALLIUM_STATIC_TARGETS
1311   if (screen->dev)
1312      pipe_loader_release(&screen->dev, 1);
1313#endif // !GALLIUM_STATIC_TARGETS
1314   FREE(screen);
1315   return NULL;
1316}
1317
1318/**
1319 * This is the driver specific part of the createNewScreen entry point.
1320 *
1321 * Returns the struct gl_config supported by this driver.
1322 */
1323static const __DRIconfig **
1324dri_kms_init_screen(__DRIscreen * sPriv)
1325{
1326#if GALLIUM_STATIC_TARGETS
1327#if defined(GALLIUM_SOFTPIPE)
1328   const __DRIconfig **configs;
1329   struct dri_screen *screen;
1330   struct pipe_screen *pscreen = NULL;
1331   uint64_t cap;
1332
1333   screen = CALLOC_STRUCT(dri_screen);
1334   if (!screen)
1335      return NULL;
1336
1337   screen->sPriv = sPriv;
1338   screen->fd = sPriv->fd;
1339
1340   sPriv->driverPrivate = (void *)screen;
1341
1342   pscreen = kms_swrast_create_screen(screen->fd);
1343
1344   if (drmGetCap(sPriv->fd, DRM_CAP_PRIME, &cap) == 0 &&
1345          (cap & DRM_PRIME_CAP_IMPORT)) {
1346      dri2ImageExtension.createImageFromFds = dri2_from_fds;
1347      dri2ImageExtension.createImageFromDmaBufs = dri2_from_dma_bufs;
1348   }
1349
1350   sPriv->extensions = dri_screen_extensions;
1351
1352   /* dri_init_screen_helper checks pscreen for us */
1353   configs = dri_init_screen_helper(screen, pscreen, "swrast");
1354   if (!configs)
1355      goto fail;
1356
1357   screen->can_share_buffer = false;
1358   screen->auto_fake_front = dri_with_format(sPriv);
1359   screen->broken_invalidate = !sPriv->dri2.useInvalidate;
1360   screen->lookup_egl_image = dri2_lookup_egl_image;
1361
1362   return configs;
1363fail:
1364   dri_destroy_screen_helper(screen);
1365   FREE(screen);
1366#endif // GALLIUM_SOFTPIPE
1367#endif // GALLIUM_STATIC_TARGETS
1368   return NULL;
1369}
1370
1371static boolean
1372dri2_create_buffer(__DRIscreen * sPriv,
1373                   __DRIdrawable * dPriv,
1374                   const struct gl_config * visual, boolean isPixmap)
1375{
1376   struct dri_drawable *drawable = NULL;
1377
1378   if (!dri_create_buffer(sPriv, dPriv, visual, isPixmap))
1379      return FALSE;
1380
1381   drawable = dPriv->driverPrivate;
1382
1383   drawable->allocate_textures = dri2_allocate_textures;
1384   drawable->flush_frontbuffer = dri2_flush_frontbuffer;
1385   drawable->update_tex_buffer = dri2_update_tex_buffer;
1386
1387   return TRUE;
1388}
1389
1390/**
1391 * DRI driver virtual function table.
1392 *
1393 * DRI versions differ in their implementation of init_screen and swap_buffers.
1394 */
1395const struct __DriverAPIRec galliumdrm_driver_api = {
1396   .InitScreen = dri2_init_screen,
1397   .DestroyScreen = dri_destroy_screen,
1398   .CreateContext = dri_create_context,
1399   .DestroyContext = dri_destroy_context,
1400   .CreateBuffer = dri2_create_buffer,
1401   .DestroyBuffer = dri_destroy_buffer,
1402   .MakeCurrent = dri_make_current,
1403   .UnbindContext = dri_unbind_context,
1404
1405   .AllocateBuffer = dri2_allocate_buffer,
1406   .ReleaseBuffer  = dri2_release_buffer,
1407};
1408
1409/**
1410 * DRI driver virtual function table.
1411 *
1412 * KMS/DRM version of the DriverAPI above sporting a different InitScreen
1413 * hook. The latter is used to explicitly initialise the kms_swrast driver
1414 * rather than selecting the approapriate driver as suggested by the loader.
1415 */
1416const struct __DriverAPIRec dri_kms_driver_api = {
1417   .InitScreen = dri_kms_init_screen,
1418   .DestroyScreen = dri_destroy_screen,
1419   .CreateContext = dri_create_context,
1420   .DestroyContext = dri_destroy_context,
1421   .CreateBuffer = dri2_create_buffer,
1422   .DestroyBuffer = dri_destroy_buffer,
1423   .MakeCurrent = dri_make_current,
1424   .UnbindContext = dri_unbind_context,
1425
1426   .AllocateBuffer = dri2_allocate_buffer,
1427   .ReleaseBuffer  = dri2_release_buffer,
1428};
1429
1430/* This is the table of extensions that the loader will dlsym() for. */
1431const __DRIextension *galliumdrm_driver_extensions[] = {
1432    &driCoreExtension.base,
1433    &driImageDriverExtension.base,
1434    &driDRI2Extension.base,
1435    &gallium_config_options.base,
1436    NULL
1437};
1438
1439/* vim: set sw=3 ts=8 sts=3 expandtab: */
1440