From 08092b494b98ca7ca22998b5afb4adcd6172a0fc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20D=C3=B6singer?= <stefan@codeweavers.com>
Date: Fri, 30 Aug 2013 17:00:35 +0200
Subject: wined3d: Wrap GL BOs in a structure

The idea is to use those structures for mapping through the command stream and caching
them for DISCARD maps.
---
 dlls/wined3d/device.c          | 53 ++++++++++++++++++++++++++++++++++++++++++
 dlls/wined3d/resource.c        | 34 +++++++++++----------------
 dlls/wined3d/surface.c         |  6 ++---
 dlls/wined3d/volume.c          |  6 ++---
 dlls/wined3d/wined3d_private.h | 15 +++++++++++-
 5 files changed, 86 insertions(+), 28 deletions(-)

diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index eb0c0ba..d0fcba2 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -5139,3 +5139,56 @@ LRESULT device_process_message(struct wined3d_device *device, HWND window, BOOL
     else
         return CallWindowProcA(proc, window, message, wparam, lparam);
 }
+
+/* Context activation is done by the caller */
+struct wined3d_gl_bo *wined3d_device_get_bo(struct wined3d_device *device, UINT size, GLenum gl_usage,
+        GLenum type_hint, struct wined3d_context *context)
+{
+    struct wined3d_gl_bo *ret;
+    const struct wined3d_gl_info *gl_info;
+
+    TRACE("device %p, size %u, gl_usage %u, type_hint %u\n", device, size, gl_usage,
+            type_hint);
+
+    ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ret));
+    if(!ret)
+        return NULL;
+    ret->type_hint = type_hint;
+    ret->size = size;
+    ret->usage = gl_usage;
+
+    gl_info = context->gl_info;
+
+    GL_EXTCALL(glGenBuffers(1, &ret->name));
+    if (type_hint == GL_ELEMENT_ARRAY_BUFFER)
+        context_invalidate_state(context, STATE_INDEXBUFFER);
+    GL_EXTCALL(glBindBuffer(type_hint, ret->name));
+    GL_EXTCALL(glBufferData(type_hint, size, NULL, gl_usage));
+    GL_EXTCALL(glBindBuffer(type_hint, 0));
+    checkGLcall("Create buffer object");
+
+    TRACE("Successfully created and set up buffer %u\n", ret->name);
+    return ret;
+}
+
+/* Context activation is done by the caller */
+static void wined3d_device_destroy_bo(struct wined3d_device *device, const struct wined3d_context *context,
+        struct wined3d_gl_bo *bo)
+{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    TRACE("device %p, bo %p, GL bo %u\n", device, bo, bo->name);
+
+    GL_EXTCALL(glDeleteBuffers(1, &bo->name));
+    checkGLcall("glDeleteBuffers");
+
+    HeapFree(GetProcessHeap(), 0, bo);
+}
+
+/* Context activation is done by the caller */
+void wined3d_device_release_bo(struct wined3d_device *device, struct wined3d_gl_bo *bo,
+        const struct wined3d_context *context)
+{
+    TRACE("device %p, bo %p, GL bo %u\n", device, bo, bo->name);
+
+    wined3d_device_destroy_bo(device, context, bo);
+}
diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c
index 49ef6b9..37a2644 100644
--- a/dlls/wined3d/resource.c
+++ b/dlls/wined3d/resource.c
@@ -226,12 +226,10 @@ HRESULT resource_init(struct wined3d_resource *resource, struct wined3d_device *
 void wined3d_resource_free_bo(struct wined3d_resource *resource)
 {
     struct wined3d_context *context = context_acquire(resource->device, NULL);
-    const struct wined3d_gl_info *gl_info = context->gl_info;
 
-    TRACE("Deleting GL buffer %u belonging to resource %p.\n", resource->buffer_object, resource);
-    GL_EXTCALL(glDeleteBuffers(1, &resource->buffer_object));
-    checkGLcall("glDeleteBuffers");
-    resource->buffer_object = 0;
+    wined3d_device_release_bo(resource->device, resource->buffer, context);
+    resource->buffer = NULL;
+
     context_release(context);
 }
 
@@ -247,7 +245,7 @@ void resource_cleanup(struct wined3d_resource *resource)
         adapter_adjust_memory(resource->device->adapter, (INT64)0 - resource->size);
     }
 
