VirtualBox

Ignore:
Timestamp:
Apr 19, 2010 3:27:01 PM (15 years ago)
Author:
vboxsync
Message:

crOpenGL: update to wine 1.1.43

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/WINNT/Graphics/Wine/wined3d/buffer.c

    r25949 r28475  
    44 * Copyright 2004 Christian Costa
    55 * Copyright 2005 Oliver Stieber
    6  * Copyright 2007 Stefan Dösinger for CodeWeavers
     6 * Copyright 2007-2010 Stefan Dösinger for CodeWeavers
    77 * Copyright 2009 Henri Verbeet for CodeWeavers
    88 *
     
    6666    }
    6767
    68     if(!offset && !size)
     68    if(offset > This->resource.size || offset + size > This->resource.size)
     69    {
     70        WARN("Invalid range dirtified, marking entire buffer dirty\n");
     71        offset = 0;
     72        size = This->resource.size;
     73    }
     74    else if(!offset && !size)
    6975    {
    7076        size = This->resource.size;
     
    99105    }
    100106    return FALSE;
     107}
     108
     109/* Context activation is done by the caller */
     110static void delete_gl_buffer(struct wined3d_buffer *This)
     111{
     112    if(!This->buffer_object) return;
     113
     114    ENTER_GL();
     115    GL_EXTCALL(glDeleteBuffersARB(1, &This->buffer_object));
     116    checkGLcall("glDeleteBuffersARB");
     117    LEAVE_GL();
     118    This->buffer_object = 0;
     119
     120    if(This->query)
     121    {
     122        wined3d_event_query_destroy(This->query);
     123        This->query = NULL;
     124    }
     125    This->flags &= ~WINED3D_BUFFER_APPLESYNC;
    101126}
    102127
     
    155180        TRACE("Gl usage = GL_STREAM_DRAW_ARB\n");
    156181        gl_usage = GL_STREAM_DRAW_ARB;
    157     }
    158     else
    159     {
    160         TRACE("Gl usage = GL_DYNAMIC_DRAW_ARB\n");
    161         gl_usage = GL_DYNAMIC_DRAW_ARB;
    162182
    163183        if(gl_info->supported[APPLE_FLUSH_BUFFER_RANGE])
     
    166186            checkGLcall("glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE)");
    167187            This->flags |= WINED3D_BUFFER_FLUSH;
    168         }
     188
     189            GL_EXTCALL(glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE));
     190            checkGLcall("glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE)");
     191            This->flags |= WINED3D_BUFFER_APPLESYNC;
     192        }
     193        /* No setup is needed here for GL_ARB_map_buffer_range */
     194    }
     195    else
     196    {
     197        TRACE("Gl usage = GL_DYNAMIC_DRAW_ARB\n");
     198        gl_usage = GL_DYNAMIC_DRAW_ARB;
    169199    }
    170200
     
    206236    /* Clean up all vbo init, but continue because we can work without a vbo :-) */
    207237    ERR("Failed to create a vertex buffer object. Continuing, but performance issues may occur\n");
    208     if (This->buffer_object)
    209     {
    210         ENTER_GL();
    211         GL_EXTCALL(glDeleteBuffersARB(1, &This->buffer_object));
    212         LEAVE_GL();
    213     }
    214     This->buffer_object = 0;
     238    delete_gl_buffer(This);
    215239    buffer_clear_dirty_areas(This);
    216240}
     
    261285    for (i = 0; i < attrib_size; ++i)
    262286    {
    263         if (This->conversion_map[data + i] != conversion_type)
    264         {
    265             TRACE("Byte %ld in vertex changed\n", i + data);
    266             TRACE("It was type %d, is %d now\n", This->conversion_map[data + i], conversion_type);
     287        DWORD_PTR idx = (data + i) % This->stride;
     288        if (This->conversion_map[idx] != conversion_type)
     289        {
     290            TRACE("Byte %ld in vertex changed\n", idx);
     291            TRACE("It was type %d, is %d now\n", This->conversion_map[idx], conversion_type);
    267292            ret = TRUE;
    268             This->conversion_map[data + i] = conversion_type;
     293            This->conversion_map[idx] = conversion_type;
    269294        }
    270295    }
     
    493518         * the attributes that our current fixed function pipeline implementation cares for.
    494519         */
    495         BOOL support_d3dcolor = gl_info->supported[EXT_VERTEX_ARRAY_BGRA];
     520        BOOL support_d3dcolor = gl_info->supported[ARB_VERTEX_ARRAY_BGRA];
    496521        ret = buffer_check_attribute(This, si, WINED3D_FFP_POSITION,
    497522                TRUE, TRUE,  FALSE, &stride_this_run, &float16_used) || ret;
     
    598623
    599624/* Context activation is done by the caller. */
    600 const BYTE *buffer_get_memory(IWineD3DBuffer *iface, UINT offset, GLuint *buffer_object)
     625const BYTE *buffer_get_memory(IWineD3DBuffer *iface, GLuint *buffer_object)
    601626{
    602627    struct wined3d_buffer *This = (struct wined3d_buffer *)iface;
     
    612637            {
    613638                *buffer_object = This->buffer_object;
    614                 return (const BYTE *)offset;
    615             }
    616         }
    617         return This->resource.allocatedMemory + offset;
     639                return NULL;
     640            }
     641        }
     642        return This->resource.allocatedMemory;
    618643    }
    619644    else
    620645    {
    621         return (const BYTE *)offset;
     646        return NULL;
    622647    }
    623648}
     
    694719        }
    695720
    696         ENTER_GL();
    697         GL_EXTCALL(glDeleteBuffersARB(1, &This->buffer_object));
    698         checkGLcall("glDeleteBuffersARB");
    699         LEAVE_GL();
    700         This->buffer_object = 0;
     721        delete_gl_buffer(This);
    701722        This->flags |= WINED3D_BUFFER_CREATEBO; /* Recreate the buffer object next load */
    702723        buffer_clear_dirty_areas(This);
     
    769790}
    770791
     792/* The caller provides a context and binds the buffer */
     793static void buffer_sync_apple(struct wined3d_buffer *This, DWORD flags, const struct wined3d_gl_info *gl_info)
     794{
     795    enum wined3d_event_query_result ret;
     796
     797    /* No fencing needs to be done if the app promises not to overwrite
     798     * existing data */
     799    if(flags & WINED3DLOCK_NOOVERWRITE) return;
     800    if(flags & WINED3DLOCK_DISCARD)
     801    {
     802        ENTER_GL();
     803        GL_EXTCALL(glBufferDataARB(This->buffer_type_hint, This->resource.size, NULL, This->buffer_object_usage));
     804        checkGLcall("glBufferDataARB\n");
     805        LEAVE_GL();
     806        return;
     807    }
     808
     809    if(!This->query)
     810    {
     811        TRACE("Creating event query for buffer %p\n", This);
     812
     813        if (!wined3d_event_query_supported(gl_info))
     814        {
     815            FIXME("Event queries not supported, dropping async buffer locks.\n");
     816            goto drop_query;
     817        }
     818
     819        This->query = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This->query));
     820        if (!This->query)
     821        {
     822            ERR("Failed to allocate event query memory, dropping async buffer locks.\n");
     823            goto drop_query;
     824        }
     825
     826        /* Since we don't know about old draws a glFinish is needed once */
     827        wglFinish();
     828        return;
     829    }
     830    TRACE("Synchronizing buffer %p\n", This);
     831    ret = wined3d_event_query_finish(This->query, This->resource.device);
     832    switch(ret)
     833    {
     834        case WINED3D_EVENT_QUERY_NOT_STARTED:
     835        case WINED3D_EVENT_QUERY_OK:
     836            /* All done */
     837            return;
     838
     839        case WINED3D_EVENT_QUERY_WRONG_THREAD:
     840            WARN("Cannot synchronize buffer lock due to a thread conflict\n");
     841            goto drop_query;
     842
     843        default:
     844            ERR("wined3d_event_query_finish returned %u, dropping async buffer locks\n", ret);
     845            goto drop_query;
     846    }
     847
     848drop_query:
     849    if(This->query)
     850    {
     851        wined3d_event_query_destroy(This->query);
     852        This->query = NULL;
     853    }
     854
     855    wglFinish();
     856    ENTER_GL();
     857    GL_EXTCALL(glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_TRUE));
     858    checkGLcall("glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_TRUE)");
     859    LEAVE_GL();
     860    This->flags &= ~WINED3D_BUFFER_APPLESYNC;
     861}
     862
     863/* The caller provides a GL context */
     864static void buffer_direct_upload(struct wined3d_buffer *This, const struct wined3d_gl_info *gl_info, DWORD flags)
     865{
     866        BYTE *map;
     867        UINT start = 0, len = 0;
     868
     869        ENTER_GL();
     870        GL_EXTCALL(glBindBufferARB(This->buffer_type_hint, This->buffer_object));
     871        checkGLcall("glBindBufferARB");
     872        if (gl_info->supported[ARB_MAP_BUFFER_RANGE])
     873        {
     874            GLbitfield mapflags;
     875            mapflags = GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT;
     876            if (flags & WINED3D_BUFFER_DISCARD)
     877            {
     878                mapflags |= GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_BUFFER_BIT;
     879            }
     880            else if (flags & WINED3D_BUFFER_NOSYNC)
     881            {
     882                mapflags |= GL_MAP_UNSYNCHRONIZED_BIT;
     883            }
     884            map = GL_EXTCALL(glMapBufferRange(This->buffer_type_hint, 0,
     885                                              This->resource.size, mapflags));
     886            checkGLcall("glMapBufferRange");
     887        }
     888        else
     889        {
     890            if (This->flags & WINED3D_BUFFER_APPLESYNC)
     891            {
     892                DWORD syncflags = 0;
     893                if (flags & WINED3D_BUFFER_DISCARD) syncflags |= WINED3DLOCK_DISCARD;
     894                if (flags & WINED3D_BUFFER_NOSYNC) syncflags |= WINED3DLOCK_NOOVERWRITE;
     895                LEAVE_GL();
     896                buffer_sync_apple(This, syncflags, gl_info);
     897                ENTER_GL();
     898            }
     899            map = GL_EXTCALL(glMapBufferARB(This->buffer_type_hint, GL_WRITE_ONLY_ARB));
     900            checkGLcall("glMapBufferARB");
     901        }
     902        if (!map)
     903        {
     904            LEAVE_GL();
     905            ERR("Failed to map opengl buffer\n");
     906            return;
     907        }
     908
     909        while(This->modified_areas)
     910        {
     911            This->modified_areas--;
     912            start = This->maps[This->modified_areas].offset;
     913            len = This->maps[This->modified_areas].size;
     914
     915            memcpy(map + start, This->resource.allocatedMemory + start, len);
     916
     917            if (gl_info->supported[ARB_MAP_BUFFER_RANGE])
     918            {
     919                GL_EXTCALL(glFlushMappedBufferRange(This->buffer_type_hint, start, len));
     920                checkGLcall("glFlushMappedBufferRange");
     921            }
     922            else if (This->flags & WINED3D_BUFFER_FLUSH)
     923            {
     924                GL_EXTCALL(glFlushMappedBufferRangeAPPLE(This->buffer_type_hint, start, len));
     925                checkGLcall("glFlushMappedBufferRangeAPPLE");
     926            }
     927        }
     928        GL_EXTCALL(glUnmapBufferARB(This->buffer_type_hint));
     929        checkGLcall("glUnmapBufferARB");
     930        LEAVE_GL();
     931}
     932
    771933static void STDMETHODCALLTYPE buffer_PreLoad(IWineD3DBuffer *iface)
    772934{
     
    778940    unsigned int i, j;
    779941    BYTE *data;
     942    DWORD flags = This->flags & (WINED3D_BUFFER_NOSYNC | WINED3D_BUFFER_DISCARD);
    780943
    781944    TRACE("iface %p\n", iface);
     945    This->flags &= ~(WINED3D_BUFFER_NOSYNC | WINED3D_BUFFER_DISCARD);
    782946
    783947    context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD);
     
    8401004        }
    8411005        buffer_check_buffer_object_size(This);
     1006
     1007        /* The declaration changed, reload the whole buffer */
     1008        WARN("Reloading buffer because of decl change\n");
     1009        buffer_clear_dirty_areas(This);
     1010        if(!buffer_add_dirty_area(This, 0, 0))
     1011        {
     1012            ERR("buffer_add_dirty_area failed, this is not expected\n");
     1013            return;
     1014        }
     1015        /* Avoid unfenced updates, we might overwrite more areas of the buffer than the application
     1016         * cleared for unsynchronized updates
     1017         */
     1018        flags = 0;
    8421019    }
    8431020    else
     
    8671044    }
    8681045
    869     if (decl_changed)
    870     {
    871         /* The declaration changed, reload the whole buffer */
    872         WARN("Reloading buffer because of decl change\n");
    873         buffer_clear_dirty_areas(This);
    874         if(!buffer_add_dirty_area(This, 0, 0))
    875         {
    876             ERR("buffer_add_dirty_area failed, this is not expected\n");
    877             return;
    878         }
    879     }
    880 
    8811046    if(This->buffer_type_hint == GL_ELEMENT_ARRAY_BUFFER_ARB)
    8821047    {
     
    8991064        }
    9001065
    901         ENTER_GL();
    902         GL_EXTCALL(glBindBufferARB(This->buffer_type_hint, This->buffer_object));
    903         checkGLcall("glBindBufferARB");
    904         while(This->modified_areas)
    905         {
    906             This->modified_areas--;
    907             start = This->maps[This->modified_areas].offset;
    908             len = This->maps[This->modified_areas].size;
    909             GL_EXTCALL(glBufferSubDataARB(This->buffer_type_hint, start, len, This->resource.allocatedMemory + start));
    910             checkGLcall("glBufferSubDataARB");
    911         }
    912         LEAVE_GL();
     1066        buffer_direct_upload(This, context->gl_info, flags);
    9131067
    9141068        context_release(context);
     
    10361190/* IWineD3DBuffer methods */
    10371191
     1192static DWORD buffer_sanitize_flags(struct wined3d_buffer *buffer, DWORD flags)
     1193{
     1194    /* Not all flags make sense together, but Windows never returns an error. Catch the
     1195     * cases that could cause issues */
     1196    if(flags & WINED3DLOCK_READONLY)
     1197    {
     1198        if(flags & WINED3DLOCK_DISCARD)
     1199        {
     1200            WARN("WINED3DLOCK_READONLY combined with WINED3DLOCK_DISCARD, ignoring flags\n");
     1201            return 0;
     1202        }
     1203        if(flags & WINED3DLOCK_NOOVERWRITE)
     1204        {
     1205            WARN("WINED3DLOCK_READONLY combined with WINED3DLOCK_NOOVERWRITE, ignoring flags\n");
     1206            return 0;
     1207        }
     1208    }
     1209    else if((flags & (WINED3DLOCK_DISCARD | WINED3DLOCK_NOOVERWRITE)) == (WINED3DLOCK_DISCARD | WINED3DLOCK_NOOVERWRITE))
     1210    {
     1211        WARN("WINED3DLOCK_DISCARD and WINED3DLOCK_NOOVERWRITE used together, ignoring\n");
     1212        return 0;
     1213    }
     1214    else if (flags & (WINED3DLOCK_DISCARD | WINED3DLOCK_NOOVERWRITE) && !(buffer->resource.usage & WINED3DUSAGE_DYNAMIC))
     1215    {
     1216        WARN("DISCARD or NOOVERWRITE lock on non-dynamic buffer, ignoring\n");
     1217        return 0;
     1218    }
     1219
     1220    return flags;
     1221}
     1222
     1223static GLbitfield buffer_gl_map_flags(DWORD d3d_flags)
     1224{
     1225    GLbitfield ret = 0;
     1226
     1227    if (!(d3d_flags & WINED3DLOCK_READONLY)) ret = GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT;
     1228
     1229    if (d3d_flags & (WINED3DLOCK_DISCARD | WINED3DLOCK_NOOVERWRITE))
     1230    {
     1231        if(d3d_flags & WINED3DLOCK_DISCARD) ret |= GL_MAP_INVALIDATE_BUFFER_BIT;
     1232        ret |= GL_MAP_UNSYNCHRONIZED_BIT;
     1233    }
     1234    else
     1235    {
     1236        ret |= GL_MAP_READ_BIT;
     1237    }
     1238
     1239    return ret;
     1240}
     1241
    10381242static HRESULT STDMETHODCALLTYPE buffer_Map(IWineD3DBuffer *iface, UINT offset, UINT size, BYTE **data, DWORD flags)
    10391243{
    10401244    struct wined3d_buffer *This = (struct wined3d_buffer *)iface;
    10411245    LONG count;
     1246    BOOL dirty = buffer_is_dirty(This);
    10421247
    10431248    TRACE("iface %p, offset %u, size %u, data %p, flags %#x\n", iface, offset, size, data, flags);
    10441249
    1045     if (!buffer_add_dirty_area(This, offset, size)) return E_OUTOFMEMORY;
     1250    flags = buffer_sanitize_flags(This, flags);
     1251    if (!(flags & WINED3DLOCK_READONLY))
     1252    {
     1253        if (!buffer_add_dirty_area(This, offset, size)) return E_OUTOFMEMORY;
     1254    }
    10461255
    10471256    count = InterlockedIncrement(&This->lock_count);
    10481257
    1049     if(!(This->flags & WINED3D_BUFFER_DOUBLEBUFFER) && This->buffer_object)
    1050     {
    1051         if(count == 1)
    1052         {
    1053             IWineD3DDeviceImpl *device = This->resource.device;
    1054             struct wined3d_context *context;
    1055 
    1056             if(This->buffer_type_hint == GL_ELEMENT_ARRAY_BUFFER_ARB)
    1057             {
    1058                 IWineD3DDeviceImpl_MarkStateDirty(This->resource.device, STATE_INDEXBUFFER);
    1059             }
    1060 
    1061             context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD);
    1062             ENTER_GL();
    1063             GL_EXTCALL(glBindBufferARB(This->buffer_type_hint, This->buffer_object));
    1064             This->resource.allocatedMemory = GL_EXTCALL(glMapBufferARB(This->buffer_type_hint, GL_READ_WRITE_ARB));
    1065             LEAVE_GL();
    1066             context_release(context);
     1258    if (This->buffer_object)
     1259    {
     1260        if(!(This->flags & WINED3D_BUFFER_DOUBLEBUFFER))
     1261        {
     1262            if(count == 1)
     1263            {
     1264                IWineD3DDeviceImpl *device = This->resource.device;
     1265                struct wined3d_context *context;
     1266                const struct wined3d_gl_info *gl_info;
     1267
     1268                if(This->buffer_type_hint == GL_ELEMENT_ARRAY_BUFFER_ARB)
     1269                {
     1270                    IWineD3DDeviceImpl_MarkStateDirty(This->resource.device, STATE_INDEXBUFFER);
     1271                }
     1272
     1273                context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD);
     1274                gl_info = context->gl_info;
     1275                ENTER_GL();
     1276                GL_EXTCALL(glBindBufferARB(This->buffer_type_hint, This->buffer_object));
     1277
     1278                if (gl_info->supported[ARB_MAP_BUFFER_RANGE])
     1279                {
     1280                    GLbitfield mapflags = buffer_gl_map_flags(flags);
     1281                    This->resource.allocatedMemory = GL_EXTCALL(glMapBufferRange(This->buffer_type_hint, 0,
     1282                                                                                This->resource.size, mapflags));
     1283                    checkGLcall("glMapBufferRange");
     1284                }
     1285                else
     1286                {
     1287                    if(This->flags & WINED3D_BUFFER_APPLESYNC)
     1288                    {
     1289                        LEAVE_GL();
     1290                        buffer_sync_apple(This, flags, gl_info);
     1291                        ENTER_GL();
     1292                    }
     1293                    This->resource.allocatedMemory = GL_EXTCALL(glMapBufferARB(This->buffer_type_hint, GL_READ_WRITE_ARB));
     1294                    checkGLcall("glMapBufferARB");
     1295                }
     1296                LEAVE_GL();
     1297
     1298                if (((DWORD_PTR) This->resource.allocatedMemory) & (RESOURCE_ALIGNMENT - 1))
     1299                {
     1300                    WARN("Pointer %p is not %u byte aligned, falling back to double buffered operation\n",
     1301                        This->resource.allocatedMemory, RESOURCE_ALIGNMENT);
     1302
     1303                    ENTER_GL();
     1304                    GL_EXTCALL(glUnmapBufferARB(This->buffer_type_hint));
     1305                    checkGLcall("glUnmapBufferARB");
     1306                    LEAVE_GL();
     1307                    This->resource.allocatedMemory = NULL;
     1308
     1309                    buffer_get_sysmem(This);
     1310                    TRACE("New pointer is %p\n", This->resource.allocatedMemory);
     1311                }
     1312                context_release(context);
     1313            }
     1314        }
     1315        else
     1316        {
     1317            if (dirty)
     1318            {
     1319                if (This->flags & WINED3D_BUFFER_NOSYNC && !(flags & WINED3DLOCK_NOOVERWRITE))
     1320                {
     1321                    This->flags &= ~WINED3D_BUFFER_NOSYNC;
     1322                }
     1323            }
     1324            else if(flags & WINED3DLOCK_NOOVERWRITE)
     1325            {
     1326                This->flags |= WINED3D_BUFFER_NOSYNC;
     1327            }
     1328
     1329            if (flags & WINED3DLOCK_DISCARD)
     1330            {
     1331                This->flags |= WINED3D_BUFFER_DISCARD;
     1332            }
    10671333        }
    10681334    }
     
    11031369    {
    11041370        IWineD3DDeviceImpl *device = This->resource.device;
     1371        const struct wined3d_gl_info *gl_info;
    11051372        struct wined3d_context *context;
    11061373
     
    11111378
    11121379        context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD);
     1380        gl_info = context->gl_info;
    11131381        ENTER_GL();
    11141382        GL_EXTCALL(glBindBufferARB(This->buffer_type_hint, This->buffer_object));
    11151383
    1116         if(This->flags & WINED3D_BUFFER_FLUSH)
     1384        if (gl_info->supported[ARB_MAP_BUFFER_RANGE])
     1385        {
     1386            for(i = 0; i < This->modified_areas; i++)
     1387            {
     1388                GL_EXTCALL(glFlushMappedBufferRange(This->buffer_type_hint,
     1389                                                    This->maps[i].offset,
     1390                                                    This->maps[i].size));
     1391                checkGLcall("glFlushMappedBufferRange");
     1392            }
     1393        }
     1394        else if (This->flags & WINED3D_BUFFER_FLUSH)
    11171395        {
    11181396            for(i = 0; i < This->modified_areas; i++)
     
    11811459        const char *data, IUnknown *parent, const struct wined3d_parent_ops *parent_ops)
    11821460{
    1183     const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(format, &device->adapter->gl_info);
     1461    const struct wined3d_format_desc *format_desc = getFormatDescEntry(format, &device->adapter->gl_info);
    11841462    HRESULT hr;
    11851463    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
     
    12061484            debug_d3dformat(buffer->resource.format_desc->format), buffer->resource.allocatedMemory, buffer);
    12071485
    1208     /* TODO: GL_ARB_map_buffer_range */
    1209     dynamic_buffer_ok = gl_info->supported[APPLE_FLUSH_BUFFER_RANGE];
     1486    dynamic_buffer_ok = gl_info->supported[APPLE_FLUSH_BUFFER_RANGE] || gl_info->supported[ARB_MAP_BUFFER_RANGE];
    12101487
    12111488    /* Observations show that drawStridedSlow is faster on dynamic VBs than converting +
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette