⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 surface.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
    /* Warn ,but be nice about things */
    TRACE("(%p)->(%s,%p)\n", This,debugstr_guid(riid),ppobj);

    if (IsEqualGUID(riid, &IID_IUnknown)
        || IsEqualGUID(riid, &IID_IWineD3DBase)
        || IsEqualGUID(riid, &IID_IWineD3DResource)
        || IsEqualGUID(riid, &IID_IWineD3DSurface)) {
        IUnknown_AddRef((IUnknown*)iface);
        *ppobj = This;
        return S_OK;
    }
    *ppobj = NULL;
    return E_NOINTERFACE;
}

ULONG WINAPI IWineD3DSurfaceImpl_AddRef(IWineD3DSurface *iface) {
    IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
    ULONG ref = InterlockedIncrement(&This->resource.ref);
    TRACE("(%p) : AddRef increasing from %d\n", This,ref - 1);
    return ref;
}

ULONG WINAPI IWineD3DSurfaceImpl_Release(IWineD3DSurface *iface) {
    IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
    ULONG ref = InterlockedDecrement(&This->resource.ref);
    TRACE("(%p) : Releasing from %d\n", This, ref + 1);
    if (ref == 0) {
        IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) This->resource.wineD3DDevice;
        renderbuffer_entry_t *entry, *entry2;
        TRACE("(%p) : cleaning up\n", This);

        if(iface == device->lastActiveRenderTarget) {
            IWineD3DSwapChainImpl *swapchain = device->swapchains ? (IWineD3DSwapChainImpl *) device->swapchains[0] : NULL;

            TRACE("Last active render target destroyed\n");
            /* Find a replacement surface for the currently active back buffer. The context manager does not do NULL
             * checks, so switch to a valid target as long as the currently set surface is still valid. Use the
             * surface of the implicit swpchain. If that is the same as the destroyed surface the device is destroyed
             * and the lastActiveRenderTarget member shouldn't matter
             */
            if(swapchain) {
                if(swapchain->backBuffer && swapchain->backBuffer[0] != iface) {
                    TRACE("Activating primary back buffer\n");
                    ActivateContext(device, swapchain->backBuffer[0], CTXUSAGE_RESOURCELOAD);
                } else if(!swapchain->backBuffer && swapchain->frontBuffer != iface) {
                    /* Single buffering environment */
                    TRACE("Activating primary front buffer\n");
                    ActivateContext(device, swapchain->frontBuffer, CTXUSAGE_RESOURCELOAD);
                } else {
                    TRACE("Device is being destroyed, setting lastActiveRenderTarget = 0xdeadbabe\n");
                    /* Implicit render target destroyed, that means the device is being destroyed
                     * whatever we set here, it shouldn't matter
                     */
                    device->lastActiveRenderTarget = (IWineD3DSurface *) 0xdeadbabe;
                }
            } else {
                /* May happen during ddraw uninitialization */
                TRACE("Render target set, but swapchain does not exist!\n");
                device->lastActiveRenderTarget = (IWineD3DSurface *) 0xdeadcafe;
            }
        }

        if (This->glDescription.textureName != 0) { /* release the openGL texture.. */

            /* Need a context to destroy the texture. Use the currently active render target, but only if
             * the primary render target exists. Otherwise lastActiveRenderTarget is garbage, see above.
             * When destroying the primary rt, Uninit3D will activate a context before doing anything
             */
            if(device->render_targets[0]) {
                ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
            }

            TRACE("Deleting texture %d\n", This->glDescription.textureName);
            ENTER_GL();
            glDeleteTextures(1, &This->glDescription.textureName);
            LEAVE_GL();
        }

        if(This->Flags & SFLAG_DIBSECTION) {
            /* Release the DC */
            SelectObject(This->hDC, This->dib.holdbitmap);
            DeleteDC(This->hDC);
            /* Release the DIB section */
            DeleteObject(This->dib.DIBsection);
            This->dib.bitmap_data = NULL;
            This->resource.allocatedMemory = NULL;
        }
        if(This->Flags & SFLAG_USERPTR) IWineD3DSurface_SetMem(iface, NULL);

        HeapFree(GetProcessHeap(), 0, This->palette9);

        IWineD3DResourceImpl_CleanUp((IWineD3DResource *)iface);
        if(iface == device->ddraw_primary)
            device->ddraw_primary = NULL;

        LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &This->renderbuffers, renderbuffer_entry_t, entry) {
            GL_EXTCALL(glDeleteRenderbuffersEXT(1, &entry->id));
            HeapFree(GetProcessHeap(), 0, entry);
        }

        TRACE("(%p) Released\n", This);
        HeapFree(GetProcessHeap(), 0, This);

    }
    return ref;
}

/* ****************************************************
   IWineD3DSurface IWineD3DResource parts follow
   **************************************************** */
HRESULT WINAPI IWineD3DSurfaceImpl_GetDevice(IWineD3DSurface *iface, IWineD3DDevice** ppDevice) {
    return IWineD3DResourceImpl_GetDevice((IWineD3DResource *)iface, ppDevice);
}

HRESULT WINAPI IWineD3DSurfaceImpl_SetPrivateData(IWineD3DSurface *iface, REFGUID refguid, CONST void* pData, DWORD SizeOfData, DWORD Flags) {
    return IWineD3DResourceImpl_SetPrivateData((IWineD3DResource *)iface, refguid, pData, SizeOfData, Flags);
}

HRESULT WINAPI IWineD3DSurfaceImpl_GetPrivateData(IWineD3DSurface *iface, REFGUID refguid, void* pData, DWORD* pSizeOfData) {
    return IWineD3DResourceImpl_GetPrivateData((IWineD3DResource *)iface, refguid, pData, pSizeOfData);
}

HRESULT WINAPI IWineD3DSurfaceImpl_FreePrivateData(IWineD3DSurface *iface, REFGUID refguid) {
    return IWineD3DResourceImpl_FreePrivateData((IWineD3DResource *)iface, refguid);
}

DWORD   WINAPI IWineD3DSurfaceImpl_SetPriority(IWineD3DSurface *iface, DWORD PriorityNew) {
    return IWineD3DResourceImpl_SetPriority((IWineD3DResource *)iface, PriorityNew);
}

DWORD   WINAPI IWineD3DSurfaceImpl_GetPriority(IWineD3DSurface *iface) {
    return IWineD3DResourceImpl_GetPriority((IWineD3DResource *)iface);
}

void WINAPI IWineD3DSurfaceImpl_PreLoad(IWineD3DSurface *iface) {
    /* TODO: check for locks */
    IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
    IWineD3DBaseTexture *baseTexture = NULL;
    IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;

    TRACE("(%p)Checking to see if the container is a base texture\n", This);
    if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture) == WINED3D_OK) {
        TRACE("Passing to container\n");
        IWineD3DBaseTexture_PreLoad(baseTexture);
        IWineD3DBaseTexture_Release(baseTexture);
    } else {
    TRACE("(%p) : About to load surface\n", This);

    if(!device->isInDraw) {
        ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
    }

    ENTER_GL();
    glEnable(This->glDescription.target);/* make sure texture support is enabled in this context */
    if (!This->glDescription.level) {
        if (!This->glDescription.textureName) {
            glGenTextures(1, &This->glDescription.textureName);
            checkGLcall("glGenTextures");
            TRACE("Surface %p given name %d\n", This, This->glDescription.textureName);
        }
        glBindTexture(This->glDescription.target, This->glDescription.textureName);
        checkGLcall("glBindTexture");
        IWineD3DSurface_LoadTexture(iface, FALSE);
        /* This is where we should be reducing the amount of GLMemoryUsed */
    } else if (This->glDescription.textureName) { /* NOTE: the level 0 surface of a mpmapped texture must be loaded first! */
        /* assume this is a coding error not a real error for now */
        FIXME("Mipmap surface has a glTexture bound to it!\n");
    }
    if (This->resource.pool == WINED3DPOOL_DEFAULT) {
       /* Tell opengl to try and keep this texture in video ram (well mostly) */
       GLclampf tmp;
       tmp = 0.9f;
        glPrioritizeTextures(1, &This->glDescription.textureName, &tmp);
    }
    LEAVE_GL();
    }
    return;
}

WINED3DRESOURCETYPE WINAPI IWineD3DSurfaceImpl_GetType(IWineD3DSurface *iface) {
    TRACE("(%p) : calling resourceimpl_GetType\n", iface);
    return IWineD3DResourceImpl_GetType((IWineD3DResource *)iface);
}

HRESULT WINAPI IWineD3DSurfaceImpl_GetParent(IWineD3DSurface *iface, IUnknown **pParent) {
    TRACE("(%p) : calling resourceimpl_GetParent\n", iface);
    return IWineD3DResourceImpl_GetParent((IWineD3DResource *)iface, pParent);
}

/* ******************************************************
   IWineD3DSurface IWineD3DSurface parts follow
   ****************************************************** */

HRESULT WINAPI IWineD3DSurfaceImpl_GetContainer(IWineD3DSurface* iface, REFIID riid, void** ppContainer) {
    IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
    IWineD3DBase *container = 0;

    TRACE("(This %p, riid %s, ppContainer %p)\n", This, debugstr_guid(riid), ppContainer);

    if (!ppContainer) {
        ERR("Called without a valid ppContainer.\n");
    }

    /** From MSDN:
     * If the surface is created using CreateImageSurface/CreateOffscreenPlainSurface, CreateRenderTarget,
     * or CreateDepthStencilSurface, the surface is considered stand alone. In this case,
     * GetContainer will return the Direct3D device used to create the surface.
     */
    if (This->container) {
        container = This->container;
    } else {
        container = (IWineD3DBase *)This->resource.wineD3DDevice;
    }

    TRACE("Relaying to QueryInterface\n");
    return IUnknown_QueryInterface(container, riid, ppContainer);
}

HRESULT WINAPI IWineD3DSurfaceImpl_GetDesc(IWineD3DSurface *iface, WINED3DSURFACE_DESC *pDesc) {
    IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;

    TRACE("(%p) : copying into %p\n", This, pDesc);
    if(pDesc->Format != NULL)             *(pDesc->Format) = This->resource.format;
    if(pDesc->Type != NULL)               *(pDesc->Type)   = This->resource.resourceType;
    if(pDesc->Usage != NULL)              *(pDesc->Usage)              = This->resource.usage;
    if(pDesc->Pool != NULL)               *(pDesc->Pool)               = This->resource.pool;
    if(pDesc->Size != NULL)               *(pDesc->Size)               = This->resource.size;   /* dx8 only */
    if(pDesc->MultiSampleType != NULL)    *(pDesc->MultiSampleType)    = This->currentDesc.MultiSampleType;
    if(pDesc->MultiSampleQuality != NULL) *(pDesc->MultiSampleQuality) = This->currentDesc.MultiSampleQuality;
    if(pDesc->Width != NULL)              *(pDesc->Width)              = This->currentDesc.Width;
    if(pDesc->Height != NULL)             *(pDesc->Height)             = This->currentDesc.Height;
    return WINED3D_OK;
}

void WINAPI IWineD3DSurfaceImpl_SetGlTextureDesc(IWineD3DSurface *iface, UINT textureName, int target) {
    IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
    TRACE("(%p) : setting textureName %u, target %i\n", This, textureName, target);
    if (This->glDescription.textureName == 0 && textureName != 0) {
        This->Flags &= ~SFLAG_INTEXTURE;
        IWineD3DSurface_AddDirtyRect(iface, NULL);
    }
    This->glDescription.textureName = textureName;
    This->glDescription.target      = target;
    This->Flags &= ~SFLAG_ALLOCATED;
}

void WINAPI IWineD3DSurfaceImpl_GetGlDesc(IWineD3DSurface *iface, glDescriptor **glDescription) {
    IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
    TRACE("(%p) : returning %p\n", This, &This->glDescription);
    *glDescription = &This->glDescription;
}

/* TODO: think about moving this down to resource? */
const void *WINAPI IWineD3DSurfaceImpl_GetData(IWineD3DSurface *iface) {
    IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
    /* This should only be called for sysmem textures, it may be a good idea to extend this to all pools at some point in the future  */
    if (This->resource.pool != WINED3DPOOL_SYSTEMMEM) {
        FIXME(" (%p)Attempting to get system memory for a non-system memory texture\n", iface);
    }
    return (CONST void*)(This->resource.allocatedMemory);
}

static void read_from_framebuffer(IWineD3DSurfaceImpl *This, CONST RECT *rect, void *dest, UINT pitch, BOOL srcUpsideDown) {
    BYTE *mem;
    GLint fmt;
    GLint type;
    BYTE *row, *top, *bottom;
    int i;
    BOOL bpp;

    switch(This->resource.format)
    {
        case WINED3DFMT_P8:
        {
            /* GL can't return palettized data, so read ARGB pixels into a
             * separate block of memory and convert them into palettized format
             * in software. Slow, but if the app means to use palettized render
             * targets and locks it...
             *
             * Use GL_RGB, GL_UNSIGNED_BYTE to read the surface for performance reasons
             * Don't use GL_BGR as in the WINED3DFMT_R8G8B8 case, instead watch out
             * for the color channels when palettizing the colors.
             */
            fmt = GL_RGB;
            type = GL_UNSIGNED_BYTE;
            pitch *= 3;
            mem = HeapAlloc(GetProcessHeap(), 0, This->resource.size * 3);
            if(!mem) {
                ERR("Out of memory\n");
                return;
            }
            bpp = This->bytesPerPixel * 3;
        }
        break;

        default:
            mem = dest;
            fmt = This->glDescription.glFormat;
            type = This->glDescription.glType;
            bpp = This->bytesPerPixel;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -