📄 device.c
字号:
}
for (j = 0 ; j < MAX_COMBINED_SAMPLERS; j++){
for (i =0; i < NUM_SAVEDVERTEXSTATES_S;i++) {
object->changed.samplerState[j][SavedVertexStates_S[i]] = TRUE;
object->contained_sampler_states[object->num_contained_sampler_states].stage = j;
object->contained_sampler_states[object->num_contained_sampler_states].state = SavedVertexStates_S[i];
object->num_contained_sampler_states++;
}
}
for(j = 0; j < LIGHTMAP_SIZE; j++) {
struct list *e;
LIST_FOR_EACH(e, &object->lightMap[j]) {
PLIGHTINFOEL *light = LIST_ENTRY(e, PLIGHTINFOEL, entry);
light->changed = TRUE;
light->enabledChanged = TRUE;
}
}
} else {
FIXME("Unrecognized state block type %d\n", Type);
}
TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
return WINED3D_OK;
}
/* ************************************
MSDN:
[in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
Discard
[in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
If this flag is set, the contents of the depth stencil buffer will be invalid after calling either IDirect3DDevice9::Present or IDirect3DDevice9::SetDepthStencilSurface with a different depth surface.
******************************** */
static HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UINT Width, UINT Height, WINED3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level, IWineD3DSurface **ppSurface,WINED3DRESOURCETYPE Type, DWORD Usage, WINED3DPOOL Pool, WINED3DMULTISAMPLE_TYPE MultiSample ,DWORD MultisampleQuality, HANDLE* pSharedHandle, 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 StaticPixelFormatDesc *tableEntry = getFormatDescEntry(Format, NULL, NULL);
TRACE("(%p) Create surface\n",This);
/** FIXME: Check ranges on the inputs are valid
* MSDN
* MultisampleQuality
* [in] Quality level. The valid range is between zero and one less than the level
* returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
* Passing a larger value returns the error WINED3DERR_INVALIDCALL. The MultisampleQuality
* values of paired render targets, depth stencil surfaces, and the MultiSample type
* must all match.
*******************************/
/**
* TODO: Discard MSDN
* [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
*
* If this flag is set, the contents of the depth stencil buffer will be
* invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
* with a different depth surface.
*
*This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
***************************/
if(MultisampleQuality < 0) {
FIXME("Invalid multisample level %d\n", MultisampleQuality);
return WINED3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
}
if(MultisampleQuality > 0) {
FIXME("MultisampleQuality set to %d, substituting 0\n", MultisampleQuality);
MultisampleQuality=0;
}
/** FIXME: Check that the format is supported
* by the device.
*******************************/
/** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
* it is based around 4x4 pixel blocks it requires padding, so allocate enough
* space!
*********************************/
if (WINED3DFMT_UNKNOWN == Format) {
Size = 0;
} else if (Format == WINED3DFMT_DXT1) {
/* DXT1 is half byte per pixel */
Size = ((max(Width,4) * tableEntry->bpp) * max(Height,4)) >> 1;
} else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
Size = ((max(Width,4) * tableEntry->bpp) * max(Height,4));
} else {
/* The pitch is a multiple of 4 bytes */
Size = ((Width * tableEntry->bpp) + This->surface_alignment - 1) & ~(This->surface_alignment - 1);
Size *= Height;
}
/** Create and initialise the surface resource **/
D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,WINED3DRTYPE_SURFACE, Size)
/* "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;
/* Flags */
object->Flags = 0;
object->Flags |= Discard ? SFLAG_DISCARD : 0;
object->Flags |= (WINED3DFMT_D16_LOCKABLE == Format) ? SFLAG_LOCKABLE : 0;
object->Flags |= Lockable ? SFLAG_LOCKABLE : 0;
if (WINED3DFMT_UNKNOWN != Format) {
object->bytesPerPixel = tableEntry->bpp;
} else {
object->bytesPerPixel = 0;
}
/** TODO: change this into a texture transform matrix so that it's processed in hardware **/
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*/
IWineD3DSurface_AddDirtyRect(*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);
/* Store the DirectDraw primary surface. This is the first rendertarget surface created */
if( (Usage & WINED3DUSAGE_RENDERTARGET) && (!This->ddraw_primary) )
This->ddraw_primary = (IWineD3DSurface *) object;
/* 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->resource.allocatedMemory);
HeapFree(GetProcessHeap(), 0, object);
return WINED3DERR_NOTAVAILABLE;
}
break;
case SURFACE_GDI:
object->lpVtbl = &IWineGDISurface_Vtbl;
break;
default:
/* To be sure to catch this */
ERR("Unknown requested surface implementation %d!\n", Impl);
IWineD3DSurface_Release((IWineD3DSurface *) object);
return WINED3DERR_INVALIDCALL;
}
list_init(&object->renderbuffers);
/* Call the private setup routine */
return IWineD3DSurface_PrivateSetup( (IWineD3DSurface *) object );
}
static HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool,
IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
IWineD3DTextureImpl *object;
unsigned int i;
UINT tmpW;
UINT tmpH;
HRESULT hr;
unsigned int pow2Width;
unsigned int pow2Height;
TRACE("(%p) : Width %d, Height %d, Levels %d, Usage %#x\n", This, Width, Height, Levels, Usage);
TRACE("Format %#x (%s), Pool %#x, ppTexture %p, pSharedHandle %p, parent %p\n",
Format, debug_d3dformat(Format), Pool, ppTexture, pSharedHandle, parent);
/* TODO: It should only be possible to create textures for formats
that are reported as supported */
if (WINED3DFMT_UNKNOWN >= Format) {
WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN\n", This);
return WINED3DERR_INVALIDCALL;
}
D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, WINED3DRTYPE_TEXTURE, 0);
D3DINITIALIZEBASETEXTURE(object->baseTexture);
object->width = Width;
object->height = Height;
/** Non-power2 support **/
if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
pow2Width = Width;
pow2Height = Height;
} else {
/* Find the nearest pow2 match */
pow2Width = pow2Height = 1;
while (pow2Width < Width) pow2Width <<= 1;
while (pow2Height < Height) pow2Height <<= 1;
}
/** FIXME: add support for real non-power-two if it's provided by the video card **/
/* Precalculated scaling for 'faked' non power of two texture coords */
object->pow2scalingFactorX = (((float)Width) / ((float)pow2Width));
object->pow2scalingFactorY = (((float)Height) / ((float)pow2Height));
TRACE(" xf(%f) yf(%f)\n", object->pow2scalingFactorX, object->pow2scalingFactorY);
/* Calculate levels for mip mapping */
if (Levels == 0) {
TRACE("calculating levels %d\n", object->baseTexture.levels);
object->baseTexture.levels++;
tmpW = Width;
tmpH = Height;
while (tmpW > 1 || tmpH > 1) {
tmpW = max(1, tmpW >> 1);
tmpH = max(1, tmpH >> 1);
object->baseTexture.levels++;
}
TRACE("Calculated levels = %d\n", object->baseTexture.levels);
}
/* Generate all the surfaces */
tmpW = Width;
tmpH = Height;
for (i = 0; i < object->baseTexture.levels; i++)
{
/* use the callback to create the texture surface */
hr = D3DCB_CreateSurface(This->parent, parent, tmpW, tmpH, Format, Usage, Pool, i, WINED3DCUBEMAP_FACE_POSITIVE_X, &object->surfaces[i],NULL);
if (hr!= WINED3D_OK || ( (IWineD3DSurfaceImpl *) object->surfaces[i])->Flags & SFLAG_OVERSIZE) {
FIXME("Failed to create surface %p\n", object);
/* clean up */
object->surfaces[i] = NULL;
IWineD3DTexture_Release((IWineD3DTexture *)object);
*ppTexture = NULL;
return hr;
}
IWineD3DSurface_SetContainer(object->surfaces[i], (IWineD3DBase *)object);
TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
/* calculate the next mipmap level */
tmpW = max(1, tmpW >> 1);
tmpH = max(1, tmpH >> 1);
}
TRACE("(%p) : Created texture %p\n", This, object);
return WINED3D_OK;
}
static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
UINT Width, UINT Height, UINT Depth,
UINT Levels, DWORD Usage,
WINED3DFORMAT Format, WINED3DPOOL Pool,
IWineD3DVolumeTexture **ppVolumeTexture,
HANDLE *pSharedHandle, IUnknown *parent,
D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -