Пример #1
0
/*****************************************************************************
 * IDirect3DViewport3::Release
 *
 * Reduces the refcount. If it falls to 0, the interface is released
 *
 * Returns:
 *  The new refcount
 *
 *****************************************************************************/
static ULONG WINAPI
IDirect3DViewportImpl_Release(IDirect3DViewport3 *iface)
{
    ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
    ULONG ref = InterlockedDecrement(&This->ref);

    TRACE("(%p)->() decrementing from %u.\n", This, ref + 1);

    if (!ref) {
        HeapFree(GetProcessHeap(), 0, This);
	return 0;
    }
    return ref;
}
Пример #2
0
/*****************************************************************************
 * IDirect3DVertexBuffer7::ProcessVerticesStrided
 *
 * This method processes untransformed strided vertices into a processed
 * or optimized vertex buffer.
 *
 * For more details on the parameters, see
 * IDirect3DVertexBuffer7::ProcessVertices
 *
 * Params:
 *  VertexOp: Operations to perform
 *  DestIndex: Destination index to write the vertices to
 *  Count: Number of input vertices
 *  StrideData: Array containing the input vertices
 *  VertexTypeDesc: Vertex Description or source index?????????
 *  D3DDevice: IDirect3DDevice7 to use for processing
 *  Flags: Can be D3DPV_DONOTCOPYDATA to avoid copying unmodified vertices
 *
 * Returns
 *  D3D_OK on success, or DDERR_*
 *
 *****************************************************************************/
static HRESULT WINAPI
IDirect3DVertexBufferImpl_ProcessVerticesStrided(IDirect3DVertexBuffer7 *iface,
                                                 DWORD VertexOp,
                                                 DWORD DestIndex,
                                                 DWORD Count,
                                                 D3DDRAWPRIMITIVESTRIDEDDATA *StrideData,
                                                 DWORD VertexTypeDesc,
                                                 IDirect3DDevice7 *D3DDevice,
                                                 DWORD Flags)
{
    ICOM_THIS_FROM(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, iface);
    IDirect3DDeviceImpl *D3D = ICOM_OBJECT(IDirect3DDeviceImpl, IDirect3DDevice7, D3DDevice);
    FIXME("(%p)->(%08x,%08x,%08x,%p,%08x,%p,%08x): stub!\n", This, VertexOp, DestIndex, Count, StrideData, VertexTypeDesc, D3D, Flags);
    return DD_OK;
}
Пример #3
0
/*****************************************************************************
 * IDirect3DVertexBuffer7::Release
 *
 * Release for Vertex Buffers
 *
 * Returns:
 *  The new refcount
 *
 *****************************************************************************/
static ULONG WINAPI
IDirect3DVertexBufferImpl_Release(IDirect3DVertexBuffer7 *iface)
{
    ICOM_THIS_FROM(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, iface);
    ULONG ref = InterlockedDecrement(&This->ref);

    TRACE("(%p)->() decrementing from %u.\n", This, ref + 1);

    if (ref == 0)
    {
        IWineD3DVertexBuffer *curVB = NULL;
        UINT offset, stride;

        EnterCriticalSection(&ddraw_cs);
        /* D3D7 Vertex buffers don't stay bound in the device, they are passed as a parameter
         * to drawPrimitiveVB. DrawPrimitiveVB sets them as the stream source in wined3d,
         * and they should get unset there before they are destroyed
         */
        IWineD3DDevice_GetStreamSource(This->ddraw->wineD3DDevice,
                                       0 /* Stream number */,
                                       &curVB,
                                       &offset,
                                       &stride);
        if(curVB == This->wineD3DVertexBuffer)
        {
            IWineD3DDevice_SetStreamSource(This->ddraw->wineD3DDevice,
                                        0 /* Steam number */,
                                        NULL /* stream data */,
                                        0 /* Offset */,
                                        0 /* stride */);
        }
        if(curVB)
        {
            IWineD3DVertexBuffer_Release(curVB); /* For the GetStreamSource */
        }

        IWineD3DVertexDeclaration_Release(This->wineD3DVertexDeclaration);
        IWineD3DVertexBuffer_Release(This->wineD3DVertexBuffer);
        LeaveCriticalSection(&ddraw_cs);
        HeapFree(GetProcessHeap(), 0, This);

        return 0;
    }
    return ref;
}
Пример #4
0
/*****************************************************************************
 * IDirect3DVertexBuffer7::Optimize
 *
 * Converts an unoptimized vertex buffer into an optimized buffer
 *
 * Params:
 *  D3DDevice: Device for which this buffer is optimized
 *  Flags: Not used, should be set to 0
 *
 * Returns
 *  D3D_OK, because it's a stub
 *
 *****************************************************************************/
static HRESULT WINAPI
IDirect3DVertexBufferImpl_Optimize(IDirect3DVertexBuffer7 *iface,
                                   IDirect3DDevice7 *D3DDevice,
                                   DWORD Flags)
{
    ICOM_THIS_FROM(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, iface);
    IDirect3DDeviceImpl *D3D = ICOM_OBJECT(IDirect3DDeviceImpl, IDirect3DDevice7, D3DDevice);
    FIXME("(%p)->(%p,%08x): stub!\n", This, D3D, Flags);

    /* We could forward this call to WineD3D and take advantage
     * of it once we use OpenGL vertex buffers
     */
    EnterCriticalSection(&ddraw_cs);
    This->Caps |= D3DVBCAPS_OPTIMIZED;
    LeaveCriticalSection(&ddraw_cs);

    return DD_OK;
}
Пример #5
0
static HRESULT WINAPI
IDirect3DLightImpl_SetLight(IDirect3DLight *iface,
                            D3DLIGHT *lpLight)
{
    ICOM_THIS_FROM(IDirect3DLightImpl, IDirect3DLight, iface);
    LPD3DLIGHT7 light7 = &(This->light7);
    TRACE("(%p)->(%p)\n", This, lpLight);
    if (TRACE_ON(d3d7)) {
        TRACE("  Light definition :\n");
	dump_light((LPD3DLIGHT2) lpLight);
    }

    if ( (lpLight->dltType == 0) || (lpLight->dltType > D3DLIGHT_PARALLELPOINT) )
         return DDERR_INVALIDPARAMS;
    
    if ( lpLight->dltType == D3DLIGHT_PARALLELPOINT )
	 FIXME("D3DLIGHT_PARALLELPOINT no supported\n");
    
    /* Translate D3DLIGH2 structure to D3DLIGHT7 */
    light7->dltType        = lpLight->dltType;
    light7->dcvDiffuse     = lpLight->dcvColor;
    if ((((LPD3DLIGHT2)lpLight)->dwFlags & D3DLIGHT_NO_SPECULAR) != 0)	    
      light7->dcvSpecular    = lpLight->dcvColor;
    else
      light7->dcvSpecular    = *(const D3DCOLORVALUE*)zero_value;	    
    light7->dcvAmbient     = lpLight->dcvColor;
    light7->dvPosition     = lpLight->dvPosition;
    light7->dvDirection    = lpLight->dvDirection;
    light7->dvRange        = lpLight->dvRange;
    light7->dvFalloff      = lpLight->dvFalloff;
    light7->dvAttenuation0 = lpLight->dvAttenuation0;
    light7->dvAttenuation1 = lpLight->dvAttenuation1;
    light7->dvAttenuation2 = lpLight->dvAttenuation2;
    light7->dvTheta        = lpLight->dvTheta;
    light7->dvPhi          = lpLight->dvPhi;

    memcpy(&This->light, lpLight, lpLight->dwSize);
    if ((This->light.dwFlags & D3DLIGHT_ACTIVE) != 0) {
        This->update(This);        
    }
    return D3D_OK;
}
Пример #6
0
/*****************************************************************************
 * IDirect3DViewport3::AddLight
 *
 * Adds an light to the viewport
 *
 * Params:
 *  lpDirect3DLight: Interface of the light to add
 *
 * Returns:
 *  D3D_OK on success
 *  DDERR_INVALIDPARAMS if Direct3DLight is NULL
 *  DDERR_INVALIDPARAMS if there are 8 lights or more
 *
 *****************************************************************************/
static HRESULT WINAPI
IDirect3DViewportImpl_AddLight(IDirect3DViewport3 *iface,
                               IDirect3DLight *lpDirect3DLight)
{
    ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
    IDirect3DLightImpl *lpDirect3DLightImpl = ICOM_OBJECT(IDirect3DLightImpl, IDirect3DLight, lpDirect3DLight);
    DWORD i = 0;
    DWORD map = This->map_lights;
    
    TRACE("(%p)->(%p)\n", This, lpDirect3DLight);

    EnterCriticalSection(&ddraw_cs);
    if (This->num_lights >= 8)
    {
        LeaveCriticalSection(&ddraw_cs);
        return DDERR_INVALIDPARAMS;
    }

    /* Find a light number and update both light and viewports objects accordingly */
    while(map&1) {
        map>>=1;
	i++;
    }
    lpDirect3DLightImpl->dwLightIndex = i;
    This->num_lights++;
    This->map_lights |= 1<<i;

    /* Add the light in the 'linked' chain */
    lpDirect3DLightImpl->next = This->lights;
    This->lights = lpDirect3DLightImpl;

    /* Attach the light to the viewport */
    lpDirect3DLightImpl->active_viewport = This;
    
    /* If active, activate the light */
    if (This->active_device != NULL) {
        lpDirect3DLightImpl->activate(lpDirect3DLightImpl);
    }

    LeaveCriticalSection(&ddraw_cs);
    return D3D_OK;
}
Пример #7
0
/*****************************************************************************
 * IDirect3DViewport3::Clear2
 *
 * Another clearing method
 *
 * Params:
 *  Count: Number of rectangles to clear
 *  Rects: Rectangle array to clear
 *  Flags: Some flags :)
 *  Color: Color to fill the render target with
 *  Z: Value to fill the depth buffer with
 *  Stencil: Value to fill the stencil bits with
 *
 * Returns:
 *
 *****************************************************************************/
static HRESULT WINAPI
IDirect3DViewportImpl_Clear2(IDirect3DViewport3 *iface,
                             DWORD dwCount,
                             LPD3DRECT lpRects,
                             DWORD dwFlags,
                             DWORD dwColor,
                             D3DVALUE dvZ,
                             DWORD dwStencil)
{
    ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
    HRESULT hr;
    LPDIRECT3DVIEWPORT3 current_viewport;
    TRACE("(%p)->(%08x,%p,%08x,%08x,%f,%08x)\n", This, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);

    EnterCriticalSection(&ddraw_cs);
    if (This->active_device == NULL) {
        ERR(" Trying to clear a viewport not attached to a device !\n");
        LeaveCriticalSection(&ddraw_cs);
        return D3DERR_VIEWPORTHASNODEVICE;
    }
    /* Need to temporarily activate viewport to clear it. Previously active one will be restored
        afterwards. */
    This->activate(This, TRUE);

    hr = IDirect3DDevice7_Clear(ICOM_INTERFACE(This->active_device, IDirect3DDevice7),
                                dwCount,
                                lpRects,
                                dwFlags,
                                dwColor,
                                dvZ,
                                dwStencil);
    IDirect3DDevice3_GetCurrentViewport(ICOM_INTERFACE(This->active_device, IDirect3DDevice3), &current_viewport);
    if(current_viewport) {
        IDirect3DViewportImpl *vp = ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, current_viewport);
        vp->activate(vp, TRUE);
        IDirect3DViewport3_Release(current_viewport);
    }
    LeaveCriticalSection(&ddraw_cs);
    return hr;
}
Пример #8
0
/*****************************************************************************
 * IDirect3DViewport3::SetBackground
 *
 * Sets tje background material
 *
 * Params:
 *  hMat: Handle from a IDirect3DMaterial interface
 *
 * Returns:
 *  D3D_OK on success
 *
 *****************************************************************************/
static HRESULT WINAPI
IDirect3DViewportImpl_SetBackground(IDirect3DViewport3 *iface,
                                    D3DMATERIALHANDLE hMat)
{
    ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
    TRACE("(%p)->(%d)\n", This, hMat);

    EnterCriticalSection(&ddraw_cs);
    if(hMat && hMat > This->ddraw->d3ddevice->numHandles)
    {
        WARN("Specified Handle %d out of range\n", hMat);
        LeaveCriticalSection(&ddraw_cs);
        return DDERR_INVALIDPARAMS;
    }
    else if(hMat && This->ddraw->d3ddevice->Handles[hMat - 1].type != DDrawHandle_Material)
    {
        WARN("Handle %d is not a material handle\n", hMat);
        LeaveCriticalSection(&ddraw_cs);
        return DDERR_INVALIDPARAMS;
    }

    if(hMat)
    {
        This->background = This->ddraw->d3ddevice->Handles[hMat - 1].ptr;
        TRACE(" setting background color : %f %f %f %f\n",
              This->background->mat.u.diffuse.u1.r,
              This->background->mat.u.diffuse.u2.g,
              This->background->mat.u.diffuse.u3.b,
              This->background->mat.u.diffuse.u4.a);
    }
    else
    {
        This->background = NULL;
        TRACE("Setting background to NULL\n");
    }

    LeaveCriticalSection(&ddraw_cs);
    return D3D_OK;
}
Пример #9
0
/*****************************************************************************
 * IDirect3DViewport3::QueryInterface
 *
 * A normal QueryInterface. Can query all interface versions and the
 * IUnknown interface. The VTables of the different versions
 * are equal
 *
 * Params:
 *  refiid: Interface id queried for
 *  obj: Address to write the interface pointer to
 *
 * Returns:
 *  S_OK on success.
 *  E_NOINTERFACE if the requested interface wasn't found
 *
 *****************************************************************************/
static HRESULT WINAPI
IDirect3DViewportImpl_QueryInterface(IDirect3DViewport3 *iface,
                                     REFIID riid,
                                     void **obp)
{
    ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
    TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), obp);

    *obp = NULL;

    if ( IsEqualGUID(&IID_IUnknown,  riid) ||
	 IsEqualGUID(&IID_IDirect3DViewport, riid) ||
	 IsEqualGUID(&IID_IDirect3DViewport2, riid) ||
	 IsEqualGUID(&IID_IDirect3DViewport3, riid) ) {
        IDirect3DViewport3_AddRef(ICOM_INTERFACE(This, IDirect3DViewport3));
        *obp = ICOM_INTERFACE(This, IDirect3DViewport3);
	TRACE("  Creating IDirect3DViewport1/2/3 interface %p\n", *obp);
	return S_OK;
    }
    FIXME("(%p): interface for IID %s NOT found!\n", This, debugstr_guid(riid));
    return E_NOINTERFACE;
}
Пример #10
0
/*****************************************************************************
 * IDirect3DViewport3::SetViewport
 *
 * Sets the viewport information for this interface
 *
 * Params:
 *  lpData: Viewport to set
 *
 * Returns:
 *  D3D_OK on success
 *  DDERR_INVALIDPARAMS if Data is NULL
 *
 *****************************************************************************/
static HRESULT WINAPI
IDirect3DViewportImpl_SetViewport(IDirect3DViewport3 *iface,
                                  D3DVIEWPORT *lpData)
{
    ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
    LPDIRECT3DVIEWPORT3 current_viewport;
    TRACE("(%p/%p)->(%p)\n", This, iface, lpData);

    if (TRACE_ON(d3d7)) {
        TRACE("  getting D3DVIEWPORT :\n");
	_dump_D3DVIEWPORT(lpData);
    }

    EnterCriticalSection(&ddraw_cs);
    This->use_vp2 = 0;
    memset(&(This->viewports.vp1), 0, sizeof(This->viewports.vp1));
    memcpy(&(This->viewports.vp1), lpData, lpData->dwSize);

    /* Tests on two games show that these values are never used properly so override
       them with proper ones :-)
    */
    This->viewports.vp1.dvMinZ = 0.0;
    This->viewports.vp1.dvMaxZ = 1.0;

    if (This->active_device) {
        IDirect3DDevice3_GetCurrentViewport(ICOM_INTERFACE(This->active_device, IDirect3DDevice3), &current_viewport);
        if (current_viewport) {
            if (ICOM_OBJECT(IDirect3DViewportImpl, IDirect3DViewport3, current_viewport) == This)
                This->activate(This, FALSE);
            IDirect3DViewport3_Release(current_viewport);
        }
    }
    LeaveCriticalSection(&ddraw_cs);

    return DD_OK;
}
Пример #11
0
/*****************************************************************************
 * IDirect3DTexture2::Load
 *
 * Loads a texture created with the DDSCAPS_ALLOCONLOAD
 *
 * This function isn't relayed to WineD3D because the whole interface is
 * implemented in DDraw only. For speed improvements a implementation which
 * takes OpenGL more into account could be placed into WineD3D.
 *
 * Params:
 *  D3DTexture2: Address of the texture to load
 *
 * Returns:
 *  D3D_OK on success
 *  D3DERR_TEXTURE_LOAD_FAILED.
 *
 *****************************************************************************/
static HRESULT WINAPI
IDirect3DTextureImpl_Load(IDirect3DTexture2 *iface,
                          IDirect3DTexture2 *D3DTexture2)
{
    ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture2, iface);
    IDirectDrawSurfaceImpl *src_ptr = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirect3DTexture2, D3DTexture2);
    IWineD3DPalette *wine_pal, *wine_pal_src;
    IDirectDrawPalette *pal = NULL, *pal_src = NULL;
    IDirectDrawPaletteImpl *pal_impl, *pal_impl_src;
    HRESULT ret_value = D3D_OK;

    TRACE("(%p)->(%p)\n", This, src_ptr);

    if (((src_ptr->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) != (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)) ||
        (src_ptr->surface_desc.u2.dwMipMapCount != This->surface_desc.u2.dwMipMapCount))
    {
        ERR("Trying to load surfaces with different mip-map counts !\n");
    }

    while(1)
    {
        DDSURFACEDESC *src_d, *dst_d;

        TRACE(" copying surface %p to surface %p (mipmap level %d)\n", src_ptr, This, src_ptr->mipmap_level);

        if ( This->surface_desc.ddsCaps.dwCaps & DDSCAPS_ALLOCONLOAD )
            /* If the surface is not allocated and its location is not yet specified,
              force it to video memory */ 
            if ( !(This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_SYSTEMMEMORY|DDSCAPS_VIDEOMEMORY)) )
                This->surface_desc.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;

        /* Suppress the ALLOCONLOAD flag */
        This->surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_ALLOCONLOAD;

        /* Get the palettes */
        ret_value = IWineD3DSurface_GetPalette(This->WineD3DSurface, &wine_pal);
        if( ret_value != D3D_OK)
        {
            ERR("IWineD3DSurface::GetPalette failed! This is unexpected\n");
            return D3DERR_TEXTURE_LOAD_FAILED;
        }
        if(wine_pal)
        {
            ret_value = IWineD3DPalette_GetParent(wine_pal, (IUnknown **) &pal);
            if(ret_value != D3D_OK)
            {
                ERR("IWineD3DPalette::GetParent failed! This is unexpected\n");
                return D3DERR_TEXTURE_LOAD_FAILED;
            }
            pal_impl = ICOM_OBJECT(IDirectDrawPaletteImpl, IDirectDrawPalette, pal);
        }
        else
        {
          pal_impl = NULL;
        }

        ret_value = IWineD3DSurface_GetPalette(src_ptr->WineD3DSurface, &wine_pal_src);
        if( ret_value != D3D_OK)
        {
            ERR("IWineD3DSurface::GetPalette failed! This is unexpected\n");
            return D3DERR_TEXTURE_LOAD_FAILED;
        }
        if(wine_pal_src)
        {
            ret_value = IWineD3DPalette_GetParent(wine_pal_src, (IUnknown **) &pal_src);
            if(ret_value != D3D_OK)
            {
                ERR("IWineD3DPalette::GetParent failed! This is unexpected\n");
                return D3DERR_TEXTURE_LOAD_FAILED;
            }
            pal_impl_src = ICOM_OBJECT(IDirectDrawPaletteImpl, IDirectDrawPalette, pal_src);
        }
        else
        {
            pal_impl_src = NULL;
        }

        /* After seeing some logs, not sure at all about this... */
        if (pal_impl == NULL)
        {
            IWineD3DSurface_SetPalette(This->WineD3DSurface, wine_pal);
            if (pal_impl_src != NULL) IDirectDrawPalette_AddRef(ICOM_INTERFACE(pal_impl_src, IDirectDrawPalette));
        }
        else
        {
            if (pal_impl_src != NULL)
            {
                PALETTEENTRY palent[256];
                IDirectDrawPalette_GetEntries(ICOM_INTERFACE(pal_impl_src, IDirectDrawPalette),
                                              0, 0, 256, palent);
                IDirectDrawPalette_SetEntries(ICOM_INTERFACE(pal_impl, IDirectDrawPalette),
                                              0, 0, 256, palent);
            }
        }

        /* Copy one surface on the other */
        dst_d = (DDSURFACEDESC *)&(This->surface_desc);
        src_d = (DDSURFACEDESC *)&(src_ptr->surface_desc);

        if ((src_d->dwWidth != dst_d->dwWidth) || (src_d->dwHeight != dst_d->dwHeight))
        {
            /* Should also check for same pixel format, u1.lPitch, ... */
            ERR("Error in surface sizes\n");
            return D3DERR_TEXTURE_LOAD_FAILED;
        }
        else
        {
            WINED3DLOCKED_RECT pSrcRect, pDstRect;

            /* LPDIRECT3DDEVICE2 d3dd = (LPDIRECT3DDEVICE2) This->D3Ddevice; */
            /* I should put a macro for the calculus of bpp */

            /* Copy also the ColorKeying stuff */
            if (src_d->dwFlags & DDSD_CKSRCBLT)
            {
                dst_d->dwFlags |= DDSD_CKSRCBLT;
                dst_d->ddckCKSrcBlt.dwColorSpaceLowValue = src_d->ddckCKSrcBlt.dwColorSpaceLowValue;
                dst_d->ddckCKSrcBlt.dwColorSpaceHighValue = src_d->ddckCKSrcBlt.dwColorSpaceHighValue;
            }

            /* Copy the main memory texture into the surface that corresponds to the OpenGL
              texture object. */

            ret_value = IWineD3DSurface_LockRect(src_ptr->WineD3DSurface, &pSrcRect, NULL, 0);
            if(ret_value != D3D_OK)
            {
                ERR(" (%p) Locking the source surface failed\n", This);
                return D3DERR_TEXTURE_LOAD_FAILED;
            }

            ret_value = IWineD3DSurface_LockRect(This->WineD3DSurface, &pDstRect, NULL, 0);
            if(ret_value != D3D_OK)
            {
                ERR(" (%p) Locking the destination surface failed\n", This);
                IWineD3DSurface_UnlockRect(src_ptr->WineD3DSurface);
                return D3DERR_TEXTURE_LOAD_FAILED;
            }

            if (This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC)
                memcpy(pDstRect.pBits, pSrcRect.pBits, src_ptr->surface_desc.u1.dwLinearSize);
            else
                memcpy(pDstRect.pBits, pSrcRect.pBits, pSrcRect.Pitch * src_d->dwHeight);

            IWineD3DSurface_UnlockRect(src_ptr->WineD3DSurface);
            IWineD3DSurface_UnlockRect(This->WineD3DSurface);
        }

        if (src_ptr->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
        {
            src_ptr = get_sub_mimaplevel(src_ptr);
        }
        else
        {
            src_ptr = NULL;
        }
        if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
        {
            This = get_sub_mimaplevel(This);
        }
        else
        {
            This = NULL;
        }

        if ((src_ptr == NULL) || (This == NULL))
        {
            if (src_ptr != This)
            {
                ERR(" Loading surface with different mipmap structure !!!\n");
            }
            break;
        }
    }

    return ret_value;
}
Пример #12
0
/*****************************************************************************
 * IDirect3DVertexBuffer7::ProcessVertices
 *
 * Processes untransformed Vertices into a transformed or optimized vertex
 * buffer. It can also perform other operations, such as lighting or clipping
 *
 * Params
 *  VertexOp: Operation(s) to perform: D3DVOP_CLIP, _EXTENTS, _LIGHT, _TRANSFORM
 *  DestIndex: Index in the destination buffer(This), where the vertices are
 *             placed
 *  Count: Number of Vertices in the Source buffer to process
 *  SrcBuffer: Source vertex buffer
 *  SrcIndex: Index of the first vertex in the src buffer to process
 *  D3DDevice: Device to use for transformation
 *  Flags: 0 for default, D3DPV_DONOTCOPYDATA to prevent copying
 *         unchaned vertices
 *
 * Returns:
 *  D3D_OK on success
 *  DDERR_INVALIDPARAMS If D3DVOP_TRANSFORM wasn't passed
 *
 *****************************************************************************/
