Home | History | Annotate | Download | only in common
      1 /*
      2  * Mesa 3-D graphics library
      3  * Version:  7.9
      4  *
      5  * Copyright (C) 2010 LunarG Inc.
      6  *
      7  * Permission is hereby granted, free of charge, to any person obtaining a
      8  * copy of this software and associated documentation files (the "Software"),
      9  * to deal in the Software without restriction, including without limitation
     10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     11  * and/or sell copies of the Software, and to permit persons to whom the
     12  * Software is furnished to do so, subject to the following conditions:
     13  *
     14  * The above copyright notice and this permission notice shall be included
     15  * in all copies or substantial portions of the Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     22  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     23  * DEALINGS IN THE SOFTWARE.
     24  *
     25  * Authors:
     26  *    Chia-I Wu <olv (at) lunarg.com>
     27  */
     28 
     29 #include "util/u_memory.h"
     30 #include "util/u_string.h"
     31 #include "util/u_inlines.h"
     32 #include "util/u_pointer.h"
     33 #include "util/u_dl.h"
     34 #include "egldriver.h"
     35 #include "eglimage.h"
     36 #include "eglmutex.h"
     37 
     38 #include "egl_g3d.h"
     39 #include "egl_g3d_st.h"
     40 
     41 struct egl_g3d_st_manager {
     42    struct st_manager base;
     43    _EGLDisplay *display;
     44 };
     45 
     46 static INLINE struct egl_g3d_st_manager *
     47 egl_g3d_st_manager(struct st_manager *smapi)
     48 {
     49    return (struct egl_g3d_st_manager *) smapi;
     50 }
     51 
     52 static boolean
     53 egl_g3d_st_manager_get_egl_image(struct st_manager *smapi,
     54                                  void *egl_image,
     55                                  struct st_egl_image *out)
     56 {
     57    struct egl_g3d_st_manager *gsmapi = egl_g3d_st_manager(smapi);
     58    EGLImageKHR handle = (EGLImageKHR) egl_image;
     59    _EGLImage *img;
     60    struct egl_g3d_image *gimg;
     61 
     62    /* this is called from state trackers */
     63    _eglLockMutex(&gsmapi->display->Mutex);
     64 
     65    img = _eglLookupImage(handle, gsmapi->display);
     66    if (!img) {
     67       _eglUnlockMutex(&gsmapi->display->Mutex);
     68       return FALSE;
     69    }
     70 
     71    gimg = egl_g3d_image(img);
     72 
     73    out->texture = NULL;
     74    pipe_resource_reference(&out->texture, gimg->texture);
     75    out->level = gimg->level;
     76    out->layer = gimg->layer;
     77 
     78    _eglUnlockMutex(&gsmapi->display->Mutex);
     79 
     80    return TRUE;
     81 }
     82 
     83 static int
     84 egl_g3d_st_manager_get_param(struct st_manager *smapi,
     85                              enum st_manager_param param)
     86 {
     87    return 0;
     88 }
     89 
     90 struct st_manager *
     91 egl_g3d_create_st_manager(_EGLDisplay *dpy)
     92 {
     93    struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
     94    struct egl_g3d_st_manager *gsmapi;
     95 
     96    gsmapi = CALLOC_STRUCT(egl_g3d_st_manager);
     97    if (gsmapi) {
     98       gsmapi->display = dpy;
     99 
    100       gsmapi->base.screen = gdpy->native->screen;
    101       gsmapi->base.get_egl_image = egl_g3d_st_manager_get_egl_image;
    102       gsmapi->base.get_param = egl_g3d_st_manager_get_param;
    103    }
    104 
    105    return &gsmapi->base;;
    106 }
    107 
    108 void
    109 egl_g3d_destroy_st_manager(struct st_manager *smapi)
    110 {
    111    struct egl_g3d_st_manager *gsmapi = egl_g3d_st_manager(smapi);
    112    FREE(gsmapi);
    113 }
    114 
    115 static boolean
    116 egl_g3d_st_framebuffer_flush_front_pbuffer(struct st_framebuffer_iface *stfbi,
    117                                            enum st_attachment_type statt)
    118 {
    119    return TRUE;
    120 }
    121 
    122 static void
    123 pbuffer_reference_openvg_image(struct egl_g3d_surface *gsurf)
    124 {
    125    /* TODO */
    126 }
    127 
    128 static void
    129 pbuffer_allocate_pbuffer_texture(struct egl_g3d_surface *gsurf)
    130 {
    131    struct egl_g3d_display *gdpy =
    132       egl_g3d_display(gsurf->base.Resource.Display);
    133    struct pipe_screen *screen = gdpy->native->screen;
    134    struct pipe_resource templ, *ptex;
    135 
    136    memset(&templ, 0, sizeof(templ));
    137    templ.target = PIPE_TEXTURE_2D;
    138    templ.last_level = 0;
    139    templ.width0 = gsurf->base.Width;
    140    templ.height0 = gsurf->base.Height;
    141    templ.depth0 = 1;
    142    templ.array_size = 1;
    143    templ.format = gsurf->stvis.color_format;
    144    /* for rendering and binding to texture */
    145    templ.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
    146 
    147    ptex = screen->resource_create(screen, &templ);
    148    gsurf->render_texture = ptex;
    149 }
    150 
    151 static boolean
    152 egl_g3d_st_framebuffer_validate_pbuffer(struct st_framebuffer_iface *stfbi,
    153                                         const enum st_attachment_type *statts,
    154                                         unsigned count,
    155                                         struct pipe_resource **out)
    156 {
    157    _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private;
    158    struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
    159    unsigned i;
    160 
    161    for (i = 0; i < count; i++) {
    162       out[i] = NULL;
    163 
    164       if (gsurf->stvis.render_buffer != statts[i])
    165          continue;
    166 
    167       if (!gsurf->render_texture) {
    168          switch (gsurf->client_buffer_type) {
    169          case EGL_NONE:
    170             pbuffer_allocate_pbuffer_texture(gsurf);
    171             break;
    172          case EGL_OPENVG_IMAGE:
    173             pbuffer_reference_openvg_image(gsurf);
    174             break;
    175          default:
    176             break;
    177          }
    178 
    179          if (!gsurf->render_texture)
    180             return FALSE;
    181       }
    182 
    183       pipe_resource_reference(&out[i], gsurf->render_texture);
    184    }
    185 
    186    return TRUE;
    187 }
    188 
    189 static boolean
    190 egl_g3d_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi,
    191                                    enum st_attachment_type statt)
    192 {
    193    _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private;
    194    struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
    195    struct native_present_control ctrl;
    196 
    197    memset(&ctrl, 0, sizeof(ctrl));
    198    ctrl.natt = NATIVE_ATTACHMENT_FRONT_LEFT;
    199 
    200    return gsurf->native->present(gsurf->native, &ctrl);
    201 }
    202 
    203 static boolean
    204 egl_g3d_st_framebuffer_validate(struct st_framebuffer_iface *stfbi,
    205                                 const enum st_attachment_type *statts,
    206                                 unsigned count,
    207                                 struct pipe_resource **out)
    208 {
    209    _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private;
    210    struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
    211    struct pipe_resource *textures[NUM_NATIVE_ATTACHMENTS];
    212    uint attachment_mask = 0;
    213    unsigned i;
    214 
    215    for (i = 0; i < count; i++) {
    216       int natt;
    217 
    218       switch (statts[i]) {
    219       case ST_ATTACHMENT_FRONT_LEFT:
    220          natt = NATIVE_ATTACHMENT_FRONT_LEFT;
    221          break;
    222       case ST_ATTACHMENT_BACK_LEFT:
    223          natt = NATIVE_ATTACHMENT_BACK_LEFT;
    224          break;
    225       case ST_ATTACHMENT_FRONT_RIGHT:
    226          natt = NATIVE_ATTACHMENT_FRONT_RIGHT;
    227          break;
    228       case ST_ATTACHMENT_BACK_RIGHT:
    229          natt = NATIVE_ATTACHMENT_BACK_RIGHT;
    230          break;
    231       default:
    232          natt = -1;
    233          break;
    234       }
    235 
    236       if (natt >= 0)
    237          attachment_mask |= 1 << natt;
    238    }
    239 
    240    if (!gsurf->native->validate(gsurf->native, attachment_mask,
    241          &gsurf->sequence_number, textures, &gsurf->base.Width,
    242          &gsurf->base.Height))
    243       return FALSE;
    244 
    245    for (i = 0; i < count; i++) {
    246       struct pipe_resource *tex;
    247       int natt;
    248 
    249       switch (statts[i]) {
    250       case ST_ATTACHMENT_FRONT_LEFT:
    251          natt = NATIVE_ATTACHMENT_FRONT_LEFT;
    252          break;
    253       case ST_ATTACHMENT_BACK_LEFT:
    254          natt = NATIVE_ATTACHMENT_BACK_LEFT;
    255          break;
    256       case ST_ATTACHMENT_FRONT_RIGHT:
    257          natt = NATIVE_ATTACHMENT_FRONT_RIGHT;
    258          break;
    259       case ST_ATTACHMENT_BACK_RIGHT:
    260          natt = NATIVE_ATTACHMENT_BACK_RIGHT;
    261          break;
    262       default:
    263          natt = -1;
    264          break;
    265       }
    266 
    267       if (natt >= 0) {
    268          tex = textures[natt];
    269 
    270          if (statts[i] == stfbi->visual->render_buffer)
    271             pipe_resource_reference(&gsurf->render_texture, tex);
    272 
    273          if (attachment_mask & (1 << natt)) {
    274             /* transfer the ownership to the caller */
    275             out[i] = tex;
    276             attachment_mask &= ~(1 << natt);
    277          }
    278          else {
    279             /* the attachment is listed more than once */
    280             pipe_resource_reference(&out[i], tex);
    281          }
    282       }
    283    }
    284 
    285    return TRUE;
    286 }
    287 
    288 struct st_framebuffer_iface *
    289 egl_g3d_create_st_framebuffer(_EGLSurface *surf)
    290 {
    291    struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
    292    struct st_framebuffer_iface *stfbi;
    293 
    294    stfbi = CALLOC_STRUCT(st_framebuffer_iface);
    295    if (!stfbi)
    296       return NULL;
    297 
    298    stfbi->visual = &gsurf->stvis;
    299    p_atomic_set(&stfbi->stamp, 1);
    300 
    301    if (gsurf->base.Type != EGL_PBUFFER_BIT) {
    302       stfbi->flush_front = egl_g3d_st_framebuffer_flush_front;
    303       stfbi->validate = egl_g3d_st_framebuffer_validate;
    304    }
    305    else {
    306       stfbi->flush_front = egl_g3d_st_framebuffer_flush_front_pbuffer;
    307       stfbi->validate = egl_g3d_st_framebuffer_validate_pbuffer;
    308    }
    309    stfbi->st_manager_private = (void *) &gsurf->base;
    310 
    311    return stfbi;
    312 }
    313 
    314 void
    315 egl_g3d_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi)
    316 {
    317    FREE(stfbi);
    318 }
    319