mesa.c

来自「Wine-20031016」· C语言 代码 · 共 1,666 行 · 第 1/5 页

C
1,666
字号
/* Direct3D Device * Copyright (c) 1998 Lionel ULMER * * This file contains the MESA implementation of all the D3D devices that * Wine supports. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */#include "config.h"#include "wine/port.h"#include <stdarg.h>#include <string.h>#include <math.h>#define NONAMELESSUNION#define NONAMELESSSTRUCT#include "windef.h"#include "winbase.h"#include "winerror.h"#include "objbase.h"#include "wingdi.h"#include "ddraw.h"#include "d3d.h"#include "wine/debug.h"#include "wine/library.h"#include "mesa_private.h"#include "main.h"WINE_DEFAULT_DEBUG_CHANNEL(ddraw);WINE_DECLARE_DEBUG_CHANNEL(ddraw_geom);WINE_DECLARE_DEBUG_CHANNEL(ddraw_fps);/* x11drv GDI escapes */#define X11DRV_ESCAPE 6789enum x11drv_escape_codes{    X11DRV_GET_DISPLAY,   /* get X11 display for a DC */    X11DRV_GET_DRAWABLE,  /* get current drawable for a DC */    X11DRV_GET_FONT,      /* get current X font for a DC */};/* They are non-static as they are used by Direct3D in the creation function */const GUID IID_D3DDEVICE_OpenGL = {  0x31416d44,  0x86ae,  0x11d2,  { 0x82,0x2d,0xa8,0xd5,0x31,0x87,0xca,0xfa }};const float id_mat[16] = {    1.0, 0.0, 0.0, 0.0,    0.0, 1.0, 0.0, 0.0,    0.0, 0.0, 1.0, 0.0,    0.0, 0.0, 0.0, 1.0};/* This is filled at DLL loading time */static D3DDEVICEDESC7 opengl_device_caps;GL_EXTENSIONS_LIST GL_extensions;static void draw_primitive_strided(IDirect3DDeviceImpl *This,				   D3DPRIMITIVETYPE d3dptPrimitiveType,				   DWORD d3dvtVertexType,				   LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,				   DWORD dwVertexCount,				   LPWORD dwIndices,				   DWORD dwIndexCount,				   DWORD dwFlags) ;static DWORD draw_primitive_handle_textures(IDirect3DDeviceImpl *This);/* retrieve the X display to use on a given DC */inline static Display *get_display( HDC hdc ){    Display *display;    enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;    if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,                    sizeof(display), (LPSTR)&display )) display = NULL;    return display;}#define UNLOCK_TEX_SIZE 256#define DEPTH_RANGE_BIT (0x00000001 << 0)#define VIEWPORT_BIT    (0x00000001 << 1)static DWORD d3ddevice_set_state_for_flush(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect, BOOLEAN use_alpha, BOOLEAN *initial) {    IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;    DWORD opt_bitmap = 0x00000000;        if (gl_d3d_dev->current_active_tex_unit != GL_TEXTURE0_WINE) {	GL_extensions.glActiveTexture(GL_TEXTURE0_WINE);	gl_d3d_dev->current_active_tex_unit = GL_TEXTURE0_WINE;    }    if (gl_d3d_dev->unlock_tex == 0) {        glGenTextures(1, &gl_d3d_dev->unlock_tex);	glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);	*initial = TRUE;	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);    } else {        glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);	*initial = FALSE;    }    if (d3d_dev->tex_mat_is_identity[0] == FALSE) {	glMatrixMode(GL_TEXTURE);	glLoadIdentity();    }        if (gl_d3d_dev->transform_state != GL_TRANSFORM_ORTHO) {	gl_d3d_dev->transform_state = GL_TRANSFORM_ORTHO;	d3ddevice_set_ortho(d3d_dev);    }        if (gl_d3d_dev->depth_test != FALSE) glDisable(GL_DEPTH_TEST);    if ((gl_d3d_dev->current_bound_texture[0] == NULL) ||	(d3d_dev->state_block.texture_stage_state[0][D3DTSS_COLOROP - 1] == D3DTOP_DISABLE))	glEnable(GL_TEXTURE_2D);    if (gl_d3d_dev->current_bound_texture[1] != NULL) {	if (gl_d3d_dev->current_active_tex_unit != GL_TEXTURE1_WINE) {	    GL_extensions.glActiveTexture(GL_TEXTURE1_WINE);	    gl_d3d_dev->current_active_tex_unit = GL_TEXTURE1_WINE;	}	/* 'unbound' texture level 1 in that case to disable multi-texturing */	glBindTexture(GL_TEXTURE_2D, 0);	glDisable(GL_TEXTURE_2D);    }    glEnable(GL_SCISSOR_TEST);    if ((d3d_dev->active_viewport.dvMinZ != 0.0) ||	(d3d_dev->active_viewport.dvMaxZ != 1.0)) {	glDepthRange(0.0, 1.0);	opt_bitmap |= DEPTH_RANGE_BIT;    }    if ((d3d_dev->active_viewport.dwX != 0) ||	(d3d_dev->active_viewport.dwY != 0) ||	(d3d_dev->active_viewport.dwWidth != d3d_dev->surface->surface_desc.dwWidth) ||	(d3d_dev->active_viewport.dwHeight != d3d_dev->surface->surface_desc.dwHeight)) {	glViewport(0, 0, d3d_dev->surface->surface_desc.dwWidth, d3d_dev->surface->surface_desc.dwHeight);	opt_bitmap |= VIEWPORT_BIT;    }    glScissor(pRect->left, d3d_dev->surface->surface_desc.dwHeight - pRect->bottom,	      pRect->right - pRect->left, pRect->bottom - pRect->top);    if (gl_d3d_dev->lighting != FALSE) glDisable(GL_LIGHTING);    if (gl_d3d_dev->cull_face != FALSE) glDisable(GL_CULL_FACE);    if (use_alpha) {	if (gl_d3d_dev->alpha_test == FALSE) glEnable(GL_ALPHA_TEST);	if (((d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAREF - 1] & 0x000000FF) != 0x00) ||	    ((d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAFUNC - 1]) != D3DCMP_GREATER)) {	    glAlphaFunc(GL_GREATER, 0.0);	}    } else {	if (gl_d3d_dev->alpha_test != FALSE) glDisable(GL_ALPHA_TEST);    }    if (gl_d3d_dev->stencil_test != FALSE) glDisable(GL_STENCIL_TEST);    if (gl_d3d_dev->blending != FALSE) glDisable(GL_BLEND);    if (gl_d3d_dev->fogging != FALSE) glDisable(GL_FOG);    if (gl_d3d_dev->current_tex_env != GL_REPLACE)	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);        return opt_bitmap;}static void d3ddevice_restore_state_after_flush(IDirect3DDeviceImpl *d3d_dev, DWORD opt_bitmap, BOOLEAN use_alpha) {    IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;    /* And restore all the various states modified by this code */    if (gl_d3d_dev->depth_test != 0) glEnable(GL_DEPTH_TEST);    if (gl_d3d_dev->lighting != 0) glEnable(GL_LIGHTING);    if ((gl_d3d_dev->alpha_test != 0) && (use_alpha == 0))	glEnable(GL_ALPHA_TEST);    else if ((gl_d3d_dev->alpha_test == 0) && (use_alpha != 0))	glDisable(GL_ALPHA_TEST);    if (use_alpha) {	if (((d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAREF - 1] & 0x000000FF) != 0x00) ||	    ((d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAFUNC - 1]) != D3DCMP_GREATER)) {	    glAlphaFunc(convert_D3D_compare_to_GL(d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAFUNC - 1]),			(d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAREF - 1] & 0x000000FF) / 255.0);	}    }    if (gl_d3d_dev->stencil_test != 0) glEnable(GL_STENCIL_TEST);    if (gl_d3d_dev->cull_face != 0) glEnable(GL_CULL_FACE);    if (gl_d3d_dev->blending != 0) glEnable(GL_BLEND);    if (gl_d3d_dev->fogging != 0) glEnable(GL_FOG);    glDisable(GL_SCISSOR_TEST);    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, gl_d3d_dev->current_tex_env);    if (opt_bitmap & DEPTH_RANGE_BIT) {	glDepthRange(d3d_dev->active_viewport.dvMinZ, d3d_dev->active_viewport.dvMaxZ);    }    if (opt_bitmap & VIEWPORT_BIT) {	glViewport(d3d_dev->active_viewport.dwX,		   d3d_dev->surface->surface_desc.dwHeight - (d3d_dev->active_viewport.dwHeight + d3d_dev->active_viewport.dwY),		   d3d_dev->active_viewport.dwWidth, d3d_dev->active_viewport.dwHeight);    }    if (d3d_dev->tex_mat_is_identity[0] == FALSE) {	d3d_dev->matrices_updated(d3d_dev, TEXMAT0_CHANGED);    }        /* This is a hack to prevent querying the current texture from GL. Basically, at the next       DrawPrimitive call, this will bind the correct texture to this stage. */    gl_d3d_dev->current_bound_texture[0] = (IDirectDrawSurfaceImpl *) 0x00000001;    gl_d3d_dev->current_bound_texture[1] = (IDirectDrawSurfaceImpl *) 0x00000000;    if (d3d_dev->state_block.texture_stage_state[0][D3DTSS_COLOROP - 1] == D3DTOP_DISABLE) glDisable(GL_TEXTURE_2D);}/* retrieve the X drawable to use on a given DC */inline static Drawable get_drawable( HDC hdc ){    Drawable drawable;    enum x11drv_escape_codes escape = X11DRV_GET_DRAWABLE;    if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,                    sizeof(drawable), (LPSTR)&drawable )) drawable = 0;    return drawable;}/* This is unnecessarely complicated :-) */#define MEASUREMENT_WINDOW 5#define NUMBER_OF_WINDOWS 10static LONGLONG perf_freq;static LONGLONG perf_storage[NUMBER_OF_WINDOWS];static LONGLONG prev_time = 0;static unsigned int current_window;static unsigned int measurements_in_window;static unsigned int valid_windows;static BOOL opengl_flip( LPVOID dev, LPVOID drawable){    IDirect3DDeviceImpl *d3d_dev = (IDirect3DDeviceImpl *) dev;    IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) dev;    TRACE("(%p, %ld)\n", gl_d3d_dev->display,(Drawable)drawable);    ENTER_GL();    if (gl_d3d_dev->state[WINE_GL_BUFFER_BACK] == SURFACE_MEMORY_DIRTY) {        d3d_dev->flush_to_framebuffer(d3d_dev, &(gl_d3d_dev->lock_rect[WINE_GL_BUFFER_BACK]), gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK]);    }    gl_d3d_dev->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;    gl_d3d_dev->state[WINE_GL_BUFFER_FRONT] = SURFACE_GL;    glXSwapBuffers(gl_d3d_dev->display, (Drawable)drawable);    LEAVE_GL();    if (TRACE_ON(ddraw_fps)) {	LONGLONG current_time;	LONGLONG frame_duration;	QueryPerformanceCounter((LARGE_INTEGER *) &current_time);	if (prev_time != 0) {	    LONGLONG total_time = 0;	    int tot_meas;	    	    frame_duration = current_time - prev_time;	    prev_time = current_time;	    	    perf_storage[current_window] += frame_duration;	    measurements_in_window++;	    	    if (measurements_in_window >= MEASUREMENT_WINDOW) {		current_window++;		valid_windows++;		if (valid_windows < NUMBER_OF_WINDOWS) {		    int i;		    tot_meas = valid_windows * MEASUREMENT_WINDOW;		    for (i = 0; i < valid_windows; i++) {			total_time += perf_storage[i];		    }		} else {		    int i;		    tot_meas = NUMBER_OF_WINDOWS * MEASUREMENT_WINDOW;		    for (i = 0; i < NUMBER_OF_WINDOWS; i++) {			total_time += perf_storage[i];		    }		}		TRACE_(ddraw_fps)(" %9.5f\n", (double) (perf_freq * tot_meas) / (double) total_time);				if (current_window >= NUMBER_OF_WINDOWS) {		    current_window = 0;		}		perf_storage[current_window] = 0;		measurements_in_window = 0;	    }	} else {	    prev_time = current_time;	    memset(perf_storage, 0, sizeof(perf_storage));	    current_window = 0;	    valid_windows = 0;	    measurements_in_window = 0;	    QueryPerformanceFrequency((LARGE_INTEGER *) &perf_freq);	}    }        return TRUE;}/******************************************************************************* *				OpenGL static functions */static void set_context(IDirect3DDeviceImpl* This){    IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;       TRACE("glxMakeCurrent %p, %ld, %p\n",glThis->display,glThis->drawable, glThis->gl_context);    ENTER_GL();    if (glXMakeCurrent(glThis->display, glThis->drawable, glThis->gl_context) == False) {	ERR("Error in setting current context (context %p drawable %ld)!\n",	    glThis->gl_context, glThis->drawable);    }    LEAVE_GL();}static void fill_opengl_caps(D3DDEVICEDESC *d1){

⌨️ 快捷键说明

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