static HRESULT WINAPI
IDirect3DVertexBufferImpl_ProcessVertices(IDirect3DVertexBuffer7 *iface,
                                          DWORD VertexOp,
                                          DWORD DestIndex,
                                          DWORD Count,
                                          IDirect3DVertexBuffer7 *SrcBuffer,
                                          DWORD SrcIndex,
                                          IDirect3DDevice7 *D3DDevice,
                                          DWORD Flags)
{
    ICOM_THIS_FROM(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, iface);
    IDirect3DVertexBufferImpl *Src = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, SrcBuffer);
    IDirect3DDeviceImpl *D3D = ICOM_OBJECT(IDirect3DDeviceImpl, IDirect3DDevice7, D3DDevice);
    BOOL oldClip, doClip;
    HRESULT hr;
    WINED3DVERTEXBUFFER_DESC Desc;

    TRACE("(%p)->(%08x,%d,%d,%p,%d,%p,%08x)\n", This, VertexOp, DestIndex, Count, Src, SrcIndex, D3D, Flags);

    /* Vertex operations:
     * D3DVOP_CLIP: Clips vertices outside the viewing frustrum. Needs clipping information
     * in the vertex buffer (Buffer may not be created with D3DVBCAPS_DONOTCLIP)
     * D3DVOP_EXTENTS: Causes the screen extents to be updated when rendering the vertices
     * D3DVOP_LIGHT: Lights the vertices
     * D3DVOP_TRANSFORM: Transform the vertices. This flag is necessary
     *
     * WineD3D only transforms and clips the vertices by now, so EXTENTS and LIGHT
     * are not implemented. Clipping is disabled ATM, because of unsure conditions.
     */
    if( !(VertexOp & D3DVOP_TRANSFORM) ) return DDERR_INVALIDPARAMS;

    EnterCriticalSection(&ddraw_cs);
    /* WineD3D doesn't know d3d7 vertex operation, it uses
     * render states instead. Set the render states according to
     * the vertex ops
     */
    doClip = VertexOp & D3DVOP_CLIP ? TRUE : FALSE;
    IWineD3DDevice_GetRenderState(D3D->wineD3DDevice,
                                  WINED3DRS_CLIPPING,
                                  (DWORD *) &oldClip);
    if(doClip != oldClip)
    {
        IWineD3DDevice_SetRenderState(D3D->wineD3DDevice,
                                      WINED3DRS_CLIPPING,
                                      doClip);
    }

    IWineD3DVertexBuffer_GetDesc(Src->wineD3DVertexBuffer,
                                 &Desc);
    IWineD3DDevice_SetStreamSource(D3D->wineD3DDevice,
                                   0, /* Stream No */
                                   Src->wineD3DVertexBuffer,
                                   0, /* Offset */
                                   get_flexible_vertex_size(Desc.FVF));
    IWineD3DDevice_SetVertexDeclaration(D3D->wineD3DDevice,
                                        Src->wineD3DVertexDeclaration);
    hr = IWineD3DDevice_ProcessVertices(D3D->wineD3DDevice,
                                        SrcIndex,
                                        DestIndex,
                                        Count,
                                        This->wineD3DVertexBuffer,
                                        NULL /* Output vdecl */,
                                        Flags);

    /* Restore the states if needed */
    if(doClip != oldClip)
        IWineD3DDevice_SetRenderState(D3D->wineD3DDevice,
                                      WINED3DRS_CLIPPING,
                                      oldClip);
    LeaveCriticalSection(&ddraw_cs);
    return hr;
}
Пример #13
0
/*****************************************************************************
 * IDirect3DViewport3::TransformVertices
 *
 * Transforms vertices by the transformation matrix.
 *
 * This function is pretty similar to IDirect3DVertexBuffer7::ProcessVertices,
 * so it's tempting to forward it to there. However, there are some
 * tiny differences. First, the lpOffscreen flag that is reported back,
 * then there is the homogeneous vertex that is generated. Also there's a lack
 * of FVFs, but still a custom stride. Last, the d3d1 - d3d3 viewport has some
 * settings (scale) that d3d7 and wined3d do not have. All in all wrapping to
 * ProcessVertices doesn't pay of in terms of wrapper code needed and code
 * reused.
 *
 * Params:
 *  dwVertexCount: The number of vertices to be transformed
 *  lpData: Pointer to the vertex data
 *  dwFlags: D3DTRANSFORM_CLIPPED or D3DTRANSFORM_UNCLIPPED
 *  lpOffScreen: Set to the clipping plane clipping the vertex, if only one
 *               vertex is transformed and clipping is on. 0 otherwise
 *
 * Returns:
 *  D3D_OK on success
 *  D3DERR_VIEWPORTHASNODEVICE if the viewport is not assigned to a device
 *  DDERR_INVALIDPARAMS if no clipping flag is specified
 *
 *****************************************************************************/
static HRESULT WINAPI
IDirect3DViewportImpl_TransformVertices(IDirect3DViewport3 *iface,
                                        DWORD dwVertexCount,
                                        D3DTRANSFORMDATA *lpData,
                                        DWORD dwFlags,
                                        DWORD *lpOffScreen)
{
    ICOM_THIS_FROM(IDirect3DViewportImpl, IDirect3DViewport3, iface);
    D3DMATRIX view_mat, world_mat, proj_mat, mat;
    float *in;
    float *out;
    float x, y, z, w;
    unsigned int i;
    D3DVIEWPORT vp = This->viewports.vp1;
    D3DHVERTEX *outH;
    TRACE("(%p)->(%08x,%p,%08x,%p)\n", This, dwVertexCount, lpData, dwFlags, lpOffScreen);

    /* Tests on windows show that Windows crashes when this occurs,
     * so don't return the (intuitive) return value
    if(!This->active_device)
    {
        WARN("No device active, returning D3DERR_VIEWPORTHASNODEVICE\n");
        return D3DERR_VIEWPORTHASNODEVICE;
    }
     */

    if(!(dwFlags & (D3DTRANSFORM_UNCLIPPED | D3DTRANSFORM_CLIPPED)))
    {
        WARN("No clipping flag passed, returning DDERR_INVALIDPARAMS\n");
        return DDERR_INVALIDPARAMS;
    }


    EnterCriticalSection(&ddraw_cs);
    IWineD3DDevice_GetTransform(This->active_device->wineD3DDevice,
                                D3DTRANSFORMSTATE_VIEW,
                                (WINED3DMATRIX*) &view_mat);

    IWineD3DDevice_GetTransform(This->active_device->wineD3DDevice,
                                D3DTRANSFORMSTATE_PROJECTION,
                                (WINED3DMATRIX*) &proj_mat);

    IWineD3DDevice_GetTransform(This->active_device->wineD3DDevice,
                                WINED3DTS_WORLDMATRIX(0),
                                (WINED3DMATRIX*) &world_mat);
    multiply_matrix(&mat,&view_mat,&world_mat);
    multiply_matrix(&mat,&proj_mat,&mat);

    in = lpData->lpIn;
    out = lpData->lpOut;
    outH = lpData->lpHOut;
    for(i = 0; i < dwVertexCount; i++)
    {
        x = (in[0] * mat._11) + (in[1] * mat._21) + (in[2] * mat._31) + (1.0 * mat._41);
        y = (in[0] * mat._12) + (in[1] * mat._22) + (in[2] * mat._32) + (1.0 * mat._42);
        z = (in[0] * mat._13) + (in[1] * mat._23) + (in[2] * mat._33) + (1.0 * mat._43);
        w = (in[0] * mat._14) + (in[1] * mat._24) + (in[2] * mat._34) + (1.0 * mat._44);

        if(dwFlags & D3DTRANSFORM_CLIPPED)
        {
            /* If clipping is enabled, Windows assumes that outH is
             * a valid pointer
             */
            outH[i].u1.hx = x; outH[i].u2.hy = y; outH[i].u3.hz = z;

            outH[i].dwFlags = 0;
            if(x * vp.dvScaleX > ((float) vp.dwWidth * 0.5))
                outH[i].dwFlags |= D3DCLIP_RIGHT;
            if(x * vp.dvScaleX <= -((float) vp.dwWidth) * 0.5)
                outH[i].dwFlags |= D3DCLIP_LEFT;
            if(y * vp.dvScaleY > ((float) vp.dwHeight * 0.5))
                outH[i].dwFlags |= D3DCLIP_TOP;
            if(y * vp.dvScaleY <= -((float) vp.dwHeight) * 0.5)
                outH[i].dwFlags |= D3DCLIP_BOTTOM;
            if(z < 0.0)
                outH[i].dwFlags |= D3DCLIP_FRONT;
            if(z > 1.0)
                outH[i].dwFlags |= D3DCLIP_BACK;

            if(outH[i].dwFlags)
            {
                /* Looks like native just drops the vertex, leaves whatever data
                 * it has in the output buffer and goes on with the next vertex.
                 * The exact scheme hasn't been figured out yet, but windows
                 * definitely writes something there.
                 */
                out[0] = x;
                out[1] = y;
                out[2] = z;
                out[3] = w;
                in = (float *) ((char *) in + lpData->dwInSize);
                out = (float *) ((char *) out + lpData->dwOutSize);
                continue;
            }
        }

        w = 1 / w;
        x *= w; y *= w; z *= w;

        out[0] = vp.dwWidth / 2 + vp.dwX + x * vp.dvScaleX;
        out[1] = vp.dwHeight / 2 + vp.dwY - y * vp.dvScaleY;
        out[2] = z;
        out[3] = w;
        in = (float *) ((char *) in + lpData->dwInSize);
        out = (float *) ((char *) out + lpData->dwOutSize);
    }

    /* According to the d3d test, the offscreen flag is set only
     * if exactly one vertex is transformed. Its not documented,
     * but the test shows that the lpOffscreen flag is set to the
     * flag combination of clipping planes that clips the vertex.
     *
     * If clipping is requested, Windows assumes that the offscreen
     * param is a valid pointer.
     */
    if(dwVertexCount == 1 && dwFlags & D3DTRANSFORM_CLIPPED)
    {
        *lpOffScreen = outH[0].dwFlags;
    }
    else if(*lpOffScreen)
    {
        *lpOffScreen = 0;
    }
    LeaveCriticalSection(&ddraw_cs);

    TRACE("All done\n");
    return DD_OK;
}