device.c revision af062818b47340eef15700d2f0211576ba3506ee
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * IWineD3DDevice implementation
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * Copyright 2002 Lionel Ulmer
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * Copyright 2002-2005 Jason Edmeades
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * Copyright 2003-2004 Raphael Junqueira
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * Copyright 2004 Christian Costa
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * Copyright 2005 Oliver Stieber
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * Copyright 2006-2008 Stefan Dösinger for CodeWeavers
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * Copyright 2006-2008 Henri Verbeet
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * Copyright 2007 Andrew Riedi
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * This library is free software; you can redistribute it and/or
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * modify it under the terms of the GNU Lesser General Public
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * License as published by the Free Software Foundation; either
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * version 2.1 of the License, or (at your option) any later version.
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * This library is distributed in the hope that it will be useful,
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * but WITHOUT ANY WARRANTY; without even the implied warranty of
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * Lesser General Public License for more details.
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * You should have received a copy of the GNU Lesser General Public
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * License along with this library; if not, write to the Free Software
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync/* Define the default light parameters as specified by MSDN */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync/* static function declarations */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsyncstatic void IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync/* helper macros */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync#define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return WINED3DERR_OUTOFVIDEOMEMORY;}
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync#define D3DCREATESHADEROBJECTINSTANCE(object, type) { \
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync object->baseShader.device = (IWineD3DDevice*) This; \
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync#define D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync /* Check that we have enough video ram left */ \
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync object->resource.heapMemory = (0 == _size ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size + RESOURCE_ALIGNMENT)); \
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync if (object->resource.heapMemory == NULL && _size != 0) { \
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync object->resource.allocatedMemory = (BYTE *)(((ULONG_PTR) object->resource.heapMemory + (RESOURCE_ALIGNMENT - 1)) & ~(RESOURCE_ALIGNMENT - 1)); \
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync TRACE("(%p) : Created resource %p\n", This, object); \
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync _basetexture.filterType = (Usage & WINED3DUSAGE_AUTOGENMIPMAP) ? WINED3DTEXF_LINEAR : WINED3DTEXF_NONE; \
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync/**********************************************************
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * Global variable / Constants follow
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync **********************************************************/
1b33c96954667ba382fa595baf7b31290bfdd517vboxsyncconst float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync/**********************************************************
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * IUnknown parts follows
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync **********************************************************/
1b33c96954667ba382fa595baf7b31290bfdd517vboxsyncstatic HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsyncstatic ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsyncstatic ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync TRACE("(%p) : Releasing from %d\n", This, refCount + 1);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync /* TODO: Clean up all the surfaces and textures! */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync /* NOTE: You must release the parent if the object was created via a callback
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync ** ***************************/
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync FIXME("(%p) Device released with resources still bound, acceptable but unexpected\n", This);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync if(This->contexts) ERR("Context array not freed!\n");
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync if (This->hardwareCursor) DestroyCursor(This->hardwareCursor);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync/**********************************************************
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * IWineD3DDevice implementation follows
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync **********************************************************/
1b33c96954667ba382fa595baf7b31290bfdd517vboxsyncstatic HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsyncstatic HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage,
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync DWORD FVF, WINED3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync int dxVersion = ( (IWineD3DImpl *) This->wineD3D)->dxVersion;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync WARN("Size 0 requested, returning WINED3DERR_INVALIDCALL\n");
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync /* The d3d9 testsuit shows that this is not allowed. It doesn't make much sense
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * anyway, SCRATCH vertex buffers aren't usable anywhere
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync WARN("Vertex buffer in D3DPOOL_SCRATCH requested, returning WINED3DERR_INVALIDCALL\n");
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, WINED3DRTYPE_VERTEXBUFFER, Size)
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync TRACE("(%p) : Size=%d, Usage=0x%08x, FVF=%x, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync /* Observations show that drawStridedSlow is faster on dynamic VBs than converting +
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * drawStridedFast (half-life 2).
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * Basically converting the vertices in the buffer is quite expensive, and observations
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * show that drawStridedSlow is faster than converting + uploading + drawStridedFast.
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * Therefore do not create a VBO for WINED3DUSAGE_DYNAMIC buffers.
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * Direct3D7 has another problem: Its vertexbuffer api doesn't offer a way to specify
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * the range of vertices being locked, so each lock will require the whole buffer to be transformed.
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * Moreover geometry data in dx7 is quite simple, so drawStridedSlow isn't a big hit. A plus
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * is that the vertex buffers fvf can be trusted in dx7. So only create non-converted vbos for
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * dx7 apps.
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * There is a IDirect3DVertexBuffer7::Optimize call after which the buffer can't be locked any
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * more. In this call we can convert dx7 buffers too.
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync conv = ((FVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW ) || (FVF & (WINED3DFVF_DIFFUSE | WINED3DFVF_SPECULAR));
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync TRACE("Not creating a vbo because GL_ARB_vertex_buffer is not supported\n");
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync TRACE("Not creating a vbo because the vertex buffer is in system memory\n");
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync TRACE("Not creating a vbo because the buffer has dynamic usage\n");
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync TRACE("Not creating a vbo because dxVersion is 7 and the fvf needs conversion\n");
1b33c96954667ba382fa595baf7b31290bfdd517vboxsyncstatic void CreateIndexBufferVBO(IWineD3DDeviceImpl *This, IWineD3DIndexBufferImpl *object) {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync TRACE("Creating VBO for Index Buffer %p\n", object);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync /* The following code will modify the ELEMENT_ARRAY_BUFFER binding, make sure it is
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * restored on the next draw
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync /* Make sure that a context is there. Needed in a multithreaded environment. Otherwise this call is a nop */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync ERR("Creating a vbo failed with error %s (%#x), continuing without vbo for this buffer\n", debug_glerror(error), error);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, object->vbo));
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync ERR("Failed to bind index buffer with error %s (%#x), continuing without vbo for this buffer\n", debug_glerror(error), error);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync /* Use static write only usage for now. Dynamic index buffers stay in sysmem, and due to the sysmem
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * copy no readback will be needed
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync GL_EXTCALL(glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, object->resource.size, NULL, glUsage));
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync ERR("Failed to initialize the index buffer with error %s (%#x)\n", debug_glerror(error), error);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync TRACE("Successfully created vbo %d for index buffer %p\n", object->vbo, object);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0));
1b33c96954667ba382fa595baf7b31290bfdd517vboxsyncstatic HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage,
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync WINED3DFORMAT Format, WINED3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync /* Allocate the storage for the device */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,WINED3DRTYPE_INDEXBUFFER, Length)
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync if(Pool != WINED3DPOOL_SYSTEMMEM && !(Usage & WINED3DUSAGE_DYNAMIC) && GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync TRACE("(%p) : Len=%d, Use=%x, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format,
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsyncstatic HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, WINED3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync for(i = 0; i < LIGHTMAP_SIZE; i++) {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync /* Special case - Used during initialization to produce a placeholder stateblock
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync so other functions called can update a state block */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync /* Don't bother increasing the reference count otherwise a device will never
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync be freed due to circular dependencies */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync /* Otherwise, might as well set the whole state block to the appropriate values */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync stateblock_copy((IWineD3DStateBlock*) object, (IWineD3DStateBlock*) This->stateBlock);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync memset(object->streamFreq, 1, sizeof(object->streamFreq));
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync /* Reset the ref and type after kludging it */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync TRACE("Updating changed flags appropriate for type %d\n", Type);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, TRUE);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync /* Lights are not part of the changed / set structure */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync for(j = 0; j < LIGHTMAP_SIZE; j++) {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync PLIGHTINFOEL *light = LIST_ENTRY(e, PLIGHTINFOEL, entry);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync object->num_contained_render_states = WINEHIGHEST_RENDER_STATE;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync /* TODO: Filter unused transforms between TEXTURE8 and WORLD0? */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync object->num_contained_transform_states = HIGHEST_TRANSFORMSTATE;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync for(j = 0; j < GL_LIMITS(vshader_constantsF); j++) {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync object->num_contained_vs_consts_f = GL_LIMITS(vshader_constantsF);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync for(j = 0; j < MAX_CONST_I; j++) {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync for(j = 0; j < MAX_CONST_B; j++) {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync for(j = 0; j < GL_LIMITS(pshader_constantsF); j++) {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync object->num_contained_ps_consts_f = GL_LIMITS(pshader_constantsF);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync for(j = 0; j < MAX_CONST_I; j++) {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync for(j = 0; j < MAX_CONST_B; j++) {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync for(i = 0; i < MAX_TEXTURES; i++) {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync for(j = 1; j <= WINED3D_HIGHEST_TEXTURE_STATE; j++) {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync object->contained_tss_states[object->num_contained_tss_states].stage = i;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync object->contained_tss_states[object->num_contained_tss_states].state = j;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync for(i = 0; i < MAX_COMBINED_SAMPLERS; i++) {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync for(j = 1; j <= WINED3D_HIGHEST_SAMPLER_STATE; j++) {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync object->contained_sampler_states[object->num_contained_sampler_states].stage = i;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync object->contained_sampler_states[object->num_contained_sampler_states].state = j;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync for(i = 0; i < MAX_STREAMS; i++) {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync IWineD3DVertexBuffer_AddRef(object->streamSource[i]);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync TRACE("PIXELSTATE => Pretend all pixel shates have changed\n");
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, FALSE);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync /* Pixel Shader Constants */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync for (i = 0; i < GL_LIMITS(pshader_constantsF); ++i) {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync object->num_contained_ps_consts_f = GL_LIMITS(pshader_constantsF);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync for (i = 0; i < MAX_CONST_B; ++i) {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync for (i = 0; i < MAX_CONST_I; ++i) {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync object->contained_render_states[i] = SavedPixelStates_R[i];
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync object->num_contained_render_states = NUM_SAVEDPIXELSTATES_R;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync for (j = 0; j < MAX_TEXTURES; j++) {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync object->changed.textureState[j][SavedPixelStates_T[i]] = TRUE;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync object->contained_tss_states[object->num_contained_tss_states].stage = j;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync object->contained_tss_states[object->num_contained_tss_states].state = SavedPixelStates_T[i];
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync for (j = 0 ; j < MAX_COMBINED_SAMPLERS; j++) {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync for (i =0; i < NUM_SAVEDPIXELSTATES_S;i++) {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync object->changed.samplerState[j][SavedPixelStates_S[i]] = TRUE;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync object->contained_sampler_states[object->num_contained_sampler_states].stage = j;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync object->contained_sampler_states[object->num_contained_sampler_states].state = SavedPixelStates_S[i];
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync /* Pixel state blocks do not contain vertex buffers. Set them to NULL to avoid wrong refcounting
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * on them. This makes releasing the buffer easier
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync for(i = 0; i < MAX_STREAMS; i++) {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync TRACE("VERTEXSTATE => Pretend all vertex shates have changed\n");
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, FALSE);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync /* Vertex Shader Constants */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync for (i = 0; i < GL_LIMITS(vshader_constantsF); ++i) {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync object->num_contained_vs_consts_f = GL_LIMITS(vshader_constantsF);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync for (i = 0; i < MAX_CONST_B; ++i) {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync object->changed.vertexShaderConstantsB |= (1 << i);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync for (i = 0; i < MAX_CONST_I; ++i) {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync object->changed.vertexShaderConstantsI |= (1 << i);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync object->contained_render_states[i] = SavedVertexStates_R[i];
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync object->num_contained_render_states = NUM_SAVEDVERTEXSTATES_R;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync for (j = 0; j < MAX_TEXTURES; j++) {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync object->changed.textureState[j][SavedVertexStates_T[i]] = TRUE;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync object->contained_tss_states[object->num_contained_tss_states].stage = j;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync object->contained_tss_states[object->num_contained_tss_states].state = SavedVertexStates_T[i];
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync for (j = 0 ; j < MAX_COMBINED_SAMPLERS; j++){
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync for (i =0; i < NUM_SAVEDVERTEXSTATES_S;i++) {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync object->changed.samplerState[j][SavedVertexStates_S[i]] = TRUE;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync object->contained_sampler_states[object->num_contained_sampler_states].stage = j;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync object->contained_sampler_states[object->num_contained_sampler_states].state = SavedVertexStates_S[i];
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync for(j = 0; j < LIGHTMAP_SIZE; j++) {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync PLIGHTINFOEL *light = LIST_ENTRY(e, PLIGHTINFOEL, entry);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync for(i = 0; i < MAX_STREAMS; i++) {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync IWineD3DVertexBuffer_AddRef(object->streamSource[i]);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync/* ************************************
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync[in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
1b33c96954667ba382fa595baf7b31290bfdd517vboxsyncIf 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.
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync******************************** */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsyncstatic 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) {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync const StaticPixelFormatDesc *tableEntry = getFormatDescEntry(Format, &GLINFO_LOCATION, &glDesc);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync /** FIXME: Check ranges on the inputs are valid
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * MultisampleQuality
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * [in] Quality level. The valid range is between zero and one less than the level
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * Passing a larger value returns the error WINED3DERR_INVALIDCALL. The MultisampleQuality
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * values of paired render targets, depth stencil surfaces, and the MultiSample type
* invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
*This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
if(MultisampleQuality > 0) {
Size = 0;
/** Quick lockable sanity check TODO: remove this after surfaces, usage and lockability have been debugged properly
switch(Pool) {
case WINED3DPOOL_SCRATCH:
if(!Lockable)
case WINED3DPOOL_SYSTEMMEM:
case WINED3DPOOL_MANAGED:
case WINED3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
WARN("Creating a surface with a POOL of DEFAULT with Lockable true, that doesn't specify DYNAMIC usage.\n");
(WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
switch(Impl) {
case SURFACE_OPENGL:
return WINED3DERR_NOTAVAILABLE;
case SURFACE_GDI:
return WINED3DERR_INVALIDCALL;
static HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
unsigned int pow2Width;
unsigned int pow2Height;
return WINED3DERR_INVALIDCALL;
return WINED3DERR_INVALIDCALL;
Second also don't use ARB_TEXTURE_RECTANGLE in case the surface format is P8 and EXT_PALETTED_TEXTURE
is used in combination with texture uploads (RTL_READTEX/RTL_TEXTEX). The reason is that EXT_PALETTED_TEXTURE
!((Format == WINED3DFMT_P8) && GL_SUPPORT(EXT_PALETTED_TEXTURE) && (wined3d_settings.rendertargetlock_mode == RTL_READTEX || wined3d_settings.rendertargetlock_mode == RTL_TEXTEX)))
return WINED3DERR_INVALIDCALL;
return WINED3DERR_INVALIDCALL;
} else if (Levels == 0) {
hr = D3DCB_CreateSurface(This->parent, parent, tmpW, tmpH, Format, Usage, Pool, i, WINED3DCUBEMAP_FACE_POSITIVE_X, &object->surfaces[i],NULL);
return hr;
return WINED3D_OK;
return WINED3DERR_INVALIDCALL;
return WINED3DERR_INVALIDCALL;
return WINED3DERR_INVALIDCALL;
return WINED3DERR_INVALIDCALL;
} else if (Levels == 0) {
return hr;
return WINED3D_OK;
return WINED3DERR_INVALIDCALL;
D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, WINED3DRTYPE_VOLUME, ((Width * formatDesc->bpp) * Height * Depth))
unsigned int pow2EdgeLength;
return WINED3DERR_INVALIDCALL;
return WINED3DERR_INVALIDCALL;
return WINED3DERR_INVALIDCALL;
return WINED3DERR_INVALIDCALL;
} else if (Levels == 0) {
return hr;
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
switch(Type) {
case WINED3DQUERYTYPE_EVENT:
* Pretend to support it, faking this query does not do much harm except potentially lowering performance
case WINED3DQUERYTYPE_VCACHE:
return hr;
switch(Type){
object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryOcclusionData));
ENTER_GL();
LEAVE_GL();
case WINED3DQUERYTYPE_EVENT:
ENTER_GL();
LEAVE_GL();
case WINED3DQUERYTYPE_VCACHE:
return WINED3D_OK;
return style;
return exStyle;
static void IWineD3DDeviceImpl_SetupFullscreenWindow(IWineD3DDevice *iface, HWND window, UINT w, UINT h) {
/* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
ERR("App requested %d back buffers, this is not supported for now\n", pPresentationParameters->BackBufferCount);
return WINED3DERR_INVALIDCALL;
FIXME("The app requests more than one back buffer, this can't be supported properly. Please configure the application to use double buffering(=1 back buffer) if possible\n");
switch(surface_type) {
case SURFACE_GDI:
case SURFACE_OPENGL:
case SURFACE_UNKNOWN:
return WINED3DERR_INVALIDCALL;
return WINED3DERR_NOTAVAILABLE;
/** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
goto error;
* I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
goto error;
object->context[0] = CreateContext(This, (IWineD3DSurfaceImpl *) object->frontBuffer, object->win_handle, FALSE /* pbuffer */, pPresentationParameters);
goto error;
UINT i;
object->backBuffer = HeapAlloc(GetProcessHeap(), 0, sizeof(IWineD3DSurface *) * object->presentParms.BackBufferCount);
goto error;
goto error;
ENTER_GL();
LEAVE_GL();
ENTER_GL();
LEAVE_GL();
goto error;
TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer ? object->backBuffer[0] : NULL, pPresentationParameters->EnableAutoDepthStencil);
return WINED3D_OK;
if (displaymode_set) {
UINT i;
return hr;
static HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
return WINED3D_OK;
return WINED3DERR_INVALIDCALL;
static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppVertexDeclaration,
hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, elements, element_count);
return hr;
static unsigned int ConvertFvfToDeclaration(IWineD3DDeviceImpl *This, /* For the GL info, which has the type table */
unsigned int offset;
unsigned int size;
if (!elements)
idx = 0;
if (has_pos) {
idx++;
switch(num_blends) {
idx++;
if (has_blend_idx) {
idx++;
if (has_normal) {
idx++;
if (has_psize) {
idx++;
if (has_diffuse) {
idx++;
if (has_specular) {
idx++;
switch (numcoords) {
idx++;
return size;
static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclarationFromFVF(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *Parent, DWORD Fvf) {
unsigned int size;
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, IWineD3DVertexDeclaration *vertex_declaration, CONST DWORD *pFunction, IWineD3DVertexShader **ppVertexShader, IUnknown *parent) {
if (vertex_declaration) {
return WINED3DERR_INVALIDCALL;
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DPixelShader **ppPixelShader, IUnknown *parent) {
return hr;
if(!object) {
return E_OUTOFMEMORY;
return E_OUTOFMEMORY;
hr = IWineD3DPalette_SetEntries((IWineD3DPalette *) object, 0, 0, IWineD3DPaletteImpl_Size(Flags), PalEnt);
return hr;
return WINED3D_OK;
hbm = (HBITMAP) LoadImageA(NULL, filename, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
if(hbm)
hr = IWineD3DDevice_CreateSurface((IWineD3DDevice *) This, bm.bmWidth, bm.bmHeight, WINED3DFMT_R5G6B5,
goto out;
if(dcb) {
out:
if(dcb) {
if(hbm) {
ENTER_GL();
FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
LEAVE_GL();
static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATESWAPCHAIN D3DCB_CreateSwapChain) {
NULL);
goto err_out;
goto err_out;
This->render_targets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *) * GL_LIMITS(buffers));
This->draw_buffers = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GLenum) * GL_LIMITS(buffers));
goto err_out;
goto err_out;
goto err_out;
This->swapchains = HeapAlloc(GetProcessHeap(), 0, This->NumberOfSwapChains * sizeof(IWineD3DSwapChain *));
goto err_out;
goto err_out;
goto err_out;
goto err_out;
ENTER_GL();
vp.X = 0;
vp.Y = 0;
case ORM_FBO:
case ORM_PBUFFER:
case ORM_BACKBUFFER:
LEAVE_GL();
WINED3DCLEAR_TARGET | pPresentationParameters->EnableAutoDepthStencil ? WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL : 0,
return WINED3D_OK;
if(swapchain) {
return hr;
static HRESULT WINAPI IWineD3DDeviceImpl_InitGDI(IWineD3DDevice *iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATESWAPCHAIN D3DCB_CreateSwapChain) {
goto err_out;
This->swapchains = HeapAlloc(GetProcessHeap(), 0, This->NumberOfSwapChains * sizeof(IWineD3DSwapChain *));
goto err_out;
return WINED3D_OK;
return hr;
static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface, D3DCB_DESTROYSURFACEFN D3DCB_DestroyDepthStencilSurface, D3DCB_DESTROYSWAPCHAINFN D3DCB_DestroySwapChain) {
int sampler;
UINT i;
for(i = 0; i < PATCHMAP_SIZE; i++) {
ENTER_GL();
LEAVE_GL();
ENTER_GL();
LEAVE_GL();
/* This check is a bit silly, it should be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_UninitGDI(IWineD3DDevice *iface, D3DCB_DESTROYSWAPCHAINFN D3DCB_DestroySwapChain) {
return WINED3D_OK;
TRACE("(%p)->(%d,%p) Mode=%dx%dx@%d, %s\n", This, iSwapChain, pMode, pMode->Width, pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
return WINED3D_OK;
ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL;
return WINED3DERR_NOTAVAILABLE;
return WINED3D_OK;
return WINED3D_OK;
return WINED3D_OK;
return WINED3D_OK;
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
return WINED3DERR_INVALIDCALL;
return WINED3DERR_INVALIDCALL;
TRACE("(%p) : StreamNo: %u, OldStream (%p), NewStream (%p), OffsetInBytes %u, NewStride %u\n", This, StreamNumber, oldSrc, pStreamData, OffsetInBytes, Stride);
return WINED3D_OK;
if (pStreamData) {
return WINED3D_OK;
/* MSDN says ..... When an application no longer holds a reference to this interface, the interface will automatically be freed.
which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
return WINED3DERR_INVALIDCALL;
if (pOffset) {
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
return WINED3DERR_INVALIDCALL;
return WINED3DERR_INVALIDCALL;
if( Divider == 0 ){
return WINED3DERR_INVALIDCALL;
This->updateStateBlock->streamFlags[StreamNumber] = Divider & (WINED3DSTREAMSOURCE_INSTANCEDATA | WINED3DSTREAMSOURCE_INDEXEDDATA );
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
*Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE d3dts, CONST WINED3DMATRIX* lpmatrix) {
return WINED3D_OK;
return WINED3D_OK;
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE State, WINED3DMATRIX* pMatrix) {
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE State, CONST WINED3DMATRIX* pMatrix) {
static HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
float rho;
struct list *e;
if(!pLight) {
return WINED3DERR_INVALIDCALL;
case WINED3DLIGHT_POINT:
case WINED3DLIGHT_SPOT:
case WINED3DLIGHT_GLSPOT:
return WINED3DERR_INVALIDCALL;
case WINED3DLIGHT_DIRECTIONAL:
return WINED3DERR_INVALIDCALL;
if(!object) {
if(!object) {
return E_OUTOFMEMORY;
TRACE("Light %d setting to type %d, Diffuse(%f,%f,%f,%f), Specular(%f,%f,%f,%f), Ambient(%f,%f,%f,%f)\n", Index, pLight->Type,
TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
case WINED3DLIGHT_POINT:
case WINED3DLIGHT_DIRECTIONAL:
case WINED3DLIGHT_SPOT:
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
struct list *e;
return WINED3DERR_INVALIDCALL;
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
struct list *e;
return WINED3DERR_INVALIDCALL;
if(!Enable) {
return WINED3D_OK;
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
struct list *e;
return WINED3DERR_INVALIDCALL;
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
return WINED3DERR_INVALIDCALL;
return WINED3D_OK;
return WINED3D_OK;
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
return WINED3DERR_INVALIDCALL;
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
return WINED3DERR_INVALIDCALL;
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
return WINED3DERR_INVALIDCALL;
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
return WINED3D_OK;
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData) {
return WINED3D_OK;
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData) {
if (*ppIndexData) {
return WINED3D_OK;
/* Method to offer d3d9 a simple way to set the base vertex index without messing with the index buffer */
return WINED3D_OK;
return WINED3D_OK;
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_GetBaseVertexIndex(IWineD3DDevice *iface, INT* base_index) {
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
return WINED3D_OK;
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, WINED3DRENDERSTATETYPE State, DWORD Value) {
return WINED3D_OK;
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, WINED3DRENDERSTATETYPE State, DWORD *pValue) {
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
* Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
return WINED3D_OK;
return WINED3D_OK;
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
return WINED3D_OK;
return WINED3D_OK;
return WINED3D_OK;
return WINED3D_OK;
TRACE("(%p)Returning a Scissor Rect of %d:%d-%d:%d\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
return WINED3D_OK;
return WINED3D_OK;
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
return WINED3D_OK;
return WINED3D_OK;
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
return WINED3DERR_INVALIDCALL;
return WINED3D_OK;
return WINED3DERR_INVALIDCALL;
for (i = 0; i < cnt; i++)
return WINED3D_OK;
return WINED3DERR_INVALIDCALL;
return WINED3D_OK;
return WINED3DERR_INVALIDCALL;
for (i = 0; i < cnt; i++)
return WINED3D_OK;
int *dstData,
return WINED3DERR_INVALIDCALL;
return WINED3D_OK;
UINT i;
if (srcData == NULL || start + count > GL_LIMITS(vshader_constantsF) || start > GL_LIMITS(vshader_constantsF))
return WINED3DERR_INVALIDCALL;
memcpy(&This->updateStateBlock->vertexShaderConstantF[start * 4], srcData, count * sizeof(float) * 4);
for (i = 0; i < count; i++)
constants_entry *ptr = LIST_ENTRY(list_head(&This->updateStateBlock->set_vconstantsF), constants_entry, entry);
return WINED3D_OK;
UINT i;
if (srcData == NULL || start + count > GL_LIMITS(vshader_constantsF) || start > GL_LIMITS(vshader_constantsF))
return WINED3DERR_INVALIDCALL;
memcpy(&This->updateStateBlock->vertexShaderConstantF[start * 4], srcData, count * sizeof(float) * 4);
for (i = 0; i < count; i++)
return WINED3D_OK;
float *dstData,
return WINED3DERR_INVALIDCALL;
return WINED3D_OK;
DWORD i;
for(i = 0; i < WINED3D_HIGHEST_TEXTURE_STATE; i++) {
for (i = 0; i < MAX_TEXTURES; ++i) {
while (i < MAX_TEXTURES) {
|| ((color_arg3 == WINED3DTA_TEXTURE) && (color_op == WINED3DTOP_MULTIPLYADD || color_op == WINED3DTOP_LERP))
|| ((alpha_arg3 == WINED3DTA_TEXTURE) && (alpha_op == WINED3DTOP_MULTIPLYADD || alpha_op == WINED3DTOP_LERP))) {
if ((color_op == WINED3DTOP_BUMPENVMAP || color_op == WINED3DTOP_BUMPENVMAPLUMINANCE) && i < MAX_TEXTURES - 1) {
int i, tex;
tex = 0;
++tex;
for (i = 0; i < MAX_FRAGMENT_SAMPLERS; ++i) {
if (i < MAX_TEXTURES) {
return TRUE;
if (!pshader_sampler_tokens) {
if (ps) {
for (i = 0; i < MAX_VERTEX_SAMPLERS; ++i) {
if (vshader_sampler_tokens[i]) {
while (start >= 0) {
--start;
--start;
if (ps) {
if (vs) {
static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
return WINED3D_OK;
return WINED3D_OK;
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
return WINED3DERR_INVALIDCALL;
return WINED3D_OK;
return WINED3DERR_INVALIDCALL;
for (i = 0; i < cnt; i++)
return WINED3D_OK;
return WINED3DERR_INVALIDCALL;
return WINED3D_OK;
return WINED3DERR_INVALIDCALL;
for (i = 0; i < cnt; i++)
return WINED3D_OK;
int *dstData,
return WINED3DERR_INVALIDCALL;
return WINED3D_OK;
UINT i;
if (srcData == NULL || start + count > GL_LIMITS(pshader_constantsF) || start > GL_LIMITS(pshader_constantsF))
return WINED3DERR_INVALIDCALL;
memcpy(&This->updateStateBlock->pixelShaderConstantF[start * 4], srcData, count * sizeof(float) * 4);
for (i = 0; i < count; i++)
constants_entry *ptr = LIST_ENTRY(list_head(&This->updateStateBlock->set_pconstantsF), constants_entry, entry);
return WINED3D_OK;
UINT i;
if (srcData == NULL || start + count > GL_LIMITS(pshader_constantsF) || start > GL_LIMITS(pshader_constantsF))
return WINED3DERR_INVALIDCALL;
memcpy(&This->updateStateBlock->pixelShaderConstantF[start * 4], srcData, count * sizeof(float) * 4);
for (i = 0; i < count; i++)
return WINED3D_OK;
float *dstData,
return WINED3DERR_INVALIDCALL;
return WINED3D_OK;
return WINED3DERR_INVALIDCALL;
ENTER_GL();
LEAVE_GL();
return E_OUTOFMEMORY;
const void *src;
if(src) {
unsigned char extrabytes = 0;
/* If the destination vertex buffer has D3DFVF_XYZ position(non-rhw), native d3d writes RHW position, where the RHW
* gets written into the 4 bytes after the Z position. In the case of a dest buffer that only has D3DFVF_XYZ data,
dest_conv_addr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwCount * get_flexible_vertex_size(DestFVF) + extrabytes);
if(!dest_conv_addr) {
if(!warned) {
dest_ptr = ((char *) dest->resource.allocatedMemory) + dwDestIndex * get_flexible_vertex_size(DestFVF);
&view_mat);
&proj_mat);
&world_mat);
unsigned int tex_index;
float x, y, z, rhw;
if( !doClip ||
x /= rhw;
y /= rhw;
z /= rhw;
x += rhw;
y += rhw;
( (float *) dest_ptr)[0] = x;
dest_ptr += sizeof(float);
if(dest_conv) {
( (float *) dest_conv)[0] = x * w;
dest_conv += sizeof(float);
const float *normal =
if(dest_conv) {
if(!color_d) {
if(!warned) {
if(dest_conv) {
if(dest_conv) {
if(!color_s) {
if(!warned) {
if(dest_conv) {
if(dest_conv) {
const float *tex_coord =
if(!tex_coord) {
if(dest_conv) {
copy_and_next(dest_conv, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
if(dest_conv) {
LEAVE_GL();
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexDeclaration* pVertexDecl, DWORD Flags) {
TRACE("(%p)->(%d,%d,%d,%p,%p,%d\n", This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags);
if(pVertexDecl) {
/* ProcessVertices reads from vertex buffers, which have to be assigned. DrawPrimitive and DrawPrimitiveUP
/* ProcessVertices can't convert FROM a vbo, and vertex buffers used to source into ProcessVertices are
* unlikely to ever be used for drawing. Release vbos in those buffers and fix up the strided structure
IWineD3DVertexBufferImpl *vb = (IWineD3DVertexBufferImpl *) This->stateBlock->streamSource[strided.u.s.type.streamNo]; \
strided.u.s.type.lpData = (BYTE *) ((unsigned long) strided.u.s.type.lpData + (unsigned long) vb->resource.allocatedMemory); \
ENTER_GL(); \
LEAVE_GL(); \
for(i = 0; i < WINED3DDP_MAXTEXCOORD; i++) {
return process_vertices_strided(This, DestIndex, VertexCount, &strided, (IWineD3DVertexBufferImpl *) pDestBuffer, Flags);
static HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
TRACE("(%p) : Stage=%d, Type=%s(%d), Value=%d\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
WARN("Attempting to set stage %u which is higher than the max stage %u, ignoring\n", Stage, MAX_TEXTURES - 1);
return WINED3D_OK;
return WINED3D_OK;
return WINED3D_OK;
This->StateTable[STATE_TEXTURESTAGE(0, Type)].representative == STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP)) {
return WINED3D_OK;
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
TRACE("(%p) : requesting Stage %d, Type %d getting %d\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
return WINED3DERR_INVALIDCALL;
return WINED3D_OK;
return WINED3D_OK;
/* The source arguments for color and alpha ops have different meanings when a NULL texture is bound,
/* More than one assignment? Doesn't matter, we only need one gl texture unit to use for uploading */
for(i = 0; i < MAX_COMBINED_SAMPLERS; i++) {
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
if (*ppTexture)
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, WINED3DBACKBUFFER_TYPE Type,
TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
return hr;
static HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
if(iSwapChain > 0) {
return hr;
return WINED3DERR_INVALIDCALL;
return E_OUTOFMEMORY;
for(i = 0; i < LIGHTMAP_SIZE; i++) {
return temp_result;
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
return WINED3DERR_INVALIDCALL;
for(i = 0; i < MAX_CONST_I; i++) {
for(i = 0; i < MAX_CONST_B; i++) {
for(i = 0; i < MAX_CONST_I; i++) {
for(i = 0; i < MAX_CONST_B; i++) {
for(i = 0; i < MAX_TEXTURES; i++) {
for(i = 0; i < MAX_COMBINED_SAMPLERS; i++){
/* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
return WINED3D_OK;
return WINED3DERR_INVALIDCALL;
return WINED3D_OK;
return WINED3DERR_INVALIDCALL;
glFlush();
return WINED3D_OK;
for(i = 0 ; i < swapchains ; i ++) {
return WINED3D_OK;
HRESULT IWineD3DDeviceImpl_ClearSurface(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *target, DWORD Count,
/* When we're clearing parts of the drawable, make sure that the target surface is well up to date in the
* drawable. After the clear we'll mark the drawable up to date, so we have to make sure that this is true
* If we're clearing the whole target there is no need to copy it into the drawable, it will be overwritten
* anyway. If we're not clearing the color buffer we don't have to copy either since we're not going to set
* the drawable up to date. We have to check all settings that limit the clear area though. Do not bother
ENTER_GL();
glClearDepth(Z);
for (i = 0; i < Count; i++) {
/* Dirtify the target surface for now. If the surface is locked regularly, and an up to date sysmem copy exists,
* it is most likely more efficient to perform a clear on the sysmem copy too instead of downloading it
LEAVE_GL();
if (SUCCEEDED(IWineD3DSurface_GetContainer((IWineD3DSurface *)target, &IID_IWineD3DSwapChain, (void **)&swapchain))) {
glFlush();
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST WINED3DRECT* pRects,
WARN("Clearing depth and/or stencil without a depth stencil buffer attached, returning WINED3DERR_INVALIDCALL\n");
return WINED3DERR_INVALIDCALL;
static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
return WINED3DERR_INVALIDCALL;
/* Account for the loading offset due to index buffers. Instead of reloading all sources correct it with the startvertex parameter */
drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
return WINED3D_OK;
/* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
if (!pIB) {
return WINED3DERR_INVALIDCALL;
return WINED3DERR_INVALIDCALL;
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
return WINED3DERR_INVALIDCALL;
/* stream zero settings set to null at end, as per the msdn. No need to mark dirty here, the app has to set
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
int idxStride;
TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
return WINED3DERR_INVALIDCALL;
drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex);
if(ib) {
/* No need to mark the stream source state dirty here. Either the app calls UP drawing again, or it has to call
return WINED3D_OK;
return WINED3D_OK;
drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* startvertexidx */, 0 /* numindices */, 0 /* startidx */, idxSize, pIndexData, 0 /* minindex */);
return WINED3D_OK;
static HRESULT IWineD3DDeviceImpl_UpdateVolume(IWineD3DDevice *iface, IWineD3DVolume *pSourceVolume, IWineD3DVolume *pDestinationVolume) {
/* This is a helper function for UpdateTexture, there is no public UpdateVolume method in d3d. Since it's
return hr;
return hr;
/* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
static HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
int i ,levels;
WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
This);
if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
WARN("(%p) : source (%p) and destination (%p) textures must have identical numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
switch (sourceType) {
case WINED3DRTYPE_TEXTURE:
for (i = 0 ; i < levels ; ++i) {
return hr;
case WINED3DRTYPE_CUBETEXTURE:
for (i = 0 ; i < levels ; ++i) {
for (faceType = WINED3DCUBEMAP_FACE_POSITIVE_X; faceType <= WINED3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture, faceType, i, &srcSurface);
hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
return hr;
for (i = 0 ; i < levels ; ++i) {
return hr;
return hr;
static HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
return hr;
DWORD i;
for(i = 0; i < MAX_COMBINED_SAMPLERS; i++) {
WARN("Sampler state %u has minfilter D3DTEXF_NONE, returning D3DERR_UNSUPPORTEDTEXTUREFILTER\n", i);
WARN("Sampler state %u has magfilter D3DTEXF_NONE, returning D3DERR_UNSUPPORTEDTEXTUREFILTER\n", i);
if(!texture) continue;
return E_FAIL;
return E_FAIL;
return E_FAIL;
return WINED3D_OK;
for (i = 0; i < MAX_COMBINED_SAMPLERS; i++) {
if (texture && (texture->resource.format == WINED3DFMT_P8 || texture->resource.format == WINED3DFMT_A8P8)) {
static HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
return WINED3DERR_INVALIDCALL;
palettes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->palettes, sizeof(PALETTEENTRY*) * NewSize);
if (!palettes) {
return E_OUTOFMEMORY;
return E_OUTOFMEMORY;
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
ERR("(%p) : (%u) Nonexistent palette. NumberOfPalettes %u\n", This, PaletteNumber, This->NumberOfPalettes);
return WINED3DERR_INVALIDCALL;
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
ERR("(%p) : (%u) Nonexistent palette. NumberOfPalettes %u\n", This, PaletteNumber, This->NumberOfPalettes);
return WINED3DERR_INVALIDCALL;
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
return WINED3DERR_INVALIDCALL;
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
if (!warned)
return WINED3D_OK;
if (!warned)
static HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
return hr;
if (!warned)
return WINED3D_OK;
if (!warned)
static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
int offset = 0;
int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
int sampler;
int bpp;
TRACE("(%p) : Source (%p) Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
return WINED3DERR_INVALIDCALL;
TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
ENTER_GL();
LEAVE_GL();
/* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
TRACE("(%p) glTexSubImage2D, level %d, left %d, top %d, width %d, height %d, fmt %#x, type %#x, memory %p+%#x\n",
ENTER_GL();
if(rowoffset != 0){
const unsigned char* data =((const unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
const unsigned char* data = ((const unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
LEAVE_GL();
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
struct list *e;
return WINED3DERR_INVALIDCALL;
if(Handle) {
if(!found) {
if(pRectPatchInfo) {
if(!Handle) {
return hr;
IWineD3DDevice_DrawPrimitiveStrided(iface, WINED3DPT_TRIANGLELIST, patch->numSegs[0] * patch->numSegs[1] * 2, &patch->strided);
if(!Handle) {
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
return WINED3D_OK;
struct list *e;
return WINED3D_OK;
return WINED3DERR_INVALIDCALL;
return swapchain;
return NULL;
static void color_fill_fbo(IWineD3DDevice *iface, IWineD3DSurface *surface, CONST WINED3DRECT *rect, WINED3DCOLOR color) {
if (swapchain) {
ENTER_GL();
ENTER_GL();
GL_EXTCALL(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0));
if (rect) {
if(!swapchain) {
LEAVE_GL();
return color;
switch(destfmt)
case WINED3DFMT_R5G6B5:
ret |= b;
return ret;
case WINED3DFMT_X1R5G5B5:
case WINED3DFMT_A1R5G5B5:
ret |= b << 0;
return ret;
case WINED3DFMT_A8:
case WINED3DFMT_X4R4G4B4:
case WINED3DFMT_A4R4G4B4:
ret |= b << 0;
return ret;
case WINED3DFMT_R3G3B2:
ret |= b << 0;
return ret;
case WINED3DFMT_X8B8G8R8:
case WINED3DFMT_A8B8G8R8:
ret |= r << 0;
return ret;
case WINED3DFMT_A2R10G10B10:
ret |= b << 0;
return ret;
case WINED3DFMT_A2B10G10R10:
ret |= r << 0;
return ret;
static HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST WINED3DRECT* pRect, WINED3DCOLOR color) {
if (surface->resource.pool != WINED3DPOOL_DEFAULT && surface->resource.pool != WINED3DPOOL_SYSTEMMEM) {
return WINED3DERR_INVALIDCALL;
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
return WINED3DERR_INVALIDCALL;
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface, IWineD3DSurface *Front, IWineD3DSurface *Back) {
return hr;
return WINED3DERR_INVALIDCALL;
return WINED3DERR_INVALIDCALL;
return E_OUTOFMEMORY;
ENTER_GL();
} else if (!Back) {
LEAVE_GL();
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
return WINED3D_OK;
return WINED3DERR_NOTFOUND;
IWineD3DSurface *dst_surface, WINED3DRECT *dst_rect, const WINED3DTEXTUREFILTERTYPE filter, BOOL flip)
TRACE("(%p) : src_surface %p, src_rect %p, dst_surface %p, dst_rect %p, filter %s (0x%08x), flip %u\n",
This, src_surface, src_rect, dst_surface, dst_rect, debug_d3dtexturefiltertype(filter), filter, flip);
switch (filter) {
case WINED3DTEXF_LINEAR:
case WINED3DTEXF_NONE:
case WINED3DTEXF_POINT:
if (src_swapchain) {
UINT h;
ENTER_GL();
ENTER_GL();
GL_EXTCALL(glFramebufferRenderbufferEXT(GL_READ_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0));
LEAVE_GL();
if (dst_swapchain) {
UINT h;
ENTER_GL();
if(!src_swapchain) {
ENTER_GL();
GL_EXTCALL(glFramebufferRenderbufferEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0));
if (flip) {
LEAVE_GL();
static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
return WINED3DERR_INVALIDCALL;
return WINED3DERR_INVALIDCALL;
if (pRenderTarget && !(((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
FIXME("(%p)Trying to set the render target to a surface(%p) that wasn't created with a usage of WINED3DUSAGE_RENDERTARGET\n",This ,pRenderTarget);
return WINED3DERR_INVALIDCALL;
return WINED3D_OK;
if(This->render_targets[RenderTargetIndex]) IWineD3DSurface_Release(This->render_targets[RenderTargetIndex]);
if(RenderTargetIndex == 0) {
viewport.X = 0;
viewport.Y = 0;
* SetViewport may catch NOP viewport changes, which would occur when switching between equally sized targets
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
TRACE("(%p) Swapping z-buffer. Old = %p, new = %p\n",This, This->stencilBufferTarget, pNewZStencil);
* A shared context implementation will share all buffers between all rendertargets (including swapchains),
* implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
if (((IWineD3DSwapChainImpl *)This->swapchains[0])->presentParms.Flags & WINED3DPRESENTFLAG_DISCARD_DEPTHSTENCIL
return hr;
ENTER_GL();
LEAVE_GL();
if(pCursorBitmap) {
return WINED3DERR_INVALIDCALL;
ERR("(%p) : Surface(%p) is %dx%d pixels, but screen res is %dx%d\n", This, pSur, pSur->currentDesc.Width, pSur->currentDesc.Height, This->ddraw_width, This->ddraw_height);
return WINED3DERR_INVALIDCALL;
const StaticPixelFormatDesc *tableEntry = getFormatDescEntry(WINED3DFMT_A8R8G8B8, &GLINFO_LOCATION, &glDesc);
for(i = 0; i < height; i++)
ENTER_GL();
LEAVE_GL();
return WINED3D_OK;
static void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
if (bShow)
return oldVisible;
/* TODO: Implement wrapping of the WndProc so that mimimize and maximize can be monitored and the states adjusted. */
case WINED3D_OK:
return WINED3D_OK;
case WINED3DERR_DEVICELOST:
LIST_FOR_EACH_ENTRY(resource, &This->resources, IWineD3DResourceImpl, resource.resource_list_entry) {
return WINED3DERR_DEVICENOTRESET;
return WINED3DERR_DEVICELOST;
return WINED3DERR_DRIVERINTERNALERROR;
return WINED3DERR_DRIVERINTERNALERROR;
return WINED3D_OK;
static void updateSurfaceDesc(IWineD3DSurfaceImpl *surface, const WINED3DPRESENT_PARAMETERS* pPresentationParameters)
ENTER_GL();
LEAVE_GL();
surface->resource.size = IWineD3DSurface_GetPitch((IWineD3DSurface *) surface) * surface->pow2Width;
/* INDRAWABLE is a sane place for implicit targets after the reset, INSYSMEM is more appropriate for depth stencils. */
return S_OK;
static BOOL is_display_mode_supported(IWineD3DDeviceImpl *This, const WINED3DPRESENT_PARAMETERS *pp)
for(i = 0; i < count; i++) {
memset(&m, 0, sizeof(m));
return TRUE;
return FALSE;
UINT i;
ENTER_GL();
LEAVE_GL();
ENTER_GL();
LEAVE_GL();
goto err_out;
goto err_out;
goto err_out;
return WINED3D_OK;
return hr;
static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
return hr;
return WINED3DERR_INVALIDCALL;
* TODO: Figure out how Reset influences resources in D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEMORY and D3DPOOL_MANAGED
* TODO: Figure out what happens to explicit swapchains, or if we have more than one implicit swapchain
TRACE("EnableAutoDepthStencil = %s\n", pPresentationParameters->EnableAutoDepthStencil ? "true" : "false");
swapchain->presentParms.FullScreen_RefreshRateInHz = pPresentationParameters->FullScreen_RefreshRateInHz;
WARN("Auto depth stencil enabled, but no auto depth stencil present, returning WINED3DERR_INVALIDCALL\n");
return WINED3DERR_INVALIDCALL;
if(pPresentationParameters->BackBufferWidth != 0 && pPresentationParameters->BackBufferHeight != 0 &&
UINT i;
vp.X = 0;
vp.Y = 0;
TRUE);
return hr;
static HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
if(!bEnableDialogs) {
return WINED3D_OK;
static HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
return WINED3D_OK;
static void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
static void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
* (e.g. a texture should release all held surfaces because telling the device that it's been released.)
list_add_head(&This->resources, &((IWineD3DResourceImpl *) resource)->resource.resource_list_entry);
static void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
int counter;
switch (type) {
case WINED3DRTYPE_SURFACE: {
IWineD3DSwapChainImpl *swapchain = This->swapchains ? (IWineD3DSwapChainImpl *) This->swapchains[0] : NULL;
/* Find a replacement surface for the currently active back buffer. The context manager does not do NULL
* surface of the implicit swpchain. If that is the same as the destroyed surface the device is destroyed
if(swapchain) {
case WINED3DRTYPE_TEXTURE:
case WINED3DRTYPE_CUBETEXTURE:
if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
case WINED3DRTYPE_VOLUME:
/* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
int streamNumber;
/* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
FINDOUT: should changes.streamSource[StreamNumber] be set ?
if (This->stateBlock != NULL ) { /* only happens if there is an error in the application, or on reset/release (because we don't manage internal tracking properly) */
case WINED3DRTYPE_INDEXBUFFER:
/* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
static HRESULT WINAPI IWineD3DDeviceImpl_EnumResources(IWineD3DDevice *iface, D3DCB_ENUMRESOURCES pCallback, void *pData) {
LIST_FOR_EACH_ENTRY_SAFE(resource, cursor, &This->resources, IWineD3DResourceImpl, resource.resource_list_entry) {
return WINED3D_OK;
UINT i;
if(!rep) return;