-    if (resource->buffer_object)
+    if (resource->buffer)
         wined3d_resource_free_bo(resource);
 
     wined3d_resource_free_sysmem(resource);
@@ -260,7 +258,7 @@ void resource_unload(struct wined3d_resource *resource)
     if (resource->map_count)
         ERR("Resource %p is being unloaded while mapped.\n", resource);
 
-    if (resource->buffer_object)
+    if (resource->buffer)
         wined3d_resource_free_bo(resource);
 
     context_resource_unloaded(resource->device,
@@ -511,7 +509,7 @@ void wined3d_resource_get_memory(const struct wined3d_resource *resource,
 {
     if (location & WINED3D_LOCATION_BUFFER)
     {
-        data->buffer_object = resource->buffer_object;
+        data->buffer_object = resource->buffer->name;
         data->addr = NULL;
         return;
     }
@@ -620,7 +618,7 @@ BYTE *wined3d_resource_get_map_ptr(const struct wined3d_resource *resource,
     {
         case WINED3D_LOCATION_BUFFER:
             gl_info = context->gl_info;
-            GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, resource->buffer_object));
+            GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, resource->buffer->name));
 
             if (gl_info->supported[ARB_MAP_BUFFER_RANGE])
             {
@@ -663,7 +661,7 @@ void wined3d_resource_release_map_ptr(const struct wined3d_resource *resource,
     {
         case WINED3D_LOCATION_BUFFER:
             gl_info = context->gl_info;
-            GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, resource->buffer_object));
+            GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, resource->buffer->name));
             GL_EXTCALL(glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER));
             GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0));
             checkGLcall("Unmap GL buffer");
@@ -681,20 +679,14 @@ void wined3d_resource_release_map_ptr(const struct wined3d_resource *resource,
 }
 
 /* Context activation is done by the caller. */
-static void wined3d_resource_prepare_bo(struct wined3d_resource *resource, const struct wined3d_context *context)
+static void wined3d_resource_prepare_bo(struct wined3d_resource *resource, struct wined3d_context *context)
 {
-    const struct wined3d_gl_info *gl_info = context->gl_info;
-
-    if (resource->buffer_object)
+    if (resource->buffer)
         return;
 
-    GL_EXTCALL(glGenBuffers(1, &resource->buffer_object));
-    GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, resource->buffer_object));
-    GL_EXTCALL(glBufferData(GL_PIXEL_UNPACK_BUFFER, resource->size, NULL, GL_STREAM_DRAW));
-    GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0));
-    checkGLcall("Create GL buffer");
-
-    TRACE("Created GL buffer %u for resource %p.\n", resource->buffer_object, resource);
+    resource->buffer = wined3d_device_get_bo(resource->device, resource->size,
+            GL_STREAM_DRAW, GL_PIXEL_UNPACK_BUFFER, context);
+    TRACE("Created GL buffer %u for resource %p.\n", resource->buffer->name, resource);
 }
 
 BOOL wined3d_resource_prepare_system_memory(struct wined3d_resource *resource)
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index 025e85e1..fc1fc45 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -48,7 +48,7 @@ static void surface_cleanup(struct wined3d_surface *surface)
         surface->resource.device->cs->ops->finish(surface->resource.device->cs);
     }
 
-    if (surface->resource.buffer_object || surface->rb_multisample
+    if (surface->resource.buffer || surface->rb_multisample
             || surface->rb_resolved || !list_empty(&surface->renderbuffers))
     {
         struct wined3d_renderbuffer_entry *entry, *entry2;
@@ -2586,7 +2586,7 @@ HRESULT CDECL wined3d_surface_getdc(struct wined3d_surface *surface, HDC *dc)
         }
         if (!(surface->resource.map_binding == WINED3D_LOCATION_USER_MEMORY
                 || surface->container->flags & WINED3D_TEXTURE_PIN_SYSMEM
-                || surface->resource.buffer_object))
+                || surface->resource.buffer))
             surface->resource.map_binding = WINED3D_LOCATION_DIB;
     }
 
@@ -3905,7 +3905,7 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface,
     /* Don't use PBOs for converted surfaces. During PBO conversion we look at
      * WINED3D_TEXTURE_CONVERTED but it isn't set (yet) in all cases it is
      * getting called. */
-    if ((format.convert || conversion) && surface->resource.buffer_object)
+    if ((format.convert || conversion) && surface->resource.buffer)
     {
         TRACE("Removing the pbo attached to surface %p.\n", surface);
 
diff --git a/dlls/wined3d/volume.c b/dlls/wined3d/volume.c
index b79f44e..ea9a047 100644
--- a/dlls/wined3d/volume.c
+++ b/dlls/wined3d/volume.c
@@ -218,7 +218,7 @@ static void wined3d_volume_load_location(struct wined3d_resource *resource,
             }
             else if (volume->resource.locations & WINED3D_LOCATION_BUFFER)
             {
-                struct wined3d_const_bo_address data = {volume->resource.buffer_object, NULL};
+                struct wined3d_const_bo_address data = {volume->resource.buffer->name, NULL};
                 wined3d_texture_bind_and_dirtify(volume->container, context,
                         location == WINED3D_LOCATION_TEXTURE_SRGB);
                 wined3d_volume_upload_data(volume, context, &data);
@@ -269,12 +269,12 @@ static void wined3d_volume_load_location(struct wined3d_resource *resource,
             break;
 
         case WINED3D_LOCATION_BUFFER:
-            if (!volume->resource.buffer_object)
+            if (!volume->resource.buffer)
                 ERR("Trying to load WINED3D_LOCATION_BUFFER without setting it up first.\n");
 
             if (volume->resource.locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB))
             {
-                struct wined3d_bo_address data = {volume->resource.buffer_object, NULL};
+                struct wined3d_bo_address data = {volume->resource.buffer->name, NULL};
 
                 if (volume->resource.locations & WINED3D_LOCATION_TEXTURE_RGB)
                     wined3d_texture_bind_and_dirtify(volume->container, context, FALSE);
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 8a25420..9eb038e 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2048,6 +2048,14 @@ struct wined3d_state
     DWORD render_states[WINEHIGHEST_RENDER_STATE + 1];
 };
 
+struct wined3d_gl_bo
+{
+    GLuint name;
+    GLenum usage;
+    GLenum type_hint;
+    UINT size;
+};
+
 #define WINED3D_UNMAPPED_STAGE ~0U
 
 /* Multithreaded flag. Removed from the public header to signal that
@@ -2154,6 +2162,11 @@ void device_invalidate_state(const struct wined3d_device *device, DWORD state) D
 void device_invalidate_shader_constants(const struct wined3d_device *device, DWORD mask) DECLSPEC_HIDDEN;
 void device_exec_update_texture(struct wined3d_context *context, struct wined3d_texture *src_texture,
         struct wined3d_texture *dst_texture) DECLSPEC_HIDDEN;
+struct wined3d_gl_bo *wined3d_device_get_bo(struct wined3d_device *device, UINT size, GLenum gl_usage,
+        GLenum type_hint, struct wined3d_context *context) DECLSPEC_HIDDEN;
+void wined3d_device_release_bo(struct wined3d_device *device, struct wined3d_gl_bo *bo,
+        const struct wined3d_context *context) DECLSPEC_HIDDEN;
+
 
 static inline BOOL isStateDirty(const struct wined3d_context *context, DWORD state)
 {
@@ -2199,7 +2212,7 @@ struct wined3d_resource
     DWORD priority;
     void *heap_memory, *user_memory, *bitmap_data;
     UINT custom_row_pitch, custom_slice_pitch;
-    GLuint buffer_object;
+    struct wined3d_gl_bo *buffer;
     struct list resource_list_entry;
     DWORD locations;
     LONG access_fence;
-- 
2.5.1

