Commit 5f581975 authored by Henri Verbeet's avatar Henri Verbeet Committed by Alexandre Julliard

wined3d: Introduce surface_init() to handle most of the surface initialization.

parent bbfdfb2f
......@@ -895,156 +895,39 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UI
WINED3DSURFTYPE Impl, IUnknown *parent)
{
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
unsigned int Size = 1;
const struct GlPixelFormatDesc *glDesc = getFormatDescEntry(Format, &GLINFO_LOCATION);
IWineD3DSurfaceImpl *object;
HRESULT hr;
TRACE("(%p) Create surface\n",This);
if(MultisampleQuality > 0) {
FIXME("MultisampleQuality set to %d, substituting 0\n", MultisampleQuality);
MultisampleQuality=0;
}
/** FIXME: Check that the format is supported
* by the device.
*******************************/
if (WINED3DFMT_UNKNOWN == Format) {
Size = 0;
}
else if (glDesc->Flags & WINED3DFMT_FLAG_COMPRESSED)
{
UINT row_block_count = (Width + glDesc->block_width - 1) / glDesc->block_width;
UINT row_count = (Height + glDesc->block_height - 1) / glDesc->block_height;
Size = row_count * row_block_count * glDesc->block_byte_count;
}
else
if (Impl == SURFACE_OPENGL && !This->adapter)
{
/* The pitch is a multiple of 4 bytes */
Size = ((Width * glDesc->byte_count) + This->surface_alignment - 1) & ~(This->surface_alignment - 1);
Size *= Height;
ERR("OpenGL surfaces are not available without OpenGL.\n");
return WINED3DERR_NOTAVAILABLE;
}
if(glDesc->heightscale != 0.0) Size *= glDesc->heightscale;
/** Create and initialise the surface resource **/
object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
if (!object)
{
ERR("Out of memory\n");
ERR("Failed to allocate surface memory.\n");
*ppSurface = NULL;
return WINED3DERR_OUTOFVIDEOMEMORY;
}
/* Look at the implementation and set the correct Vtable */
switch(Impl)
{
case SURFACE_OPENGL:
/* Check if a 3D adapter is available when creating gl surfaces */
if (!This->adapter)
{
ERR("OpenGL surfaces are not available without opengl\n");
HeapFree(GetProcessHeap(), 0, object);
return WINED3DERR_NOTAVAILABLE;
}
object->lpVtbl = &IWineD3DSurface_Vtbl;
break;
case SURFACE_GDI:
object->lpVtbl = &IWineGDISurface_Vtbl;
break;
default:
/* To be sure to catch this */
ERR("Unknown requested surface implementation %d!\n", Impl);
HeapFree(GetProcessHeap(), 0, object);
return WINED3DERR_INVALIDCALL;
}
hr = resource_init((IWineD3DResource *)object, WINED3DRTYPE_SURFACE, This, Size, Usage, glDesc, Pool, parent);
hr = surface_init(object, Impl, This->surface_alignment, Width, Height, Level, Lockable,
Discard, MultiSample, MultisampleQuality, This, Usage, Format, Pool, parent);
if (FAILED(hr))
{
WARN("Failed to initialize resource, returning %#x\n", hr);
WARN("Failed to initialize surface, returning %#x.\n", hr);
HeapFree(GetProcessHeap(), 0, object);
*ppSurface = NULL;
return hr;
}
TRACE("(%p) : Created resource %p\n", This, object);
TRACE("(%p) : Created surface %p\n", This, object);
*ppSurface = (IWineD3DSurface *)object;
/* "Standalone" surface */
IWineD3DSurface_SetContainer((IWineD3DSurface *)object, NULL);
object->currentDesc.Width = Width;
object->currentDesc.Height = Height;
object->currentDesc.MultiSampleType = MultiSample;
object->currentDesc.MultiSampleQuality = MultisampleQuality;
object->glDescription.level = Level;
list_init(&object->overlays);
/* Flags */
object->Flags = SFLAG_NORMCOORD; /* Default to normalized coords */
object->Flags |= Discard ? SFLAG_DISCARD : 0;
object->Flags |= (WINED3DFMT_D16_LOCKABLE == Format) ? SFLAG_LOCKABLE : 0;
object->Flags |= Lockable ? SFLAG_LOCKABLE : 0;
TRACE("Pool %d %d %d %d\n",Pool, WINED3DPOOL_DEFAULT, WINED3DPOOL_MANAGED, WINED3DPOOL_SYSTEMMEM);
/** Quick lockable sanity check TODO: remove this after surfaces, usage and lockability have been debugged properly
* this function is too deep to need to care about things like this.
* Levels need to be checked too, and possibly Type since they all affect what can be done.
* ****************************************/
switch(Pool) {
case WINED3DPOOL_SCRATCH:
if(!Lockable)
FIXME("Create surface called with a pool of SCRATCH and a Lockable of FALSE "
"which are mutually exclusive, setting lockable to TRUE\n");
Lockable = TRUE;
break;
case WINED3DPOOL_SYSTEMMEM:
if(!Lockable) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, "
"this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
case WINED3DPOOL_MANAGED:
if(Usage == WINED3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a "
"Usage of DYNAMIC which are mutually exclusive, not doing "
"anything just telling you.\n");
break;
case WINED3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
if(!(Usage & WINED3DUSAGE_DYNAMIC) && !(Usage & WINED3DUSAGE_RENDERTARGET)
&& !(Usage & WINED3DUSAGE_DEPTHSTENCIL ) && Lockable)
WARN("Creating a surface with a POOL of DEFAULT with Lockable true, that doesn't specify DYNAMIC usage.\n");
break;
default:
FIXME("(%p) Unknown pool %d\n", This, Pool);
break;
};
if (Usage & WINED3DUSAGE_RENDERTARGET && Pool != WINED3DPOOL_DEFAULT) {
FIXME("Trying to create a render target that isn't in the default pool\n");
}
/* mark the texture as dirty so that it gets loaded first time around*/
surface_add_dirty_rect(*ppSurface, NULL);
TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
This, Width, Height, Format, debug_d3dformat(Format),
(WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
list_init(&object->renderbuffers);
/* Call the private setup routine */
hr = IWineD3DSurface_PrivateSetup((IWineD3DSurface *)object);
if (FAILED(hr))
{
ERR("Private setup failed, returning %#x\n", hr);
IWineD3DSurface_Release(*ppSurface);
*ppSurface = NULL;
return hr;
}
return hr;
}
......
......@@ -32,11 +32,13 @@
WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface);
WINE_DECLARE_DEBUG_CHANNEL(d3d);
#define GLINFO_LOCATION This->resource.wineD3DDevice->adapter->gl_info
#define GLINFO_LOCATION (*gl_info)
static void surface_cleanup(IWineD3DSurfaceImpl *This)
{
IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
const WineD3D_GL_Info *gl_info = &device->adapter->gl_info;
renderbuffer_entry_t *entry, *entry2;
TRACE("(%p) : Cleaning up.\n", This);
......@@ -92,6 +94,143 @@ static void surface_cleanup(IWineD3DSurfaceImpl *This)
resource_cleanup((IWineD3DResource *)This);
}
HRESULT surface_init(IWineD3DSurfaceImpl *surface, WINED3DSURFTYPE surface_type, UINT alignment,
UINT width, UINT height, UINT level, BOOL lockable, BOOL discard, WINED3DMULTISAMPLE_TYPE multisample_type,
UINT multisample_quality, IWineD3DDeviceImpl *device, DWORD usage, WINED3DFORMAT format,
WINED3DPOOL pool, IUnknown *parent)
{
const WineD3D_GL_Info *gl_info = &device->adapter->gl_info;
const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(format, &GLINFO_LOCATION);
void (*cleanup)(IWineD3DSurfaceImpl *This);
unsigned int resource_size;
HRESULT hr;
if (multisample_quality > 0)
{
FIXME("multisample_quality set to %u, substituting 0\n", multisample_quality);
multisample_quality = 0;
}
/* FIXME: Check that the format is supported by the device. */
if (format == WINED3DFMT_UNKNOWN)
{
resource_size = 0;
}
else if (format_desc->Flags & WINED3DFMT_FLAG_COMPRESSED)
{
UINT row_block_count = (width + format_desc->block_width - 1) / format_desc->block_width;
UINT row_count = (height + format_desc->block_height - 1) / format_desc->block_height;
resource_size = row_count * row_block_count * format_desc->block_byte_count;
}
else
{
/* The pitch is a multiple of 4 bytes. */
resource_size = ((width * format_desc->byte_count) + alignment - 1) & ~(alignment - 1);
resource_size *= height;
}
if (format_desc->heightscale != 0.0) resource_size *= format_desc->heightscale;
/* Look at the implementation and set the correct Vtable. */
switch (surface_type)
{
case SURFACE_OPENGL:
surface->lpVtbl = &IWineD3DSurface_Vtbl;
cleanup = surface_cleanup;
break;
case SURFACE_GDI:
surface->lpVtbl = &IWineGDISurface_Vtbl;
cleanup = surface_gdi_cleanup;
break;
default:
ERR("Requested unknown surface implementation %#x.\n", surface_type);
return WINED3DERR_INVALIDCALL;
}
hr = resource_init((IWineD3DResource *)surface, WINED3DRTYPE_SURFACE,
device, resource_size, usage, format_desc, pool, parent);
if (FAILED(hr))
{
WARN("Failed to initialize resource, returning %#x.\n", hr);
return hr;
}
/* "Standalone" surface. */
IWineD3DSurface_SetContainer((IWineD3DSurface *)surface, NULL);
surface->currentDesc.Width = width;
surface->currentDesc.Height = height;
surface->currentDesc.MultiSampleType = multisample_type;
surface->currentDesc.MultiSampleQuality = multisample_quality;
surface->glDescription.level = level;
list_init(&surface->overlays);
/* Flags */
surface->Flags = SFLAG_NORMCOORD; /* Default to normalized coords. */
if (discard) surface->Flags |= SFLAG_DISCARD;
if (lockable || format == WINED3DFMT_D16_LOCKABLE) surface->Flags |= SFLAG_LOCKABLE;
/* Quick lockable sanity check.
* TODO: remove this after surfaces, usage and lockability have been debugged properly
* this function is too deep to need to care about things like this.
* Levels need to be checked too, since they all affect what can be done. */
switch (pool)
{
case WINED3DPOOL_SCRATCH:
if(!lockable)
{
FIXME("Called with a pool of SCRATCH and a lockable of FALSE "
"which are mutually exclusive, setting lockable to TRUE.\n");
lockable = TRUE;
}
break;
case WINED3DPOOL_SYSTEMMEM:
if (!lockable)
FIXME("Called with a pool of SYSTEMMEM and a lockable of FALSE, this is acceptable but unexpected.\n");
break;
case WINED3DPOOL_MANAGED:
if (usage & WINED3DUSAGE_DYNAMIC)
FIXME("Called with a pool of MANAGED and a usage of DYNAMIC which are mutually exclusive.\n");
break;
case WINED3DPOOL_DEFAULT:
if (lockable && !(usage & (WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_RENDERTARGET | WINED3DUSAGE_DEPTHSTENCIL)))
WARN("Creating a lockable surface with a POOL of DEFAULT, that doesn't specify DYNAMIC usage.\n");
break;
default:
FIXME("Unknown pool %#x.\n", pool);
break;
};
if (usage & WINED3DUSAGE_RENDERTARGET && pool != WINED3DPOOL_DEFAULT)
{
FIXME("Trying to create a render target that isn't in the default pool.\n");
}
/* Mark the texture as dirty so that it gets loaded first time around. */
surface_add_dirty_rect((IWineD3DSurface *)surface, NULL);
list_init(&surface->renderbuffers);
TRACE("surface %p, memory %p, size %u\n", surface, surface->resource.allocatedMemory, surface->resource.size);
/* Call the private setup routine */
hr = IWineD3DSurface_PrivateSetup((IWineD3DSurface *)surface);
if (FAILED(hr))
{
ERR("Private setup failed, returning %#x\n", hr);
cleanup(surface);
return hr;
}
return hr;
}
static void surface_force_reload(IWineD3DSurface *iface)
{
IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
......@@ -190,6 +329,10 @@ static BOOL primary_render_target_is_p8(IWineD3DDeviceImpl *device)
return FALSE;
}
#undef GLINFO_LOCATION
#define GLINFO_LOCATION This->resource.wineD3DDevice->adapter->gl_info
/* This call just downloads data, the caller is responsible for activating the
* right context and binding the correct texture. */
static void surface_download_data(IWineD3DSurfaceImpl *This) {
......
......@@ -35,7 +35,7 @@
/* Use the d3d_surface debug channel to have one channel for all surfaces */
WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface);
static void surface_gdi_cleanup(IWineD3DSurfaceImpl *This)
void surface_gdi_cleanup(IWineD3DSurfaceImpl *This)
{
TRACE("(%p) : Cleaning up.\n", This);
......
......@@ -1920,6 +1920,12 @@ struct IWineD3DSurfaceImpl
extern const IWineD3DSurfaceVtbl IWineD3DSurface_Vtbl;
extern const IWineD3DSurfaceVtbl IWineGDISurface_Vtbl;
void surface_gdi_cleanup(IWineD3DSurfaceImpl *This);
HRESULT surface_init(IWineD3DSurfaceImpl *surface, WINED3DSURFTYPE surface_type, UINT alignment,
UINT width, UINT height, UINT level, BOOL lockable, BOOL discard, WINED3DMULTISAMPLE_TYPE multisample_type,
UINT multisample_quality, IWineD3DDeviceImpl *device, DWORD usage, WINED3DFORMAT format,
WINED3DPOOL pool, IUnknown *parent);
/* Predeclare the shared Surface functions */
HRESULT WINAPI IWineD3DBaseSurfaceImpl_QueryInterface(IWineD3DSurface *iface, REFIID riid, LPVOID *ppobj);
ULONG WINAPI IWineD3DBaseSurfaceImpl_AddRef(IWineD3DSurface *iface);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment