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

📄 surface.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
    GLint fmt, type;
    BYTE *mem;
    UINT bpp;
    UINT pitch = IWineD3DSurface_GetPitch((IWineD3DSurface *) This);    /* target is argb, 4 byte */

    glDisable(GL_TEXTURE_2D);
    vcheckGLcall("glDisable(GL_TEXTURE_2D)");

    glFlush();
    vcheckGLcall("glFlush");
    glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
    vcheckGLcall("glIntegerv");
    glGetIntegerv(GL_CURRENT_RASTER_POSITION, &prev_rasterpos[0]);
    vcheckGLcall("glIntegerv");
    glPixelZoom(1.0, -1.0);
    vcheckGLcall("glPixelZoom");

    /* If not fullscreen, we need to skip a number of bytes to find the next row of data */
    glGetIntegerv(GL_UNPACK_ROW_LENGTH, &skipBytes);
    glPixelStorei(GL_UNPACK_ROW_LENGTH, This->currentDesc.Width);

    glRasterPos3i(This->lockedRect.left, This->lockedRect.top, 1);
    vcheckGLcall("glRasterPos2f");

    /* Some drivers(radeon dri, others?) don't like exceptions during
     * glDrawPixels. If the surface is a DIB section, it might be in GDIMode
     * after ReleaseDC. Reading it will cause an exception, which x11drv will
     * catch to put the dib section in InSync mode, which leads to a crash
     * and a blocked x server on my radeon card.
     *
     * The following lines read the dib section so it is put in inSync mode
     * before glDrawPixels is called and the crash is prevented. There won't
     * be any interfering gdi accesses, because UnlockRect is called from
     * ReleaseDC, and the app won't use the dc any more afterwards.
     */
    if(This->Flags & SFLAG_DIBSECTION) {
        volatile BYTE read;
        read = This->resource.allocatedMemory[0];
    }

    switch (This->resource.format) {
        /* No special care needed */
        case WINED3DFMT_A4R4G4B4:
        case WINED3DFMT_R5G6B5:
        case WINED3DFMT_A1R5G5B5:
        case WINED3DFMT_R8G8B8:
            type = This->glDescription.glType;
            fmt = This->glDescription.glFormat;
            mem = This->resource.allocatedMemory;
            bpp = This->bytesPerPixel;
            break;

        case WINED3DFMT_X4R4G4B4:
        {
            int size;
            unsigned short *data;
            data = (unsigned short *)This->resource.allocatedMemory;
            size = (This->lockedRect.bottom - This->lockedRect.top) * (This->lockedRect.right - This->lockedRect.left);
            while(size > 0) {
                *data |= 0xF000;
                data++;
                size--;
            }
            type = This->glDescription.glType;
            fmt = This->glDescription.glFormat;
            mem = This->resource.allocatedMemory;
            bpp = This->bytesPerPixel;
        }
        break;

        case WINED3DFMT_X1R5G5B5:
        {
            int size;
            unsigned short *data;
            data = (unsigned short *)This->resource.allocatedMemory;
            size = (This->lockedRect.bottom - This->lockedRect.top) * (This->lockedRect.right - This->lockedRect.left);
            while(size > 0) {
                *data |= 0x8000;
                data++;
                size--;
            }
            type = This->glDescription.glType;
            fmt = This->glDescription.glFormat;
            mem = This->resource.allocatedMemory;
            bpp = This->bytesPerPixel;
        }
        break;

        case WINED3DFMT_X8R8G8B8:
        {
            /* make sure the X byte is set to alpha on, since it 
               could be any random value. This fixes the intro movie in Pirates! */
            int size;
            unsigned int *data;
            data = (unsigned int *)This->resource.allocatedMemory;
            size = (This->lockedRect.bottom - This->lockedRect.top) * (This->lockedRect.right - This->lockedRect.left);
            while(size > 0) {
                *data |= 0xFF000000;
                data++;
                size--;
            }
        }
        /* Fall through */

        case WINED3DFMT_A8R8G8B8:
        {
            glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
            vcheckGLcall("glPixelStorei");
            storechanged = TRUE;
            type = This->glDescription.glType;
            fmt = This->glDescription.glFormat;
            mem = This->resource.allocatedMemory;
            bpp = This->bytesPerPixel;
        }
        break;

        case WINED3DFMT_A2R10G10B10:
        {
            glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
            vcheckGLcall("glPixelStorei");
            storechanged = TRUE;
            type = This->glDescription.glType;
            fmt = This->glDescription.glFormat;
            mem = This->resource.allocatedMemory;
            bpp = This->bytesPerPixel;
        }
        break;

        case WINED3DFMT_P8:
        {
            int height = This->glRect.bottom - This->glRect.top;
            type = GL_UNSIGNED_BYTE;
            fmt = GL_RGBA;

            mem = HeapAlloc(GetProcessHeap(), 0, This->resource.size * sizeof(DWORD));
            if(!mem) {
                ERR("Out of memory\n");
                return;
            }
            memory_allocated = TRUE;
            d3dfmt_convert_surface(This->resource.allocatedMemory,
                                   mem,
                                   pitch,
                                   pitch,
                                   height,
                                   pitch * 4,
                                   CONVERT_PALETTED,
                                   This);
            bpp = This->bytesPerPixel * 4;
            pitch *= 4;
        }
        break;

        default:
            FIXME("Unsupported Format %u in locking func\n", This->resource.format);

            /* Give it a try */
            type = This->glDescription.glType;
            fmt = This->glDescription.glFormat;
            mem = This->resource.allocatedMemory;
            bpp = This->bytesPerPixel;
    }

    glDrawPixels(This->lockedRect.right - This->lockedRect.left,
                 (This->lockedRect.bottom - This->lockedRect.top)-1,
                 fmt, type,
                 mem + bpp * This->lockedRect.left + pitch * This->lockedRect.top);
    checkGLcall("glDrawPixels");
    glPixelZoom(1.0,1.0);
    vcheckGLcall("glPixelZoom");

    glRasterPos3iv(&prev_rasterpos[0]);
    vcheckGLcall("glRasterPos3iv");

    /* Reset to previous pack row length */
    glPixelStorei(GL_UNPACK_ROW_LENGTH, skipBytes);
    vcheckGLcall("glPixelStorei GL_UNPACK_ROW_LENGTH");
    if(storechanged) {
        glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
        vcheckGLcall("glPixelStorei GL_PACK_SWAP_BYTES");
    }

    /* Blitting environment requires that 2D texturing is enabled. It was turned off before,
     * turn it on again
     */
    glEnable(GL_TEXTURE_2D);
    checkGLcall("glEnable(GL_TEXTURE_2D)");

    if(memory_allocated) HeapFree(GetProcessHeap(), 0, mem);
    return;
}

static void flush_to_framebuffer_texture(IWineD3DSurfaceImpl *This) {
    float glTexCoord[4];

    glTexCoord[0] = (float) This->lockedRect.left   / (float) This->pow2Width; /* left */
    glTexCoord[1] = (float) This->lockedRect.right  / (float) This->pow2Width; /* right */
    glTexCoord[2] = (float) This->lockedRect.top    / (float) This->pow2Height; /* top */
    glTexCoord[3] = (float) This->lockedRect.bottom / (float) This->pow2Height; /* bottom */

    IWineD3DSurface_PreLoad((IWineD3DSurface *) This);

    ENTER_GL();

    glBindTexture(GL_TEXTURE_2D, This->glDescription.textureName);
    checkGLcall("glEnable glBindTexture");

    /* No filtering for blts */
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    checkGLcall("glTexParameteri");
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    checkGLcall("glTexParameteri");

    /* Start drawing a quad */
    glBegin(GL_QUADS);

    glColor3d(1.0f, 1.0f, 1.0f);
    glTexCoord2f(glTexCoord[0], glTexCoord[2]);
    glVertex3f(This->lockedRect.left, This->lockedRect.top, 0.0);

    glTexCoord2f(glTexCoord[0], glTexCoord[3]);
    glVertex3f(This->lockedRect.left, This->lockedRect.bottom, 0.0);

    glTexCoord2f(glTexCoord[1], glTexCoord[3]);
    glVertex3d(This->lockedRect.right, This->lockedRect.bottom, 0.0);

    glTexCoord2f(glTexCoord[1], glTexCoord[2]);
    glVertex3f(This->lockedRect.right, This->lockedRect.top, 0.0);

    glEnd();
    checkGLcall("glEnd");

    /* Unbind the texture */
    glBindTexture(GL_TEXTURE_2D, 0);
    checkGLcall("glEnable glBindTexture");

    LEAVE_GL();
}

static HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) {
    IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
    IWineD3DDeviceImpl  *myDevice = This->resource.wineD3DDevice;
    IWineD3DSwapChainImpl *swapchain = NULL;

    if (!(This->Flags & SFLAG_LOCKED)) {
        WARN("trying to Unlock an unlocked surf@%p\n", This);
        return WINED3DERR_INVALIDCALL;
    }

    TRACE("(%p) : dirtyfied(%d)\n", This, This->Flags & (SFLAG_INDRAWABLE | SFLAG_INTEXTURE) ? 0 : 1);

    if (This->Flags & (SFLAG_INDRAWABLE | SFLAG_INTEXTURE)) {
        TRACE("(%p) : Not Dirtified so nothing to do, return now\n", This);
        goto unlock_end;
    }

    IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
    if(swapchain || iface == myDevice->render_targets[0]) {
        if(wined3d_settings.rendertargetlock_mode == RTL_DISABLE) {
            static BOOL warned = FALSE;
            if(!warned) {
                ERR("The application tries to write to the render target, but render target locking is disabled\n");
                warned = TRUE;
            }
            if(swapchain) IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
            goto unlock_end;
        }

        /* Activate the correct context for the render target */
        ActivateContext(myDevice, iface, CTXUSAGE_BLIT);
        ENTER_GL();

        if(!swapchain) {
            /* Primary offscreen render target */
            TRACE("Offscreen render target\n");
            glDrawBuffer(myDevice->offscreenBuffer);
            checkGLcall("glDrawBuffer(myDevice->offscreenBuffer)");
        } else {
            GLenum buffer = surface_get_gl_buffer(iface, (IWineD3DSwapChain *)swapchain);
            TRACE("Unlocking %#x buffer\n", buffer);
            glDrawBuffer(buffer);
            checkGLcall("glDrawBuffer");

            IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
        }

        switch(wined3d_settings.rendertargetlock_mode) {
            case RTL_AUTO:
            case RTL_READDRAW:
            case RTL_TEXDRAW:
                flush_to_framebuffer_drawpixels(This);
                break;

            case RTL_READTEX:
            case RTL_TEXTEX:
                flush_to_framebuffer_texture(This);
                break;
        }
        if(!swapchain) {
            glDrawBuffer(myDevice->offscreenBuffer);

⌨️ 快捷键说明

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