aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/mesa/drivers
diff options
context:
space:
mode:
authormarha <marha@users.sourceforge.net>2010-12-28 16:10:20 +0000
committermarha <marha@users.sourceforge.net>2010-12-28 16:10:20 +0000
commit807c6931fe683fd844ceec1b023232181e6aae03 (patch)
tree1a131ed95fe2200d0ad33da8f7755a7ed2364adc /mesalib/src/mesa/drivers
parent973099dda7e49e5abe29819a7124b3b1e7bd8b92 (diff)
downloadvcxsrv-807c6931fe683fd844ceec1b023232181e6aae03.tar.gz
vcxsrv-807c6931fe683fd844ceec1b023232181e6aae03.tar.bz2
vcxsrv-807c6931fe683fd844ceec1b023232181e6aae03.zip
xserver and mesa git update 28-12-2010
Diffstat (limited to 'mesalib/src/mesa/drivers')
-rw-r--r--mesalib/src/mesa/drivers/common/driverfuncs.c650
-rw-r--r--mesalib/src/mesa/drivers/common/driverfuncs.h74
-rw-r--r--mesalib/src/mesa/drivers/common/meta.c5722
-rw-r--r--mesalib/src/mesa/drivers/common/meta.h236
-rw-r--r--mesalib/src/mesa/drivers/dri/Makefile.template227
-rw-r--r--mesalib/src/mesa/drivers/dri/common/depthtmp.h540
-rw-r--r--mesalib/src/mesa/drivers/dri/common/dri_metaops.c582
-rw-r--r--mesalib/src/mesa/drivers/dri/common/dri_metaops.h162
-rw-r--r--mesalib/src/mesa/drivers/dri/common/dri_util.c2019
-rw-r--r--mesalib/src/mesa/drivers/dri/common/dri_util.h1115
-rw-r--r--mesalib/src/mesa/drivers/dri/common/drirenderbuffer.c400
-rw-r--r--mesalib/src/mesa/drivers/dri/common/drirenderbuffer.h158
-rw-r--r--mesalib/src/mesa/drivers/dri/common/drisw_util.h269
-rw-r--r--mesalib/src/mesa/drivers/dri/common/spantmp.h650
-rw-r--r--mesalib/src/mesa/drivers/dri/common/spantmp2.h1954
-rw-r--r--mesalib/src/mesa/drivers/dri/common/stenciltmp.h490
-rw-r--r--mesalib/src/mesa/drivers/dri/common/texmem.c2682
-rw-r--r--mesalib/src/mesa/drivers/dri/common/texmem.h668
-rw-r--r--mesalib/src/mesa/drivers/dri/common/utils.c1619
-rw-r--r--mesalib/src/mesa/drivers/dri/common/utils.h246
-rw-r--r--mesalib/src/mesa/drivers/dri/common/vblank.c868
-rw-r--r--mesalib/src/mesa/drivers/dri/common/vblank.h146
-rw-r--r--mesalib/src/mesa/drivers/dri/common/xmlconfig.c2005
-rw-r--r--mesalib/src/mesa/drivers/dri/common/xmlpool/Makefile192
-rw-r--r--mesalib/src/mesa/drivers/dri/common/xmlpool/gen_xmlpool.py191
-rw-r--r--mesalib/src/mesa/drivers/dri/swrast/swrast.c1480
-rw-r--r--mesalib/src/mesa/drivers/dri/swrast/swrast_priv.h276
-rw-r--r--mesalib/src/mesa/drivers/dri/swrast/swrast_spantemp.h638
-rw-r--r--mesalib/src/mesa/drivers/windows/fx/fx.rc39
-rw-r--r--mesalib/src/mesa/drivers/windows/fx/fxopengl.def1908
-rw-r--r--mesalib/src/mesa/drivers/windows/gdi/InitCritSections.cpp33
-rw-r--r--mesalib/src/mesa/drivers/windows/gdi/wmesa.c3322
-rw-r--r--mesalib/src/mesa/drivers/windows/gdi/wmesadef.h86
-rw-r--r--mesalib/src/mesa/drivers/windows/gldirect/dglcontext.c4424
-rw-r--r--mesalib/src/mesa/drivers/windows/gldirect/dglcontext.h562
-rw-r--r--mesalib/src/mesa/drivers/windows/gldirect/dglwgl.c5928
-rw-r--r--mesalib/src/mesa/drivers/windows/gldirect/dglwgl.h254
-rw-r--r--mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_driver_dx9.c1206
-rw-r--r--mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_dx9.h327
-rw-r--r--mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_dxerr9.h77
-rw-r--r--mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_ext_dx9.c344
-rw-r--r--mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_pipeline_dx9.c77
-rw-r--r--mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_primitive_dx9.c1446
-rw-r--r--mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_texture_dx9.c2104
-rw-r--r--mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_vb_d3d_render_dx9.c263
-rw-r--r--mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_vb_mesa_render_dx9.c443
-rw-r--r--mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_wgl_dx9.c1346
-rw-r--r--mesalib/src/mesa/drivers/windows/gldirect/gld_driver.c558
-rw-r--r--mesalib/src/mesa/drivers/windows/gldirect/gld_driver.h180
-rw-r--r--mesalib/src/mesa/drivers/windows/gldirect/gldirect.rc43
-rw-r--r--mesalib/src/mesa/drivers/windows/gldirect/mesasw/colors.h520
-rw-r--r--mesalib/src/mesa/drivers/windows/gldirect/mesasw/gld_wgl_mesasw.c1682
-rw-r--r--mesalib/src/mesa/drivers/windows/gldirect/opengl32.ref495
53 files changed, 32342 insertions, 21584 deletions
diff --git a/mesalib/src/mesa/drivers/common/driverfuncs.c b/mesalib/src/mesa/drivers/common/driverfuncs.c
index f92cdc5a7..e049cc368 100644
--- a/mesalib/src/mesa/drivers/common/driverfuncs.c
+++ b/mesalib/src/mesa/drivers/common/driverfuncs.c
@@ -1,326 +1,324 @@
-/*
- * Mesa 3-D graphics library
- * Version: 7.1
- *
- * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#include "main/glheader.h"
-#include "main/imports.h"
-#include "main/arrayobj.h"
-#include "main/context.h"
-#include "main/framebuffer.h"
-#include "main/mipmap.h"
-#include "main/queryobj.h"
-#include "main/renderbuffer.h"
-#include "main/shaderobj.h"
-#include "main/texcompress.h"
-#include "main/texformat.h"
-#include "main/texgetimage.h"
-#include "main/teximage.h"
-#include "main/texobj.h"
-#include "main/texstore.h"
-#include "main/bufferobj.h"
-#include "main/fbobject.h"
-#include "main/texrender.h"
-#include "main/syncobj.h"
-#include "main/transformfeedback.h"
-
-#include "program/program.h"
-#include "tnl/tnl.h"
-#include "swrast/swrast.h"
-
-#include "driverfuncs.h"
-#include "meta.h"
-
-
-
-/**
- * Plug in default functions for all pointers in the dd_function_table
- * structure.
- * Device drivers should call this function and then plug in any
- * functions which it wants to override.
- * Some functions (pointers) MUST be implemented by all drivers (REQUIRED).
- *
- * \param table the dd_function_table to initialize
- */
-void
-_mesa_init_driver_functions(struct dd_function_table *driver)
-{
- memset(driver, 0, sizeof(*driver));
-
- driver->GetString = NULL; /* REQUIRED! */
- driver->UpdateState = NULL; /* REQUIRED! */
- driver->GetBufferSize = NULL; /* REQUIRED! */
- driver->ResizeBuffers = _mesa_resize_framebuffer;
- driver->Error = NULL;
-
- driver->Finish = NULL;
- driver->Flush = NULL;
-
- /* framebuffer/image functions */
- driver->Clear = _swrast_Clear;
- driver->Accum = _swrast_Accum;
- driver->RasterPos = _tnl_RasterPos;
- driver->DrawPixels = _swrast_DrawPixels;
- driver->ReadPixels = _swrast_ReadPixels;
- driver->CopyPixels = _swrast_CopyPixels;
- driver->Bitmap = _swrast_Bitmap;
-
- /* Texture functions */
- driver->ChooseTextureFormat = _mesa_choose_tex_format;
- driver->TexImage1D = _mesa_store_teximage1d;
- driver->TexImage2D = _mesa_store_teximage2d;
- driver->TexImage3D = _mesa_store_teximage3d;
- driver->TexSubImage1D = _mesa_store_texsubimage1d;
- driver->TexSubImage2D = _mesa_store_texsubimage2d;
- driver->TexSubImage3D = _mesa_store_texsubimage3d;
- driver->GetTexImage = _mesa_get_teximage;
- driver->CopyTexImage1D = _mesa_meta_CopyTexImage1D;
- driver->CopyTexImage2D = _mesa_meta_CopyTexImage2D;
- driver->CopyTexSubImage1D = _mesa_meta_CopyTexSubImage1D;
- driver->CopyTexSubImage2D = _mesa_meta_CopyTexSubImage2D;
- driver->CopyTexSubImage3D = _mesa_meta_CopyTexSubImage3D;
- driver->GenerateMipmap = _mesa_meta_GenerateMipmap;
- driver->TestProxyTexImage = _mesa_test_proxy_teximage;
- driver->CompressedTexImage1D = _mesa_store_compressed_teximage1d;
- driver->CompressedTexImage2D = _mesa_store_compressed_teximage2d;
- driver->CompressedTexImage3D = _mesa_store_compressed_teximage3d;
- driver->CompressedTexSubImage1D = _mesa_store_compressed_texsubimage1d;
- driver->CompressedTexSubImage2D = _mesa_store_compressed_texsubimage2d;
- driver->CompressedTexSubImage3D = _mesa_store_compressed_texsubimage3d;
- driver->GetCompressedTexImage = _mesa_get_compressed_teximage;
- driver->BindTexture = NULL;
- driver->NewTextureObject = _mesa_new_texture_object;
- driver->DeleteTexture = _mesa_delete_texture_object;
- driver->NewTextureImage = _mesa_new_texture_image;
- driver->FreeTexImageData = _mesa_free_texture_image_data;
- driver->MapTexture = NULL;
- driver->UnmapTexture = NULL;
- driver->TextureMemCpy = memcpy;
- driver->IsTextureResident = NULL;
- driver->UpdateTexturePalette = NULL;
-
- /* imaging */
- driver->CopyColorTable = _mesa_meta_CopyColorTable;
- driver->CopyColorSubTable = _mesa_meta_CopyColorSubTable;
- driver->CopyConvolutionFilter1D = _mesa_meta_CopyConvolutionFilter1D;
- driver->CopyConvolutionFilter2D = _mesa_meta_CopyConvolutionFilter2D;
-
- /* Vertex/fragment programs */
- driver->BindProgram = NULL;
- driver->NewProgram = _mesa_new_program;
- driver->DeleteProgram = _mesa_delete_program;
-
- /* simple state commands */
- driver->AlphaFunc = NULL;
- driver->BlendColor = NULL;
- driver->BlendEquationSeparate = NULL;
- driver->BlendFuncSeparate = NULL;
- driver->ClearColor = NULL;
- driver->ClearDepth = NULL;
- driver->ClearStencil = NULL;
- driver->ClipPlane = NULL;
- driver->ColorMask = NULL;
- driver->ColorMaterial = NULL;
- driver->CullFace = NULL;
- driver->DrawBuffer = NULL;
- driver->DrawBuffers = NULL;
- driver->FrontFace = NULL;
- driver->DepthFunc = NULL;
- driver->DepthMask = NULL;
- driver->DepthRange = NULL;
- driver->Enable = NULL;
- driver->Fogfv = NULL;
- driver->Hint = NULL;
- driver->Lightfv = NULL;
- driver->LightModelfv = NULL;
- driver->LineStipple = NULL;
- driver->LineWidth = NULL;
- driver->LogicOpcode = NULL;
- driver->PointParameterfv = NULL;
- driver->PointSize = NULL;
- driver->PolygonMode = NULL;
- driver->PolygonOffset = NULL;
- driver->PolygonStipple = NULL;
- driver->ReadBuffer = NULL;
- driver->RenderMode = NULL;
- driver->Scissor = NULL;
- driver->ShadeModel = NULL;
- driver->StencilFuncSeparate = NULL;
- driver->StencilOpSeparate = NULL;
- driver->StencilMaskSeparate = NULL;
- driver->TexGen = NULL;
- driver->TexEnv = NULL;
- driver->TexParameter = NULL;
- driver->Viewport = NULL;
-
- /* buffer objects */
- _mesa_init_buffer_object_functions(driver);
-
- /* query objects */
- _mesa_init_query_object_functions(driver);
-
- _mesa_init_sync_object_functions(driver);
-
- driver->NewFramebuffer = _mesa_new_framebuffer;
- driver->NewRenderbuffer = _mesa_new_soft_renderbuffer;
- driver->RenderTexture = _mesa_render_texture;
- driver->FinishRenderTexture = _mesa_finish_render_texture;
- driver->FramebufferRenderbuffer = _mesa_framebuffer_renderbuffer;
-
- driver->BlitFramebuffer = _swrast_BlitFramebuffer;
-
- /* APPLE_vertex_array_object */
- driver->NewArrayObject = _mesa_new_array_object;
- driver->DeleteArrayObject = _mesa_delete_array_object;
- driver->BindArrayObject = NULL;
-
- _mesa_init_shader_object_functions(driver);
-
- _mesa_init_transform_feedback_functions(driver);
-
- /* T&L stuff */
- driver->NeedValidate = GL_FALSE;
- driver->ValidateTnlModule = NULL;
- driver->CurrentExecPrimitive = 0;
- driver->CurrentSavePrimitive = 0;
- driver->NeedFlush = 0;
- driver->SaveNeedFlush = 0;
-
- driver->ProgramStringNotify = _tnl_program_string;
- driver->FlushVertices = NULL;
- driver->SaveFlushVertices = NULL;
- driver->NotifySaveBegin = NULL;
- driver->LightingSpaceChange = NULL;
-
- /* display list */
- driver->NewList = NULL;
- driver->EndList = NULL;
- driver->BeginCallList = NULL;
- driver->EndCallList = NULL;
-}
-
-
-/**
- * Call the ctx->Driver.* state functions with current values to initialize
- * driver state.
- * Only the Intel drivers use this so far.
- */
-void
-_mesa_init_driver_state(GLcontext *ctx)
-{
- ctx->Driver.AlphaFunc(ctx, ctx->Color.AlphaFunc, ctx->Color.AlphaRef);
-
- ctx->Driver.BlendColor(ctx, ctx->Color.BlendColor);
-
- ctx->Driver.BlendEquationSeparate(ctx,
- ctx->Color.BlendEquationRGB,
- ctx->Color.BlendEquationA);
-
- ctx->Driver.BlendFuncSeparate(ctx,
- ctx->Color.BlendSrcRGB,
- ctx->Color.BlendDstRGB,
- ctx->Color.BlendSrcA, ctx->Color.BlendDstA);
-
- if (ctx->Driver.ColorMaskIndexed) {
- GLuint i;
- for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
- ctx->Driver.ColorMaskIndexed(ctx, i,
- ctx->Color.ColorMask[0][RCOMP],
- ctx->Color.ColorMask[0][GCOMP],
- ctx->Color.ColorMask[0][BCOMP],
- ctx->Color.ColorMask[0][ACOMP]);
- }
- }
- else {
- ctx->Driver.ColorMask(ctx,
- ctx->Color.ColorMask[0][RCOMP],
- ctx->Color.ColorMask[0][GCOMP],
- ctx->Color.ColorMask[0][BCOMP],
- ctx->Color.ColorMask[0][ACOMP]);
- }
-
- ctx->Driver.CullFace(ctx, ctx->Polygon.CullFaceMode);
- ctx->Driver.DepthFunc(ctx, ctx->Depth.Func);
- ctx->Driver.DepthMask(ctx, ctx->Depth.Mask);
-
- ctx->Driver.Enable(ctx, GL_ALPHA_TEST, ctx->Color.AlphaEnabled);
- ctx->Driver.Enable(ctx, GL_BLEND, ctx->Color.BlendEnabled);
- ctx->Driver.Enable(ctx, GL_COLOR_LOGIC_OP, ctx->Color.ColorLogicOpEnabled);
- ctx->Driver.Enable(ctx, GL_COLOR_SUM, ctx->Fog.ColorSumEnabled);
- ctx->Driver.Enable(ctx, GL_CULL_FACE, ctx->Polygon.CullFlag);
- ctx->Driver.Enable(ctx, GL_DEPTH_TEST, ctx->Depth.Test);
- ctx->Driver.Enable(ctx, GL_DITHER, ctx->Color.DitherFlag);
- ctx->Driver.Enable(ctx, GL_FOG, ctx->Fog.Enabled);
- ctx->Driver.Enable(ctx, GL_LIGHTING, ctx->Light.Enabled);
- ctx->Driver.Enable(ctx, GL_LINE_SMOOTH, ctx->Line.SmoothFlag);
- ctx->Driver.Enable(ctx, GL_POLYGON_STIPPLE, ctx->Polygon.StippleFlag);
- ctx->Driver.Enable(ctx, GL_SCISSOR_TEST, ctx->Scissor.Enabled);
- ctx->Driver.Enable(ctx, GL_STENCIL_TEST, ctx->Stencil._Enabled);
- ctx->Driver.Enable(ctx, GL_TEXTURE_1D, GL_FALSE);
- ctx->Driver.Enable(ctx, GL_TEXTURE_2D, GL_FALSE);
- ctx->Driver.Enable(ctx, GL_TEXTURE_RECTANGLE_NV, GL_FALSE);
- ctx->Driver.Enable(ctx, GL_TEXTURE_3D, GL_FALSE);
- ctx->Driver.Enable(ctx, GL_TEXTURE_CUBE_MAP, GL_FALSE);
-
- ctx->Driver.Fogfv(ctx, GL_FOG_COLOR, ctx->Fog.Color);
- ctx->Driver.Fogfv(ctx, GL_FOG_MODE, 0);
- ctx->Driver.Fogfv(ctx, GL_FOG_DENSITY, &ctx->Fog.Density);
- ctx->Driver.Fogfv(ctx, GL_FOG_START, &ctx->Fog.Start);
- ctx->Driver.Fogfv(ctx, GL_FOG_END, &ctx->Fog.End);
-
- ctx->Driver.FrontFace(ctx, ctx->Polygon.FrontFace);
-
- {
- GLfloat f = (GLfloat) ctx->Light.Model.ColorControl;
- ctx->Driver.LightModelfv(ctx, GL_LIGHT_MODEL_COLOR_CONTROL, &f);
- }
-
- ctx->Driver.LineWidth(ctx, ctx->Line.Width);
- ctx->Driver.LogicOpcode(ctx, ctx->Color.LogicOp);
- ctx->Driver.PointSize(ctx, ctx->Point.Size);
- ctx->Driver.PolygonStipple(ctx, (const GLubyte *) ctx->PolygonStipple);
- ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
- ctx->Scissor.Width, ctx->Scissor.Height);
- ctx->Driver.ShadeModel(ctx, ctx->Light.ShadeModel);
- ctx->Driver.StencilFuncSeparate(ctx, GL_FRONT,
- ctx->Stencil.Function[0],
- ctx->Stencil.Ref[0],
- ctx->Stencil.ValueMask[0]);
- ctx->Driver.StencilFuncSeparate(ctx, GL_BACK,
- ctx->Stencil.Function[1],
- ctx->Stencil.Ref[1],
- ctx->Stencil.ValueMask[1]);
- ctx->Driver.StencilMaskSeparate(ctx, GL_FRONT, ctx->Stencil.WriteMask[0]);
- ctx->Driver.StencilMaskSeparate(ctx, GL_BACK, ctx->Stencil.WriteMask[1]);
- ctx->Driver.StencilOpSeparate(ctx, GL_FRONT,
- ctx->Stencil.FailFunc[0],
- ctx->Stencil.ZFailFunc[0],
- ctx->Stencil.ZPassFunc[0]);
- ctx->Driver.StencilOpSeparate(ctx, GL_BACK,
- ctx->Stencil.FailFunc[1],
- ctx->Stencil.ZFailFunc[1],
- ctx->Stencil.ZPassFunc[1]);
-
-
- ctx->Driver.DrawBuffer(ctx, ctx->Color.DrawBuffer[0]);
-}
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#include "main/glheader.h"
+#include "main/imports.h"
+#include "main/arrayobj.h"
+#include "main/context.h"
+#include "main/framebuffer.h"
+#include "main/mipmap.h"
+#include "main/queryobj.h"
+#include "main/renderbuffer.h"
+#include "main/shaderobj.h"
+#include "main/texcompress.h"
+#include "main/texformat.h"
+#include "main/texgetimage.h"
+#include "main/teximage.h"
+#include "main/texobj.h"
+#include "main/texstore.h"
+#include "main/bufferobj.h"
+#include "main/fbobject.h"
+#include "main/texrender.h"
+#include "main/syncobj.h"
+#include "main/transformfeedback.h"
+
+#include "program/program.h"
+#include "tnl/tnl.h"
+#include "swrast/swrast.h"
+
+#include "driverfuncs.h"
+#include "meta.h"
+
+
+
+/**
+ * Plug in default functions for all pointers in the dd_function_table
+ * structure.
+ * Device drivers should call this function and then plug in any
+ * functions which it wants to override.
+ * Some functions (pointers) MUST be implemented by all drivers (REQUIRED).
+ *
+ * \param table the dd_function_table to initialize
+ */
+void
+_mesa_init_driver_functions(struct dd_function_table *driver)
+{
+ memset(driver, 0, sizeof(*driver));
+
+ driver->GetString = NULL; /* REQUIRED! */
+ driver->UpdateState = NULL; /* REQUIRED! */
+ driver->GetBufferSize = NULL; /* REQUIRED! */
+ driver->ResizeBuffers = _mesa_resize_framebuffer;
+ driver->Error = NULL;
+
+ driver->Finish = NULL;
+ driver->Flush = NULL;
+
+ /* framebuffer/image functions */
+ driver->Clear = _swrast_Clear;
+ driver->Accum = _swrast_Accum;
+ driver->RasterPos = _tnl_RasterPos;
+ driver->DrawPixels = _swrast_DrawPixels;
+ driver->ReadPixels = _swrast_ReadPixels;
+ driver->CopyPixels = _swrast_CopyPixels;
+ driver->Bitmap = _swrast_Bitmap;
+
+ /* Texture functions */
+ driver->ChooseTextureFormat = _mesa_choose_tex_format;
+ driver->TexImage1D = _mesa_store_teximage1d;
+ driver->TexImage2D = _mesa_store_teximage2d;
+ driver->TexImage3D = _mesa_store_teximage3d;
+ driver->TexSubImage1D = _mesa_store_texsubimage1d;
+ driver->TexSubImage2D = _mesa_store_texsubimage2d;
+ driver->TexSubImage3D = _mesa_store_texsubimage3d;
+ driver->GetTexImage = _mesa_get_teximage;
+ driver->CopyTexImage1D = _mesa_meta_CopyTexImage1D;
+ driver->CopyTexImage2D = _mesa_meta_CopyTexImage2D;
+ driver->CopyTexSubImage1D = _mesa_meta_CopyTexSubImage1D;
+ driver->CopyTexSubImage2D = _mesa_meta_CopyTexSubImage2D;
+ driver->CopyTexSubImage3D = _mesa_meta_CopyTexSubImage3D;
+ driver->GenerateMipmap = _mesa_meta_GenerateMipmap;
+ driver->TestProxyTexImage = _mesa_test_proxy_teximage;
+ driver->CompressedTexImage1D = _mesa_store_compressed_teximage1d;
+ driver->CompressedTexImage2D = _mesa_store_compressed_teximage2d;
+ driver->CompressedTexImage3D = _mesa_store_compressed_teximage3d;
+ driver->CompressedTexSubImage1D = _mesa_store_compressed_texsubimage1d;
+ driver->CompressedTexSubImage2D = _mesa_store_compressed_texsubimage2d;
+ driver->CompressedTexSubImage3D = _mesa_store_compressed_texsubimage3d;
+ driver->GetCompressedTexImage = _mesa_get_compressed_teximage;
+ driver->BindTexture = NULL;
+ driver->NewTextureObject = _mesa_new_texture_object;
+ driver->DeleteTexture = _mesa_delete_texture_object;
+ driver->NewTextureImage = _mesa_new_texture_image;
+ driver->FreeTexImageData = _mesa_free_texture_image_data;
+ driver->MapTexture = NULL;
+ driver->UnmapTexture = NULL;
+ driver->TextureMemCpy = memcpy;
+ driver->IsTextureResident = NULL;
+ driver->UpdateTexturePalette = NULL;
+
+ /* imaging */
+ driver->CopyColorTable = _mesa_meta_CopyColorTable;
+ driver->CopyColorSubTable = _mesa_meta_CopyColorSubTable;
+
+ /* Vertex/fragment programs */
+ driver->BindProgram = NULL;
+ driver->NewProgram = _mesa_new_program;
+ driver->DeleteProgram = _mesa_delete_program;
+
+ /* simple state commands */
+ driver->AlphaFunc = NULL;
+ driver->BlendColor = NULL;
+ driver->BlendEquationSeparate = NULL;
+ driver->BlendFuncSeparate = NULL;
+ driver->ClearColor = NULL;
+ driver->ClearDepth = NULL;
+ driver->ClearStencil = NULL;
+ driver->ClipPlane = NULL;
+ driver->ColorMask = NULL;
+ driver->ColorMaterial = NULL;
+ driver->CullFace = NULL;
+ driver->DrawBuffer = NULL;
+ driver->DrawBuffers = NULL;
+ driver->FrontFace = NULL;
+ driver->DepthFunc = NULL;
+ driver->DepthMask = NULL;
+ driver->DepthRange = NULL;
+ driver->Enable = NULL;
+ driver->Fogfv = NULL;
+ driver->Hint = NULL;
+ driver->Lightfv = NULL;
+ driver->LightModelfv = NULL;
+ driver->LineStipple = NULL;
+ driver->LineWidth = NULL;
+ driver->LogicOpcode = NULL;
+ driver->PointParameterfv = NULL;
+ driver->PointSize = NULL;
+ driver->PolygonMode = NULL;
+ driver->PolygonOffset = NULL;
+ driver->PolygonStipple = NULL;
+ driver->ReadBuffer = NULL;
+ driver->RenderMode = NULL;
+ driver->Scissor = NULL;
+ driver->ShadeModel = NULL;
+ driver->StencilFuncSeparate = NULL;
+ driver->StencilOpSeparate = NULL;
+ driver->StencilMaskSeparate = NULL;
+ driver->TexGen = NULL;
+ driver->TexEnv = NULL;
+ driver->TexParameter = NULL;
+ driver->Viewport = NULL;
+
+ /* buffer objects */
+ _mesa_init_buffer_object_functions(driver);
+
+ /* query objects */
+ _mesa_init_query_object_functions(driver);
+
+ _mesa_init_sync_object_functions(driver);
+
+ driver->NewFramebuffer = _mesa_new_framebuffer;
+ driver->NewRenderbuffer = _mesa_new_soft_renderbuffer;
+ driver->RenderTexture = _mesa_render_texture;
+ driver->FinishRenderTexture = _mesa_finish_render_texture;
+ driver->FramebufferRenderbuffer = _mesa_framebuffer_renderbuffer;
+
+ driver->BlitFramebuffer = _swrast_BlitFramebuffer;
+
+ /* APPLE_vertex_array_object */
+ driver->NewArrayObject = _mesa_new_array_object;
+ driver->DeleteArrayObject = _mesa_delete_array_object;
+ driver->BindArrayObject = NULL;
+
+ _mesa_init_shader_object_functions(driver);
+
+ _mesa_init_transform_feedback_functions(driver);
+
+ /* T&L stuff */
+ driver->NeedValidate = GL_FALSE;
+ driver->ValidateTnlModule = NULL;
+ driver->CurrentExecPrimitive = 0;
+ driver->CurrentSavePrimitive = 0;
+ driver->NeedFlush = 0;
+ driver->SaveNeedFlush = 0;
+
+ driver->ProgramStringNotify = _tnl_program_string;
+ driver->FlushVertices = NULL;
+ driver->SaveFlushVertices = NULL;
+ driver->NotifySaveBegin = NULL;
+ driver->LightingSpaceChange = NULL;
+
+ /* display list */
+ driver->NewList = NULL;
+ driver->EndList = NULL;
+ driver->BeginCallList = NULL;
+ driver->EndCallList = NULL;
+}
+
+
+/**
+ * Call the ctx->Driver.* state functions with current values to initialize
+ * driver state.
+ * Only the Intel drivers use this so far.
+ */
+void
+_mesa_init_driver_state(struct gl_context *ctx)
+{
+ ctx->Driver.AlphaFunc(ctx, ctx->Color.AlphaFunc, ctx->Color.AlphaRef);
+
+ ctx->Driver.BlendColor(ctx, ctx->Color.BlendColor);
+
+ ctx->Driver.BlendEquationSeparate(ctx,
+ ctx->Color.BlendEquationRGB,
+ ctx->Color.BlendEquationA);
+
+ ctx->Driver.BlendFuncSeparate(ctx,
+ ctx->Color.BlendSrcRGB,
+ ctx->Color.BlendDstRGB,
+ ctx->Color.BlendSrcA, ctx->Color.BlendDstA);
+
+ if (ctx->Driver.ColorMaskIndexed) {
+ GLuint i;
+ for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
+ ctx->Driver.ColorMaskIndexed(ctx, i,
+ ctx->Color.ColorMask[0][RCOMP],
+ ctx->Color.ColorMask[0][GCOMP],
+ ctx->Color.ColorMask[0][BCOMP],
+ ctx->Color.ColorMask[0][ACOMP]);
+ }
+ }
+ else {
+ ctx->Driver.ColorMask(ctx,
+ ctx->Color.ColorMask[0][RCOMP],
+ ctx->Color.ColorMask[0][GCOMP],
+ ctx->Color.ColorMask[0][BCOMP],
+ ctx->Color.ColorMask[0][ACOMP]);
+ }
+
+ ctx->Driver.CullFace(ctx, ctx->Polygon.CullFaceMode);
+ ctx->Driver.DepthFunc(ctx, ctx->Depth.Func);
+ ctx->Driver.DepthMask(ctx, ctx->Depth.Mask);
+
+ ctx->Driver.Enable(ctx, GL_ALPHA_TEST, ctx->Color.AlphaEnabled);
+ ctx->Driver.Enable(ctx, GL_BLEND, ctx->Color.BlendEnabled);
+ ctx->Driver.Enable(ctx, GL_COLOR_LOGIC_OP, ctx->Color.ColorLogicOpEnabled);
+ ctx->Driver.Enable(ctx, GL_COLOR_SUM, ctx->Fog.ColorSumEnabled);
+ ctx->Driver.Enable(ctx, GL_CULL_FACE, ctx->Polygon.CullFlag);
+ ctx->Driver.Enable(ctx, GL_DEPTH_TEST, ctx->Depth.Test);
+ ctx->Driver.Enable(ctx, GL_DITHER, ctx->Color.DitherFlag);
+ ctx->Driver.Enable(ctx, GL_FOG, ctx->Fog.Enabled);
+ ctx->Driver.Enable(ctx, GL_LIGHTING, ctx->Light.Enabled);
+ ctx->Driver.Enable(ctx, GL_LINE_SMOOTH, ctx->Line.SmoothFlag);
+ ctx->Driver.Enable(ctx, GL_POLYGON_STIPPLE, ctx->Polygon.StippleFlag);
+ ctx->Driver.Enable(ctx, GL_SCISSOR_TEST, ctx->Scissor.Enabled);
+ ctx->Driver.Enable(ctx, GL_STENCIL_TEST, ctx->Stencil._Enabled);
+ ctx->Driver.Enable(ctx, GL_TEXTURE_1D, GL_FALSE);
+ ctx->Driver.Enable(ctx, GL_TEXTURE_2D, GL_FALSE);
+ ctx->Driver.Enable(ctx, GL_TEXTURE_RECTANGLE_NV, GL_FALSE);
+ ctx->Driver.Enable(ctx, GL_TEXTURE_3D, GL_FALSE);
+ ctx->Driver.Enable(ctx, GL_TEXTURE_CUBE_MAP, GL_FALSE);
+
+ ctx->Driver.Fogfv(ctx, GL_FOG_COLOR, ctx->Fog.Color);
+ ctx->Driver.Fogfv(ctx, GL_FOG_MODE, 0);
+ ctx->Driver.Fogfv(ctx, GL_FOG_DENSITY, &ctx->Fog.Density);
+ ctx->Driver.Fogfv(ctx, GL_FOG_START, &ctx->Fog.Start);
+ ctx->Driver.Fogfv(ctx, GL_FOG_END, &ctx->Fog.End);
+
+ ctx->Driver.FrontFace(ctx, ctx->Polygon.FrontFace);
+
+ {
+ GLfloat f = (GLfloat) ctx->Light.Model.ColorControl;
+ ctx->Driver.LightModelfv(ctx, GL_LIGHT_MODEL_COLOR_CONTROL, &f);
+ }
+
+ ctx->Driver.LineWidth(ctx, ctx->Line.Width);
+ ctx->Driver.LogicOpcode(ctx, ctx->Color.LogicOp);
+ ctx->Driver.PointSize(ctx, ctx->Point.Size);
+ ctx->Driver.PolygonStipple(ctx, (const GLubyte *) ctx->PolygonStipple);
+ ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
+ ctx->Scissor.Width, ctx->Scissor.Height);
+ ctx->Driver.ShadeModel(ctx, ctx->Light.ShadeModel);
+ ctx->Driver.StencilFuncSeparate(ctx, GL_FRONT,
+ ctx->Stencil.Function[0],
+ ctx->Stencil.Ref[0],
+ ctx->Stencil.ValueMask[0]);
+ ctx->Driver.StencilFuncSeparate(ctx, GL_BACK,
+ ctx->Stencil.Function[1],
+ ctx->Stencil.Ref[1],
+ ctx->Stencil.ValueMask[1]);
+ ctx->Driver.StencilMaskSeparate(ctx, GL_FRONT, ctx->Stencil.WriteMask[0]);
+ ctx->Driver.StencilMaskSeparate(ctx, GL_BACK, ctx->Stencil.WriteMask[1]);
+ ctx->Driver.StencilOpSeparate(ctx, GL_FRONT,
+ ctx->Stencil.FailFunc[0],
+ ctx->Stencil.ZFailFunc[0],
+ ctx->Stencil.ZPassFunc[0]);
+ ctx->Driver.StencilOpSeparate(ctx, GL_BACK,
+ ctx->Stencil.FailFunc[1],
+ ctx->Stencil.ZFailFunc[1],
+ ctx->Stencil.ZPassFunc[1]);
+
+
+ ctx->Driver.DrawBuffer(ctx, ctx->Color.DrawBuffer[0]);
+}
diff --git a/mesalib/src/mesa/drivers/common/driverfuncs.h b/mesalib/src/mesa/drivers/common/driverfuncs.h
index 4c90ed12f..31549f65a 100644
--- a/mesalib/src/mesa/drivers/common/driverfuncs.h
+++ b/mesalib/src/mesa/drivers/common/driverfuncs.h
@@ -1,37 +1,37 @@
-/*
- * Mesa 3-D graphics library
- * Version: 7.1
- *
- * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#ifndef DRIVERFUNCS_H
-#define DRIVERFUNCS_H
-
-extern void
-_mesa_init_driver_functions(struct dd_function_table *driver);
-
-
-extern void
-_mesa_init_driver_state(GLcontext *ctx);
-
-
-#endif
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef DRIVERFUNCS_H
+#define DRIVERFUNCS_H
+
+extern void
+_mesa_init_driver_functions(struct dd_function_table *driver);
+
+
+extern void
+_mesa_init_driver_state(struct gl_context *ctx);
+
+
+#endif
diff --git a/mesalib/src/mesa/drivers/common/meta.c b/mesalib/src/mesa/drivers/common/meta.c
index a03cb68ec..b2cd8dca7 100644
--- a/mesalib/src/mesa/drivers/common/meta.c
+++ b/mesalib/src/mesa/drivers/common/meta.c
@@ -1,2868 +1,2854 @@
-/*
- * Mesa 3-D graphics library
- * Version: 7.6
- *
- * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * Meta operations. Some GL operations can be expressed in terms of
- * other GL operations. For example, glBlitFramebuffer() can be done
- * with texture mapping and glClear() can be done with polygon rendering.
- *
- * \author Brian Paul
- */
-
-
-#include "main/glheader.h"
-#include "main/mtypes.h"
-#include "main/imports.h"
-#include "main/arbprogram.h"
-#include "main/arrayobj.h"
-#include "main/blend.h"
-#include "main/bufferobj.h"
-#include "main/buffers.h"
-#include "main/colortab.h"
-#include "main/convolve.h"
-#include "main/depth.h"
-#include "main/enable.h"
-#include "main/fbobject.h"
-#include "main/formats.h"
-#include "main/image.h"
-#include "main/macros.h"
-#include "main/matrix.h"
-#include "main/mipmap.h"
-#include "main/polygon.h"
-#include "main/readpix.h"
-#include "main/scissor.h"
-#include "main/shaderapi.h"
-#include "main/state.h"
-#include "main/stencil.h"
-#include "main/texobj.h"
-#include "main/texenv.h"
-#include "main/teximage.h"
-#include "main/texparam.h"
-#include "main/texstate.h"
-#include "main/varray.h"
-#include "main/viewport.h"
-#include "program/program.h"
-#include "swrast/swrast.h"
-#include "drivers/common/meta.h"
-
-
-/** Return offset in bytes of the field within a vertex struct */
-#define OFFSET(FIELD) ((void *) offsetof(struct vertex, FIELD))
-
-
-/**
- * Flags passed to _mesa_meta_begin().
- */
-/*@{*/
-#define META_ALL ~0x0
-#define META_ALPHA_TEST 0x1
-#define META_BLEND 0x2 /**< includes logicop */
-#define META_COLOR_MASK 0x4
-#define META_DEPTH_TEST 0x8
-#define META_FOG 0x10
-#define META_PIXEL_STORE 0x20
-#define META_PIXEL_TRANSFER 0x40
-#define META_RASTERIZATION 0x80
-#define META_SCISSOR 0x100
-#define META_SHADER 0x200
-#define META_STENCIL_TEST 0x400
-#define META_TRANSFORM 0x800 /**< modelview, projection, clip planes */
-#define META_TEXTURE 0x1000
-#define META_VERTEX 0x2000
-#define META_VIEWPORT 0x4000
-/*@}*/
-
-
-/**
- * State which we may save/restore across meta ops.
- * XXX this may be incomplete...
- */
-struct save_state
-{
- GLbitfield SavedState; /**< bitmask of META_* flags */
-
- /** META_ALPHA_TEST */
- GLboolean AlphaEnabled;
-
- /** META_BLEND */
- GLbitfield BlendEnabled;
- GLboolean ColorLogicOpEnabled;
-
- /** META_COLOR_MASK */
- GLubyte ColorMask[MAX_DRAW_BUFFERS][4];
-
- /** META_DEPTH_TEST */
- struct gl_depthbuffer_attrib Depth;
-
- /** META_FOG */
- GLboolean Fog;
-
- /** META_PIXEL_STORE */
- struct gl_pixelstore_attrib Pack, Unpack;
-
- /** META_PIXEL_TRANSFER */
- GLfloat RedBias, RedScale;
- GLfloat GreenBias, GreenScale;
- GLfloat BlueBias, BlueScale;
- GLfloat AlphaBias, AlphaScale;
- GLfloat DepthBias, DepthScale;
- GLboolean MapColorFlag;
- GLboolean Convolution1DEnabled;
- GLboolean Convolution2DEnabled;
- GLboolean Separable2DEnabled;
-
- /** META_RASTERIZATION */
- GLenum FrontPolygonMode, BackPolygonMode;
- GLboolean PolygonOffset;
- GLboolean PolygonSmooth;
- GLboolean PolygonStipple;
- GLboolean PolygonCull;
-
- /** META_SCISSOR */
- struct gl_scissor_attrib Scissor;
-
- /** META_SHADER */
- GLboolean VertexProgramEnabled;
- struct gl_vertex_program *VertexProgram;
- GLboolean FragmentProgramEnabled;
- struct gl_fragment_program *FragmentProgram;
- GLuint Shader;
-
- /** META_STENCIL_TEST */
- struct gl_stencil_attrib Stencil;
-
- /** META_TRANSFORM */
- GLenum MatrixMode;
- GLfloat ModelviewMatrix[16];
- GLfloat ProjectionMatrix[16];
- GLfloat TextureMatrix[16];
- GLbitfield ClipPlanesEnabled;
-
- /** META_TEXTURE */
- GLuint ActiveUnit;
- GLuint ClientActiveUnit;
- /** for unit[0] only */
- struct gl_texture_object *CurrentTexture[NUM_TEXTURE_TARGETS];
- /** mask of TEXTURE_2D_BIT, etc */
- GLbitfield TexEnabled[MAX_TEXTURE_UNITS];
- GLbitfield TexGenEnabled[MAX_TEXTURE_UNITS];
- GLuint EnvMode; /* unit[0] only */
-
- /** META_VERTEX */
- struct gl_array_object *ArrayObj;
- struct gl_buffer_object *ArrayBufferObj;
-
- /** META_VIEWPORT */
- GLint ViewportX, ViewportY, ViewportW, ViewportH;
- GLclampd DepthNear, DepthFar;
-
- /** Miscellaneous (always disabled) */
- GLboolean Lighting;
-};
-
-
-/**
- * Temporary texture used for glBlitFramebuffer, glDrawPixels, etc.
- * This is currently shared by all the meta ops. But we could create a
- * separate one for each of glDrawPixel, glBlitFramebuffer, glCopyPixels, etc.
- */
-struct temp_texture
-{
- GLuint TexObj;
- GLenum Target; /**< GL_TEXTURE_2D or GL_TEXTURE_RECTANGLE */
- GLsizei MinSize; /**< Min texture size to allocate */
- GLsizei MaxSize; /**< Max possible texture size */
- GLboolean NPOT; /**< Non-power of two size OK? */
- GLsizei Width, Height; /**< Current texture size */
- GLenum IntFormat;
- GLfloat Sright, Ttop; /**< right, top texcoords */
-};
-
-
-/**
- * State for glBlitFramebufer()
- */
-struct blit_state
-{
- GLuint ArrayObj;
- GLuint VBO;
- GLuint DepthFP;
-};
-
-
-/**
- * State for glClear()
- */
-struct clear_state
-{
- GLuint ArrayObj;
- GLuint VBO;
-};
-
-
-/**
- * State for glCopyPixels()
- */
-struct copypix_state
-{
- GLuint ArrayObj;
- GLuint VBO;
-};
-
-
-/**
- * State for glDrawPixels()
- */
-struct drawpix_state
-{
- GLuint ArrayObj;
-
- GLuint StencilFP; /**< Fragment program for drawing stencil images */
- GLuint DepthFP; /**< Fragment program for drawing depth images */
-};
-
-
-/**
- * State for glBitmap()
- */
-struct bitmap_state
-{
- GLuint ArrayObj;
- GLuint VBO;
- struct temp_texture Tex; /**< separate texture from other meta ops */
-};
-
-
-/**
- * State for _mesa_meta_generate_mipmap()
- */
-struct gen_mipmap_state
-{
- GLuint ArrayObj;
- GLuint VBO;
- GLuint FBO;
-};
-
-
-/**
- * All per-context meta state.
- */
-struct gl_meta_state
-{
- struct save_state Save; /**< state saved during meta-ops */
-
- struct temp_texture TempTex;
-
- struct blit_state Blit; /**< For _mesa_meta_BlitFramebuffer() */
- struct clear_state Clear; /**< For _mesa_meta_Clear() */
- struct copypix_state CopyPix; /**< For _mesa_meta_CopyPixels() */
- struct drawpix_state DrawPix; /**< For _mesa_meta_DrawPixels() */
- struct bitmap_state Bitmap; /**< For _mesa_meta_Bitmap() */
- struct gen_mipmap_state Mipmap; /**< For _mesa_meta_GenerateMipmap() */
-};
-
-
-/**
- * Initialize meta-ops for a context.
- * To be called once during context creation.
- */
-void
-_mesa_meta_init(GLcontext *ctx)
-{
- ASSERT(!ctx->Meta);
-
- ctx->Meta = CALLOC_STRUCT(gl_meta_state);
-}
-
-
-/**
- * Free context meta-op state.
- * To be called once during context destruction.
- */
-void
-_mesa_meta_free(GLcontext *ctx)
-{
- /* Note: Any textures, VBOs, etc, that we allocate should get
- * freed by the normal context destruction code. But this would be
- * the place to free other meta data someday.
- */
- free(ctx->Meta);
- ctx->Meta = NULL;
-}
-
-
-/**
- * Enter meta state. This is like a light-weight version of glPushAttrib
- * but it also resets most GL state back to default values.
- *
- * \param state bitmask of META_* flags indicating which attribute groups
- * to save and reset to their defaults
- */
-static void
-_mesa_meta_begin(GLcontext *ctx, GLbitfield state)
-{
- struct save_state *save = &ctx->Meta->Save;
-
- save->SavedState = state;
-
- if (state & META_ALPHA_TEST) {
- save->AlphaEnabled = ctx->Color.AlphaEnabled;
- if (ctx->Color.AlphaEnabled)
- _mesa_set_enable(ctx, GL_ALPHA_TEST, GL_FALSE);
- }
-
- if (state & META_BLEND) {
- save->BlendEnabled = ctx->Color.BlendEnabled;
- if (ctx->Color.BlendEnabled) {
- if (ctx->Extensions.EXT_draw_buffers2) {
- GLuint i;
- for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
- _mesa_set_enablei(ctx, GL_BLEND, i, GL_FALSE);
- }
- }
- else {
- _mesa_set_enable(ctx, GL_BLEND, GL_FALSE);
- }
- }
- save->ColorLogicOpEnabled = ctx->Color.ColorLogicOpEnabled;
- if (ctx->Color.ColorLogicOpEnabled)
- _mesa_set_enable(ctx, GL_COLOR_LOGIC_OP, GL_FALSE);
- }
-
- if (state & META_COLOR_MASK) {
- memcpy(save->ColorMask, ctx->Color.ColorMask,
- sizeof(ctx->Color.ColorMask));
- if (!ctx->Color.ColorMask[0][0] ||
- !ctx->Color.ColorMask[0][1] ||
- !ctx->Color.ColorMask[0][2] ||
- !ctx->Color.ColorMask[0][3])
- _mesa_ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- }
-
- if (state & META_DEPTH_TEST) {
- save->Depth = ctx->Depth; /* struct copy */
- if (ctx->Depth.Test)
- _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_FALSE);
- }
-
- if (state & META_FOG) {
- save->Fog = ctx->Fog.Enabled;
- if (ctx->Fog.Enabled)
- _mesa_set_enable(ctx, GL_FOG, GL_FALSE);
- }
-
- if (state & META_PIXEL_STORE) {
- save->Pack = ctx->Pack;
- save->Unpack = ctx->Unpack;
- ctx->Pack = ctx->DefaultPacking;
- ctx->Unpack = ctx->DefaultPacking;
- }
-
- if (state & META_PIXEL_TRANSFER) {
- save->RedScale = ctx->Pixel.RedScale;
- save->RedBias = ctx->Pixel.RedBias;
- save->GreenScale = ctx->Pixel.GreenScale;
- save->GreenBias = ctx->Pixel.GreenBias;
- save->BlueScale = ctx->Pixel.BlueScale;
- save->BlueBias = ctx->Pixel.BlueBias;
- save->AlphaScale = ctx->Pixel.AlphaScale;
- save->AlphaBias = ctx->Pixel.AlphaBias;
- save->MapColorFlag = ctx->Pixel.MapColorFlag;
- save->Convolution1DEnabled = ctx->Pixel.Convolution1DEnabled;
- save->Convolution2DEnabled = ctx->Pixel.Convolution2DEnabled;
- save->Separable2DEnabled = ctx->Pixel.Separable2DEnabled;
- ctx->Pixel.RedScale = 1.0F;
- ctx->Pixel.RedBias = 0.0F;
- ctx->Pixel.GreenScale = 1.0F;
- ctx->Pixel.GreenBias = 0.0F;
- ctx->Pixel.BlueScale = 1.0F;
- ctx->Pixel.BlueBias = 0.0F;
- ctx->Pixel.AlphaScale = 1.0F;
- ctx->Pixel.AlphaBias = 0.0F;
- ctx->Pixel.MapColorFlag = GL_FALSE;
- ctx->Pixel.Convolution1DEnabled = GL_FALSE;
- ctx->Pixel.Convolution2DEnabled = GL_FALSE;
- ctx->Pixel.Separable2DEnabled = GL_FALSE;
- /* XXX more state */
- ctx->NewState |=_NEW_PIXEL;
- }
-
- if (state & META_RASTERIZATION) {
- save->FrontPolygonMode = ctx->Polygon.FrontMode;
- save->BackPolygonMode = ctx->Polygon.BackMode;
- save->PolygonOffset = ctx->Polygon.OffsetFill;
- save->PolygonSmooth = ctx->Polygon.SmoothFlag;
- save->PolygonStipple = ctx->Polygon.StippleFlag;
- save->PolygonCull = ctx->Polygon.CullFlag;
- _mesa_PolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- _mesa_set_enable(ctx, GL_POLYGON_OFFSET_FILL, GL_FALSE);
- _mesa_set_enable(ctx, GL_POLYGON_SMOOTH, GL_FALSE);
- _mesa_set_enable(ctx, GL_POLYGON_STIPPLE, GL_FALSE);
- _mesa_set_enable(ctx, GL_CULL_FACE, GL_FALSE);
- }
-
- if (state & META_SCISSOR) {
- save->Scissor = ctx->Scissor; /* struct copy */
- _mesa_set_enable(ctx, GL_SCISSOR_TEST, GL_FALSE);
- }
-
- if (state & META_SHADER) {
- if (ctx->Extensions.ARB_vertex_program) {
- save->VertexProgramEnabled = ctx->VertexProgram.Enabled;
- _mesa_reference_vertprog(ctx, &save->VertexProgram,
- ctx->VertexProgram.Current);
- _mesa_set_enable(ctx, GL_VERTEX_PROGRAM_ARB, GL_FALSE);
- }
-
- if (ctx->Extensions.ARB_fragment_program) {
- save->FragmentProgramEnabled = ctx->FragmentProgram.Enabled;
- _mesa_reference_fragprog(ctx, &save->FragmentProgram,
- ctx->FragmentProgram.Current);
- _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_FALSE);
- }
-
- if (ctx->Extensions.ARB_shader_objects) {
- save->Shader = ctx->Shader.CurrentProgram ?
- ctx->Shader.CurrentProgram->Name : 0;
- _mesa_UseProgramObjectARB(0);
- }
- }
-
- if (state & META_STENCIL_TEST) {
- save->Stencil = ctx->Stencil; /* struct copy */
- if (ctx->Stencil.Enabled)
- _mesa_set_enable(ctx, GL_STENCIL_TEST, GL_FALSE);
- /* NOTE: other stencil state not reset */
- }
-
- if (state & META_TEXTURE) {
- GLuint u, tgt;
-
- save->ActiveUnit = ctx->Texture.CurrentUnit;
- save->ClientActiveUnit = ctx->Array.ActiveTexture;
- save->EnvMode = ctx->Texture.Unit[0].EnvMode;
-
- /* Disable all texture units */
- for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
- save->TexEnabled[u] = ctx->Texture.Unit[u].Enabled;
- save->TexGenEnabled[u] = ctx->Texture.Unit[u].TexGenEnabled;
- if (ctx->Texture.Unit[u].Enabled ||
- ctx->Texture.Unit[u].TexGenEnabled) {
- _mesa_ActiveTextureARB(GL_TEXTURE0 + u);
- _mesa_set_enable(ctx, GL_TEXTURE_1D, GL_FALSE);
- _mesa_set_enable(ctx, GL_TEXTURE_2D, GL_FALSE);
- _mesa_set_enable(ctx, GL_TEXTURE_3D, GL_FALSE);
- _mesa_set_enable(ctx, GL_TEXTURE_CUBE_MAP, GL_FALSE);
- _mesa_set_enable(ctx, GL_TEXTURE_RECTANGLE, GL_FALSE);
- _mesa_set_enable(ctx, GL_TEXTURE_GEN_S, GL_FALSE);
- _mesa_set_enable(ctx, GL_TEXTURE_GEN_T, GL_FALSE);
- _mesa_set_enable(ctx, GL_TEXTURE_GEN_R, GL_FALSE);
- _mesa_set_enable(ctx, GL_TEXTURE_GEN_Q, GL_FALSE);
- }
- }
-
- /* save current texture objects for unit[0] only */
- for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
- _mesa_reference_texobj(&save->CurrentTexture[tgt],
- ctx->Texture.Unit[0].CurrentTex[tgt]);
- }
-
- /* set defaults for unit[0] */
- _mesa_ActiveTextureARB(GL_TEXTURE0);
- _mesa_ClientActiveTextureARB(GL_TEXTURE0);
- _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
- }
-
- if (state & META_TRANSFORM) {
- GLuint activeTexture = ctx->Texture.CurrentUnit;
- memcpy(save->ModelviewMatrix, ctx->ModelviewMatrixStack.Top->m,
- 16 * sizeof(GLfloat));
- memcpy(save->ProjectionMatrix, ctx->ProjectionMatrixStack.Top->m,
- 16 * sizeof(GLfloat));
- memcpy(save->TextureMatrix, ctx->TextureMatrixStack[0].Top->m,
- 16 * sizeof(GLfloat));
- save->MatrixMode = ctx->Transform.MatrixMode;
- /* set 1:1 vertex:pixel coordinate transform */
- _mesa_ActiveTextureARB(GL_TEXTURE0);
- _mesa_MatrixMode(GL_TEXTURE);
- _mesa_LoadIdentity();
- _mesa_ActiveTextureARB(GL_TEXTURE0 + activeTexture);
- _mesa_MatrixMode(GL_MODELVIEW);
- _mesa_LoadIdentity();
- _mesa_MatrixMode(GL_PROJECTION);
- _mesa_LoadIdentity();
- _mesa_Ortho(0.0, ctx->DrawBuffer->Width,
- 0.0, ctx->DrawBuffer->Height,
- -1.0, 1.0);
- save->ClipPlanesEnabled = ctx->Transform.ClipPlanesEnabled;
- if (ctx->Transform.ClipPlanesEnabled) {
- GLuint i;
- for (i = 0; i < ctx->Const.MaxClipPlanes; i++) {
- _mesa_set_enable(ctx, GL_CLIP_PLANE0 + i, GL_FALSE);
- }
- }
- }
-
- if (state & META_VERTEX) {
- /* save vertex array object state */
- _mesa_reference_array_object(ctx, &save->ArrayObj,
- ctx->Array.ArrayObj);
- _mesa_reference_buffer_object(ctx, &save->ArrayBufferObj,
- ctx->Array.ArrayBufferObj);
- /* set some default state? */
- }
-
- if (state & META_VIEWPORT) {
- /* save viewport state */
- save->ViewportX = ctx->Viewport.X;
- save->ViewportY = ctx->Viewport.Y;
- save->ViewportW = ctx->Viewport.Width;
- save->ViewportH = ctx->Viewport.Height;
- /* set viewport to match window size */
- if (ctx->Viewport.X != 0 ||
- ctx->Viewport.Y != 0 ||
- ctx->Viewport.Width != ctx->DrawBuffer->Width ||
- ctx->Viewport.Height != ctx->DrawBuffer->Height) {
- _mesa_set_viewport(ctx, 0, 0,
- ctx->DrawBuffer->Width, ctx->DrawBuffer->Height);
- }
- /* save depth range state */
- save->DepthNear = ctx->Viewport.Near;
- save->DepthFar = ctx->Viewport.Far;
- /* set depth range to default */
- _mesa_DepthRange(0.0, 1.0);
- }
-
- /* misc */
- {
- save->Lighting = ctx->Light.Enabled;
- if (ctx->Light.Enabled)
- _mesa_set_enable(ctx, GL_LIGHTING, GL_FALSE);
- }
-}
-
-
-/**
- * Leave meta state. This is like a light-weight version of glPopAttrib().
- */
-static void
-_mesa_meta_end(GLcontext *ctx)
-{
- struct save_state *save = &ctx->Meta->Save;
- const GLbitfield state = save->SavedState;
-
- if (state & META_ALPHA_TEST) {
- if (ctx->Color.AlphaEnabled != save->AlphaEnabled)
- _mesa_set_enable(ctx, GL_ALPHA_TEST, save->AlphaEnabled);
- }
-
- if (state & META_BLEND) {
- if (ctx->Color.BlendEnabled != save->BlendEnabled) {
- if (ctx->Extensions.EXT_draw_buffers2) {
- GLuint i;
- for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
- _mesa_set_enablei(ctx, GL_BLEND, i, (save->BlendEnabled >> i) & 1);
- }
- }
- else {
- _mesa_set_enable(ctx, GL_BLEND, (save->BlendEnabled & 1));
- }
- }
- if (ctx->Color.ColorLogicOpEnabled != save->ColorLogicOpEnabled)
- _mesa_set_enable(ctx, GL_COLOR_LOGIC_OP, save->ColorLogicOpEnabled);
- }
-
- if (state & META_COLOR_MASK) {
- GLuint i;
- for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
- if (!TEST_EQ_4V(ctx->Color.ColorMask[i], save->ColorMask[i])) {
- if (i == 0) {
- _mesa_ColorMask(save->ColorMask[i][0], save->ColorMask[i][1],
- save->ColorMask[i][2], save->ColorMask[i][3]);
- }
- else {
- _mesa_ColorMaskIndexed(i,
- save->ColorMask[i][0],
- save->ColorMask[i][1],
- save->ColorMask[i][2],
- save->ColorMask[i][3]);
- }
- }
- }
- }
-
- if (state & META_DEPTH_TEST) {
- if (ctx->Depth.Test != save->Depth.Test)
- _mesa_set_enable(ctx, GL_DEPTH_TEST, save->Depth.Test);
- _mesa_DepthFunc(save->Depth.Func);
- _mesa_DepthMask(save->Depth.Mask);
- }
-
- if (state & META_FOG) {
- _mesa_set_enable(ctx, GL_FOG, save->Fog);
- }
-
- if (state & META_PIXEL_STORE) {
- ctx->Pack = save->Pack;
- ctx->Unpack = save->Unpack;
- }
-
- if (state & META_PIXEL_TRANSFER) {
- ctx->Pixel.RedScale = save->RedScale;
- ctx->Pixel.RedBias = save->RedBias;
- ctx->Pixel.GreenScale = save->GreenScale;
- ctx->Pixel.GreenBias = save->GreenBias;
- ctx->Pixel.BlueScale = save->BlueScale;
- ctx->Pixel.BlueBias = save->BlueBias;
- ctx->Pixel.AlphaScale = save->AlphaScale;
- ctx->Pixel.AlphaBias = save->AlphaBias;
- ctx->Pixel.MapColorFlag = save->MapColorFlag;
- ctx->Pixel.Convolution1DEnabled = save->Convolution1DEnabled;
- ctx->Pixel.Convolution2DEnabled = save->Convolution2DEnabled;
- ctx->Pixel.Separable2DEnabled = save->Separable2DEnabled;
- /* XXX more state */
- ctx->NewState |=_NEW_PIXEL;
- }
-
- if (state & META_RASTERIZATION) {
- _mesa_PolygonMode(GL_FRONT, save->FrontPolygonMode);
- _mesa_PolygonMode(GL_BACK, save->BackPolygonMode);
- _mesa_set_enable(ctx, GL_POLYGON_STIPPLE, save->PolygonStipple);
- _mesa_set_enable(ctx, GL_POLYGON_OFFSET_FILL, save->PolygonOffset);
- _mesa_set_enable(ctx, GL_POLYGON_SMOOTH, save->PolygonSmooth);
- _mesa_set_enable(ctx, GL_CULL_FACE, save->PolygonCull);
- }
-
- if (state & META_SCISSOR) {
- _mesa_set_enable(ctx, GL_SCISSOR_TEST, save->Scissor.Enabled);
- _mesa_Scissor(save->Scissor.X, save->Scissor.Y,
- save->Scissor.Width, save->Scissor.Height);
- }
-
- if (state & META_SHADER) {
- if (ctx->Extensions.ARB_vertex_program) {
- _mesa_set_enable(ctx, GL_VERTEX_PROGRAM_ARB,
- save->VertexProgramEnabled);
- _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
- save->VertexProgram);
- _mesa_reference_vertprog(ctx, &save->VertexProgram, NULL);
- }
-
- if (ctx->Extensions.ARB_fragment_program) {
- _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB,
- save->FragmentProgramEnabled);
- _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current,
- save->FragmentProgram);
- _mesa_reference_fragprog(ctx, &save->FragmentProgram, NULL);
- }
-
- if (ctx->Extensions.ARB_shader_objects) {
- _mesa_UseProgramObjectARB(save->Shader);
- }
- }
-
- if (state & META_STENCIL_TEST) {
- const struct gl_stencil_attrib *stencil = &save->Stencil;
-
- _mesa_set_enable(ctx, GL_STENCIL_TEST, stencil->Enabled);
- _mesa_ClearStencil(stencil->Clear);
- if (ctx->Extensions.EXT_stencil_two_side) {
- _mesa_set_enable(ctx, GL_STENCIL_TEST_TWO_SIDE_EXT,
- stencil->TestTwoSide);
- _mesa_ActiveStencilFaceEXT(stencil->ActiveFace
- ? GL_BACK : GL_FRONT);
- }
- /* front state */
- _mesa_StencilFuncSeparate(GL_FRONT,
- stencil->Function[0],
- stencil->Ref[0],
- stencil->ValueMask[0]);
- _mesa_StencilMaskSeparate(GL_FRONT, stencil->WriteMask[0]);
- _mesa_StencilOpSeparate(GL_FRONT, stencil->FailFunc[0],
- stencil->ZFailFunc[0],
- stencil->ZPassFunc[0]);
- /* back state */
- _mesa_StencilFuncSeparate(GL_BACK,
- stencil->Function[1],
- stencil->Ref[1],
- stencil->ValueMask[1]);
- _mesa_StencilMaskSeparate(GL_BACK, stencil->WriteMask[1]);
- _mesa_StencilOpSeparate(GL_BACK, stencil->FailFunc[1],
- stencil->ZFailFunc[1],
- stencil->ZPassFunc[1]);
- }
-
- if (state & META_TEXTURE) {
- GLuint u, tgt;
-
- ASSERT(ctx->Texture.CurrentUnit == 0);
-
- /* restore texenv for unit[0] */
- _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, save->EnvMode);
-
- /* restore texture objects for unit[0] only */
- for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
- _mesa_reference_texobj(&ctx->Texture.Unit[0].CurrentTex[tgt],
- save->CurrentTexture[tgt]);
- _mesa_reference_texobj(&save->CurrentTexture[tgt], NULL);
- }
-
- /* Re-enable textures, texgen */
- for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
- if (save->TexEnabled[u]) {
- _mesa_ActiveTextureARB(GL_TEXTURE0 + u);
-
- if (save->TexEnabled[u] & TEXTURE_1D_BIT)
- _mesa_set_enable(ctx, GL_TEXTURE_1D, GL_TRUE);
- if (save->TexEnabled[u] & TEXTURE_2D_BIT)
- _mesa_set_enable(ctx, GL_TEXTURE_2D, GL_TRUE);
- if (save->TexEnabled[u] & TEXTURE_3D_BIT)
- _mesa_set_enable(ctx, GL_TEXTURE_3D, GL_TRUE);
- if (save->TexEnabled[u] & TEXTURE_CUBE_BIT)
- _mesa_set_enable(ctx, GL_TEXTURE_CUBE_MAP, GL_TRUE);
- if (save->TexEnabled[u] & TEXTURE_RECT_BIT)
- _mesa_set_enable(ctx, GL_TEXTURE_RECTANGLE, GL_TRUE);
- }
-
- if (save->TexGenEnabled[u]) {
- _mesa_ActiveTextureARB(GL_TEXTURE0 + u);
-
- if (save->TexGenEnabled[u] & S_BIT)
- _mesa_set_enable(ctx, GL_TEXTURE_GEN_S, GL_TRUE);
- if (save->TexGenEnabled[u] & T_BIT)
- _mesa_set_enable(ctx, GL_TEXTURE_GEN_T, GL_TRUE);
- if (save->TexGenEnabled[u] & R_BIT)
- _mesa_set_enable(ctx, GL_TEXTURE_GEN_R, GL_TRUE);
- if (save->TexGenEnabled[u] & Q_BIT)
- _mesa_set_enable(ctx, GL_TEXTURE_GEN_Q, GL_TRUE);
- }
- }
-
- /* restore current unit state */
- _mesa_ActiveTextureARB(GL_TEXTURE0 + save->ActiveUnit);
- _mesa_ClientActiveTextureARB(GL_TEXTURE0 + save->ClientActiveUnit);
- }
-
- if (state & META_TRANSFORM) {
- GLuint activeTexture = ctx->Texture.CurrentUnit;
- _mesa_ActiveTextureARB(GL_TEXTURE0);
- _mesa_MatrixMode(GL_TEXTURE);
- _mesa_LoadMatrixf(save->TextureMatrix);
- _mesa_ActiveTextureARB(GL_TEXTURE0 + activeTexture);
-
- _mesa_MatrixMode(GL_MODELVIEW);
- _mesa_LoadMatrixf(save->ModelviewMatrix);
-
- _mesa_MatrixMode(GL_PROJECTION);
- _mesa_LoadMatrixf(save->ProjectionMatrix);
-
- _mesa_MatrixMode(save->MatrixMode);
-
- if (save->ClipPlanesEnabled) {
- GLuint i;
- for (i = 0; i < ctx->Const.MaxClipPlanes; i++) {
- if (save->ClipPlanesEnabled & (1 << i)) {
- _mesa_set_enable(ctx, GL_CLIP_PLANE0 + i, GL_TRUE);
- }
- }
- }
- }
-
- if (state & META_VERTEX) {
- /* restore vertex buffer object */
- _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, save->ArrayBufferObj->Name);
- _mesa_reference_buffer_object(ctx, &save->ArrayBufferObj, NULL);
-
- /* restore vertex array object */
- _mesa_BindVertexArray(save->ArrayObj->Name);
- _mesa_reference_array_object(ctx, &save->ArrayObj, NULL);
- }
-
- if (state & META_VIEWPORT) {
- if (save->ViewportX != ctx->Viewport.X ||
- save->ViewportY != ctx->Viewport.Y ||
- save->ViewportW != ctx->Viewport.Width ||
- save->ViewportH != ctx->Viewport.Height) {
- _mesa_set_viewport(ctx, save->ViewportX, save->ViewportY,
- save->ViewportW, save->ViewportH);
- }
- _mesa_DepthRange(save->DepthNear, save->DepthFar);
- }
-
- /* misc */
- if (save->Lighting) {
- _mesa_set_enable(ctx, GL_LIGHTING, GL_TRUE);
- }
-}
-
-
-/**
- * Convert Z from a normalized value in the range [0, 1] to an object-space
- * Z coordinate in [-1, +1] so that drawing at the new Z position with the
- * default/identity ortho projection results in the original Z value.
- * Used by the meta-Clear, Draw/CopyPixels and Bitmap functions where the Z
- * value comes from the clear value or raster position.
- */
-static INLINE GLfloat
-invert_z(GLfloat normZ)
-{
- GLfloat objZ = 1.0 - 2.0 * normZ;
- return objZ;
-}
-
-
-/**
- * One-time init for a temp_texture object.
- * Choose tex target, compute max tex size, etc.
- */
-static void
-init_temp_texture(GLcontext *ctx, struct temp_texture *tex)
-{
- /* prefer texture rectangle */
- if (ctx->Extensions.NV_texture_rectangle) {
- tex->Target = GL_TEXTURE_RECTANGLE;
- tex->MaxSize = ctx->Const.MaxTextureRectSize;
- tex->NPOT = GL_TRUE;
- }
- else {
- /* use 2D texture, NPOT if possible */
- tex->Target = GL_TEXTURE_2D;
- tex->MaxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
- tex->NPOT = ctx->Extensions.ARB_texture_non_power_of_two;
- }
- tex->MinSize = 16; /* 16 x 16 at least */
- assert(tex->MaxSize > 0);
-
- _mesa_GenTextures(1, &tex->TexObj);
- _mesa_BindTexture(tex->Target, tex->TexObj);
-}
-
-
-/**
- * Return pointer to temp_texture info for non-bitmap ops.
- * This does some one-time init if needed.
- */
-static struct temp_texture *
-get_temp_texture(GLcontext *ctx)
-{
- struct temp_texture *tex = &ctx->Meta->TempTex;
-
- if (!tex->TexObj) {
- init_temp_texture(ctx, tex);
- }
-
- return tex;
-}
-
-
-/**
- * Return pointer to temp_texture info for _mesa_meta_bitmap().
- * We use a separate texture for bitmaps to reduce texture
- * allocation/deallocation.
- */
-static struct temp_texture *
-get_bitmap_temp_texture(GLcontext *ctx)
-{
- struct temp_texture *tex = &ctx->Meta->Bitmap.Tex;
-
- if (!tex->TexObj) {
- init_temp_texture(ctx, tex);
- }
-
- return tex;
-}
-
-
-/**
- * Compute the width/height of texture needed to draw an image of the
- * given size. Return a flag indicating whether the current texture
- * can be re-used (glTexSubImage2D) or if a new texture needs to be
- * allocated (glTexImage2D).
- * Also, compute s/t texcoords for drawing.
- *
- * \return GL_TRUE if new texture is needed, GL_FALSE otherwise
- */
-static GLboolean
-alloc_texture(struct temp_texture *tex,
- GLsizei width, GLsizei height, GLenum intFormat)
-{
- GLboolean newTex = GL_FALSE;
-
- ASSERT(width <= tex->MaxSize);
- ASSERT(height <= tex->MaxSize);
-
- if (width > tex->Width ||
- height > tex->Height ||
- intFormat != tex->IntFormat) {
- /* alloc new texture (larger or different format) */
-
- if (tex->NPOT) {
- /* use non-power of two size */
- tex->Width = MAX2(tex->MinSize, width);
- tex->Height = MAX2(tex->MinSize, height);
- }
- else {
- /* find power of two size */
- GLsizei w, h;
- w = h = tex->MinSize;
- while (w < width)
- w *= 2;
- while (h < height)
- h *= 2;
- tex->Width = w;
- tex->Height = h;
- }
-
- tex->IntFormat = intFormat;
-
- newTex = GL_TRUE;
- }
-
- /* compute texcoords */
- if (tex->Target == GL_TEXTURE_RECTANGLE) {
- tex->Sright = (GLfloat) width;
- tex->Ttop = (GLfloat) height;
- }
- else {
- tex->Sright = (GLfloat) width / tex->Width;
- tex->Ttop = (GLfloat) height / tex->Height;
- }
-
- return newTex;
-}
-
-
-/**
- * Setup/load texture for glCopyPixels or glBlitFramebuffer.
- */
-static void
-setup_copypix_texture(struct temp_texture *tex,
- GLboolean newTex,
- GLint srcX, GLint srcY,
- GLsizei width, GLsizei height, GLenum intFormat,
- GLenum filter)
-{
- _mesa_BindTexture(tex->Target, tex->TexObj);
- _mesa_TexParameteri(tex->Target, GL_TEXTURE_MIN_FILTER, filter);
- _mesa_TexParameteri(tex->Target, GL_TEXTURE_MAG_FILTER, filter);
- _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
-
- /* copy framebuffer image to texture */
- if (newTex) {
- /* create new tex image */
- if (tex->Width == width && tex->Height == height) {
- /* create new tex with framebuffer data */
- _mesa_CopyTexImage2D(tex->Target, 0, tex->IntFormat,
- srcX, srcY, width, height, 0);
- }
- else {
- /* create empty texture */
- _mesa_TexImage2D(tex->Target, 0, tex->IntFormat,
- tex->Width, tex->Height, 0,
- intFormat, GL_UNSIGNED_BYTE, NULL);
- /* load image */
- _mesa_CopyTexSubImage2D(tex->Target, 0,
- 0, 0, srcX, srcY, width, height);
- }
- }
- else {
- /* replace existing tex image */
- _mesa_CopyTexSubImage2D(tex->Target, 0,
- 0, 0, srcX, srcY, width, height);
- }
-}
-
-
-/**
- * Setup/load texture for glDrawPixels.
- */
-static void
-setup_drawpix_texture(GLcontext *ctx,
- struct temp_texture *tex,
- GLboolean newTex,
- GLenum texIntFormat,
- GLsizei width, GLsizei height,
- GLenum format, GLenum type,
- const GLvoid *pixels)
-{
- _mesa_BindTexture(tex->Target, tex->TexObj);
- _mesa_TexParameteri(tex->Target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- _mesa_TexParameteri(tex->Target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
-
- /* copy pixel data to texture */
- if (newTex) {
- /* create new tex image */
- if (tex->Width == width && tex->Height == height) {
- /* create new tex and load image data */
- _mesa_TexImage2D(tex->Target, 0, tex->IntFormat,
- tex->Width, tex->Height, 0, format, type, pixels);
- }
- else {
- struct gl_buffer_object *save_unpack_obj = NULL;
-
- _mesa_reference_buffer_object(ctx, &save_unpack_obj,
- ctx->Unpack.BufferObj);
- _mesa_BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
- /* create empty texture */
- _mesa_TexImage2D(tex->Target, 0, tex->IntFormat,
- tex->Width, tex->Height, 0, format, type, NULL);
- if (save_unpack_obj != NULL)
- _mesa_BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB,
- save_unpack_obj->Name);
- /* load image */
- _mesa_TexSubImage2D(tex->Target, 0,
- 0, 0, width, height, format, type, pixels);
- }
- }
- else {
- /* replace existing tex image */
- _mesa_TexSubImage2D(tex->Target, 0,
- 0, 0, width, height, format, type, pixels);
- }
-}
-
-
-
-/**
- * One-time init for drawing depth pixels.
- */
-static void
-init_blit_depth_pixels(GLcontext *ctx)
-{
- static const char *program =
- "!!ARBfp1.0\n"
- "TEX result.depth, fragment.texcoord[0], texture[0], %s; \n"
- "END \n";
- char program2[200];
- struct blit_state *blit = &ctx->Meta->Blit;
- struct temp_texture *tex = get_temp_texture(ctx);
- const char *texTarget;
-
- assert(blit->DepthFP == 0);
-
- /* replace %s with "RECT" or "2D" */
- assert(strlen(program) + 4 < sizeof(program2));
- if (tex->Target == GL_TEXTURE_RECTANGLE)
- texTarget = "RECT";
- else
- texTarget = "2D";
- _mesa_snprintf(program2, sizeof(program2), program, texTarget);
-
- _mesa_GenPrograms(1, &blit->DepthFP);
- _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, blit->DepthFP);
- _mesa_ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
- strlen(program2), (const GLubyte *) program2);
-}
-
-
-/**
- * Try to do a glBlitFramebuffer using no-copy texturing.
- * We can do this when the src renderbuffer is actually a texture.
- * But if the src buffer == dst buffer we cannot do this.
- *
- * \return new buffer mask indicating the buffers left to blit using the
- * normal path.
- */
-static GLbitfield
-blitframebuffer_texture(GLcontext *ctx,
- GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
- GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
- GLbitfield mask, GLenum filter)
-{
- if (mask & GL_COLOR_BUFFER_BIT) {
- const struct gl_framebuffer *drawFb = ctx->DrawBuffer;
- const struct gl_framebuffer *readFb = ctx->ReadBuffer;
- const struct gl_renderbuffer_attachment *drawAtt =
- &drawFb->Attachment[drawFb->_ColorDrawBufferIndexes[0]];
- const struct gl_renderbuffer_attachment *readAtt =
- &readFb->Attachment[readFb->_ColorReadBufferIndex];
-
- if (readAtt && readAtt->Texture) {
- const struct gl_texture_object *texObj = readAtt->Texture;
- const GLuint srcLevel = readAtt->TextureLevel;
- const GLenum minFilterSave = texObj->MinFilter;
- const GLenum magFilterSave = texObj->MagFilter;
- const GLint baseLevelSave = texObj->BaseLevel;
- const GLint maxLevelSave = texObj->MaxLevel;
- const GLenum wrapSSave = texObj->WrapS;
- const GLenum wrapTSave = texObj->WrapT;
- const GLenum target = texObj->Target;
-
- if (drawAtt->Texture == readAtt->Texture) {
- /* Can't use same texture as both the source and dest. We need
- * to handle overlapping blits and besides, some hw may not
- * support this.
- */
- return mask;
- }
-
- if (target != GL_TEXTURE_2D && target != GL_TEXTURE_RECTANGLE_ARB) {
- /* Can't handle other texture types at this time */
- return mask;
- }
-
- /*
- printf("Blit from texture!\n");
- printf(" srcAtt %p dstAtt %p\n", readAtt, drawAtt);
- printf(" srcTex %p dstText %p\n", texObj, drawAtt->Texture);
- */
-
- /* Prepare src texture state */
- _mesa_BindTexture(target, texObj->Name);
- _mesa_TexParameteri(target, GL_TEXTURE_MIN_FILTER, filter);
- _mesa_TexParameteri(target, GL_TEXTURE_MAG_FILTER, filter);
- if (target != GL_TEXTURE_RECTANGLE_ARB) {
- _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, srcLevel);
- _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, srcLevel);
- }
- _mesa_TexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- _mesa_TexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
- _mesa_set_enable(ctx, target, GL_TRUE);
-
- /* Prepare vertex data (the VBO was previously created and bound) */
- {
- struct vertex {
- GLfloat x, y, s, t;
- };
- struct vertex verts[4];
- GLfloat s0, t0, s1, t1;
-
- if (target == GL_TEXTURE_2D) {
- const struct gl_texture_image *texImage
- = _mesa_select_tex_image(ctx, texObj, target, srcLevel);
- s0 = srcX0 / (float) texImage->Width;
- s1 = srcX1 / (float) texImage->Width;
- t0 = srcY0 / (float) texImage->Height;
- t1 = srcY1 / (float) texImage->Height;
- }
- else {
- assert(target == GL_TEXTURE_RECTANGLE_ARB);
- s0 = srcX0;
- s1 = srcX1;
- t0 = srcY0;
- t1 = srcY1;
- }
-
- verts[0].x = (GLfloat) dstX0;
- verts[0].y = (GLfloat) dstY0;
- verts[1].x = (GLfloat) dstX1;
- verts[1].y = (GLfloat) dstY0;
- verts[2].x = (GLfloat) dstX1;
- verts[2].y = (GLfloat) dstY1;
- verts[3].x = (GLfloat) dstX0;
- verts[3].y = (GLfloat) dstY1;
-
- verts[0].s = s0;
- verts[0].t = t0;
- verts[1].s = s1;
- verts[1].t = t0;
- verts[2].s = s1;
- verts[2].t = t1;
- verts[3].s = s0;
- verts[3].t = t1;
-
- _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts);
- }
-
- _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
-
- /* Restore texture object state, the texture binding will
- * be restored by _mesa_meta_end().
- */
- _mesa_TexParameteri(target, GL_TEXTURE_MIN_FILTER, minFilterSave);
- _mesa_TexParameteri(target, GL_TEXTURE_MAG_FILTER, magFilterSave);
- if (target != GL_TEXTURE_RECTANGLE_ARB) {
- _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, baseLevelSave);
- _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, maxLevelSave);
- }
- _mesa_TexParameteri(target, GL_TEXTURE_WRAP_S, wrapSSave);
- _mesa_TexParameteri(target, GL_TEXTURE_WRAP_T, wrapTSave);
-
- /* Done with color buffer */
- mask &= ~GL_COLOR_BUFFER_BIT;
- }
- }
-
- return mask;
-}
-
-
-/**
- * Meta implementation of ctx->Driver.BlitFramebuffer() in terms
- * of texture mapping and polygon rendering.
- */
-void
-_mesa_meta_BlitFramebuffer(GLcontext *ctx,
- GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
- GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
- GLbitfield mask, GLenum filter)
-{
- struct blit_state *blit = &ctx->Meta->Blit;
- struct temp_texture *tex = get_temp_texture(ctx);
- const GLsizei maxTexSize = tex->MaxSize;
- const GLint srcX = MIN2(srcX0, srcX1);
- const GLint srcY = MIN2(srcY0, srcY1);
- const GLint srcW = abs(srcX1 - srcX0);
- const GLint srcH = abs(srcY1 - srcY0);
- const GLboolean srcFlipX = srcX1 < srcX0;
- const GLboolean srcFlipY = srcY1 < srcY0;
- struct vertex {
- GLfloat x, y, s, t;
- };
- struct vertex verts[4];
- GLboolean newTex;
-
- if (srcW > maxTexSize || srcH > maxTexSize) {
- /* XXX avoid this fallback */
- _swrast_BlitFramebuffer(ctx, srcX0, srcY0, srcX1, srcY1,
- dstX0, dstY0, dstX1, dstY1, mask, filter);
- return;
- }
-
- if (srcFlipX) {
- GLint tmp = dstX0;
- dstX0 = dstX1;
- dstX1 = tmp;
- }
-
- if (srcFlipY) {
- GLint tmp = dstY0;
- dstY0 = dstY1;
- dstY1 = tmp;
- }
-
- /* only scissor effects blit so save/clear all other relevant state */
- _mesa_meta_begin(ctx, ~META_SCISSOR);
-
- if (blit->ArrayObj == 0) {
- /* one-time setup */
-
- /* create vertex array object */
- _mesa_GenVertexArrays(1, &blit->ArrayObj);
- _mesa_BindVertexArray(blit->ArrayObj);
-
- /* create vertex array buffer */
- _mesa_GenBuffersARB(1, &blit->VBO);
- _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, blit->VBO);
- _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts),
- NULL, GL_DYNAMIC_DRAW_ARB);
-
- /* setup vertex arrays */
- _mesa_VertexPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(x));
- _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(s));
- _mesa_EnableClientState(GL_VERTEX_ARRAY);
- _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY);
- }
- else {
- _mesa_BindVertexArray(blit->ArrayObj);
- _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, blit->VBO);
- }
-
- /* Try faster, direct texture approach first */
- mask = blitframebuffer_texture(ctx, srcX0, srcY0, srcX1, srcY1,
- dstX0, dstY0, dstX1, dstY1, mask, filter);
- if (mask == 0x0) {
- _mesa_meta_end(ctx);
- return;
- }
-
- /* Continue with "normal" approach which involves copying the src rect
- * into a temporary texture and is "blitted" by drawing a textured quad.
- */
-
- newTex = alloc_texture(tex, srcW, srcH, GL_RGBA);
-
- /* vertex positions/texcoords (after texture allocation!) */
- {
- verts[0].x = (GLfloat) dstX0;
- verts[0].y = (GLfloat) dstY0;
- verts[1].x = (GLfloat) dstX1;
- verts[1].y = (GLfloat) dstY0;
- verts[2].x = (GLfloat) dstX1;
- verts[2].y = (GLfloat) dstY1;
- verts[3].x = (GLfloat) dstX0;
- verts[3].y = (GLfloat) dstY1;
-
- verts[0].s = 0.0F;
- verts[0].t = 0.0F;
- verts[1].s = tex->Sright;
- verts[1].t = 0.0F;
- verts[2].s = tex->Sright;
- verts[2].t = tex->Ttop;
- verts[3].s = 0.0F;
- verts[3].t = tex->Ttop;
-
- /* upload new vertex data */
- _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts);
- }
-
- _mesa_set_enable(ctx, tex->Target, GL_TRUE);
-
- if (mask & GL_COLOR_BUFFER_BIT) {
- setup_copypix_texture(tex, newTex, srcX, srcY, srcW, srcH,
- GL_RGBA, filter);
- _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
- mask &= ~GL_COLOR_BUFFER_BIT;
- }
-
- if (mask & GL_DEPTH_BUFFER_BIT) {
- GLuint *tmp = (GLuint *) malloc(srcW * srcH * sizeof(GLuint));
- if (tmp) {
- if (!blit->DepthFP)
- init_blit_depth_pixels(ctx);
-
- /* maybe change tex format here */
- newTex = alloc_texture(tex, srcW, srcH, GL_DEPTH_COMPONENT);
-
- _mesa_ReadPixels(srcX, srcY, srcW, srcH,
- GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, tmp);
-
- setup_drawpix_texture(ctx, tex, newTex, GL_DEPTH_COMPONENT, srcW, srcH,
- GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, tmp);
-
- _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, blit->DepthFP);
- _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_TRUE);
- _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
- _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_TRUE);
- _mesa_DepthFunc(GL_ALWAYS);
- _mesa_DepthMask(GL_TRUE);
-
- _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
- mask &= ~GL_DEPTH_BUFFER_BIT;
-
- free(tmp);
- }
- }
-
- if (mask & GL_STENCIL_BUFFER_BIT) {
- /* XXX can't easily do stencil */
- }
-
- _mesa_set_enable(ctx, tex->Target, GL_FALSE);
-
- _mesa_meta_end(ctx);
-
- if (mask) {
- _swrast_BlitFramebuffer(ctx, srcX0, srcY0, srcX1, srcY1,
- dstX0, dstY0, dstX1, dstY1, mask, filter);
- }
-}
-
-
-/**
- * Meta implementation of ctx->Driver.Clear() in terms of polygon rendering.
- */
-void
-_mesa_meta_Clear(GLcontext *ctx, GLbitfield buffers)
-{
- struct clear_state *clear = &ctx->Meta->Clear;
- struct vertex {
- GLfloat x, y, z, r, g, b, a;
- };
- struct vertex verts[4];
- /* save all state but scissor, pixel pack/unpack */
- GLbitfield metaSave = META_ALL - META_SCISSOR - META_PIXEL_STORE;
-
- if (buffers & BUFFER_BITS_COLOR) {
- /* if clearing color buffers, don't save/restore colormask */
- metaSave -= META_COLOR_MASK;
- }
-
- _mesa_meta_begin(ctx, metaSave);
-
- if (clear->ArrayObj == 0) {
- /* one-time setup */
-
- /* create vertex array object */
- _mesa_GenVertexArrays(1, &clear->ArrayObj);
- _mesa_BindVertexArray(clear->ArrayObj);
-
- /* create vertex array buffer */
- _mesa_GenBuffersARB(1, &clear->VBO);
- _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, clear->VBO);
-
- /* setup vertex arrays */
- _mesa_VertexPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(x));
- _mesa_ColorPointer(4, GL_FLOAT, sizeof(struct vertex), OFFSET(r));
- _mesa_EnableClientState(GL_VERTEX_ARRAY);
- _mesa_EnableClientState(GL_COLOR_ARRAY);
- }
- else {
- _mesa_BindVertexArray(clear->ArrayObj);
- _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, clear->VBO);
- }
-
- /* GL_COLOR_BUFFER_BIT */
- if (buffers & BUFFER_BITS_COLOR) {
- /* leave colormask, glDrawBuffer state as-is */
- }
- else {
- ASSERT(metaSave & META_COLOR_MASK);
- _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
- }
-
- /* GL_DEPTH_BUFFER_BIT */
- if (buffers & BUFFER_BIT_DEPTH) {
- _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_TRUE);
- _mesa_DepthFunc(GL_ALWAYS);
- _mesa_DepthMask(GL_TRUE);
- }
- else {
- assert(!ctx->Depth.Test);
- }
-
- /* GL_STENCIL_BUFFER_BIT */
- if (buffers & BUFFER_BIT_STENCIL) {
- _mesa_set_enable(ctx, GL_STENCIL_TEST, GL_TRUE);
- _mesa_StencilOpSeparate(GL_FRONT_AND_BACK,
- GL_REPLACE, GL_REPLACE, GL_REPLACE);
- _mesa_StencilFuncSeparate(GL_FRONT_AND_BACK, GL_ALWAYS,
- ctx->Stencil.Clear & 0x7fffffff,
- ctx->Stencil.WriteMask[0]);
- }
- else {
- assert(!ctx->Stencil.Enabled);
- }
-
- /* vertex positions/colors */
- {
- const GLfloat x0 = (GLfloat) ctx->DrawBuffer->_Xmin;
- const GLfloat y0 = (GLfloat) ctx->DrawBuffer->_Ymin;
- const GLfloat x1 = (GLfloat) ctx->DrawBuffer->_Xmax;
- const GLfloat y1 = (GLfloat) ctx->DrawBuffer->_Ymax;
- const GLfloat z = invert_z(ctx->Depth.Clear);
- GLuint i;
-
- verts[0].x = x0;
- verts[0].y = y0;
- verts[0].z = z;
- verts[1].x = x1;
- verts[1].y = y0;
- verts[1].z = z;
- verts[2].x = x1;
- verts[2].y = y1;
- verts[2].z = z;
- verts[3].x = x0;
- verts[3].y = y1;
- verts[3].z = z;
-
- /* vertex colors */
- for (i = 0; i < 4; i++) {
- verts[i].r = ctx->Color.ClearColor[0];
- verts[i].g = ctx->Color.ClearColor[1];
- verts[i].b = ctx->Color.ClearColor[2];
- verts[i].a = ctx->Color.ClearColor[3];
- }
-
- /* upload new vertex data */
- _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts), verts,
- GL_DYNAMIC_DRAW_ARB);
- }
-
- /* draw quad */
- _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
-
- _mesa_meta_end(ctx);
-}
-
-
-/**
- * Meta implementation of ctx->Driver.CopyPixels() in terms
- * of texture mapping and polygon rendering.
- */
-void
-_mesa_meta_CopyPixels(GLcontext *ctx, GLint srcX, GLint srcY,
- GLsizei width, GLsizei height,
- GLint dstX, GLint dstY, GLenum type)
-{
- struct copypix_state *copypix = &ctx->Meta->CopyPix;
- struct temp_texture *tex = get_temp_texture(ctx);
- struct vertex {
- GLfloat x, y, z, s, t;
- };
- struct vertex verts[4];
- GLboolean newTex;
- GLenum intFormat = GL_RGBA;
-
- if (type != GL_COLOR ||
- ctx->_ImageTransferState ||
- ctx->Fog.Enabled ||
- width > tex->MaxSize ||
- height > tex->MaxSize) {
- /* XXX avoid this fallback */
- _swrast_CopyPixels(ctx, srcX, srcY, width, height, dstX, dstY, type);
- return;
- }
-
- /* Most GL state applies to glCopyPixels, but a there's a few things
- * we need to override:
- */
- _mesa_meta_begin(ctx, (META_RASTERIZATION |
- META_SHADER |
- META_TEXTURE |
- META_TRANSFORM |
- META_VERTEX |
- META_VIEWPORT));
-
- if (copypix->ArrayObj == 0) {
- /* one-time setup */
-
- /* create vertex array object */
- _mesa_GenVertexArrays(1, &copypix->ArrayObj);
- _mesa_BindVertexArray(copypix->ArrayObj);
-
- /* create vertex array buffer */
- _mesa_GenBuffersARB(1, &copypix->VBO);
- _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, copypix->VBO);
- _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts),
- NULL, GL_DYNAMIC_DRAW_ARB);
-
- /* setup vertex arrays */
- _mesa_VertexPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(x));
- _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(s));
- _mesa_EnableClientState(GL_VERTEX_ARRAY);
- _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY);
- }
- else {
- _mesa_BindVertexArray(copypix->ArrayObj);
- _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, copypix->VBO);
- }
-
- newTex = alloc_texture(tex, width, height, intFormat);
-
- /* vertex positions, texcoords (after texture allocation!) */
- {
- const GLfloat dstX0 = (GLfloat) dstX;
- const GLfloat dstY0 = (GLfloat) dstY;
- const GLfloat dstX1 = dstX + width * ctx->Pixel.ZoomX;
- const GLfloat dstY1 = dstY + height * ctx->Pixel.ZoomY;
- const GLfloat z = invert_z(ctx->Current.RasterPos[2]);
-
- verts[0].x = dstX0;
- verts[0].y = dstY0;
- verts[0].z = z;
- verts[0].s = 0.0F;
- verts[0].t = 0.0F;
- verts[1].x = dstX1;
- verts[1].y = dstY0;
- verts[1].z = z;
- verts[1].s = tex->Sright;
- verts[1].t = 0.0F;
- verts[2].x = dstX1;
- verts[2].y = dstY1;
- verts[2].z = z;
- verts[2].s = tex->Sright;
- verts[2].t = tex->Ttop;
- verts[3].x = dstX0;
- verts[3].y = dstY1;
- verts[3].z = z;
- verts[3].s = 0.0F;
- verts[3].t = tex->Ttop;
-
- /* upload new vertex data */
- _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts);
- }
-
- /* Alloc/setup texture */
- setup_copypix_texture(tex, newTex, srcX, srcY, width, height,
- GL_RGBA, GL_NEAREST);
-
- _mesa_set_enable(ctx, tex->Target, GL_TRUE);
-
- /* draw textured quad */
- _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
-
- _mesa_set_enable(ctx, tex->Target, GL_FALSE);
-
- _mesa_meta_end(ctx);
-}
-
-
-
-/**
- * When the glDrawPixels() image size is greater than the max rectangle
- * texture size we use this function to break the glDrawPixels() image
- * into tiles which fit into the max texture size.
- */
-static void
-tiled_draw_pixels(GLcontext *ctx,
- GLint tileSize,
- GLint x, GLint y, GLsizei width, GLsizei height,
- GLenum format, GLenum type,
- const struct gl_pixelstore_attrib *unpack,
- const GLvoid *pixels)
-{
- struct gl_pixelstore_attrib tileUnpack = *unpack;
- GLint i, j;
-
- if (tileUnpack.RowLength == 0)
- tileUnpack.RowLength = width;
-
- for (i = 0; i < width; i += tileSize) {
- const GLint tileWidth = MIN2(tileSize, width - i);
- const GLint tileX = (GLint) (x + i * ctx->Pixel.ZoomX);
-
- tileUnpack.SkipPixels = unpack->SkipPixels + i;
-
- for (j = 0; j < height; j += tileSize) {
- const GLint tileHeight = MIN2(tileSize, height - j);
- const GLint tileY = (GLint) (y + j * ctx->Pixel.ZoomY);
-
- tileUnpack.SkipRows = unpack->SkipRows + j;
-
- _mesa_meta_DrawPixels(ctx, tileX, tileY, tileWidth, tileHeight,
- format, type, &tileUnpack, pixels);
- }
- }
-}
-
-
-/**
- * One-time init for drawing stencil pixels.
- */
-static void
-init_draw_stencil_pixels(GLcontext *ctx)
-{
- /* This program is run eight times, once for each stencil bit.
- * The stencil values to draw are found in an 8-bit alpha texture.
- * We read the texture/stencil value and test if bit 'b' is set.
- * If the bit is not set, use KIL to kill the fragment.
- * Finally, we use the stencil test to update the stencil buffer.
- *
- * The basic algorithm for checking if a bit is set is:
- * if (is_odd(value / (1 << bit)))
- * result is one (or non-zero).
- * else
- * result is zero.
- * The program parameter contains three values:
- * parm.x = 255 / (1 << bit)
- * parm.y = 0.5
- * parm.z = 0.0
- */
- static const char *program =
- "!!ARBfp1.0\n"
- "PARAM parm = program.local[0]; \n"
- "TEMP t; \n"
- "TEX t, fragment.texcoord[0], texture[0], %s; \n" /* NOTE %s here! */
- "# t = t * 255 / bit \n"
- "MUL t.x, t.a, parm.x; \n"
- "# t = (int) t \n"
- "FRC t.y, t.x; \n"
- "SUB t.x, t.x, t.y; \n"
- "# t = t * 0.5 \n"
- "MUL t.x, t.x, parm.y; \n"
- "# t = fract(t.x) \n"
- "FRC t.x, t.x; # if t.x != 0, then the bit is set \n"
- "# t.x = (t.x == 0 ? 1 : 0) \n"
- "SGE t.x, -t.x, parm.z; \n"
- "KIL -t.x; \n"
- "# for debug only \n"
- "#MOV result.color, t.x; \n"
- "END \n";
- char program2[1000];
- struct drawpix_state *drawpix = &ctx->Meta->DrawPix;
- struct temp_texture *tex = get_temp_texture(ctx);
- const char *texTarget;
-
- assert(drawpix->StencilFP == 0);
-
- /* replace %s with "RECT" or "2D" */
- assert(strlen(program) + 4 < sizeof(program2));
- if (tex->Target == GL_TEXTURE_RECTANGLE)
- texTarget = "RECT";
- else
- texTarget = "2D";
- _mesa_snprintf(program2, sizeof(program2), program, texTarget);
-
- _mesa_GenPrograms(1, &drawpix->StencilFP);
- _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, drawpix->StencilFP);
- _mesa_ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
- strlen(program2), (const GLubyte *) program2);
-}
-
-
-/**
- * One-time init for drawing depth pixels.
- */
-static void
-init_draw_depth_pixels(GLcontext *ctx)
-{
- static const char *program =
- "!!ARBfp1.0\n"
- "PARAM color = program.local[0]; \n"
- "TEX result.depth, fragment.texcoord[0], texture[0], %s; \n"
- "MOV result.color, color; \n"
- "END \n";
- char program2[200];
- struct drawpix_state *drawpix = &ctx->Meta->DrawPix;
- struct temp_texture *tex = get_temp_texture(ctx);
- const char *texTarget;
-
- assert(drawpix->DepthFP == 0);
-
- /* replace %s with "RECT" or "2D" */
- assert(strlen(program) + 4 < sizeof(program2));
- if (tex->Target == GL_TEXTURE_RECTANGLE)
- texTarget = "RECT";
- else
- texTarget = "2D";
- _mesa_snprintf(program2, sizeof(program2), program, texTarget);
-
- _mesa_GenPrograms(1, &drawpix->DepthFP);
- _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, drawpix->DepthFP);
- _mesa_ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
- strlen(program2), (const GLubyte *) program2);
-}
-
-
-/**
- * Meta implementation of ctx->Driver.DrawPixels() in terms
- * of texture mapping and polygon rendering.
- */
-void
-_mesa_meta_DrawPixels(GLcontext *ctx,
- GLint x, GLint y, GLsizei width, GLsizei height,
- GLenum format, GLenum type,
- const struct gl_pixelstore_attrib *unpack,
- const GLvoid *pixels)
-{
- struct drawpix_state *drawpix = &ctx->Meta->DrawPix;
- struct temp_texture *tex = get_temp_texture(ctx);
- const struct gl_pixelstore_attrib unpackSave = ctx->Unpack;
- const GLuint origStencilMask = ctx->Stencil.WriteMask[0];
- struct vertex {
- GLfloat x, y, z, s, t;
- };
- struct vertex verts[4];
- GLenum texIntFormat;
- GLboolean fallback, newTex;
- GLbitfield metaExtraSave = 0x0;
- GLuint vbo;
-
- /*
- * Determine if we can do the glDrawPixels with texture mapping.
- */
- fallback = GL_FALSE;
- if (ctx->_ImageTransferState ||
- ctx->Fog.Enabled) {
- fallback = GL_TRUE;
- }
-
- if (_mesa_is_color_format(format)) {
- /* use more compact format when possible */
- /* XXX disable special case for GL_LUMINANCE for now to work around
- * apparent i965 driver bug (see bug #23670).
- */
- if (/*format == GL_LUMINANCE ||*/ format == GL_LUMINANCE_ALPHA)
- texIntFormat = format;
- else
- texIntFormat = GL_RGBA;
- }
- else if (_mesa_is_stencil_format(format)) {
- if (ctx->Extensions.ARB_fragment_program &&
- ctx->Pixel.IndexShift == 0 &&
- ctx->Pixel.IndexOffset == 0 &&
- type == GL_UNSIGNED_BYTE) {
- /* We'll store stencil as alpha. This only works for GLubyte
- * image data because of how incoming values are mapped to alpha
- * in [0,1].
- */
- texIntFormat = GL_ALPHA;
- metaExtraSave = (META_COLOR_MASK |
- META_DEPTH_TEST |
- META_SHADER |
- META_STENCIL_TEST);
- }
- else {
- fallback = GL_TRUE;
- }
- }
- else if (_mesa_is_depth_format(format)) {
- if (ctx->Extensions.ARB_depth_texture &&
- ctx->Extensions.ARB_fragment_program) {
- texIntFormat = GL_DEPTH_COMPONENT;
- metaExtraSave = (META_SHADER);
- }
- else {
- fallback = GL_TRUE;
- }
- }
- else {
- fallback = GL_TRUE;
- }
-
- if (fallback) {
- _swrast_DrawPixels(ctx, x, y, width, height,
- format, type, unpack, pixels);
- return;
- }
-
- /*
- * Check image size against max texture size, draw as tiles if needed.
- */
- if (width > tex->MaxSize || height > tex->MaxSize) {
- tiled_draw_pixels(ctx, tex->MaxSize, x, y, width, height,
- format, type, unpack, pixels);
- return;
- }
-
- /* Most GL state applies to glDrawPixels (like blending, stencil, etc),
- * but a there's a few things we need to override:
- */
- _mesa_meta_begin(ctx, (META_RASTERIZATION |
- META_SHADER |
- META_TEXTURE |
- META_TRANSFORM |
- META_VERTEX |
- META_VIEWPORT |
- metaExtraSave));
-
- newTex = alloc_texture(tex, width, height, texIntFormat);
-
- /* vertex positions, texcoords (after texture allocation!) */
- {
- const GLfloat x0 = (GLfloat) x;
- const GLfloat y0 = (GLfloat) y;
- const GLfloat x1 = x + width * ctx->Pixel.ZoomX;
- const GLfloat y1 = y + height * ctx->Pixel.ZoomY;
- const GLfloat z = invert_z(ctx->Current.RasterPos[2]);
-
- verts[0].x = x0;
- verts[0].y = y0;
- verts[0].z = z;
- verts[0].s = 0.0F;
- verts[0].t = 0.0F;
- verts[1].x = x1;
- verts[1].y = y0;
- verts[1].z = z;
- verts[1].s = tex->Sright;
- verts[1].t = 0.0F;
- verts[2].x = x1;
- verts[2].y = y1;
- verts[2].z = z;
- verts[2].s = tex->Sright;
- verts[2].t = tex->Ttop;
- verts[3].x = x0;
- verts[3].y = y1;
- verts[3].z = z;
- verts[3].s = 0.0F;
- verts[3].t = tex->Ttop;
- }
-
- if (drawpix->ArrayObj == 0) {
- /* one-time setup: create vertex array object */
- _mesa_GenVertexArrays(1, &drawpix->ArrayObj);
- }
- _mesa_BindVertexArray(drawpix->ArrayObj);
-
- /* create vertex array buffer */
- _mesa_GenBuffersARB(1, &vbo);
- _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, vbo);
- _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts),
- verts, GL_DYNAMIC_DRAW_ARB);
-
- /* setup vertex arrays */
- _mesa_VertexPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(x));
- _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(s));
- _mesa_EnableClientState(GL_VERTEX_ARRAY);
- _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY);
-
- /* set given unpack params */
- ctx->Unpack = *unpack;
-
- _mesa_set_enable(ctx, tex->Target, GL_TRUE);
-
- if (_mesa_is_stencil_format(format)) {
- /* Drawing stencil */
- GLint bit;
-
- if (!drawpix->StencilFP)
- init_draw_stencil_pixels(ctx);
-
- setup_drawpix_texture(ctx, tex, newTex, texIntFormat, width, height,
- GL_ALPHA, type, pixels);
-
- _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
-
- _mesa_set_enable(ctx, GL_STENCIL_TEST, GL_TRUE);
-
- /* set all stencil bits to 0 */
- _mesa_StencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
- _mesa_StencilFunc(GL_ALWAYS, 0, 255);
- _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
-
- /* set stencil bits to 1 where needed */
- _mesa_StencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
-
- _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, drawpix->StencilFP);
- _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_TRUE);
-
- for (bit = 0; bit < ctx->DrawBuffer->Visual.stencilBits; bit++) {
- const GLuint mask = 1 << bit;
- if (mask & origStencilMask) {
- _mesa_StencilFunc(GL_ALWAYS, mask, mask);
- _mesa_StencilMask(mask);
-
- _mesa_ProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0,
- 255.0 / mask, 0.5, 0.0, 0.0);
-
- _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
- }
- }
- }
- else if (_mesa_is_depth_format(format)) {
- /* Drawing depth */
- if (!drawpix->DepthFP)
- init_draw_depth_pixels(ctx);
-
- _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, drawpix->DepthFP);
- _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_TRUE);
-
- /* polygon color = current raster color */
- _mesa_ProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 0,
- ctx->Current.RasterColor);
-
- setup_drawpix_texture(ctx, tex, newTex, texIntFormat, width, height,
- format, type, pixels);
-
- _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
- }
- else {
- /* Drawing RGBA */
- setup_drawpix_texture(ctx, tex, newTex, texIntFormat, width, height,
- format, type, pixels);
- _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
- }
-
- _mesa_set_enable(ctx, tex->Target, GL_FALSE);
-
- _mesa_DeleteBuffersARB(1, &vbo);
-
- /* restore unpack params */
- ctx->Unpack = unpackSave;
-
- _mesa_meta_end(ctx);
-}
-
-
-/**
- * Do glBitmap with a alpha texture quad. Use the alpha test to
- * cull the 'off' bits. If alpha test is already enabled, fall back
- * to swrast (should be a rare case).
- * A bitmap cache as in the gallium/mesa state tracker would
- * improve performance a lot.
- */
-void
-_mesa_meta_Bitmap(GLcontext *ctx,
- GLint x, GLint y, GLsizei width, GLsizei height,
- const struct gl_pixelstore_attrib *unpack,
- const GLubyte *bitmap1)
-{
- struct bitmap_state *bitmap = &ctx->Meta->Bitmap;
- struct temp_texture *tex = get_bitmap_temp_texture(ctx);
- const GLenum texIntFormat = GL_ALPHA;
- const struct gl_pixelstore_attrib unpackSave = *unpack;
- struct vertex {
- GLfloat x, y, z, s, t, r, g, b, a;
- };
- struct vertex verts[4];
- GLboolean newTex;
- GLubyte *bitmap8;
-
- /*
- * Check if swrast fallback is needed.
- */
- if (ctx->_ImageTransferState ||
- ctx->Color.AlphaEnabled ||
- ctx->Fog.Enabled ||
- ctx->Texture._EnabledUnits ||
- width > tex->MaxSize ||
- height > tex->MaxSize) {
- _swrast_Bitmap(ctx, x, y, width, height, unpack, bitmap1);
- return;
- }
-
- /* Most GL state applies to glBitmap (like blending, stencil, etc),
- * but a there's a few things we need to override:
- */
- _mesa_meta_begin(ctx, (META_ALPHA_TEST |
- META_PIXEL_STORE |
- META_RASTERIZATION |
- META_SHADER |
- META_TEXTURE |
- META_TRANSFORM |
- META_VERTEX |
- META_VIEWPORT));
-
- if (bitmap->ArrayObj == 0) {
- /* one-time setup */
-
- /* create vertex array object */
- _mesa_GenVertexArraysAPPLE(1, &bitmap->ArrayObj);
- _mesa_BindVertexArrayAPPLE(bitmap->ArrayObj);
-
- /* create vertex array buffer */
- _mesa_GenBuffersARB(1, &bitmap->VBO);
- _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, bitmap->VBO);
- _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts),
- NULL, GL_DYNAMIC_DRAW_ARB);
-
- /* setup vertex arrays */
- _mesa_VertexPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(x));
- _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(s));
- _mesa_ColorPointer(4, GL_FLOAT, sizeof(struct vertex), OFFSET(r));
- _mesa_EnableClientState(GL_VERTEX_ARRAY);
- _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY);
- _mesa_EnableClientState(GL_COLOR_ARRAY);
- }
- else {
- _mesa_BindVertexArray(bitmap->ArrayObj);
- _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, bitmap->VBO);
- }
-
- newTex = alloc_texture(tex, width, height, texIntFormat);
-
- /* vertex positions, texcoords, colors (after texture allocation!) */
- {
- const GLfloat x0 = (GLfloat) x;
- const GLfloat y0 = (GLfloat) y;
- const GLfloat x1 = (GLfloat) (x + width);
- const GLfloat y1 = (GLfloat) (y + height);
- const GLfloat z = invert_z(ctx->Current.RasterPos[2]);
- GLuint i;
-
- verts[0].x = x0;
- verts[0].y = y0;
- verts[0].z = z;
- verts[0].s = 0.0F;
- verts[0].t = 0.0F;
- verts[1].x = x1;
- verts[1].y = y0;
- verts[1].z = z;
- verts[1].s = tex->Sright;
- verts[1].t = 0.0F;
- verts[2].x = x1;
- verts[2].y = y1;
- verts[2].z = z;
- verts[2].s = tex->Sright;
- verts[2].t = tex->Ttop;
- verts[3].x = x0;
- verts[3].y = y1;
- verts[3].z = z;
- verts[3].s = 0.0F;
- verts[3].t = tex->Ttop;
-
- for (i = 0; i < 4; i++) {
- verts[i].r = ctx->Current.RasterColor[0];
- verts[i].g = ctx->Current.RasterColor[1];
- verts[i].b = ctx->Current.RasterColor[2];
- verts[i].a = ctx->Current.RasterColor[3];
- }
-
- /* upload new vertex data */
- _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts);
- }
-
- bitmap1 = _mesa_map_pbo_source(ctx, &unpackSave, bitmap1);
- if (!bitmap1) {
- _mesa_meta_end(ctx);
- return;
- }
-
- bitmap8 = (GLubyte *) calloc(1, width * height);
- if (bitmap8) {
- _mesa_expand_bitmap(width, height, &unpackSave, bitmap1,
- bitmap8, width, 0xff);
-
- _mesa_set_enable(ctx, tex->Target, GL_TRUE);
-
- _mesa_set_enable(ctx, GL_ALPHA_TEST, GL_TRUE);
- _mesa_AlphaFunc(GL_GREATER, 0.0);
-
- setup_drawpix_texture(ctx, tex, newTex, texIntFormat, width, height,
- GL_ALPHA, GL_UNSIGNED_BYTE, bitmap8);
-
- _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
-
- _mesa_set_enable(ctx, tex->Target, GL_FALSE);
-
- free(bitmap8);
- }
-
- _mesa_unmap_pbo_source(ctx, &unpackSave);
-
- _mesa_meta_end(ctx);
-}
-
-
-/**
- * Check if the call to _mesa_meta_GenerateMipmap() will require a
- * software fallback. The fallback path will require that the texture
- * images are mapped.
- * \return GL_TRUE if a fallback is needed, GL_FALSE otherwise
- */
-GLboolean
-_mesa_meta_check_generate_mipmap_fallback(GLcontext *ctx, GLenum target,
- struct gl_texture_object *texObj)
-{
- const GLuint fboSave = ctx->DrawBuffer->Name;
- struct gen_mipmap_state *mipmap = &ctx->Meta->Mipmap;
- struct gl_texture_image *baseImage;
- GLuint srcLevel;
- GLenum status;
-
- /* check for fallbacks */
- if (!ctx->Extensions.EXT_framebuffer_object ||
- target == GL_TEXTURE_3D) {
- return GL_TRUE;
- }
-
- srcLevel = texObj->BaseLevel;
- baseImage = _mesa_select_tex_image(ctx, texObj, target, srcLevel);
- if (!baseImage || _mesa_is_format_compressed(baseImage->TexFormat)) {
- return GL_TRUE;
- }
-
- /*
- * Test that we can actually render in the texture's format.
- */
- if (!mipmap->FBO)
- _mesa_GenFramebuffersEXT(1, &mipmap->FBO);
- _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, mipmap->FBO);
-
- if (target == GL_TEXTURE_1D) {
- _mesa_FramebufferTexture1DEXT(GL_FRAMEBUFFER_EXT,
- GL_COLOR_ATTACHMENT0_EXT,
- target, texObj->Name, srcLevel);
- }
-#if 0
- /* other work is needed to enable 3D mipmap generation */
- else if (target == GL_TEXTURE_3D) {
- GLint zoffset = 0;
- _mesa_FramebufferTexture3DEXT(GL_FRAMEBUFFER_EXT,
- GL_COLOR_ATTACHMENT0_EXT,
- target, texObj->Name, srcLevel, zoffset);
- }
-#endif
- else {
- /* 2D / cube */
- _mesa_FramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
- GL_COLOR_ATTACHMENT0_EXT,
- target, texObj->Name, srcLevel);
- }
-
- status = _mesa_CheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
-
- _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboSave);
-
- if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
- return GL_TRUE;
- }
-
- return GL_FALSE;
-}
-
-
-/**
- * Called via ctx->Driver.GenerateMipmap()
- * Note: texture borders and 3D texture support not yet complete.
- */
-void
-_mesa_meta_GenerateMipmap(GLcontext *ctx, GLenum target,
- struct gl_texture_object *texObj)
-{
- struct gen_mipmap_state *mipmap = &ctx->Meta->Mipmap;
- struct vertex {
- GLfloat x, y, s, t, r;
- };
- struct vertex verts[4];
- const GLuint baseLevel = texObj->BaseLevel;
- const GLuint maxLevel = texObj->MaxLevel;
- const GLenum minFilterSave = texObj->MinFilter;
- const GLenum magFilterSave = texObj->MagFilter;
- const GLint baseLevelSave = texObj->BaseLevel;
- const GLint maxLevelSave = texObj->MaxLevel;
- const GLboolean genMipmapSave = texObj->GenerateMipmap;
- const GLenum wrapSSave = texObj->WrapS;
- const GLenum wrapTSave = texObj->WrapT;
- const GLenum wrapRSave = texObj->WrapR;
- const GLuint fboSave = ctx->DrawBuffer->Name;
- const GLuint original_active_unit = ctx->Texture.CurrentUnit;
- GLenum faceTarget;
- GLuint dstLevel;
- GLuint border = 0;
-
- if (_mesa_meta_check_generate_mipmap_fallback(ctx, target, texObj)) {
- _mesa_generate_mipmap(ctx, target, texObj);
- return;
- }
-
- if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X &&
- target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) {
- faceTarget = target;
- target = GL_TEXTURE_CUBE_MAP;
- }
- else {
- faceTarget = target;
- }
-
- _mesa_meta_begin(ctx, META_ALL);
-
- if (original_active_unit != 0)
- _mesa_BindTexture(target, texObj->Name);
-
- if (mipmap->ArrayObj == 0) {
- /* one-time setup */
-
- /* create vertex array object */
- _mesa_GenVertexArraysAPPLE(1, &mipmap->ArrayObj);
- _mesa_BindVertexArrayAPPLE(mipmap->ArrayObj);
-
- /* create vertex array buffer */
- _mesa_GenBuffersARB(1, &mipmap->VBO);
- _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, mipmap->VBO);
- _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts),
- NULL, GL_DYNAMIC_DRAW_ARB);
-
- /* setup vertex arrays */
- _mesa_VertexPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(x));
- _mesa_TexCoordPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(s));
- _mesa_EnableClientState(GL_VERTEX_ARRAY);
- _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY);
- }
- else {
- _mesa_BindVertexArray(mipmap->ArrayObj);
- _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, mipmap->VBO);
- }
-
- if (!mipmap->FBO) {
- _mesa_GenFramebuffersEXT(1, &mipmap->FBO);
- }
- _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, mipmap->FBO);
-
- _mesa_TexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- _mesa_TexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- _mesa_TexParameteri(target, GL_GENERATE_MIPMAP, GL_FALSE);
- _mesa_TexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- _mesa_TexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- _mesa_TexParameteri(target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
-
- _mesa_set_enable(ctx, target, GL_TRUE);
-
- /* setup texcoords once (XXX what about border?) */
- switch (faceTarget) {
- case GL_TEXTURE_1D:
- case GL_TEXTURE_2D:
- verts[0].s = 0.0F;
- verts[0].t = 0.0F;
- verts[0].r = 0.0F;
- verts[1].s = 1.0F;
- verts[1].t = 0.0F;
- verts[1].r = 0.0F;
- verts[2].s = 1.0F;
- verts[2].t = 1.0F;
- verts[2].r = 0.0F;
- verts[3].s = 0.0F;
- verts[3].t = 1.0F;
- verts[3].r = 0.0F;
- break;
- case GL_TEXTURE_3D:
- abort();
- break;
- default:
- /* cube face */
- {
- static const GLfloat st[4][2] = {
- {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f}
- };
- GLuint i;
-
- /* loop over quad verts */
- for (i = 0; i < 4; i++) {
- /* Compute sc = +/-scale and tc = +/-scale.
- * Not +/-1 to avoid cube face selection ambiguity near the edges,
- * though that can still sometimes happen with this scale factor...
- */
- const GLfloat scale = 0.9999f;
- const GLfloat sc = (2.0f * st[i][0] - 1.0f) * scale;
- const GLfloat tc = (2.0f * st[i][1] - 1.0f) * scale;
-
- switch (faceTarget) {
- case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
- verts[i].s = 1.0f;
- verts[i].t = -tc;
- verts[i].r = -sc;
- break;
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
- verts[i].s = -1.0f;
- verts[i].t = -tc;
- verts[i].r = sc;
- break;
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
- verts[i].s = sc;
- verts[i].t = 1.0f;
- verts[i].r = tc;
- break;
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
- verts[i].s = sc;
- verts[i].t = -1.0f;
- verts[i].r = -tc;
- break;
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
- verts[i].s = sc;
- verts[i].t = -tc;
- verts[i].r = 1.0f;
- break;
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
- verts[i].s = -sc;
- verts[i].t = -tc;
- verts[i].r = -1.0f;
- break;
- default:
- assert(0);
- }
- }
- }
- }
-
- _mesa_set_enable(ctx, target, GL_TRUE);
-
- /* setup vertex positions */
- {
- verts[0].x = 0.0F;
- verts[0].y = 0.0F;
- verts[1].x = 1.0F;
- verts[1].y = 0.0F;
- verts[2].x = 1.0F;
- verts[2].y = 1.0F;
- verts[3].x = 0.0F;
- verts[3].y = 1.0F;
-
- /* upload new vertex data */
- _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts);
- }
-
- /* setup projection matrix */
- _mesa_MatrixMode(GL_PROJECTION);
- _mesa_LoadIdentity();
- _mesa_Ortho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
-
- /* texture is already locked, unlock now */
- _mesa_unlock_texture(ctx, texObj);
-
- for (dstLevel = baseLevel + 1; dstLevel <= maxLevel; dstLevel++) {
- const struct gl_texture_image *srcImage;
- const GLuint srcLevel = dstLevel - 1;
- GLsizei srcWidth, srcHeight, srcDepth;
- GLsizei dstWidth, dstHeight, dstDepth;
- GLenum status;
-
- srcImage = _mesa_select_tex_image(ctx, texObj, faceTarget, srcLevel);
- assert(srcImage->Border == 0); /* XXX we can fix this */
-
- /* src size w/out border */
- srcWidth = srcImage->Width - 2 * border;
- srcHeight = srcImage->Height - 2 * border;
- srcDepth = srcImage->Depth - 2 * border;
-
- /* new dst size w/ border */
- dstWidth = MAX2(1, srcWidth / 2) + 2 * border;
- dstHeight = MAX2(1, srcHeight / 2) + 2 * border;
- dstDepth = MAX2(1, srcDepth / 2) + 2 * border;
-
- if (dstWidth == srcImage->Width &&
- dstHeight == srcImage->Height &&
- dstDepth == srcImage->Depth) {
- /* all done */
- break;
- }
-
- /* Set MaxLevel large enough to hold the new level when we allocate it */
- _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, dstLevel);
-
- /* Create empty dest image */
- if (target == GL_TEXTURE_1D) {
- _mesa_TexImage1D(target, dstLevel, srcImage->InternalFormat,
- dstWidth, border,
- GL_RGBA, GL_UNSIGNED_BYTE, NULL);
- }
- else if (target == GL_TEXTURE_3D) {
- _mesa_TexImage3D(target, dstLevel, srcImage->InternalFormat,
- dstWidth, dstHeight, dstDepth, border,
- GL_RGBA, GL_UNSIGNED_BYTE, NULL);
- }
- else {
- /* 2D or cube */
- _mesa_TexImage2D(faceTarget, dstLevel, srcImage->InternalFormat,
- dstWidth, dstHeight, border,
- GL_RGBA, GL_UNSIGNED_BYTE, NULL);
-
- if (target == GL_TEXTURE_CUBE_MAP) {
- /* If texturing from a cube, we need to make sure all src faces
- * have been defined (even if we're not sampling from them.)
- * Otherwise the texture object will be 'incomplete' and
- * texturing from it will not be allowed.
- */
- GLuint face;
- for (face = 0; face < 6; face++) {
- if (!texObj->Image[face][srcLevel] ||
- texObj->Image[face][srcLevel]->Width != srcWidth) {
- _mesa_TexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face,
- srcLevel, srcImage->InternalFormat,
- srcWidth, srcHeight, border,
- GL_RGBA, GL_UNSIGNED_BYTE, NULL);
- }
- }
- }
- }
-
- /* limit sampling to src level */
- _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, srcLevel);
- _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, srcLevel);
-
- /* Set to draw into the current dstLevel */
- if (target == GL_TEXTURE_1D) {
- _mesa_FramebufferTexture1DEXT(GL_FRAMEBUFFER_EXT,
- GL_COLOR_ATTACHMENT0_EXT,
- target,
- texObj->Name,
- dstLevel);
- }
- else if (target == GL_TEXTURE_3D) {
- GLint zoffset = 0; /* XXX unfinished */
- _mesa_FramebufferTexture3DEXT(GL_FRAMEBUFFER_EXT,
- GL_COLOR_ATTACHMENT0_EXT,
- target,
- texObj->Name,
- dstLevel, zoffset);
- }
- else {
- /* 2D / cube */
- _mesa_FramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
- GL_COLOR_ATTACHMENT0_EXT,
- faceTarget,
- texObj->Name,
- dstLevel);
- }
-
- _mesa_DrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
-
- /* sanity check */
- status = _mesa_CheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
- if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
- abort();
- break;
- }
-
- assert(dstWidth == ctx->DrawBuffer->Width);
- assert(dstHeight == ctx->DrawBuffer->Height);
-
- /* setup viewport */
- _mesa_set_viewport(ctx, 0, 0, dstWidth, dstHeight);
-
- _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
- }
-
- _mesa_lock_texture(ctx, texObj); /* relock */
-
- _mesa_meta_end(ctx);
-
- _mesa_TexParameteri(target, GL_TEXTURE_MIN_FILTER, minFilterSave);
- _mesa_TexParameteri(target, GL_TEXTURE_MAG_FILTER, magFilterSave);
- _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, baseLevelSave);
- _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, maxLevelSave);
- _mesa_TexParameteri(target, GL_GENERATE_MIPMAP, genMipmapSave);
- _mesa_TexParameteri(target, GL_TEXTURE_WRAP_S, wrapSSave);
- _mesa_TexParameteri(target, GL_TEXTURE_WRAP_T, wrapTSave);
- _mesa_TexParameteri(target, GL_TEXTURE_WRAP_R, wrapRSave);
-
- _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboSave);
-}
-
-
-/**
- * Determine the GL data type to use for the temporary image read with
- * ReadPixels() and passed to Tex[Sub]Image().
- */
-static GLenum
-get_temp_image_type(GLcontext *ctx, GLenum baseFormat)
-{
- switch (baseFormat) {
- case GL_RGBA:
- case GL_RGB:
- case GL_ALPHA:
- case GL_LUMINANCE:
- case GL_LUMINANCE_ALPHA:
- case GL_INTENSITY:
- if (ctx->DrawBuffer->Visual.redBits <= 8)
- return GL_UNSIGNED_BYTE;
- else if (ctx->DrawBuffer->Visual.redBits <= 8)
- return GL_UNSIGNED_SHORT;
- else
- return GL_FLOAT;
- case GL_DEPTH_COMPONENT:
- return GL_UNSIGNED_INT;
- case GL_DEPTH_STENCIL:
- return GL_UNSIGNED_INT_24_8;
- default:
- _mesa_problem(ctx, "Unexpected format in get_temp_image_type()");
- return 0;
- }
-}
-
-
-/**
- * Helper for _mesa_meta_CopyTexImage1/2D() functions.
- * Have to be careful with locking and meta state for pixel transfer.
- */
-static void
-copy_tex_image(GLcontext *ctx, GLuint dims, GLenum target, GLint level,
- GLenum internalFormat, GLint x, GLint y,
- GLsizei width, GLsizei height, GLint border)
-{
- struct gl_texture_object *texObj;
- struct gl_texture_image *texImage;
- GLsizei postConvWidth = width, postConvHeight = height;
- GLenum format, type;
- GLint bpp;
- void *buf;
-
- texObj = _mesa_get_current_tex_object(ctx, target);
- texImage = _mesa_get_tex_image(ctx, texObj, target, level);
-
- format = _mesa_base_tex_format(ctx, internalFormat);
- type = get_temp_image_type(ctx, format);
- bpp = _mesa_bytes_per_pixel(format, type);
- if (bpp <= 0) {
- _mesa_problem(ctx, "Bad bpp in meta copy_tex_image()");
- return;
- }
-
- /*
- * Alloc image buffer (XXX could use a PBO)
- */
- buf = malloc(width * height * bpp);
- if (!buf) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage%uD", dims);
- return;
- }
-
- _mesa_unlock_texture(ctx, texObj); /* need to unlock first */
-
- /*
- * Read image from framebuffer (disable pixel transfer ops)
- */
- _mesa_meta_begin(ctx, META_PIXEL_STORE | META_PIXEL_TRANSFER);
- ctx->Driver.ReadPixels(ctx, x, y, width, height,
- format, type, &ctx->Pack, buf);
- _mesa_meta_end(ctx);
-
- /*
- * Prepare for new texture image size/data
- */
- if (_mesa_is_color_format(internalFormat)) {
- _mesa_adjust_image_for_convolution(ctx, 2,
- &postConvWidth, &postConvHeight);
- }
-
- if (texImage->Data) {
- ctx->Driver.FreeTexImageData(ctx, texImage);
- }
-
- _mesa_init_teximage_fields(ctx, target, texImage,
- postConvWidth, postConvHeight, 1,
- border, internalFormat);
-
- _mesa_choose_texture_format(ctx, texObj, texImage, target, level,
- internalFormat, GL_NONE, GL_NONE);
-
- /*
- * Store texture data (with pixel transfer ops)
- */
- _mesa_meta_begin(ctx, META_PIXEL_STORE);
-
- _mesa_update_state(ctx); /* to update pixel transfer state */
-
- if (target == GL_TEXTURE_1D) {
- ctx->Driver.TexImage1D(ctx, target, level, internalFormat,
- width, border, format, type,
- buf, &ctx->Unpack, texObj, texImage);
- }
- else {
- ctx->Driver.TexImage2D(ctx, target, level, internalFormat,
- width, height, border, format, type,
- buf, &ctx->Unpack, texObj, texImage);
- }
- _mesa_meta_end(ctx);
-
- _mesa_lock_texture(ctx, texObj); /* re-lock */
-
- free(buf);
-}
-
-
-void
-_mesa_meta_CopyTexImage1D(GLcontext *ctx, GLenum target, GLint level,
- GLenum internalFormat, GLint x, GLint y,
- GLsizei width, GLint border)
-{
- copy_tex_image(ctx, 1, target, level, internalFormat, x, y,
- width, 1, border);
-}
-
-
-void
-_mesa_meta_CopyTexImage2D(GLcontext *ctx, GLenum target, GLint level,
- GLenum internalFormat, GLint x, GLint y,
- GLsizei width, GLsizei height, GLint border)
-{
- copy_tex_image(ctx, 2, target, level, internalFormat, x, y,
- width, height, border);
-}
-
-
-
-/**
- * Helper for _mesa_meta_CopyTexSubImage1/2/3D() functions.
- * Have to be careful with locking and meta state for pixel transfer.
- */
-static void
-copy_tex_sub_image(GLcontext *ctx, GLuint dims, GLenum target, GLint level,
- GLint xoffset, GLint yoffset, GLint zoffset,
- GLint x, GLint y,
- GLsizei width, GLsizei height)
-{
- struct gl_texture_object *texObj;
- struct gl_texture_image *texImage;
- GLenum format, type;
- GLint bpp;
- void *buf;
-
- texObj = _mesa_get_current_tex_object(ctx, target);
- texImage = _mesa_select_tex_image(ctx, texObj, target, level);
-
- format = _mesa_get_format_base_format(texImage->TexFormat);
- type = get_temp_image_type(ctx, format);
- bpp = _mesa_bytes_per_pixel(format, type);
- if (bpp <= 0) {
- _mesa_problem(ctx, "Bad bpp in meta copy_tex_sub_image()");
- return;
- }
-
- /*
- * Alloc image buffer (XXX could use a PBO)
- */
- buf = malloc(width * height * bpp);
- if (!buf) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage%uD", dims);
- return;
- }
-
- _mesa_unlock_texture(ctx, texObj); /* need to unlock first */
-
- /*
- * Read image from framebuffer (disable pixel transfer ops)
- */
- _mesa_meta_begin(ctx, META_PIXEL_STORE | META_PIXEL_TRANSFER);
- ctx->Driver.ReadPixels(ctx, x, y, width, height,
- format, type, &ctx->Pack, buf);
- _mesa_meta_end(ctx);
-
- _mesa_update_state(ctx); /* to update pixel transfer state */
-
- /*
- * Store texture data (with pixel transfer ops)
- */
- _mesa_meta_begin(ctx, META_PIXEL_STORE);
- if (target == GL_TEXTURE_1D) {
- ctx->Driver.TexSubImage1D(ctx, target, level, xoffset,
- width, format, type, buf,
- &ctx->Unpack, texObj, texImage);
- }
- else if (target == GL_TEXTURE_3D) {
- ctx->Driver.TexSubImage3D(ctx, target, level, xoffset, yoffset, zoffset,
- width, height, 1, format, type, buf,
- &ctx->Unpack, texObj, texImage);
- }
- else {
- ctx->Driver.TexSubImage2D(ctx, target, level, xoffset, yoffset,
- width, height, format, type, buf,
- &ctx->Unpack, texObj, texImage);
- }
- _mesa_meta_end(ctx);
-
- _mesa_lock_texture(ctx, texObj); /* re-lock */
-
- free(buf);
-}
-
-
-void
-_mesa_meta_CopyTexSubImage1D(GLcontext *ctx, GLenum target, GLint level,
- GLint xoffset,
- GLint x, GLint y, GLsizei width)
-{
- copy_tex_sub_image(ctx, 1, target, level, xoffset, 0, 0,
- x, y, width, 1);
-}
-
-
-void
-_mesa_meta_CopyTexSubImage2D(GLcontext *ctx, GLenum target, GLint level,
- GLint xoffset, GLint yoffset,
- GLint x, GLint y,
- GLsizei width, GLsizei height)
-{
- copy_tex_sub_image(ctx, 2, target, level, xoffset, yoffset, 0,
- x, y, width, height);
-}
-
-
-void
-_mesa_meta_CopyTexSubImage3D(GLcontext *ctx, GLenum target, GLint level,
- GLint xoffset, GLint yoffset, GLint zoffset,
- GLint x, GLint y,
- GLsizei width, GLsizei height)
-{
- copy_tex_sub_image(ctx, 3, target, level, xoffset, yoffset, zoffset,
- x, y, width, height);
-}
-
-
-void
-_mesa_meta_CopyColorTable(GLcontext *ctx,
- GLenum target, GLenum internalformat,
- GLint x, GLint y, GLsizei width)
-{
- GLfloat *buf;
-
- buf = (GLfloat *) malloc(width * 4 * sizeof(GLfloat));
- if (!buf) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyColorTable");
- return;
- }
-
- /*
- * Read image from framebuffer (disable pixel transfer ops)
- */
- _mesa_meta_begin(ctx, META_PIXEL_STORE | META_PIXEL_TRANSFER);
- ctx->Driver.ReadPixels(ctx, x, y, width, 1,
- GL_RGBA, GL_FLOAT, &ctx->Pack, buf);
-
- _mesa_ColorTable(target, internalformat, width, GL_RGBA, GL_FLOAT, buf);
-
- _mesa_meta_end(ctx);
-
- free(buf);
-}
-
-
-void
-_mesa_meta_CopyColorSubTable(GLcontext *ctx,GLenum target, GLsizei start,
- GLint x, GLint y, GLsizei width)
-{
- GLfloat *buf;
-
- buf = (GLfloat *) malloc(width * 4 * sizeof(GLfloat));
- if (!buf) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyColorSubTable");
- return;
- }
-
- /*
- * Read image from framebuffer (disable pixel transfer ops)
- */
- _mesa_meta_begin(ctx, META_PIXEL_STORE | META_PIXEL_TRANSFER);
- ctx->Driver.ReadPixels(ctx, x, y, width, 1,
- GL_RGBA, GL_FLOAT, &ctx->Pack, buf);
-
- _mesa_ColorSubTable(target, start, width, GL_RGBA, GL_FLOAT, buf);
-
- _mesa_meta_end(ctx);
-
- free(buf);
-}
-
-
-void
-_mesa_meta_CopyConvolutionFilter1D(GLcontext *ctx, GLenum target,
- GLenum internalFormat,
- GLint x, GLint y, GLsizei width)
-{
- GLfloat *buf;
-
- buf = (GLfloat *) malloc(width * 4 * sizeof(GLfloat));
- if (!buf) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyConvolutionFilter2D");
- return;
- }
-
- /*
- * Read image from framebuffer (disable pixel transfer ops)
- */
- _mesa_meta_begin(ctx, META_PIXEL_STORE | META_PIXEL_TRANSFER);
- _mesa_update_state(ctx);
- ctx->Driver.ReadPixels(ctx, x, y, width, 1,
- GL_RGBA, GL_FLOAT, &ctx->Pack, buf);
-
- _mesa_ConvolutionFilter1D(target, internalFormat, width,
- GL_RGBA, GL_FLOAT, buf);
-
- _mesa_meta_end(ctx);
-
- free(buf);
-}
-
-
-void
-_mesa_meta_CopyConvolutionFilter2D(GLcontext *ctx, GLenum target,
- GLenum internalFormat, GLint x, GLint y,
- GLsizei width, GLsizei height)
-{
- GLfloat *buf;
-
- buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
- if (!buf) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyConvolutionFilter2D");
- return;
- }
-
- /*
- * Read image from framebuffer (disable pixel transfer ops)
- */
- _mesa_meta_begin(ctx, META_PIXEL_STORE | META_PIXEL_TRANSFER);
- _mesa_update_state(ctx);
-
- ctx->Driver.ReadPixels(ctx, x, y, width, height,
- GL_RGBA, GL_FLOAT, &ctx->Pack, buf);
-
- _mesa_ConvolutionFilter2D(target, internalFormat, width, height,
- GL_RGBA, GL_FLOAT, buf);
-
- _mesa_meta_end(ctx);
-
- free(buf);
-}
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.6
+ *
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * Meta operations. Some GL operations can be expressed in terms of
+ * other GL operations. For example, glBlitFramebuffer() can be done
+ * with texture mapping and glClear() can be done with polygon rendering.
+ *
+ * \author Brian Paul
+ */
+
+
+#include "main/glheader.h"
+#include "main/mtypes.h"
+#include "main/imports.h"
+#include "main/arbprogram.h"
+#include "main/arrayobj.h"
+#include "main/blend.h"
+#include "main/bufferobj.h"
+#include "main/buffers.h"
+#include "main/colortab.h"
+#include "main/depth.h"
+#include "main/enable.h"
+#include "main/fbobject.h"
+#include "main/formats.h"
+#include "main/image.h"
+#include "main/macros.h"
+#include "main/matrix.h"
+#include "main/mipmap.h"
+#include "main/polygon.h"
+#include "main/readpix.h"
+#include "main/scissor.h"
+#include "main/shaderapi.h"
+#include "main/shaderobj.h"
+#include "main/state.h"
+#include "main/stencil.h"
+#include "main/texobj.h"
+#include "main/texenv.h"
+#include "main/teximage.h"
+#include "main/texparam.h"
+#include "main/texstate.h"
+#include "main/varray.h"
+#include "main/viewport.h"
+#include "program/program.h"
+#include "swrast/swrast.h"
+#include "drivers/common/meta.h"
+
+
+/** Return offset in bytes of the field within a vertex struct */
+#define OFFSET(FIELD) ((void *) offsetof(struct vertex, FIELD))
+
+
+/**
+ * Flags passed to _mesa_meta_begin().
+ */
+/*@{*/
+#define META_ALL ~0x0
+#define META_ALPHA_TEST 0x1
+#define META_BLEND 0x2 /**< includes logicop */
+#define META_COLOR_MASK 0x4
+#define META_DEPTH_TEST 0x8
+#define META_FOG 0x10
+#define META_PIXEL_STORE 0x20
+#define META_PIXEL_TRANSFER 0x40
+#define META_RASTERIZATION 0x80
+#define META_SCISSOR 0x100
+#define META_SHADER 0x200
+#define META_STENCIL_TEST 0x400
+#define META_TRANSFORM 0x800 /**< modelview, projection, clip planes */
+#define META_TEXTURE 0x1000
+#define META_VERTEX 0x2000
+#define META_VIEWPORT 0x4000
+/*@}*/
+
+
+/**
+ * State which we may save/restore across meta ops.
+ * XXX this may be incomplete...
+ */
+struct save_state
+{
+ GLbitfield SavedState; /**< bitmask of META_* flags */
+
+ /** META_ALPHA_TEST */
+ GLboolean AlphaEnabled;
+ GLenum AlphaFunc;
+ GLclampf AlphaRef;
+
+ /** META_BLEND */
+ GLbitfield BlendEnabled;
+ GLboolean ColorLogicOpEnabled;
+
+ /** META_COLOR_MASK */
+ GLubyte ColorMask[MAX_DRAW_BUFFERS][4];
+
+ /** META_DEPTH_TEST */
+ struct gl_depthbuffer_attrib Depth;
+
+ /** META_FOG */
+ GLboolean Fog;
+
+ /** META_PIXEL_STORE */
+ struct gl_pixelstore_attrib Pack, Unpack;
+
+ /** META_PIXEL_TRANSFER */
+ GLfloat RedBias, RedScale;
+ GLfloat GreenBias, GreenScale;
+ GLfloat BlueBias, BlueScale;
+ GLfloat AlphaBias, AlphaScale;
+ GLfloat DepthBias, DepthScale;
+ GLboolean MapColorFlag;
+
+ /** META_RASTERIZATION */
+ GLenum FrontPolygonMode, BackPolygonMode;
+ GLboolean PolygonOffset;
+ GLboolean PolygonSmooth;
+ GLboolean PolygonStipple;
+ GLboolean PolygonCull;
+
+ /** META_SCISSOR */
+ struct gl_scissor_attrib Scissor;
+
+ /** META_SHADER */
+ GLboolean VertexProgramEnabled;
+ struct gl_vertex_program *VertexProgram;
+ GLboolean FragmentProgramEnabled;
+ struct gl_fragment_program *FragmentProgram;
+ struct gl_shader_program *VertexShader;
+ struct gl_shader_program *GeometryShader;
+ struct gl_shader_program *FragmentShader;
+ struct gl_shader_program *ActiveShader;
+
+ /** META_STENCIL_TEST */
+ struct gl_stencil_attrib Stencil;
+
+ /** META_TRANSFORM */
+ GLenum MatrixMode;
+ GLfloat ModelviewMatrix[16];
+ GLfloat ProjectionMatrix[16];
+ GLfloat TextureMatrix[16];
+ GLbitfield ClipPlanesEnabled;
+
+ /** META_TEXTURE */
+ GLuint ActiveUnit;
+ GLuint ClientActiveUnit;
+ /** for unit[0] only */
+ struct gl_texture_object *CurrentTexture[NUM_TEXTURE_TARGETS];
+ /** mask of TEXTURE_2D_BIT, etc */
+ GLbitfield TexEnabled[MAX_TEXTURE_UNITS];
+ GLbitfield TexGenEnabled[MAX_TEXTURE_UNITS];
+ GLuint EnvMode; /* unit[0] only */
+
+ /** META_VERTEX */
+ struct gl_array_object *ArrayObj;
+ struct gl_buffer_object *ArrayBufferObj;
+
+ /** META_VIEWPORT */
+ GLint ViewportX, ViewportY, ViewportW, ViewportH;
+ GLclampd DepthNear, DepthFar;
+
+ /** Miscellaneous (always disabled) */
+ GLboolean Lighting;
+};
+
+
+/**
+ * Temporary texture used for glBlitFramebuffer, glDrawPixels, etc.
+ * This is currently shared by all the meta ops. But we could create a
+ * separate one for each of glDrawPixel, glBlitFramebuffer, glCopyPixels, etc.
+ */
+struct temp_texture
+{
+ GLuint TexObj;
+ GLenum Target; /**< GL_TEXTURE_2D or GL_TEXTURE_RECTANGLE */
+ GLsizei MinSize; /**< Min texture size to allocate */
+ GLsizei MaxSize; /**< Max possible texture size */
+ GLboolean NPOT; /**< Non-power of two size OK? */
+ GLsizei Width, Height; /**< Current texture size */
+ GLenum IntFormat;
+ GLfloat Sright, Ttop; /**< right, top texcoords */
+};
+
+
+/**
+ * State for glBlitFramebufer()
+ */
+struct blit_state
+{
+ GLuint ArrayObj;
+ GLuint VBO;
+ GLuint DepthFP;
+};
+
+
+/**
+ * State for glClear()
+ */
+struct clear_state
+{
+ GLuint ArrayObj;
+ GLuint VBO;
+};
+
+
+/**
+ * State for glCopyPixels()
+ */
+struct copypix_state
+{
+ GLuint ArrayObj;
+ GLuint VBO;
+};
+
+
+/**
+ * State for glDrawPixels()
+ */
+struct drawpix_state
+{
+ GLuint ArrayObj;
+
+ GLuint StencilFP; /**< Fragment program for drawing stencil images */
+ GLuint DepthFP; /**< Fragment program for drawing depth images */
+};
+
+
+/**
+ * State for glBitmap()
+ */
+struct bitmap_state
+{
+ GLuint ArrayObj;
+ GLuint VBO;
+ struct temp_texture Tex; /**< separate texture from other meta ops */
+};
+
+
+/**
+ * State for _mesa_meta_generate_mipmap()
+ */
+struct gen_mipmap_state
+{
+ GLuint ArrayObj;
+ GLuint VBO;
+ GLuint FBO;
+};
+
+#define MAX_META_OPS_DEPTH 2
+/**
+ * All per-context meta state.
+ */
+struct gl_meta_state
+{
+ /** Stack of state saved during meta-ops */
+ struct save_state Save[MAX_META_OPS_DEPTH];
+ /** Save stack depth */
+ GLuint SaveStackDepth;
+
+ struct temp_texture TempTex;
+
+ struct blit_state Blit; /**< For _mesa_meta_BlitFramebuffer() */
+ struct clear_state Clear; /**< For _mesa_meta_Clear() */
+ struct copypix_state CopyPix; /**< For _mesa_meta_CopyPixels() */
+ struct drawpix_state DrawPix; /**< For _mesa_meta_DrawPixels() */
+ struct bitmap_state Bitmap; /**< For _mesa_meta_Bitmap() */
+ struct gen_mipmap_state Mipmap; /**< For _mesa_meta_GenerateMipmap() */
+};
+
+
+/**
+ * Initialize meta-ops for a context.
+ * To be called once during context creation.
+ */
+void
+_mesa_meta_init(struct gl_context *ctx)
+{
+ ASSERT(!ctx->Meta);
+
+ ctx->Meta = CALLOC_STRUCT(gl_meta_state);
+}
+
+
+/**
+ * Free context meta-op state.
+ * To be called once during context destruction.
+ */
+void
+_mesa_meta_free(struct gl_context *ctx)
+{
+ /* Note: Any textures, VBOs, etc, that we allocate should get
+ * freed by the normal context destruction code. But this would be
+ * the place to free other meta data someday.
+ */
+ free(ctx->Meta);
+ ctx->Meta = NULL;
+}
+
+
+/**
+ * Enter meta state. This is like a light-weight version of glPushAttrib
+ * but it also resets most GL state back to default values.
+ *
+ * \param state bitmask of META_* flags indicating which attribute groups
+ * to save and reset to their defaults
+ */
+static void
+_mesa_meta_begin(struct gl_context *ctx, GLbitfield state)
+{
+ struct save_state *save;
+
+ /* hope MAX_META_OPS_DEPTH is large enough */
+ assert(ctx->Meta->SaveStackDepth < MAX_META_OPS_DEPTH);
+
+ save = &ctx->Meta->Save[ctx->Meta->SaveStackDepth++];
+ memset(save, 0, sizeof(*save));
+ save->SavedState = state;
+
+ if (state & META_ALPHA_TEST) {
+ save->AlphaEnabled = ctx->Color.AlphaEnabled;
+ save->AlphaFunc = ctx->Color.AlphaFunc;
+ save->AlphaRef = ctx->Color.AlphaRef;
+ if (ctx->Color.AlphaEnabled)
+ _mesa_set_enable(ctx, GL_ALPHA_TEST, GL_FALSE);
+ }
+
+ if (state & META_BLEND) {
+ save->BlendEnabled = ctx->Color.BlendEnabled;
+ if (ctx->Color.BlendEnabled) {
+ if (ctx->Extensions.EXT_draw_buffers2) {
+ GLuint i;
+ for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
+ _mesa_set_enablei(ctx, GL_BLEND, i, GL_FALSE);
+ }
+ }
+ else {
+ _mesa_set_enable(ctx, GL_BLEND, GL_FALSE);
+ }
+ }
+ save->ColorLogicOpEnabled = ctx->Color.ColorLogicOpEnabled;
+ if (ctx->Color.ColorLogicOpEnabled)
+ _mesa_set_enable(ctx, GL_COLOR_LOGIC_OP, GL_FALSE);
+ }
+
+ if (state & META_COLOR_MASK) {
+ memcpy(save->ColorMask, ctx->Color.ColorMask,
+ sizeof(ctx->Color.ColorMask));
+ if (!ctx->Color.ColorMask[0][0] ||
+ !ctx->Color.ColorMask[0][1] ||
+ !ctx->Color.ColorMask[0][2] ||
+ !ctx->Color.ColorMask[0][3])
+ _mesa_ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ }
+
+ if (state & META_DEPTH_TEST) {
+ save->Depth = ctx->Depth; /* struct copy */
+ if (ctx->Depth.Test)
+ _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_FALSE);
+ }
+
+ if (state & META_FOG) {
+ save->Fog = ctx->Fog.Enabled;
+ if (ctx->Fog.Enabled)
+ _mesa_set_enable(ctx, GL_FOG, GL_FALSE);
+ }
+
+ if (state & META_PIXEL_STORE) {
+ save->Pack = ctx->Pack;
+ save->Unpack = ctx->Unpack;
+ ctx->Pack = ctx->DefaultPacking;
+ ctx->Unpack = ctx->DefaultPacking;
+ }
+
+ if (state & META_PIXEL_TRANSFER) {
+ save->RedScale = ctx->Pixel.RedScale;
+ save->RedBias = ctx->Pixel.RedBias;
+ save->GreenScale = ctx->Pixel.GreenScale;
+ save->GreenBias = ctx->Pixel.GreenBias;
+ save->BlueScale = ctx->Pixel.BlueScale;
+ save->BlueBias = ctx->Pixel.BlueBias;
+ save->AlphaScale = ctx->Pixel.AlphaScale;
+ save->AlphaBias = ctx->Pixel.AlphaBias;
+ save->MapColorFlag = ctx->Pixel.MapColorFlag;
+ ctx->Pixel.RedScale = 1.0F;
+ ctx->Pixel.RedBias = 0.0F;
+ ctx->Pixel.GreenScale = 1.0F;
+ ctx->Pixel.GreenBias = 0.0F;
+ ctx->Pixel.BlueScale = 1.0F;
+ ctx->Pixel.BlueBias = 0.0F;
+ ctx->Pixel.AlphaScale = 1.0F;
+ ctx->Pixel.AlphaBias = 0.0F;
+ ctx->Pixel.MapColorFlag = GL_FALSE;
+ /* XXX more state */
+ ctx->NewState |=_NEW_PIXEL;
+ }
+
+ if (state & META_RASTERIZATION) {
+ save->FrontPolygonMode = ctx->Polygon.FrontMode;
+ save->BackPolygonMode = ctx->Polygon.BackMode;
+ save->PolygonOffset = ctx->Polygon.OffsetFill;
+ save->PolygonSmooth = ctx->Polygon.SmoothFlag;
+ save->PolygonStipple = ctx->Polygon.StippleFlag;
+ save->PolygonCull = ctx->Polygon.CullFlag;
+ _mesa_PolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ _mesa_set_enable(ctx, GL_POLYGON_OFFSET_FILL, GL_FALSE);
+ _mesa_set_enable(ctx, GL_POLYGON_SMOOTH, GL_FALSE);
+ _mesa_set_enable(ctx, GL_POLYGON_STIPPLE, GL_FALSE);
+ _mesa_set_enable(ctx, GL_CULL_FACE, GL_FALSE);
+ }
+
+ if (state & META_SCISSOR) {
+ save->Scissor = ctx->Scissor; /* struct copy */
+ _mesa_set_enable(ctx, GL_SCISSOR_TEST, GL_FALSE);
+ }
+
+ if (state & META_SHADER) {
+ if (ctx->Extensions.ARB_vertex_program) {
+ save->VertexProgramEnabled = ctx->VertexProgram.Enabled;
+ _mesa_reference_vertprog(ctx, &save->VertexProgram,
+ ctx->VertexProgram.Current);
+ _mesa_set_enable(ctx, GL_VERTEX_PROGRAM_ARB, GL_FALSE);
+ }
+
+ if (ctx->Extensions.ARB_fragment_program) {
+ save->FragmentProgramEnabled = ctx->FragmentProgram.Enabled;
+ _mesa_reference_fragprog(ctx, &save->FragmentProgram,
+ ctx->FragmentProgram.Current);
+ _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_FALSE);
+ }
+
+ if (ctx->Extensions.ARB_shader_objects) {
+ _mesa_reference_shader_program(ctx, &save->VertexShader,
+ ctx->Shader.CurrentVertexProgram);
+ _mesa_reference_shader_program(ctx, &save->GeometryShader,
+ ctx->Shader.CurrentGeometryProgram);
+ _mesa_reference_shader_program(ctx, &save->FragmentShader,
+ ctx->Shader.CurrentFragmentProgram);
+ _mesa_reference_shader_program(ctx, &save->ActiveShader,
+ ctx->Shader.CurrentFragmentProgram);
+
+ _mesa_UseProgramObjectARB(0);
+ }
+ }
+
+ if (state & META_STENCIL_TEST) {
+ save->Stencil = ctx->Stencil; /* struct copy */
+ if (ctx->Stencil.Enabled)
+ _mesa_set_enable(ctx, GL_STENCIL_TEST, GL_FALSE);
+ /* NOTE: other stencil state not reset */
+ }
+
+ if (state & META_TEXTURE) {
+ GLuint u, tgt;
+
+ save->ActiveUnit = ctx->Texture.CurrentUnit;
+ save->ClientActiveUnit = ctx->Array.ActiveTexture;
+ save->EnvMode = ctx->Texture.Unit[0].EnvMode;
+
+ /* Disable all texture units */
+ for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
+ save->TexEnabled[u] = ctx->Texture.Unit[u].Enabled;
+ save->TexGenEnabled[u] = ctx->Texture.Unit[u].TexGenEnabled;
+ if (ctx->Texture.Unit[u].Enabled ||
+ ctx->Texture.Unit[u].TexGenEnabled) {
+ _mesa_ActiveTextureARB(GL_TEXTURE0 + u);
+ _mesa_set_enable(ctx, GL_TEXTURE_1D, GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_2D, GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_3D, GL_FALSE);
+ if (ctx->Extensions.ARB_texture_cube_map)
+ _mesa_set_enable(ctx, GL_TEXTURE_CUBE_MAP, GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_RECTANGLE, GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_GEN_S, GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_GEN_T, GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_GEN_R, GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_GEN_Q, GL_FALSE);
+ }
+ }
+
+ /* save current texture objects for unit[0] only */
+ for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
+ _mesa_reference_texobj(&save->CurrentTexture[tgt],
+ ctx->Texture.Unit[0].CurrentTex[tgt]);
+ }
+
+ /* set defaults for unit[0] */
+ _mesa_ActiveTextureARB(GL_TEXTURE0);
+ _mesa_ClientActiveTextureARB(GL_TEXTURE0);
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+ }
+
+ if (state & META_TRANSFORM) {
+ GLuint activeTexture = ctx->Texture.CurrentUnit;
+ memcpy(save->ModelviewMatrix, ctx->ModelviewMatrixStack.Top->m,
+ 16 * sizeof(GLfloat));
+ memcpy(save->ProjectionMatrix, ctx->ProjectionMatrixStack.Top->m,
+ 16 * sizeof(GLfloat));
+ memcpy(save->TextureMatrix, ctx->TextureMatrixStack[0].Top->m,
+ 16 * sizeof(GLfloat));
+ save->MatrixMode = ctx->Transform.MatrixMode;
+ /* set 1:1 vertex:pixel coordinate transform */
+ _mesa_ActiveTextureARB(GL_TEXTURE0);
+ _mesa_MatrixMode(GL_TEXTURE);
+ _mesa_LoadIdentity();
+ _mesa_ActiveTextureARB(GL_TEXTURE0 + activeTexture);
+ _mesa_MatrixMode(GL_MODELVIEW);
+ _mesa_LoadIdentity();
+ _mesa_MatrixMode(GL_PROJECTION);
+ _mesa_LoadIdentity();
+ _mesa_Ortho(0.0, ctx->DrawBuffer->Width,
+ 0.0, ctx->DrawBuffer->Height,
+ -1.0, 1.0);
+ save->ClipPlanesEnabled = ctx->Transform.ClipPlanesEnabled;
+ if (ctx->Transform.ClipPlanesEnabled) {
+ GLuint i;
+ for (i = 0; i < ctx->Const.MaxClipPlanes; i++) {
+ _mesa_set_enable(ctx, GL_CLIP_PLANE0 + i, GL_FALSE);
+ }
+ }
+ }
+
+ if (state & META_VERTEX) {
+ /* save vertex array object state */
+ _mesa_reference_array_object(ctx, &save->ArrayObj,
+ ctx->Array.ArrayObj);
+ _mesa_reference_buffer_object(ctx, &save->ArrayBufferObj,
+ ctx->Array.ArrayBufferObj);
+ /* set some default state? */
+ }
+
+ if (state & META_VIEWPORT) {
+ /* save viewport state */
+ save->ViewportX = ctx->Viewport.X;
+ save->ViewportY = ctx->Viewport.Y;
+ save->ViewportW = ctx->Viewport.Width;
+ save->ViewportH = ctx->Viewport.Height;
+ /* set viewport to match window size */
+ if (ctx->Viewport.X != 0 ||
+ ctx->Viewport.Y != 0 ||
+ ctx->Viewport.Width != ctx->DrawBuffer->Width ||
+ ctx->Viewport.Height != ctx->DrawBuffer->Height) {
+ _mesa_set_viewport(ctx, 0, 0,
+ ctx->DrawBuffer->Width, ctx->DrawBuffer->Height);
+ }
+ /* save depth range state */
+ save->DepthNear = ctx->Viewport.Near;
+ save->DepthFar = ctx->Viewport.Far;
+ /* set depth range to default */
+ _mesa_DepthRange(0.0, 1.0);
+ }
+
+ /* misc */
+ {
+ save->Lighting = ctx->Light.Enabled;
+ if (ctx->Light.Enabled)
+ _mesa_set_enable(ctx, GL_LIGHTING, GL_FALSE);
+ }
+}
+
+
+/**
+ * Leave meta state. This is like a light-weight version of glPopAttrib().
+ */
+static void
+_mesa_meta_end(struct gl_context *ctx)
+{
+ struct save_state *save = &ctx->Meta->Save[--ctx->Meta->SaveStackDepth];
+ const GLbitfield state = save->SavedState;
+
+ if (state & META_ALPHA_TEST) {
+ if (ctx->Color.AlphaEnabled != save->AlphaEnabled)
+ _mesa_set_enable(ctx, GL_ALPHA_TEST, save->AlphaEnabled);
+ _mesa_AlphaFunc(save->AlphaFunc, save->AlphaRef);
+ }
+
+ if (state & META_BLEND) {
+ if (ctx->Color.BlendEnabled != save->BlendEnabled) {
+ if (ctx->Extensions.EXT_draw_buffers2) {
+ GLuint i;
+ for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
+ _mesa_set_enablei(ctx, GL_BLEND, i, (save->BlendEnabled >> i) & 1);
+ }
+ }
+ else {
+ _mesa_set_enable(ctx, GL_BLEND, (save->BlendEnabled & 1));
+ }
+ }
+ if (ctx->Color.ColorLogicOpEnabled != save->ColorLogicOpEnabled)
+ _mesa_set_enable(ctx, GL_COLOR_LOGIC_OP, save->ColorLogicOpEnabled);
+ }
+
+ if (state & META_COLOR_MASK) {
+ GLuint i;
+ for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
+ if (!TEST_EQ_4V(ctx->Color.ColorMask[i], save->ColorMask[i])) {
+ if (i == 0) {
+ _mesa_ColorMask(save->ColorMask[i][0], save->ColorMask[i][1],
+ save->ColorMask[i][2], save->ColorMask[i][3]);
+ }
+ else {
+ _mesa_ColorMaskIndexed(i,
+ save->ColorMask[i][0],
+ save->ColorMask[i][1],
+ save->ColorMask[i][2],
+ save->ColorMask[i][3]);
+ }
+ }
+ }
+ }
+
+ if (state & META_DEPTH_TEST) {
+ if (ctx->Depth.Test != save->Depth.Test)
+ _mesa_set_enable(ctx, GL_DEPTH_TEST, save->Depth.Test);
+ _mesa_DepthFunc(save->Depth.Func);
+ _mesa_DepthMask(save->Depth.Mask);
+ }
+
+ if (state & META_FOG) {
+ _mesa_set_enable(ctx, GL_FOG, save->Fog);
+ }
+
+ if (state & META_PIXEL_STORE) {
+ ctx->Pack = save->Pack;
+ ctx->Unpack = save->Unpack;
+ }
+
+ if (state & META_PIXEL_TRANSFER) {
+ ctx->Pixel.RedScale = save->RedScale;
+ ctx->Pixel.RedBias = save->RedBias;
+ ctx->Pixel.GreenScale = save->GreenScale;
+ ctx->Pixel.GreenBias = save->GreenBias;
+ ctx->Pixel.BlueScale = save->BlueScale;
+ ctx->Pixel.BlueBias = save->BlueBias;
+ ctx->Pixel.AlphaScale = save->AlphaScale;
+ ctx->Pixel.AlphaBias = save->AlphaBias;
+ ctx->Pixel.MapColorFlag = save->MapColorFlag;
+ /* XXX more state */
+ ctx->NewState |=_NEW_PIXEL;
+ }
+
+ if (state & META_RASTERIZATION) {
+ _mesa_PolygonMode(GL_FRONT, save->FrontPolygonMode);
+ _mesa_PolygonMode(GL_BACK, save->BackPolygonMode);
+ _mesa_set_enable(ctx, GL_POLYGON_STIPPLE, save->PolygonStipple);
+ _mesa_set_enable(ctx, GL_POLYGON_OFFSET_FILL, save->PolygonOffset);
+ _mesa_set_enable(ctx, GL_POLYGON_SMOOTH, save->PolygonSmooth);
+ _mesa_set_enable(ctx, GL_CULL_FACE, save->PolygonCull);
+ }
+
+ if (state & META_SCISSOR) {
+ _mesa_set_enable(ctx, GL_SCISSOR_TEST, save->Scissor.Enabled);
+ _mesa_Scissor(save->Scissor.X, save->Scissor.Y,
+ save->Scissor.Width, save->Scissor.Height);
+ }
+
+ if (state & META_SHADER) {
+ if (ctx->Extensions.ARB_vertex_program) {
+ _mesa_set_enable(ctx, GL_VERTEX_PROGRAM_ARB,
+ save->VertexProgramEnabled);
+ _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
+ save->VertexProgram);
+ _mesa_reference_vertprog(ctx, &save->VertexProgram, NULL);
+ }
+
+ if (ctx->Extensions.ARB_fragment_program) {
+ _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB,
+ save->FragmentProgramEnabled);
+ _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current,
+ save->FragmentProgram);
+ _mesa_reference_fragprog(ctx, &save->FragmentProgram, NULL);
+ }
+
+ if (ctx->Extensions.ARB_vertex_shader)
+ _mesa_use_shader_program(ctx, GL_VERTEX_SHADER, save->VertexShader);
+
+ if (ctx->Extensions.ARB_geometry_shader4)
+ _mesa_use_shader_program(ctx, GL_GEOMETRY_SHADER_ARB,
+ save->GeometryShader);
+
+ if (ctx->Extensions.ARB_fragment_shader)
+ _mesa_use_shader_program(ctx, GL_FRAGMENT_SHADER,
+ save->FragmentShader);
+
+ _mesa_reference_shader_program(ctx, &ctx->Shader.ActiveProgram,
+ save->ActiveShader);
+ }
+
+ if (state & META_STENCIL_TEST) {
+ const struct gl_stencil_attrib *stencil = &save->Stencil;
+
+ _mesa_set_enable(ctx, GL_STENCIL_TEST, stencil->Enabled);
+ _mesa_ClearStencil(stencil->Clear);
+ if (ctx->Extensions.EXT_stencil_two_side) {
+ _mesa_set_enable(ctx, GL_STENCIL_TEST_TWO_SIDE_EXT,
+ stencil->TestTwoSide);
+ _mesa_ActiveStencilFaceEXT(stencil->ActiveFace
+ ? GL_BACK : GL_FRONT);
+ }
+ /* front state */
+ _mesa_StencilFuncSeparate(GL_FRONT,
+ stencil->Function[0],
+ stencil->Ref[0],
+ stencil->ValueMask[0]);
+ _mesa_StencilMaskSeparate(GL_FRONT, stencil->WriteMask[0]);
+ _mesa_StencilOpSeparate(GL_FRONT, stencil->FailFunc[0],
+ stencil->ZFailFunc[0],
+ stencil->ZPassFunc[0]);
+ /* back state */
+ _mesa_StencilFuncSeparate(GL_BACK,
+ stencil->Function[1],
+ stencil->Ref[1],
+ stencil->ValueMask[1]);
+ _mesa_StencilMaskSeparate(GL_BACK, stencil->WriteMask[1]);
+ _mesa_StencilOpSeparate(GL_BACK, stencil->FailFunc[1],
+ stencil->ZFailFunc[1],
+ stencil->ZPassFunc[1]);
+ }
+
+ if (state & META_TEXTURE) {
+ GLuint u, tgt;
+
+ ASSERT(ctx->Texture.CurrentUnit == 0);
+
+ /* restore texenv for unit[0] */
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, save->EnvMode);
+
+ /* restore texture objects for unit[0] only */
+ for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
+ _mesa_reference_texobj(&ctx->Texture.Unit[0].CurrentTex[tgt],
+ save->CurrentTexture[tgt]);
+ _mesa_reference_texobj(&save->CurrentTexture[tgt], NULL);
+ }
+
+ /* Re-enable textures, texgen */
+ for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
+ if (save->TexEnabled[u]) {
+ _mesa_ActiveTextureARB(GL_TEXTURE0 + u);
+
+ if (save->TexEnabled[u] & TEXTURE_1D_BIT)
+ _mesa_set_enable(ctx, GL_TEXTURE_1D, GL_TRUE);
+ if (save->TexEnabled[u] & TEXTURE_2D_BIT)
+ _mesa_set_enable(ctx, GL_TEXTURE_2D, GL_TRUE);
+ if (save->TexEnabled[u] & TEXTURE_3D_BIT)
+ _mesa_set_enable(ctx, GL_TEXTURE_3D, GL_TRUE);
+ if (save->TexEnabled[u] & TEXTURE_CUBE_BIT)
+ _mesa_set_enable(ctx, GL_TEXTURE_CUBE_MAP, GL_TRUE);
+ if (save->TexEnabled[u] & TEXTURE_RECT_BIT)
+ _mesa_set_enable(ctx, GL_TEXTURE_RECTANGLE, GL_TRUE);
+ }
+
+ if (save->TexGenEnabled[u]) {
+ _mesa_ActiveTextureARB(GL_TEXTURE0 + u);
+
+ if (save->TexGenEnabled[u] & S_BIT)
+ _mesa_set_enable(ctx, GL_TEXTURE_GEN_S, GL_TRUE);
+ if (save->TexGenEnabled[u] & T_BIT)
+ _mesa_set_enable(ctx, GL_TEXTURE_GEN_T, GL_TRUE);
+ if (save->TexGenEnabled[u] & R_BIT)
+ _mesa_set_enable(ctx, GL_TEXTURE_GEN_R, GL_TRUE);
+ if (save->TexGenEnabled[u] & Q_BIT)
+ _mesa_set_enable(ctx, GL_TEXTURE_GEN_Q, GL_TRUE);
+ }
+ }
+
+ /* restore current unit state */
+ _mesa_ActiveTextureARB(GL_TEXTURE0 + save->ActiveUnit);
+ _mesa_ClientActiveTextureARB(GL_TEXTURE0 + save->ClientActiveUnit);
+ }
+
+ if (state & META_TRANSFORM) {
+ GLuint activeTexture = ctx->Texture.CurrentUnit;
+ _mesa_ActiveTextureARB(GL_TEXTURE0);
+ _mesa_MatrixMode(GL_TEXTURE);
+ _mesa_LoadMatrixf(save->TextureMatrix);
+ _mesa_ActiveTextureARB(GL_TEXTURE0 + activeTexture);
+
+ _mesa_MatrixMode(GL_MODELVIEW);
+ _mesa_LoadMatrixf(save->ModelviewMatrix);
+
+ _mesa_MatrixMode(GL_PROJECTION);
+ _mesa_LoadMatrixf(save->ProjectionMatrix);
+
+ _mesa_MatrixMode(save->MatrixMode);
+
+ if (save->ClipPlanesEnabled) {
+ GLuint i;
+ for (i = 0; i < ctx->Const.MaxClipPlanes; i++) {
+ if (save->ClipPlanesEnabled & (1 << i)) {
+ _mesa_set_enable(ctx, GL_CLIP_PLANE0 + i, GL_TRUE);
+ }
+ }
+ }
+ }
+
+ if (state & META_VERTEX) {
+ /* restore vertex buffer object */
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, save->ArrayBufferObj->Name);
+ _mesa_reference_buffer_object(ctx, &save->ArrayBufferObj, NULL);
+
+ /* restore vertex array object */
+ _mesa_BindVertexArray(save->ArrayObj->Name);
+ _mesa_reference_array_object(ctx, &save->ArrayObj, NULL);
+ }
+
+ if (state & META_VIEWPORT) {
+ if (save->ViewportX != ctx->Viewport.X ||
+ save->ViewportY != ctx->Viewport.Y ||
+ save->ViewportW != ctx->Viewport.Width ||
+ save->ViewportH != ctx->Viewport.Height) {
+ _mesa_set_viewport(ctx, save->ViewportX, save->ViewportY,
+ save->ViewportW, save->ViewportH);
+ }
+ _mesa_DepthRange(save->DepthNear, save->DepthFar);
+ }
+
+ /* misc */
+ if (save->Lighting) {
+ _mesa_set_enable(ctx, GL_LIGHTING, GL_TRUE);
+ }
+}
+
+
+/**
+ * Convert Z from a normalized value in the range [0, 1] to an object-space
+ * Z coordinate in [-1, +1] so that drawing at the new Z position with the
+ * default/identity ortho projection results in the original Z value.
+ * Used by the meta-Clear, Draw/CopyPixels and Bitmap functions where the Z
+ * value comes from the clear value or raster position.
+ */
+static INLINE GLfloat
+invert_z(GLfloat normZ)
+{
+ GLfloat objZ = 1.0 - 2.0 * normZ;
+ return objZ;
+}
+
+
+/**
+ * One-time init for a temp_texture object.
+ * Choose tex target, compute max tex size, etc.
+ */
+static void
+init_temp_texture(struct gl_context *ctx, struct temp_texture *tex)
+{
+ /* prefer texture rectangle */
+ if (ctx->Extensions.NV_texture_rectangle) {
+ tex->Target = GL_TEXTURE_RECTANGLE;
+ tex->MaxSize = ctx->Const.MaxTextureRectSize;
+ tex->NPOT = GL_TRUE;
+ }
+ else {
+ /* use 2D texture, NPOT if possible */
+ tex->Target = GL_TEXTURE_2D;
+ tex->MaxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
+ tex->NPOT = ctx->Extensions.ARB_texture_non_power_of_two;
+ }
+ tex->MinSize = 16; /* 16 x 16 at least */
+ assert(tex->MaxSize > 0);
+
+ _mesa_GenTextures(1, &tex->TexObj);
+}
+
+
+/**
+ * Return pointer to temp_texture info for non-bitmap ops.
+ * This does some one-time init if needed.
+ */
+static struct temp_texture *
+get_temp_texture(struct gl_context *ctx)
+{
+ struct temp_texture *tex = &ctx->Meta->TempTex;
+
+ if (!tex->TexObj) {
+ init_temp_texture(ctx, tex);
+ }
+
+ return tex;
+}
+
+
+/**
+ * Return pointer to temp_texture info for _mesa_meta_bitmap().
+ * We use a separate texture for bitmaps to reduce texture
+ * allocation/deallocation.
+ */
+static struct temp_texture *
+get_bitmap_temp_texture(struct gl_context *ctx)
+{
+ struct temp_texture *tex = &ctx->Meta->Bitmap.Tex;
+
+ if (!tex->TexObj) {
+ init_temp_texture(ctx, tex);
+ }
+
+ return tex;
+}
+
+
+/**
+ * Compute the width/height of texture needed to draw an image of the
+ * given size. Return a flag indicating whether the current texture
+ * can be re-used (glTexSubImage2D) or if a new texture needs to be
+ * allocated (glTexImage2D).
+ * Also, compute s/t texcoords for drawing.
+ *
+ * \return GL_TRUE if new texture is needed, GL_FALSE otherwise
+ */
+static GLboolean
+alloc_texture(struct temp_texture *tex,
+ GLsizei width, GLsizei height, GLenum intFormat)
+{
+ GLboolean newTex = GL_FALSE;
+
+ ASSERT(width <= tex->MaxSize);
+ ASSERT(height <= tex->MaxSize);
+
+ if (width > tex->Width ||
+ height > tex->Height ||
+ intFormat != tex->IntFormat) {
+ /* alloc new texture (larger or different format) */
+
+ if (tex->NPOT) {
+ /* use non-power of two size */
+ tex->Width = MAX2(tex->MinSize, width);
+ tex->Height = MAX2(tex->MinSize, height);
+ }
+ else {
+ /* find power of two size */
+ GLsizei w, h;
+ w = h = tex->MinSize;
+ while (w < width)
+ w *= 2;
+ while (h < height)
+ h *= 2;
+ tex->Width = w;
+ tex->Height = h;
+ }
+
+ tex->IntFormat = intFormat;
+
+ newTex = GL_TRUE;
+ }
+
+ /* compute texcoords */
+ if (tex->Target == GL_TEXTURE_RECTANGLE) {
+ tex->Sright = (GLfloat) width;
+ tex->Ttop = (GLfloat) height;
+ }
+ else {
+ tex->Sright = (GLfloat) width / tex->Width;
+ tex->Ttop = (GLfloat) height / tex->Height;
+ }
+
+ return newTex;
+}
+
+
+/**
+ * Setup/load texture for glCopyPixels or glBlitFramebuffer.
+ */
+static void
+setup_copypix_texture(struct temp_texture *tex,
+ GLboolean newTex,
+ GLint srcX, GLint srcY,
+ GLsizei width, GLsizei height, GLenum intFormat,
+ GLenum filter)
+{
+ _mesa_BindTexture(tex->Target, tex->TexObj);
+ _mesa_TexParameteri(tex->Target, GL_TEXTURE_MIN_FILTER, filter);
+ _mesa_TexParameteri(tex->Target, GL_TEXTURE_MAG_FILTER, filter);
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+
+ /* copy framebuffer image to texture */
+ if (newTex) {
+ /* create new tex image */
+ if (tex->Width == width && tex->Height == height) {
+ /* create new tex with framebuffer data */
+ _mesa_CopyTexImage2D(tex->Target, 0, tex->IntFormat,
+ srcX, srcY, width, height, 0);
+ }
+ else {
+ /* create empty texture */
+ _mesa_TexImage2D(tex->Target, 0, tex->IntFormat,
+ tex->Width, tex->Height, 0,
+ intFormat, GL_UNSIGNED_BYTE, NULL);
+ /* load image */
+ _mesa_CopyTexSubImage2D(tex->Target, 0,
+ 0, 0, srcX, srcY, width, height);
+ }
+ }
+ else {
+ /* replace existing tex image */
+ _mesa_CopyTexSubImage2D(tex->Target, 0,
+ 0, 0, srcX, srcY, width, height);
+ }
+}
+
+
+/**
+ * Setup/load texture for glDrawPixels.
+ */
+static void
+setup_drawpix_texture(struct gl_context *ctx,
+ struct temp_texture *tex,
+ GLboolean newTex,
+ GLenum texIntFormat,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const GLvoid *pixels)
+{
+ _mesa_BindTexture(tex->Target, tex->TexObj);
+ _mesa_TexParameteri(tex->Target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ _mesa_TexParameteri(tex->Target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+
+ /* copy pixel data to texture */
+ if (newTex) {
+ /* create new tex image */
+ if (tex->Width == width && tex->Height == height) {
+ /* create new tex and load image data */
+ _mesa_TexImage2D(tex->Target, 0, tex->IntFormat,
+ tex->Width, tex->Height, 0, format, type, pixels);
+ }
+ else {
+ struct gl_buffer_object *save_unpack_obj = NULL;
+
+ _mesa_reference_buffer_object(ctx, &save_unpack_obj,
+ ctx->Unpack.BufferObj);
+ _mesa_BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
+ /* create empty texture */
+ _mesa_TexImage2D(tex->Target, 0, tex->IntFormat,
+ tex->Width, tex->Height, 0, format, type, NULL);
+ if (save_unpack_obj != NULL)
+ _mesa_BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB,
+ save_unpack_obj->Name);
+ /* load image */
+ _mesa_TexSubImage2D(tex->Target, 0,
+ 0, 0, width, height, format, type, pixels);
+ }
+ }
+ else {
+ /* replace existing tex image */
+ _mesa_TexSubImage2D(tex->Target, 0,
+ 0, 0, width, height, format, type, pixels);
+ }
+}
+
+
+
+/**
+ * One-time init for drawing depth pixels.
+ */
+static void
+init_blit_depth_pixels(struct gl_context *ctx)
+{
+ static const char *program =
+ "!!ARBfp1.0\n"
+ "TEX result.depth, fragment.texcoord[0], texture[0], %s; \n"
+ "END \n";
+ char program2[200];
+ struct blit_state *blit = &ctx->Meta->Blit;
+ struct temp_texture *tex = get_temp_texture(ctx);
+ const char *texTarget;
+
+ assert(blit->DepthFP == 0);
+
+ /* replace %s with "RECT" or "2D" */
+ assert(strlen(program) + 4 < sizeof(program2));
+ if (tex->Target == GL_TEXTURE_RECTANGLE)
+ texTarget = "RECT";
+ else
+ texTarget = "2D";
+ _mesa_snprintf(program2, sizeof(program2), program, texTarget);
+
+ _mesa_GenPrograms(1, &blit->DepthFP);
+ _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, blit->DepthFP);
+ _mesa_ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
+ strlen(program2), (const GLubyte *) program2);
+}
+
+
+/**
+ * Try to do a glBlitFramebuffer using no-copy texturing.
+ * We can do this when the src renderbuffer is actually a texture.
+ * But if the src buffer == dst buffer we cannot do this.
+ *
+ * \return new buffer mask indicating the buffers left to blit using the
+ * normal path.
+ */
+static GLbitfield
+blitframebuffer_texture(struct gl_context *ctx,
+ GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter)
+{
+ if (mask & GL_COLOR_BUFFER_BIT) {
+ const struct gl_framebuffer *drawFb = ctx->DrawBuffer;
+ const struct gl_framebuffer *readFb = ctx->ReadBuffer;
+ const struct gl_renderbuffer_attachment *drawAtt =
+ &drawFb->Attachment[drawFb->_ColorDrawBufferIndexes[0]];
+ const struct gl_renderbuffer_attachment *readAtt =
+ &readFb->Attachment[readFb->_ColorReadBufferIndex];
+
+ if (readAtt && readAtt->Texture) {
+ const struct gl_texture_object *texObj = readAtt->Texture;
+ const GLuint srcLevel = readAtt->TextureLevel;
+ const GLenum minFilterSave = texObj->MinFilter;
+ const GLenum magFilterSave = texObj->MagFilter;
+ const GLint baseLevelSave = texObj->BaseLevel;
+ const GLint maxLevelSave = texObj->MaxLevel;
+ const GLenum wrapSSave = texObj->WrapS;
+ const GLenum wrapTSave = texObj->WrapT;
+ const GLenum target = texObj->Target;
+
+ if (drawAtt->Texture == readAtt->Texture) {
+ /* Can't use same texture as both the source and dest. We need
+ * to handle overlapping blits and besides, some hw may not
+ * support this.
+ */
+ return mask;
+ }
+
+ if (target != GL_TEXTURE_2D && target != GL_TEXTURE_RECTANGLE_ARB) {
+ /* Can't handle other texture types at this time */
+ return mask;
+ }
+
+ /*
+ printf("Blit from texture!\n");
+ printf(" srcAtt %p dstAtt %p\n", readAtt, drawAtt);
+ printf(" srcTex %p dstText %p\n", texObj, drawAtt->Texture);
+ */
+
+ /* Prepare src texture state */
+ _mesa_BindTexture(target, texObj->Name);
+ _mesa_TexParameteri(target, GL_TEXTURE_MIN_FILTER, filter);
+ _mesa_TexParameteri(target, GL_TEXTURE_MAG_FILTER, filter);
+ if (target != GL_TEXTURE_RECTANGLE_ARB) {
+ _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, srcLevel);
+ _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, srcLevel);
+ }
+ _mesa_TexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ _mesa_TexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+ _mesa_set_enable(ctx, target, GL_TRUE);
+
+ /* Prepare vertex data (the VBO was previously created and bound) */
+ {
+ struct vertex {
+ GLfloat x, y, s, t;
+ };
+ struct vertex verts[4];
+ GLfloat s0, t0, s1, t1;
+
+ if (target == GL_TEXTURE_2D) {
+ const struct gl_texture_image *texImage
+ = _mesa_select_tex_image(ctx, texObj, target, srcLevel);
+ s0 = srcX0 / (float) texImage->Width;
+ s1 = srcX1 / (float) texImage->Width;
+ t0 = srcY0 / (float) texImage->Height;
+ t1 = srcY1 / (float) texImage->Height;
+ }
+ else {
+ assert(target == GL_TEXTURE_RECTANGLE_ARB);
+ s0 = srcX0;
+ s1 = srcX1;
+ t0 = srcY0;
+ t1 = srcY1;
+ }
+
+ verts[0].x = (GLfloat) dstX0;
+ verts[0].y = (GLfloat) dstY0;
+ verts[1].x = (GLfloat) dstX1;
+ verts[1].y = (GLfloat) dstY0;
+ verts[2].x = (GLfloat) dstX1;
+ verts[2].y = (GLfloat) dstY1;
+ verts[3].x = (GLfloat) dstX0;
+ verts[3].y = (GLfloat) dstY1;
+
+ verts[0].s = s0;
+ verts[0].t = t0;
+ verts[1].s = s1;
+ verts[1].t = t0;
+ verts[2].s = s1;
+ verts[2].t = t1;
+ verts[3].s = s0;
+ verts[3].t = t1;
+
+ _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts);
+ }
+
+ _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ /* Restore texture object state, the texture binding will
+ * be restored by _mesa_meta_end().
+ */
+ _mesa_TexParameteri(target, GL_TEXTURE_MIN_FILTER, minFilterSave);
+ _mesa_TexParameteri(target, GL_TEXTURE_MAG_FILTER, magFilterSave);
+ if (target != GL_TEXTURE_RECTANGLE_ARB) {
+ _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, baseLevelSave);
+ _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, maxLevelSave);
+ }
+ _mesa_TexParameteri(target, GL_TEXTURE_WRAP_S, wrapSSave);
+ _mesa_TexParameteri(target, GL_TEXTURE_WRAP_T, wrapTSave);
+
+ /* Done with color buffer */
+ mask &= ~GL_COLOR_BUFFER_BIT;
+ }
+ }
+
+ return mask;
+}
+
+
+/**
+ * Meta implementation of ctx->Driver.BlitFramebuffer() in terms
+ * of texture mapping and polygon rendering.
+ */
+void
+_mesa_meta_BlitFramebuffer(struct gl_context *ctx,
+ GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter)
+{
+ struct blit_state *blit = &ctx->Meta->Blit;
+ struct temp_texture *tex = get_temp_texture(ctx);
+ const GLsizei maxTexSize = tex->MaxSize;
+ const GLint srcX = MIN2(srcX0, srcX1);
+ const GLint srcY = MIN2(srcY0, srcY1);
+ const GLint srcW = abs(srcX1 - srcX0);
+ const GLint srcH = abs(srcY1 - srcY0);
+ const GLboolean srcFlipX = srcX1 < srcX0;
+ const GLboolean srcFlipY = srcY1 < srcY0;
+ struct vertex {
+ GLfloat x, y, s, t;
+ };
+ struct vertex verts[4];
+ GLboolean newTex;
+
+ if (srcW > maxTexSize || srcH > maxTexSize) {
+ /* XXX avoid this fallback */
+ _swrast_BlitFramebuffer(ctx, srcX0, srcY0, srcX1, srcY1,
+ dstX0, dstY0, dstX1, dstY1, mask, filter);
+ return;
+ }
+
+ if (srcFlipX) {
+ GLint tmp = dstX0;
+ dstX0 = dstX1;
+ dstX1 = tmp;
+ }
+
+ if (srcFlipY) {
+ GLint tmp = dstY0;
+ dstY0 = dstY1;
+ dstY1 = tmp;
+ }
+
+ /* only scissor effects blit so save/clear all other relevant state */
+ _mesa_meta_begin(ctx, ~META_SCISSOR);
+
+ if (blit->ArrayObj == 0) {
+ /* one-time setup */
+
+ /* create vertex array object */
+ _mesa_GenVertexArrays(1, &blit->ArrayObj);
+ _mesa_BindVertexArray(blit->ArrayObj);
+
+ /* create vertex array buffer */
+ _mesa_GenBuffersARB(1, &blit->VBO);
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, blit->VBO);
+ _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts),
+ NULL, GL_DYNAMIC_DRAW_ARB);
+
+ /* setup vertex arrays */
+ _mesa_VertexPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(x));
+ _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(s));
+ _mesa_EnableClientState(GL_VERTEX_ARRAY);
+ _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY);
+ }
+ else {
+ _mesa_BindVertexArray(blit->ArrayObj);
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, blit->VBO);
+ }
+
+ /* Try faster, direct texture approach first */
+ mask = blitframebuffer_texture(ctx, srcX0, srcY0, srcX1, srcY1,
+ dstX0, dstY0, dstX1, dstY1, mask, filter);
+ if (mask == 0x0) {
+ _mesa_meta_end(ctx);
+ return;
+ }
+
+ /* Continue with "normal" approach which involves copying the src rect
+ * into a temporary texture and is "blitted" by drawing a textured quad.
+ */
+
+ newTex = alloc_texture(tex, srcW, srcH, GL_RGBA);
+
+ /* vertex positions/texcoords (after texture allocation!) */
+ {
+ verts[0].x = (GLfloat) dstX0;
+ verts[0].y = (GLfloat) dstY0;
+ verts[1].x = (GLfloat) dstX1;
+ verts[1].y = (GLfloat) dstY0;
+ verts[2].x = (GLfloat) dstX1;
+ verts[2].y = (GLfloat) dstY1;
+ verts[3].x = (GLfloat) dstX0;
+ verts[3].y = (GLfloat) dstY1;
+
+ verts[0].s = 0.0F;
+ verts[0].t = 0.0F;
+ verts[1].s = tex->Sright;
+ verts[1].t = 0.0F;
+ verts[2].s = tex->Sright;
+ verts[2].t = tex->Ttop;
+ verts[3].s = 0.0F;
+ verts[3].t = tex->Ttop;
+
+ /* upload new vertex data */
+ _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts);
+ }
+
+ _mesa_set_enable(ctx, tex->Target, GL_TRUE);
+
+ if (mask & GL_COLOR_BUFFER_BIT) {
+ setup_copypix_texture(tex, newTex, srcX, srcY, srcW, srcH,
+ GL_RGBA, filter);
+ _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ mask &= ~GL_COLOR_BUFFER_BIT;
+ }
+
+ if (mask & GL_DEPTH_BUFFER_BIT) {
+ GLuint *tmp = (GLuint *) malloc(srcW * srcH * sizeof(GLuint));
+ if (tmp) {
+ if (!blit->DepthFP)
+ init_blit_depth_pixels(ctx);
+
+ /* maybe change tex format here */
+ newTex = alloc_texture(tex, srcW, srcH, GL_DEPTH_COMPONENT);
+
+ _mesa_ReadPixels(srcX, srcY, srcW, srcH,
+ GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, tmp);
+
+ setup_drawpix_texture(ctx, tex, newTex, GL_DEPTH_COMPONENT, srcW, srcH,
+ GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, tmp);
+
+ _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, blit->DepthFP);
+ _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_TRUE);
+ _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+ _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_TRUE);
+ _mesa_DepthFunc(GL_ALWAYS);
+ _mesa_DepthMask(GL_TRUE);
+
+ _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ mask &= ~GL_DEPTH_BUFFER_BIT;
+
+ free(tmp);
+ }
+ }
+
+ if (mask & GL_STENCIL_BUFFER_BIT) {
+ /* XXX can't easily do stencil */
+ }
+
+ _mesa_set_enable(ctx, tex->Target, GL_FALSE);
+
+ _mesa_meta_end(ctx);
+
+ if (mask) {
+ _swrast_BlitFramebuffer(ctx, srcX0, srcY0, srcX1, srcY1,
+ dstX0, dstY0, dstX1, dstY1, mask, filter);
+ }
+}
+
+
+/**
+ * Meta implementation of ctx->Driver.Clear() in terms of polygon rendering.
+ */
+void
+_mesa_meta_Clear(struct gl_context *ctx, GLbitfield buffers)
+{
+ struct clear_state *clear = &ctx->Meta->Clear;
+ struct vertex {
+ GLfloat x, y, z, r, g, b, a;
+ };
+ struct vertex verts[4];
+ /* save all state but scissor, pixel pack/unpack */
+ GLbitfield metaSave = META_ALL - META_SCISSOR - META_PIXEL_STORE;
+ const GLuint stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1;
+
+ if (buffers & BUFFER_BITS_COLOR) {
+ /* if clearing color buffers, don't save/restore colormask */
+ metaSave -= META_COLOR_MASK;
+ }
+
+ _mesa_meta_begin(ctx, metaSave);
+
+ if (clear->ArrayObj == 0) {
+ /* one-time setup */
+
+ /* create vertex array object */
+ _mesa_GenVertexArrays(1, &clear->ArrayObj);
+ _mesa_BindVertexArray(clear->ArrayObj);
+
+ /* create vertex array buffer */
+ _mesa_GenBuffersARB(1, &clear->VBO);
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, clear->VBO);
+
+ /* setup vertex arrays */
+ _mesa_VertexPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(x));
+ _mesa_ColorPointer(4, GL_FLOAT, sizeof(struct vertex), OFFSET(r));
+ _mesa_EnableClientState(GL_VERTEX_ARRAY);
+ _mesa_EnableClientState(GL_COLOR_ARRAY);
+ }
+ else {
+ _mesa_BindVertexArray(clear->ArrayObj);
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, clear->VBO);
+ }
+
+ /* GL_COLOR_BUFFER_BIT */
+ if (buffers & BUFFER_BITS_COLOR) {
+ /* leave colormask, glDrawBuffer state as-is */
+ }
+ else {
+ ASSERT(metaSave & META_COLOR_MASK);
+ _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+ }
+
+ /* GL_DEPTH_BUFFER_BIT */
+ if (buffers & BUFFER_BIT_DEPTH) {
+ _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_TRUE);
+ _mesa_DepthFunc(GL_ALWAYS);
+ _mesa_DepthMask(GL_TRUE);
+ }
+ else {
+ assert(!ctx->Depth.Test);
+ }
+
+ /* GL_STENCIL_BUFFER_BIT */
+ if (buffers & BUFFER_BIT_STENCIL) {
+ _mesa_set_enable(ctx, GL_STENCIL_TEST, GL_TRUE);
+ _mesa_StencilOpSeparate(GL_FRONT_AND_BACK,
+ GL_REPLACE, GL_REPLACE, GL_REPLACE);
+ _mesa_StencilFuncSeparate(GL_FRONT_AND_BACK, GL_ALWAYS,
+ ctx->Stencil.Clear & stencilMax,
+ ctx->Stencil.WriteMask[0]);
+ }
+ else {
+ assert(!ctx->Stencil.Enabled);
+ }
+
+ /* vertex positions/colors */
+ {
+ const GLfloat x0 = (GLfloat) ctx->DrawBuffer->_Xmin;
+ const GLfloat y0 = (GLfloat) ctx->DrawBuffer->_Ymin;
+ const GLfloat x1 = (GLfloat) ctx->DrawBuffer->_Xmax;
+ const GLfloat y1 = (GLfloat) ctx->DrawBuffer->_Ymax;
+ const GLfloat z = invert_z(ctx->Depth.Clear);
+ GLuint i;
+
+ verts[0].x = x0;
+ verts[0].y = y0;
+ verts[0].z = z;
+ verts[1].x = x1;
+ verts[1].y = y0;
+ verts[1].z = z;
+ verts[2].x = x1;
+ verts[2].y = y1;
+ verts[2].z = z;
+ verts[3].x = x0;
+ verts[3].y = y1;
+ verts[3].z = z;
+
+ /* vertex colors */
+ for (i = 0; i < 4; i++) {
+ verts[i].r = ctx->Color.ClearColor[0];
+ verts[i].g = ctx->Color.ClearColor[1];
+ verts[i].b = ctx->Color.ClearColor[2];
+ verts[i].a = ctx->Color.ClearColor[3];
+ }
+
+ /* upload new vertex data */
+ _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts), verts,
+ GL_DYNAMIC_DRAW_ARB);
+ }
+
+ /* draw quad */
+ _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ _mesa_meta_end(ctx);
+}
+
+
+/**
+ * Meta implementation of ctx->Driver.CopyPixels() in terms
+ * of texture mapping and polygon rendering.
+ */
+void
+_mesa_meta_CopyPixels(struct gl_context *ctx, GLint srcX, GLint srcY,
+ GLsizei width, GLsizei height,
+ GLint dstX, GLint dstY, GLenum type)
+{
+ struct copypix_state *copypix = &ctx->Meta->CopyPix;
+ struct temp_texture *tex = get_temp_texture(ctx);
+ struct vertex {
+ GLfloat x, y, z, s, t;
+ };
+ struct vertex verts[4];
+ GLboolean newTex;
+ GLenum intFormat = GL_RGBA;
+
+ if (type != GL_COLOR ||
+ ctx->_ImageTransferState ||
+ ctx->Fog.Enabled ||
+ width > tex->MaxSize ||
+ height > tex->MaxSize) {
+ /* XXX avoid this fallback */
+ _swrast_CopyPixels(ctx, srcX, srcY, width, height, dstX, dstY, type);
+ return;
+ }
+
+ /* Most GL state applies to glCopyPixels, but a there's a few things
+ * we need to override:
+ */
+ _mesa_meta_begin(ctx, (META_RASTERIZATION |
+ META_SHADER |
+ META_TEXTURE |
+ META_TRANSFORM |
+ META_VERTEX |
+ META_VIEWPORT));
+
+ if (copypix->ArrayObj == 0) {
+ /* one-time setup */
+
+ /* create vertex array object */
+ _mesa_GenVertexArrays(1, &copypix->ArrayObj);
+ _mesa_BindVertexArray(copypix->ArrayObj);
+
+ /* create vertex array buffer */
+ _mesa_GenBuffersARB(1, &copypix->VBO);
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, copypix->VBO);
+ _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts),
+ NULL, GL_DYNAMIC_DRAW_ARB);
+
+ /* setup vertex arrays */
+ _mesa_VertexPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(x));
+ _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(s));
+ _mesa_EnableClientState(GL_VERTEX_ARRAY);
+ _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY);
+ }
+ else {
+ _mesa_BindVertexArray(copypix->ArrayObj);
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, copypix->VBO);
+ }
+
+ newTex = alloc_texture(tex, width, height, intFormat);
+
+ /* vertex positions, texcoords (after texture allocation!) */
+ {
+ const GLfloat dstX0 = (GLfloat) dstX;
+ const GLfloat dstY0 = (GLfloat) dstY;
+ const GLfloat dstX1 = dstX + width * ctx->Pixel.ZoomX;
+ const GLfloat dstY1 = dstY + height * ctx->Pixel.ZoomY;
+ const GLfloat z = invert_z(ctx->Current.RasterPos[2]);
+
+ verts[0].x = dstX0;
+ verts[0].y = dstY0;
+ verts[0].z = z;
+ verts[0].s = 0.0F;
+ verts[0].t = 0.0F;
+ verts[1].x = dstX1;
+ verts[1].y = dstY0;
+ verts[1].z = z;
+ verts[1].s = tex->Sright;
+ verts[1].t = 0.0F;
+ verts[2].x = dstX1;
+ verts[2].y = dstY1;
+ verts[2].z = z;
+ verts[2].s = tex->Sright;
+ verts[2].t = tex->Ttop;
+ verts[3].x = dstX0;
+ verts[3].y = dstY1;
+ verts[3].z = z;
+ verts[3].s = 0.0F;
+ verts[3].t = tex->Ttop;
+
+ /* upload new vertex data */
+ _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts);
+ }
+
+ /* Alloc/setup texture */
+ setup_copypix_texture(tex, newTex, srcX, srcY, width, height,
+ GL_RGBA, GL_NEAREST);
+
+ _mesa_set_enable(ctx, tex->Target, GL_TRUE);
+
+ /* draw textured quad */
+ _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ _mesa_set_enable(ctx, tex->Target, GL_FALSE);
+
+ _mesa_meta_end(ctx);
+}
+
+
+
+/**
+ * When the glDrawPixels() image size is greater than the max rectangle
+ * texture size we use this function to break the glDrawPixels() image
+ * into tiles which fit into the max texture size.
+ */
+static void
+tiled_draw_pixels(struct gl_context *ctx,
+ GLint tileSize,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *pixels)
+{
+ struct gl_pixelstore_attrib tileUnpack = *unpack;
+ GLint i, j;
+
+ if (tileUnpack.RowLength == 0)
+ tileUnpack.RowLength = width;
+
+ for (i = 0; i < width; i += tileSize) {
+ const GLint tileWidth = MIN2(tileSize, width - i);
+ const GLint tileX = (GLint) (x + i * ctx->Pixel.ZoomX);
+
+ tileUnpack.SkipPixels = unpack->SkipPixels + i;
+
+ for (j = 0; j < height; j += tileSize) {
+ const GLint tileHeight = MIN2(tileSize, height - j);
+ const GLint tileY = (GLint) (y + j * ctx->Pixel.ZoomY);
+
+ tileUnpack.SkipRows = unpack->SkipRows + j;
+
+ _mesa_meta_DrawPixels(ctx, tileX, tileY, tileWidth, tileHeight,
+ format, type, &tileUnpack, pixels);
+ }
+ }
+}
+
+
+/**
+ * One-time init for drawing stencil pixels.
+ */
+static void
+init_draw_stencil_pixels(struct gl_context *ctx)
+{
+ /* This program is run eight times, once for each stencil bit.
+ * The stencil values to draw are found in an 8-bit alpha texture.
+ * We read the texture/stencil value and test if bit 'b' is set.
+ * If the bit is not set, use KIL to kill the fragment.
+ * Finally, we use the stencil test to update the stencil buffer.
+ *
+ * The basic algorithm for checking if a bit is set is:
+ * if (is_odd(value / (1 << bit)))
+ * result is one (or non-zero).
+ * else
+ * result is zero.
+ * The program parameter contains three values:
+ * parm.x = 255 / (1 << bit)
+ * parm.y = 0.5
+ * parm.z = 0.0
+ */
+ static const char *program =
+ "!!ARBfp1.0\n"
+ "PARAM parm = program.local[0]; \n"
+ "TEMP t; \n"
+ "TEX t, fragment.texcoord[0], texture[0], %s; \n" /* NOTE %s here! */
+ "# t = t * 255 / bit \n"
+ "MUL t.x, t.a, parm.x; \n"
+ "# t = (int) t \n"
+ "FRC t.y, t.x; \n"
+ "SUB t.x, t.x, t.y; \n"
+ "# t = t * 0.5 \n"
+ "MUL t.x, t.x, parm.y; \n"
+ "# t = fract(t.x) \n"
+ "FRC t.x, t.x; # if t.x != 0, then the bit is set \n"
+ "# t.x = (t.x == 0 ? 1 : 0) \n"
+ "SGE t.x, -t.x, parm.z; \n"
+ "KIL -t.x; \n"
+ "# for debug only \n"
+ "#MOV result.color, t.x; \n"
+ "END \n";
+ char program2[1000];
+ struct drawpix_state *drawpix = &ctx->Meta->DrawPix;
+ struct temp_texture *tex = get_temp_texture(ctx);
+ const char *texTarget;
+
+ assert(drawpix->StencilFP == 0);
+
+ /* replace %s with "RECT" or "2D" */
+ assert(strlen(program) + 4 < sizeof(program2));
+ if (tex->Target == GL_TEXTURE_RECTANGLE)
+ texTarget = "RECT";
+ else
+ texTarget = "2D";
+ _mesa_snprintf(program2, sizeof(program2), program, texTarget);
+
+ _mesa_GenPrograms(1, &drawpix->StencilFP);
+ _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, drawpix->StencilFP);
+ _mesa_ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
+ strlen(program2), (const GLubyte *) program2);
+}
+
+
+/**
+ * One-time init for drawing depth pixels.
+ */
+static void
+init_draw_depth_pixels(struct gl_context *ctx)
+{
+ static const char *program =
+ "!!ARBfp1.0\n"
+ "PARAM color = program.local[0]; \n"
+ "TEX result.depth, fragment.texcoord[0], texture[0], %s; \n"
+ "MOV result.color, color; \n"
+ "END \n";
+ char program2[200];
+ struct drawpix_state *drawpix = &ctx->Meta->DrawPix;
+ struct temp_texture *tex = get_temp_texture(ctx);
+ const char *texTarget;
+
+ assert(drawpix->DepthFP == 0);
+
+ /* replace %s with "RECT" or "2D" */
+ assert(strlen(program) + 4 < sizeof(program2));
+ if (tex->Target == GL_TEXTURE_RECTANGLE)
+ texTarget = "RECT";
+ else
+ texTarget = "2D";
+ _mesa_snprintf(program2, sizeof(program2), program, texTarget);
+
+ _mesa_GenPrograms(1, &drawpix->DepthFP);
+ _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, drawpix->DepthFP);
+ _mesa_ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
+ strlen(program2), (const GLubyte *) program2);
+}
+
+
+/**
+ * Meta implementation of ctx->Driver.DrawPixels() in terms
+ * of texture mapping and polygon rendering.
+ */
+void
+_mesa_meta_DrawPixels(struct gl_context *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *pixels)
+{
+ struct drawpix_state *drawpix = &ctx->Meta->DrawPix;
+ struct temp_texture *tex = get_temp_texture(ctx);
+ const struct gl_pixelstore_attrib unpackSave = ctx->Unpack;
+ const GLuint origStencilMask = ctx->Stencil.WriteMask[0];
+ struct vertex {
+ GLfloat x, y, z, s, t;
+ };
+ struct vertex verts[4];
+ GLenum texIntFormat;
+ GLboolean fallback, newTex;
+ GLbitfield metaExtraSave = 0x0;
+ GLuint vbo;
+
+ /*
+ * Determine if we can do the glDrawPixels with texture mapping.
+ */
+ fallback = GL_FALSE;
+ if (ctx->_ImageTransferState ||
+ ctx->Fog.Enabled) {
+ fallback = GL_TRUE;
+ }
+
+ if (_mesa_is_color_format(format)) {
+ /* use more compact format when possible */
+ /* XXX disable special case for GL_LUMINANCE for now to work around
+ * apparent i965 driver bug (see bug #23670).
+ */
+ if (/*format == GL_LUMINANCE ||*/ format == GL_LUMINANCE_ALPHA)
+ texIntFormat = format;
+ else
+ texIntFormat = GL_RGBA;
+ }
+ else if (_mesa_is_stencil_format(format)) {
+ if (ctx->Extensions.ARB_fragment_program &&
+ ctx->Pixel.IndexShift == 0 &&
+ ctx->Pixel.IndexOffset == 0 &&
+ type == GL_UNSIGNED_BYTE) {
+ /* We'll store stencil as alpha. This only works for GLubyte
+ * image data because of how incoming values are mapped to alpha
+ * in [0,1].
+ */
+ texIntFormat = GL_ALPHA;
+ metaExtraSave = (META_COLOR_MASK |
+ META_DEPTH_TEST |
+ META_SHADER |
+ META_STENCIL_TEST);
+ }
+ else {
+ fallback = GL_TRUE;
+ }
+ }
+ else if (_mesa_is_depth_format(format)) {
+ if (ctx->Extensions.ARB_depth_texture &&
+ ctx->Extensions.ARB_fragment_program) {
+ texIntFormat = GL_DEPTH_COMPONENT;
+ metaExtraSave = (META_SHADER);
+ }
+ else {
+ fallback = GL_TRUE;
+ }
+ }
+ else {
+ fallback = GL_TRUE;
+ }
+
+ if (fallback) {
+ _swrast_DrawPixels(ctx, x, y, width, height,
+ format, type, unpack, pixels);
+ return;
+ }
+
+ /*
+ * Check image size against max texture size, draw as tiles if needed.
+ */
+ if (width > tex->MaxSize || height > tex->MaxSize) {
+ tiled_draw_pixels(ctx, tex->MaxSize, x, y, width, height,
+ format, type, unpack, pixels);
+ return;
+ }
+
+ /* Most GL state applies to glDrawPixels (like blending, stencil, etc),
+ * but a there's a few things we need to override:
+ */
+ _mesa_meta_begin(ctx, (META_RASTERIZATION |
+ META_SHADER |
+ META_TEXTURE |
+ META_TRANSFORM |
+ META_VERTEX |
+ META_VIEWPORT |
+ metaExtraSave));
+
+ newTex = alloc_texture(tex, width, height, texIntFormat);
+
+ /* vertex positions, texcoords (after texture allocation!) */
+ {
+ const GLfloat x0 = (GLfloat) x;
+ const GLfloat y0 = (GLfloat) y;
+ const GLfloat x1 = x + width * ctx->Pixel.ZoomX;
+ const GLfloat y1 = y + height * ctx->Pixel.ZoomY;
+ const GLfloat z = invert_z(ctx->Current.RasterPos[2]);
+
+ verts[0].x = x0;
+ verts[0].y = y0;
+ verts[0].z = z;
+ verts[0].s = 0.0F;
+ verts[0].t = 0.0F;
+ verts[1].x = x1;
+ verts[1].y = y0;
+ verts[1].z = z;
+ verts[1].s = tex->Sright;
+ verts[1].t = 0.0F;
+ verts[2].x = x1;
+ verts[2].y = y1;
+ verts[2].z = z;
+ verts[2].s = tex->Sright;
+ verts[2].t = tex->Ttop;
+ verts[3].x = x0;
+ verts[3].y = y1;
+ verts[3].z = z;
+ verts[3].s = 0.0F;
+ verts[3].t = tex->Ttop;
+ }
+
+ if (drawpix->ArrayObj == 0) {
+ /* one-time setup: create vertex array object */
+ _mesa_GenVertexArrays(1, &drawpix->ArrayObj);
+ }
+ _mesa_BindVertexArray(drawpix->ArrayObj);
+
+ /* create vertex array buffer */
+ _mesa_GenBuffersARB(1, &vbo);
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, vbo);
+ _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts),
+ verts, GL_DYNAMIC_DRAW_ARB);
+
+ /* setup vertex arrays */
+ _mesa_VertexPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(x));
+ _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(s));
+ _mesa_EnableClientState(GL_VERTEX_ARRAY);
+ _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ /* set given unpack params */
+ ctx->Unpack = *unpack;
+
+ _mesa_set_enable(ctx, tex->Target, GL_TRUE);
+
+ if (_mesa_is_stencil_format(format)) {
+ /* Drawing stencil */
+ GLint bit;
+
+ if (!drawpix->StencilFP)
+ init_draw_stencil_pixels(ctx);
+
+ setup_drawpix_texture(ctx, tex, newTex, texIntFormat, width, height,
+ GL_ALPHA, type, pixels);
+
+ _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+
+ _mesa_set_enable(ctx, GL_STENCIL_TEST, GL_TRUE);
+
+ /* set all stencil bits to 0 */
+ _mesa_StencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
+ _mesa_StencilFunc(GL_ALWAYS, 0, 255);
+ _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ /* set stencil bits to 1 where needed */
+ _mesa_StencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
+
+ _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, drawpix->StencilFP);
+ _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_TRUE);
+
+ for (bit = 0; bit < ctx->DrawBuffer->Visual.stencilBits; bit++) {
+ const GLuint mask = 1 << bit;
+ if (mask & origStencilMask) {
+ _mesa_StencilFunc(GL_ALWAYS, mask, mask);
+ _mesa_StencilMask(mask);
+
+ _mesa_ProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0,
+ 255.0 / mask, 0.5, 0.0, 0.0);
+
+ _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ }
+ }
+ }
+ else if (_mesa_is_depth_format(format)) {
+ /* Drawing depth */
+ if (!drawpix->DepthFP)
+ init_draw_depth_pixels(ctx);
+
+ _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, drawpix->DepthFP);
+ _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_TRUE);
+
+ /* polygon color = current raster color */
+ _mesa_ProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 0,
+ ctx->Current.RasterColor);
+
+ setup_drawpix_texture(ctx, tex, newTex, texIntFormat, width, height,
+ format, type, pixels);
+
+ _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ }
+ else {
+ /* Drawing RGBA */
+ setup_drawpix_texture(ctx, tex, newTex, texIntFormat, width, height,
+ format, type, pixels);
+ _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ }
+
+ _mesa_set_enable(ctx, tex->Target, GL_FALSE);
+
+ _mesa_DeleteBuffersARB(1, &vbo);
+
+ /* restore unpack params */
+ ctx->Unpack = unpackSave;
+
+ _mesa_meta_end(ctx);
+}
+
+static GLboolean
+alpha_test_raster_color(struct gl_context *ctx)
+{
+ GLfloat alpha = ctx->Current.RasterColor[ACOMP];
+ GLfloat ref = ctx->Color.AlphaRef;
+
+ switch (ctx->Color.AlphaFunc) {
+ case GL_NEVER:
+ return GL_FALSE;
+ case GL_LESS:
+ return alpha < ref;
+ case GL_EQUAL:
+ return alpha == ref;
+ case GL_LEQUAL:
+ return alpha <= ref;
+ case GL_GREATER:
+ return alpha > ref;
+ case GL_NOTEQUAL:
+ return alpha != ref;
+ case GL_GEQUAL:
+ return alpha >= ref;
+ case GL_ALWAYS:
+ return GL_TRUE;
+ default:
+ assert(0);
+ return GL_FALSE;
+ }
+}
+
+/**
+ * Do glBitmap with a alpha texture quad. Use the alpha test to cull
+ * the 'off' bits. A bitmap cache as in the gallium/mesa state
+ * tracker would improve performance a lot.
+ */
+void
+_mesa_meta_Bitmap(struct gl_context *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLubyte *bitmap1)
+{
+ struct bitmap_state *bitmap = &ctx->Meta->Bitmap;
+ struct temp_texture *tex = get_bitmap_temp_texture(ctx);
+ const GLenum texIntFormat = GL_ALPHA;
+ const struct gl_pixelstore_attrib unpackSave = *unpack;
+ GLubyte fg, bg;
+ struct vertex {
+ GLfloat x, y, z, s, t, r, g, b, a;
+ };
+ struct vertex verts[4];
+ GLboolean newTex;
+ GLubyte *bitmap8;
+
+ /*
+ * Check if swrast fallback is needed.
+ */
+ if (ctx->_ImageTransferState ||
+ ctx->FragmentProgram._Enabled ||
+ ctx->Fog.Enabled ||
+ ctx->Texture._EnabledUnits ||
+ width > tex->MaxSize ||
+ height > tex->MaxSize) {
+ _swrast_Bitmap(ctx, x, y, width, height, unpack, bitmap1);
+ return;
+ }
+
+ if (ctx->Color.AlphaEnabled && !alpha_test_raster_color(ctx))
+ return;
+
+ /* Most GL state applies to glBitmap (like blending, stencil, etc),
+ * but a there's a few things we need to override:
+ */
+ _mesa_meta_begin(ctx, (META_ALPHA_TEST |
+ META_PIXEL_STORE |
+ META_RASTERIZATION |
+ META_SHADER |
+ META_TEXTURE |
+ META_TRANSFORM |
+ META_VERTEX |
+ META_VIEWPORT));
+
+ if (bitmap->ArrayObj == 0) {
+ /* one-time setup */
+
+ /* create vertex array object */
+ _mesa_GenVertexArraysAPPLE(1, &bitmap->ArrayObj);
+ _mesa_BindVertexArrayAPPLE(bitmap->ArrayObj);
+
+ /* create vertex array buffer */
+ _mesa_GenBuffersARB(1, &bitmap->VBO);
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, bitmap->VBO);
+ _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts),
+ NULL, GL_DYNAMIC_DRAW_ARB);
+
+ /* setup vertex arrays */
+ _mesa_VertexPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(x));
+ _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(s));
+ _mesa_ColorPointer(4, GL_FLOAT, sizeof(struct vertex), OFFSET(r));
+ _mesa_EnableClientState(GL_VERTEX_ARRAY);
+ _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY);
+ _mesa_EnableClientState(GL_COLOR_ARRAY);
+ }
+ else {
+ _mesa_BindVertexArray(bitmap->ArrayObj);
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, bitmap->VBO);
+ }
+
+ newTex = alloc_texture(tex, width, height, texIntFormat);
+
+ /* vertex positions, texcoords, colors (after texture allocation!) */
+ {
+ const GLfloat x0 = (GLfloat) x;
+ const GLfloat y0 = (GLfloat) y;
+ const GLfloat x1 = (GLfloat) (x + width);
+ const GLfloat y1 = (GLfloat) (y + height);
+ const GLfloat z = invert_z(ctx->Current.RasterPos[2]);
+ GLuint i;
+
+ verts[0].x = x0;
+ verts[0].y = y0;
+ verts[0].z = z;
+ verts[0].s = 0.0F;
+ verts[0].t = 0.0F;
+ verts[1].x = x1;
+ verts[1].y = y0;
+ verts[1].z = z;
+ verts[1].s = tex->Sright;
+ verts[1].t = 0.0F;
+ verts[2].x = x1;
+ verts[2].y = y1;
+ verts[2].z = z;
+ verts[2].s = tex->Sright;
+ verts[2].t = tex->Ttop;
+ verts[3].x = x0;
+ verts[3].y = y1;
+ verts[3].z = z;
+ verts[3].s = 0.0F;
+ verts[3].t = tex->Ttop;
+
+ for (i = 0; i < 4; i++) {
+ verts[i].r = ctx->Current.RasterColor[0];
+ verts[i].g = ctx->Current.RasterColor[1];
+ verts[i].b = ctx->Current.RasterColor[2];
+ verts[i].a = ctx->Current.RasterColor[3];
+ }
+
+ /* upload new vertex data */
+ _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts);
+ }
+
+ /* choose different foreground/background alpha values */
+ CLAMPED_FLOAT_TO_UBYTE(fg, ctx->Current.RasterColor[ACOMP]);
+ bg = (fg > 127 ? 0 : 255);
+
+ bitmap1 = _mesa_map_pbo_source(ctx, &unpackSave, bitmap1);
+ if (!bitmap1) {
+ _mesa_meta_end(ctx);
+ return;
+ }
+
+ bitmap8 = (GLubyte *) malloc(width * height);
+ if (bitmap8) {
+ memset(bitmap8, bg, width * height);
+ _mesa_expand_bitmap(width, height, &unpackSave, bitmap1,
+ bitmap8, width, fg);
+
+ _mesa_set_enable(ctx, tex->Target, GL_TRUE);
+
+ _mesa_set_enable(ctx, GL_ALPHA_TEST, GL_TRUE);
+ _mesa_AlphaFunc(GL_NOTEQUAL, UBYTE_TO_FLOAT(bg));
+
+ setup_drawpix_texture(ctx, tex, newTex, texIntFormat, width, height,
+ GL_ALPHA, GL_UNSIGNED_BYTE, bitmap8);
+
+ _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ _mesa_set_enable(ctx, tex->Target, GL_FALSE);
+
+ free(bitmap8);
+ }
+
+ _mesa_unmap_pbo_source(ctx, &unpackSave);
+
+ _mesa_meta_end(ctx);
+}
+
+
+/**
+ * Check if the call to _mesa_meta_GenerateMipmap() will require a
+ * software fallback. The fallback path will require that the texture
+ * images are mapped.
+ * \return GL_TRUE if a fallback is needed, GL_FALSE otherwise
+ */
+GLboolean
+_mesa_meta_check_generate_mipmap_fallback(struct gl_context *ctx, GLenum target,
+ struct gl_texture_object *texObj)
+{
+ const GLuint fboSave = ctx->DrawBuffer->Name;
+ struct gen_mipmap_state *mipmap = &ctx->Meta->Mipmap;
+ struct gl_texture_image *baseImage;
+ GLuint srcLevel;
+ GLenum status;
+
+ /* check for fallbacks */
+ if (!ctx->Extensions.EXT_framebuffer_object ||
+ target == GL_TEXTURE_3D) {
+ return GL_TRUE;
+ }
+
+ srcLevel = texObj->BaseLevel;
+ baseImage = _mesa_select_tex_image(ctx, texObj, target, srcLevel);
+ if (!baseImage || _mesa_is_format_compressed(baseImage->TexFormat)) {
+ return GL_TRUE;
+ }
+
+ /*
+ * Test that we can actually render in the texture's format.
+ */
+ if (!mipmap->FBO)
+ _mesa_GenFramebuffersEXT(1, &mipmap->FBO);
+ _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, mipmap->FBO);
+
+ if (target == GL_TEXTURE_1D) {
+ _mesa_FramebufferTexture1DEXT(GL_FRAMEBUFFER_EXT,
+ GL_COLOR_ATTACHMENT0_EXT,
+ target, texObj->Name, srcLevel);
+ }
+#if 0
+ /* other work is needed to enable 3D mipmap generation */
+ else if (target == GL_TEXTURE_3D) {
+ GLint zoffset = 0;
+ _mesa_FramebufferTexture3DEXT(GL_FRAMEBUFFER_EXT,
+ GL_COLOR_ATTACHMENT0_EXT,
+ target, texObj->Name, srcLevel, zoffset);
+ }
+#endif
+ else {
+ /* 2D / cube */
+ _mesa_FramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
+ GL_COLOR_ATTACHMENT0_EXT,
+ target, texObj->Name, srcLevel);
+ }
+
+ status = _mesa_CheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
+
+ _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboSave);
+
+ if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ return GL_TRUE;
+ }
+
+ return GL_FALSE;
+}
+
+
+/**
+ * Called via ctx->Driver.GenerateMipmap()
+ * Note: texture borders and 3D texture support not yet complete.
+ */
+void
+_mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target,
+ struct gl_texture_object *texObj)
+{
+ struct gen_mipmap_state *mipmap = &ctx->Meta->Mipmap;
+ struct vertex {
+ GLfloat x, y, s, t, r;
+ };
+ struct vertex verts[4];
+ const GLuint baseLevel = texObj->BaseLevel;
+ const GLuint maxLevel = texObj->MaxLevel;
+ const GLenum minFilterSave = texObj->MinFilter;
+ const GLenum magFilterSave = texObj->MagFilter;
+ const GLint baseLevelSave = texObj->BaseLevel;
+ const GLint maxLevelSave = texObj->MaxLevel;
+ const GLboolean genMipmapSave = texObj->GenerateMipmap;
+ const GLenum wrapSSave = texObj->WrapS;
+ const GLenum wrapTSave = texObj->WrapT;
+ const GLenum wrapRSave = texObj->WrapR;
+ const GLuint fboSave = ctx->DrawBuffer->Name;
+ const GLuint original_active_unit = ctx->Texture.CurrentUnit;
+ GLenum faceTarget;
+ GLuint dstLevel;
+ GLuint border = 0;
+
+ if (_mesa_meta_check_generate_mipmap_fallback(ctx, target, texObj)) {
+ _mesa_generate_mipmap(ctx, target, texObj);
+ return;
+ }
+
+ if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X &&
+ target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) {
+ faceTarget = target;
+ target = GL_TEXTURE_CUBE_MAP;
+ }
+ else {
+ faceTarget = target;
+ }
+
+ _mesa_meta_begin(ctx, META_ALL);
+
+ if (original_active_unit != 0)
+ _mesa_BindTexture(target, texObj->Name);
+
+ if (mipmap->ArrayObj == 0) {
+ /* one-time setup */
+
+ /* create vertex array object */
+ _mesa_GenVertexArraysAPPLE(1, &mipmap->ArrayObj);
+ _mesa_BindVertexArrayAPPLE(mipmap->ArrayObj);
+
+ /* create vertex array buffer */
+ _mesa_GenBuffersARB(1, &mipmap->VBO);
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, mipmap->VBO);
+ _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts),
+ NULL, GL_DYNAMIC_DRAW_ARB);
+
+ /* setup vertex arrays */
+ _mesa_VertexPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(x));
+ _mesa_TexCoordPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(s));
+ _mesa_EnableClientState(GL_VERTEX_ARRAY);
+ _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY);
+ }
+ else {
+ _mesa_BindVertexArray(mipmap->ArrayObj);
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, mipmap->VBO);
+ }
+
+ if (!mipmap->FBO) {
+ _mesa_GenFramebuffersEXT(1, &mipmap->FBO);
+ }
+ _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, mipmap->FBO);
+
+ _mesa_TexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ _mesa_TexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ _mesa_TexParameteri(target, GL_GENERATE_MIPMAP, GL_FALSE);
+ _mesa_TexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ _mesa_TexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ _mesa_TexParameteri(target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
+
+ _mesa_set_enable(ctx, target, GL_TRUE);
+
+ /* setup texcoords once (XXX what about border?) */
+ switch (faceTarget) {
+ case GL_TEXTURE_1D:
+ case GL_TEXTURE_2D:
+ verts[0].s = 0.0F;
+ verts[0].t = 0.0F;
+ verts[0].r = 0.0F;
+ verts[1].s = 1.0F;
+ verts[1].t = 0.0F;
+ verts[1].r = 0.0F;
+ verts[2].s = 1.0F;
+ verts[2].t = 1.0F;
+ verts[2].r = 0.0F;
+ verts[3].s = 0.0F;
+ verts[3].t = 1.0F;
+ verts[3].r = 0.0F;
+ break;
+ case GL_TEXTURE_3D:
+ abort();
+ break;
+ default:
+ /* cube face */
+ {
+ static const GLfloat st[4][2] = {
+ {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f}
+ };
+ GLuint i;
+
+ /* loop over quad verts */
+ for (i = 0; i < 4; i++) {
+ /* Compute sc = +/-scale and tc = +/-scale.
+ * Not +/-1 to avoid cube face selection ambiguity near the edges,
+ * though that can still sometimes happen with this scale factor...
+ */
+ const GLfloat scale = 0.9999f;
+ const GLfloat sc = (2.0f * st[i][0] - 1.0f) * scale;
+ const GLfloat tc = (2.0f * st[i][1] - 1.0f) * scale;
+
+ switch (faceTarget) {
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+ verts[i].s = 1.0f;
+ verts[i].t = -tc;
+ verts[i].r = -sc;
+ break;
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+ verts[i].s = -1.0f;
+ verts[i].t = -tc;
+ verts[i].r = sc;
+ break;
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+ verts[i].s = sc;
+ verts[i].t = 1.0f;
+ verts[i].r = tc;
+ break;
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+ verts[i].s = sc;
+ verts[i].t = -1.0f;
+ verts[i].r = -tc;
+ break;
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+ verts[i].s = sc;
+ verts[i].t = -tc;
+ verts[i].r = 1.0f;
+ break;
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+ verts[i].s = -sc;
+ verts[i].t = -tc;
+ verts[i].r = -1.0f;
+ break;
+ default:
+ assert(0);
+ }
+ }
+ }
+ }
+
+ _mesa_set_enable(ctx, target, GL_TRUE);
+
+ /* setup vertex positions */
+ {
+ verts[0].x = 0.0F;
+ verts[0].y = 0.0F;
+ verts[1].x = 1.0F;
+ verts[1].y = 0.0F;
+ verts[2].x = 1.0F;
+ verts[2].y = 1.0F;
+ verts[3].x = 0.0F;
+ verts[3].y = 1.0F;
+
+ /* upload new vertex data */
+ _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts);
+ }
+
+ /* setup projection matrix */
+ _mesa_MatrixMode(GL_PROJECTION);
+ _mesa_LoadIdentity();
+ _mesa_Ortho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
+
+ /* texture is already locked, unlock now */
+ _mesa_unlock_texture(ctx, texObj);
+
+ for (dstLevel = baseLevel + 1; dstLevel <= maxLevel; dstLevel++) {
+ const struct gl_texture_image *srcImage;
+ const GLuint srcLevel = dstLevel - 1;
+ GLsizei srcWidth, srcHeight, srcDepth;
+ GLsizei dstWidth, dstHeight, dstDepth;
+ GLenum status;
+
+ srcImage = _mesa_select_tex_image(ctx, texObj, faceTarget, srcLevel);
+ assert(srcImage->Border == 0); /* XXX we can fix this */
+
+ /* src size w/out border */
+ srcWidth = srcImage->Width - 2 * border;
+ srcHeight = srcImage->Height - 2 * border;
+ srcDepth = srcImage->Depth - 2 * border;
+
+ /* new dst size w/ border */
+ dstWidth = MAX2(1, srcWidth / 2) + 2 * border;
+ dstHeight = MAX2(1, srcHeight / 2) + 2 * border;
+ dstDepth = MAX2(1, srcDepth / 2) + 2 * border;
+
+ if (dstWidth == srcImage->Width &&
+ dstHeight == srcImage->Height &&
+ dstDepth == srcImage->Depth) {
+ /* all done */
+ break;
+ }
+
+ /* Set MaxLevel large enough to hold the new level when we allocate it */
+ _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, dstLevel);
+
+ /* Create empty dest image */
+ if (target == GL_TEXTURE_1D) {
+ _mesa_TexImage1D(target, dstLevel, srcImage->InternalFormat,
+ dstWidth, border,
+ GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ }
+ else if (target == GL_TEXTURE_3D) {
+ _mesa_TexImage3D(target, dstLevel, srcImage->InternalFormat,
+ dstWidth, dstHeight, dstDepth, border,
+ GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ }
+ else {
+ /* 2D or cube */
+ _mesa_TexImage2D(faceTarget, dstLevel, srcImage->InternalFormat,
+ dstWidth, dstHeight, border,
+ GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+
+ if (target == GL_TEXTURE_CUBE_MAP) {
+ /* If texturing from a cube, we need to make sure all src faces
+ * have been defined (even if we're not sampling from them.)
+ * Otherwise the texture object will be 'incomplete' and
+ * texturing from it will not be allowed.
+ */
+ GLuint face;
+ for (face = 0; face < 6; face++) {
+ if (!texObj->Image[face][srcLevel] ||
+ texObj->Image[face][srcLevel]->Width != srcWidth) {
+ _mesa_TexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face,
+ srcLevel, srcImage->InternalFormat,
+ srcWidth, srcHeight, border,
+ GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ }
+ }
+ }
+ }
+
+ /* limit sampling to src level */
+ _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, srcLevel);
+ _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, srcLevel);
+
+ /* Set to draw into the current dstLevel */
+ if (target == GL_TEXTURE_1D) {
+ _mesa_FramebufferTexture1DEXT(GL_FRAMEBUFFER_EXT,
+ GL_COLOR_ATTACHMENT0_EXT,
+ target,
+ texObj->Name,
+ dstLevel);
+ }
+ else if (target == GL_TEXTURE_3D) {
+ GLint zoffset = 0; /* XXX unfinished */
+ _mesa_FramebufferTexture3DEXT(GL_FRAMEBUFFER_EXT,
+ GL_COLOR_ATTACHMENT0_EXT,
+ target,
+ texObj->Name,
+ dstLevel, zoffset);
+ }
+ else {
+ /* 2D / cube */
+ _mesa_FramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
+ GL_COLOR_ATTACHMENT0_EXT,
+ faceTarget,
+ texObj->Name,
+ dstLevel);
+ }
+
+ _mesa_DrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
+
+ /* sanity check */
+ status = _mesa_CheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
+ if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ abort();
+ break;
+ }
+
+ assert(dstWidth == ctx->DrawBuffer->Width);
+ assert(dstHeight == ctx->DrawBuffer->Height);
+
+ /* setup viewport */
+ _mesa_set_viewport(ctx, 0, 0, dstWidth, dstHeight);
+
+ _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ }
+
+ _mesa_lock_texture(ctx, texObj); /* relock */
+
+ _mesa_meta_end(ctx);
+
+ _mesa_TexParameteri(target, GL_TEXTURE_MIN_FILTER, minFilterSave);
+ _mesa_TexParameteri(target, GL_TEXTURE_MAG_FILTER, magFilterSave);
+ _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, baseLevelSave);
+ _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, maxLevelSave);
+ _mesa_TexParameteri(target, GL_GENERATE_MIPMAP, genMipmapSave);
+ _mesa_TexParameteri(target, GL_TEXTURE_WRAP_S, wrapSSave);
+ _mesa_TexParameteri(target, GL_TEXTURE_WRAP_T, wrapTSave);
+ _mesa_TexParameteri(target, GL_TEXTURE_WRAP_R, wrapRSave);
+
+ _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboSave);
+}
+
+
+/**
+ * Determine the GL data type to use for the temporary image read with
+ * ReadPixels() and passed to Tex[Sub]Image().
+ */
+static GLenum
+get_temp_image_type(struct gl_context *ctx, GLenum baseFormat)
+{
+ switch (baseFormat) {
+ case GL_RGBA:
+ case GL_RGB:
+ case GL_ALPHA:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE_ALPHA:
+ case GL_INTENSITY:
+ if (ctx->DrawBuffer->Visual.redBits <= 8)
+ return GL_UNSIGNED_BYTE;
+ else if (ctx->DrawBuffer->Visual.redBits <= 8)
+ return GL_UNSIGNED_SHORT;
+ else
+ return GL_FLOAT;
+ case GL_DEPTH_COMPONENT:
+ return GL_UNSIGNED_INT;
+ case GL_DEPTH_STENCIL:
+ return GL_UNSIGNED_INT_24_8;
+ default:
+ _mesa_problem(ctx, "Unexpected format in get_temp_image_type()");
+ return 0;
+ }
+}
+
+
+/**
+ * Helper for _mesa_meta_CopyTexImage1/2D() functions.
+ * Have to be careful with locking and meta state for pixel transfer.
+ */
+static void
+copy_tex_image(struct gl_context *ctx, GLuint dims, GLenum target, GLint level,
+ GLenum internalFormat, GLint x, GLint y,
+ GLsizei width, GLsizei height, GLint border)
+{
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ GLenum format, type;
+ GLint bpp;
+ void *buf;
+
+ texObj = _mesa_get_current_tex_object(ctx, target);
+ texImage = _mesa_get_tex_image(ctx, texObj, target, level);
+
+ /* Choose format/type for temporary image buffer */
+ format = _mesa_base_tex_format(ctx, internalFormat);
+ type = get_temp_image_type(ctx, format);
+ bpp = _mesa_bytes_per_pixel(format, type);
+ if (bpp <= 0) {
+ _mesa_problem(ctx, "Bad bpp in meta copy_tex_image()");
+ return;
+ }
+
+ /*
+ * Alloc image buffer (XXX could use a PBO)
+ */
+ buf = malloc(width * height * bpp);
+ if (!buf) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage%uD", dims);
+ return;
+ }
+
+ _mesa_unlock_texture(ctx, texObj); /* need to unlock first */
+
+ /*
+ * Read image from framebuffer (disable pixel transfer ops)
+ */
+ _mesa_meta_begin(ctx, META_PIXEL_STORE | META_PIXEL_TRANSFER);
+ ctx->Driver.ReadPixels(ctx, x, y, width, height,
+ format, type, &ctx->Pack, buf);
+ _mesa_meta_end(ctx);
+
+ if (texImage->Data) {
+ ctx->Driver.FreeTexImageData(ctx, texImage);
+ }
+
+ /* The texture's format was already chosen in _mesa_CopyTexImage() */
+ ASSERT(texImage->TexFormat != MESA_FORMAT_NONE);
+
+ /*
+ * Store texture data (with pixel transfer ops)
+ */
+ _mesa_meta_begin(ctx, META_PIXEL_STORE);
+
+ _mesa_update_state(ctx); /* to update pixel transfer state */
+
+ if (target == GL_TEXTURE_1D) {
+ ctx->Driver.TexImage1D(ctx, target, level, internalFormat,
+ width, border, format, type,
+ buf, &ctx->Unpack, texObj, texImage);
+ }
+ else {
+ ctx->Driver.TexImage2D(ctx, target, level, internalFormat,
+ width, height, border, format, type,
+ buf, &ctx->Unpack, texObj, texImage);
+ }
+ _mesa_meta_end(ctx);
+
+ _mesa_lock_texture(ctx, texObj); /* re-lock */
+
+ free(buf);
+}
+
+
+void
+_mesa_meta_CopyTexImage1D(struct gl_context *ctx, GLenum target, GLint level,
+ GLenum internalFormat, GLint x, GLint y,
+ GLsizei width, GLint border)
+{
+ copy_tex_image(ctx, 1, target, level, internalFormat, x, y,
+ width, 1, border);
+}
+
+
+void
+_mesa_meta_CopyTexImage2D(struct gl_context *ctx, GLenum target, GLint level,
+ GLenum internalFormat, GLint x, GLint y,
+ GLsizei width, GLsizei height, GLint border)
+{
+ copy_tex_image(ctx, 2, target, level, internalFormat, x, y,
+ width, height, border);
+}
+
+
+
+/**
+ * Helper for _mesa_meta_CopyTexSubImage1/2/3D() functions.
+ * Have to be careful with locking and meta state for pixel transfer.
+ */
+static void
+copy_tex_sub_image(struct gl_context *ctx,
+ GLuint dims, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height)
+{
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ GLenum format, type;
+ GLint bpp;
+ void *buf;
+
+ texObj = _mesa_get_current_tex_object(ctx, target);
+ texImage = _mesa_select_tex_image(ctx, texObj, target, level);
+
+ /* Choose format/type for temporary image buffer */
+ format = _mesa_get_format_base_format(texImage->TexFormat);
+ type = get_temp_image_type(ctx, format);
+ bpp = _mesa_bytes_per_pixel(format, type);
+ if (bpp <= 0) {
+ _mesa_problem(ctx, "Bad bpp in meta copy_tex_sub_image()");
+ return;
+ }
+
+ /*
+ * Alloc image buffer (XXX could use a PBO)
+ */
+ buf = malloc(width * height * bpp);
+ if (!buf) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage%uD", dims);
+ return;
+ }
+
+ _mesa_unlock_texture(ctx, texObj); /* need to unlock first */
+
+ /*
+ * Read image from framebuffer (disable pixel transfer ops)
+ */
+ _mesa_meta_begin(ctx, META_PIXEL_STORE | META_PIXEL_TRANSFER);
+ ctx->Driver.ReadPixels(ctx, x, y, width, height,
+ format, type, &ctx->Pack, buf);
+ _mesa_meta_end(ctx);
+
+ _mesa_update_state(ctx); /* to update pixel transfer state */
+
+ /*
+ * Store texture data (with pixel transfer ops)
+ */
+ _mesa_meta_begin(ctx, META_PIXEL_STORE);
+ if (target == GL_TEXTURE_1D) {
+ ctx->Driver.TexSubImage1D(ctx, target, level, xoffset,
+ width, format, type, buf,
+ &ctx->Unpack, texObj, texImage);
+ }
+ else if (target == GL_TEXTURE_3D) {
+ ctx->Driver.TexSubImage3D(ctx, target, level, xoffset, yoffset, zoffset,
+ width, height, 1, format, type, buf,
+ &ctx->Unpack, texObj, texImage);
+ }
+ else {
+ ctx->Driver.TexSubImage2D(ctx, target, level, xoffset, yoffset,
+ width, height, format, type, buf,
+ &ctx->Unpack, texObj, texImage);
+ }
+ _mesa_meta_end(ctx);
+
+ _mesa_lock_texture(ctx, texObj); /* re-lock */
+
+ free(buf);
+}
+
+
+void
+_mesa_meta_CopyTexSubImage1D(struct gl_context *ctx, GLenum target, GLint level,
+ GLint xoffset,
+ GLint x, GLint y, GLsizei width)
+{
+ copy_tex_sub_image(ctx, 1, target, level, xoffset, 0, 0,
+ x, y, width, 1);
+}
+
+
+void
+_mesa_meta_CopyTexSubImage2D(struct gl_context *ctx, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height)
+{
+ copy_tex_sub_image(ctx, 2, target, level, xoffset, yoffset, 0,
+ x, y, width, height);
+}
+
+
+void
+_mesa_meta_CopyTexSubImage3D(struct gl_context *ctx, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height)
+{
+ copy_tex_sub_image(ctx, 3, target, level, xoffset, yoffset, zoffset,
+ x, y, width, height);
+}
+
+
+void
+_mesa_meta_CopyColorTable(struct gl_context *ctx,
+ GLenum target, GLenum internalformat,
+ GLint x, GLint y, GLsizei width)
+{
+ GLfloat *buf;
+
+ buf = (GLfloat *) malloc(width * 4 * sizeof(GLfloat));
+ if (!buf) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyColorTable");
+ return;
+ }
+
+ /*
+ * Read image from framebuffer (disable pixel transfer ops)
+ */
+ _mesa_meta_begin(ctx, META_PIXEL_STORE | META_PIXEL_TRANSFER);
+ ctx->Driver.ReadPixels(ctx, x, y, width, 1,
+ GL_RGBA, GL_FLOAT, &ctx->Pack, buf);
+
+ _mesa_ColorTable(target, internalformat, width, GL_RGBA, GL_FLOAT, buf);
+
+ _mesa_meta_end(ctx);
+
+ free(buf);
+}
+
+
+void
+_mesa_meta_CopyColorSubTable(struct gl_context *ctx,GLenum target, GLsizei start,
+ GLint x, GLint y, GLsizei width)
+{
+ GLfloat *buf;
+
+ buf = (GLfloat *) malloc(width * 4 * sizeof(GLfloat));
+ if (!buf) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyColorSubTable");
+ return;
+ }
+
+ /*
+ * Read image from framebuffer (disable pixel transfer ops)
+ */
+ _mesa_meta_begin(ctx, META_PIXEL_STORE | META_PIXEL_TRANSFER);
+ ctx->Driver.ReadPixels(ctx, x, y, width, 1,
+ GL_RGBA, GL_FLOAT, &ctx->Pack, buf);
+
+ _mesa_ColorSubTable(target, start, width, GL_RGBA, GL_FLOAT, buf);
+
+ _mesa_meta_end(ctx);
+
+ free(buf);
+}
diff --git a/mesalib/src/mesa/drivers/common/meta.h b/mesalib/src/mesa/drivers/common/meta.h
index 6225b9418..a350a92aa 100644
--- a/mesalib/src/mesa/drivers/common/meta.h
+++ b/mesalib/src/mesa/drivers/common/meta.h
@@ -1,118 +1,118 @@
-/*
- * Mesa 3-D graphics library
- * Version: 7.6
- *
- * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#ifndef META_H
-#define META_H
-
-
-extern void
-_mesa_meta_init(GLcontext *ctx);
-
-extern void
-_mesa_meta_free(GLcontext *ctx);
-
-extern void
-_mesa_meta_BlitFramebuffer(GLcontext *ctx,
- GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
- GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
- GLbitfield mask, GLenum filter);
-
-extern void
-_mesa_meta_Clear(GLcontext *ctx, GLbitfield buffers);
-
-extern void
-_mesa_meta_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy,
- GLsizei width, GLsizei height,
- GLint dstx, GLint dsty, GLenum type);
-
-extern void
-_mesa_meta_DrawPixels(GLcontext *ctx,
- GLint x, GLint y, GLsizei width, GLsizei height,
- GLenum format, GLenum type,
- const struct gl_pixelstore_attrib *unpack,
- const GLvoid *pixels);
-
-extern void
-_mesa_meta_Bitmap(GLcontext *ctx,
- GLint x, GLint y, GLsizei width, GLsizei height,
- const struct gl_pixelstore_attrib *unpack,
- const GLubyte *bitmap);
-
-extern GLboolean
-_mesa_meta_check_generate_mipmap_fallback(GLcontext *ctx, GLenum target,
- struct gl_texture_object *texObj);
-
-extern void
-_mesa_meta_GenerateMipmap(GLcontext *ctx, GLenum target,
- struct gl_texture_object *texObj);
-
-extern void
-_mesa_meta_CopyTexImage1D(GLcontext *ctx, GLenum target, GLint level,
- GLenum internalFormat, GLint x, GLint y,
- GLsizei width, GLint border);
-
-extern void
-_mesa_meta_CopyTexImage2D(GLcontext *ctx, GLenum target, GLint level,
- GLenum internalFormat, GLint x, GLint y,
- GLsizei width, GLsizei height, GLint border);
-
-extern void
-_mesa_meta_CopyTexSubImage1D(GLcontext *ctx, GLenum target, GLint level,
- GLint xoffset,
- GLint x, GLint y, GLsizei width);
-
-extern void
-_mesa_meta_CopyTexSubImage2D(GLcontext *ctx, GLenum target, GLint level,
- GLint xoffset, GLint yoffset,
- GLint x, GLint y,
- GLsizei width, GLsizei height);
-
-extern void
-_mesa_meta_CopyTexSubImage3D(GLcontext *ctx, GLenum target, GLint level,
- GLint xoffset, GLint yoffset, GLint zoffset,
- GLint x, GLint y,
- GLsizei width, GLsizei height);
-
-extern void
-_mesa_meta_CopyColorTable(GLcontext *ctx,
- GLenum target, GLenum internalformat,
- GLint x, GLint y, GLsizei width);
-
-extern void
-_mesa_meta_CopyColorSubTable(GLcontext *ctx,GLenum target, GLsizei start,
- GLint x, GLint y, GLsizei width);
-
-extern void
-_mesa_meta_CopyConvolutionFilter1D(GLcontext *ctx, GLenum target,
- GLenum internalFormat,
- GLint x, GLint y, GLsizei width);
-
-extern void
-_mesa_meta_CopyConvolutionFilter2D(GLcontext *ctx, GLenum target,
- GLenum internalFormat, GLint x, GLint y,
- GLsizei width, GLsizei height);
-
-
-#endif /* META_H */
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.6
+ *
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef META_H
+#define META_H
+
+
+extern void
+_mesa_meta_init(struct gl_context *ctx);
+
+extern void
+_mesa_meta_free(struct gl_context *ctx);
+
+extern void
+_mesa_meta_BlitFramebuffer(struct gl_context *ctx,
+ GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter);
+
+extern void
+_mesa_meta_Clear(struct gl_context *ctx, GLbitfield buffers);
+
+extern void
+_mesa_meta_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
+ GLsizei width, GLsizei height,
+ GLint dstx, GLint dsty, GLenum type);
+
+extern void
+_mesa_meta_DrawPixels(struct gl_context *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *pixels);
+
+extern void
+_mesa_meta_Bitmap(struct gl_context *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLubyte *bitmap);
+
+extern GLboolean
+_mesa_meta_check_generate_mipmap_fallback(struct gl_context *ctx, GLenum target,
+ struct gl_texture_object *texObj);
+
+extern void
+_mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target,
+ struct gl_texture_object *texObj);
+
+extern void
+_mesa_meta_CopyTexImage1D(struct gl_context *ctx, GLenum target, GLint level,
+ GLenum internalFormat, GLint x, GLint y,
+ GLsizei width, GLint border);
+
+extern void
+_mesa_meta_CopyTexImage2D(struct gl_context *ctx, GLenum target, GLint level,
+ GLenum internalFormat, GLint x, GLint y,
+ GLsizei width, GLsizei height, GLint border);
+
+extern void
+_mesa_meta_CopyTexSubImage1D(struct gl_context *ctx, GLenum target, GLint level,
+ GLint xoffset,
+ GLint x, GLint y, GLsizei width);
+
+extern void
+_mesa_meta_CopyTexSubImage2D(struct gl_context *ctx, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height);
+
+extern void
+_mesa_meta_CopyTexSubImage3D(struct gl_context *ctx, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height);
+
+extern void
+_mesa_meta_CopyColorTable(struct gl_context *ctx,
+ GLenum target, GLenum internalformat,
+ GLint x, GLint y, GLsizei width);
+
+extern void
+_mesa_meta_CopyColorSubTable(struct gl_context *ctx,GLenum target, GLsizei start,
+ GLint x, GLint y, GLsizei width);
+
+extern void
+_mesa_meta_CopyConvolutionFilter1D(struct gl_context *ctx, GLenum target,
+ GLenum internalFormat,
+ GLint x, GLint y, GLsizei width);
+
+extern void
+_mesa_meta_CopyConvolutionFilter2D(struct gl_context *ctx, GLenum target,
+ GLenum internalFormat, GLint x, GLint y,
+ GLsizei width, GLsizei height);
+
+
+#endif /* META_H */
diff --git a/mesalib/src/mesa/drivers/dri/Makefile.template b/mesalib/src/mesa/drivers/dri/Makefile.template
index a00018caf..6be554af7 100644
--- a/mesalib/src/mesa/drivers/dri/Makefile.template
+++ b/mesalib/src/mesa/drivers/dri/Makefile.template
@@ -1,113 +1,114 @@
-# -*-makefile-*-
-
-MESA_MODULES = $(TOP)/src/mesa/libmesa.a
-
-COMMON_GALLIUM_SOURCES = \
- ../common/utils.c \
- ../common/vblank.c \
- ../common/dri_util.c \
- ../common/xmlconfig.c
-
-COMMON_SOURCES = $(COMMON_GALLIUM_SOURCES) \
- ../../common/driverfuncs.c \
- ../common/texmem.c \
- ../common/drirenderbuffer.c \
- ../common/dri_metaops.c
-
-INCLUDES = $(SHARED_INCLUDES) $(EXPAT_INCLUDES)
-
-OBJECTS = $(C_SOURCES:.c=.o) \
- $(CXX_SOURCES:.cpp=.o) \
- $(ASM_SOURCES:.S=.o)
-
-
-### Include directories
-SHARED_INCLUDES = \
- -I. \
- -I$(TOP)/src/mesa/drivers/dri/common \
- -Iserver \
- -I$(TOP)/include \
- -I$(TOP)/src/mapi \
- -I$(TOP)/src/mesa \
- -I$(TOP)/src/egl/main \
- -I$(TOP)/src/egl/drivers/dri \
- $(LIBDRM_CFLAGS)
-
-CFLAGS += $(API_DEFINES)
-CXXFLAGS += $(API_DEFINES)
-
-##### RULES #####
-
-.c.o:
- $(CC) -c $(INCLUDES) $(CFLAGS) $(DRIVER_DEFINES) $< -o $@
-
-.cpp.o:
- $(CC) -c $(INCLUDES) $(CXXFLAGS) $(DRIVER_DEFINES) $< -o $@
-
-.S.o:
- $(CC) -c $(INCLUDES) $(CFLAGS) $(DRIVER_DEFINES) $< -o $@
-
-
-##### TARGETS #####
-
-default: subdirs lib
-
-
-.PHONY: lib
-lib: symlinks subdirs depend
- @$(MAKE) $(LIBNAME) $(TOP)/$(LIB_DIR)/$(LIBNAME)
-
-$(LIBNAME): $(OBJECTS) $(MESA_MODULES) $(EXTRA_MODULES) Makefile \
- $(TOP)/src/mesa/drivers/dri/Makefile.template $(TOP)/src/mesa/drivers/dri/common/dri_test.o
- $(MKLIB) -o $@.tmp -noprefix -linker '$(CXX)' -ldflags '$(LDFLAGS)' \
- $(OBJECTS) $(MESA_MODULES) $(EXTRA_MODULES) $(DRI_LIB_DEPS)
- $(CXX) $(CFLAGS) -o $@.test $(TOP)/src/mesa/drivers/dri/common/dri_test.o $@.tmp $(DRI_LIB_DEPS)
- @rm -f $@.test
- mv -f $@.tmp $@
-
-
-$(TOP)/$(LIB_DIR)/$(LIBNAME): $(LIBNAME)
- $(INSTALL) $(LIBNAME) $(TOP)/$(LIB_DIR)
-
-
-# If the Makefile defined SUBDIRS, run make in each
-.PHONY: subdirs
-subdirs:
- @if test -n "$(SUBDIRS)" ; then \
- for dir in $(SUBDIRS) ; do \
- if [ -d $$dir ] ; then \
- (cd $$dir && $(MAKE)) || exit 1; \
- fi \
- done \
- fi
-
-
-.PHONY: symlinks
-symlinks:
-
-
-depend: $(C_SOURCES) $(ASM_SOURCES) $(SYMLINKS)
- @ echo "running $(MKDEP)"
- @ rm -f depend
- @ touch depend
- @ $(MKDEP) $(MKDEP_OPTIONS) $(DRIVER_DEFINES) $(INCLUDES) $(C_SOURCES) \
- $(ASM_SOURCES) > /dev/null 2>/dev/null
-
-
-# Emacs tags
-tags:
- etags `find . -name \*.[ch]` `find ../include`
-
-
-# Remove .o and backup files
-clean:
- -rm -f *.o */*.o *~ *.so *~ server/*.o $(SYMLINKS)
- -rm -f depend depend.bak
-
-
-install: $(LIBNAME)
- $(INSTALL) -d $(DESTDIR)$(DRI_DRIVER_INSTALL_DIR)
- $(MINSTALL) -m 755 $(LIBNAME) $(DESTDIR)$(DRI_DRIVER_INSTALL_DIR)
-
-
--include depend
+# -*-makefile-*-
+
+MESA_MODULES = $(TOP)/src/mesa/libmesa.a
+
+COMMON_GALLIUM_SOURCES = \
+ ../common/utils.c \
+ ../common/vblank.c \
+ ../common/dri_util.c \
+ ../common/xmlconfig.c
+
+COMMON_SOURCES = $(COMMON_GALLIUM_SOURCES) \
+ ../../common/driverfuncs.c \
+ ../common/texmem.c \
+ ../common/drirenderbuffer.c \
+ ../common/dri_metaops.c
+
+INCLUDES = $(SHARED_INCLUDES) $(EXPAT_INCLUDES)
+
+OBJECTS = $(C_SOURCES:.c=.o) \
+ $(CXX_SOURCES:.cpp=.o) \
+ $(ASM_SOURCES:.S=.o)
+
+
+### Include directories
+SHARED_INCLUDES = \
+ -I. \
+ -I$(TOP)/src/mesa/drivers/dri/common \
+ -Iserver \
+ -I$(TOP)/include \
+ -I$(TOP)/src/mapi \
+ -I$(TOP)/src/mesa \
+ -I$(TOP)/src/egl/main \
+ -I$(TOP)/src/egl/drivers/dri \
+ $(LIBDRM_CFLAGS)
+
+CFLAGS += $(API_DEFINES)
+CXXFLAGS += $(API_DEFINES)
+
+##### RULES #####
+
+.c.o:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $(DRIVER_DEFINES) $< -o $@
+
+.cpp.o:
+ $(CC) -c $(INCLUDES) $(CXXFLAGS) $(DRIVER_DEFINES) $< -o $@
+
+.S.o:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $(DRIVER_DEFINES) $< -o $@
+
+
+##### TARGETS #####
+
+default: subdirs lib
+
+
+.PHONY: lib
+lib: symlinks subdirs depend
+ @$(MAKE) $(LIBNAME) $(TOP)/$(LIB_DIR)/$(LIBNAME)
+
+$(LIBNAME): $(OBJECTS) $(MESA_MODULES) $(EXTRA_MODULES) Makefile \
+ $(TOP)/src/mesa/drivers/dri/Makefile.template $(TOP)/src/mesa/drivers/dri/common/dri_test.o
+ $(MKLIB) -o $@.tmp -noprefix -linker '$(CXX)' -ldflags '$(LDFLAGS)' \
+ $(OBJECTS) $(MESA_MODULES) $(EXTRA_MODULES) $(DRI_LIB_DEPS)
+ $(CXX) $(CFLAGS) -o $@.test $(TOP)/src/mesa/drivers/dri/common/dri_test.o $@.tmp $(DRI_LIB_DEPS)
+ @rm -f $@.test
+ mv -f $@.tmp $@
+
+
+$(TOP)/$(LIB_DIR)/$(LIBNAME): $(LIBNAME)
+ $(INSTALL) $(LIBNAME) $(TOP)/$(LIB_DIR)
+
+
+# If the Makefile defined SUBDIRS, run make in each
+.PHONY: subdirs
+subdirs:
+ @if test -n "$(SUBDIRS)" ; then \
+ for dir in $(SUBDIRS) ; do \
+ if [ -d $$dir ] ; then \
+ (cd $$dir && $(MAKE)) || exit 1; \
+ fi \
+ done \
+ fi
+
+
+.PHONY: symlinks
+symlinks:
+
+
+depend: $(C_SOURCES) $(CXX_SOURCES) $(ASM_SOURCES) $(SYMLINKS)
+ @ echo "running $(MKDEP)"
+ @ rm -f depend
+ @ touch depend
+ @ $(MKDEP) $(MKDEP_OPTIONS) $(DRIVER_DEFINES) $(INCLUDES) \
+ $(C_SOURCES) $(CXX_SOURCES) \
+ $(ASM_SOURCES) > /dev/null 2>/dev/null
+
+
+# Emacs tags
+tags:
+ etags `find . -name \*.[ch]` `find ../include`
+
+
+# Remove .o and backup files
+clean:
+ -rm -f *.o */*.o *~ *.so *~ server/*.o $(SYMLINKS)
+ -rm -f depend depend.bak
+
+
+install: $(LIBNAME)
+ $(INSTALL) -d $(DESTDIR)$(DRI_DRIVER_INSTALL_DIR)
+ $(MINSTALL) -m 755 $(LIBNAME) $(DESTDIR)$(DRI_DRIVER_INSTALL_DIR)
+
+
+-include depend
diff --git a/mesalib/src/mesa/drivers/dri/common/depthtmp.h b/mesalib/src/mesa/drivers/dri/common/depthtmp.h
index fd2dab3b4..8e751d7b2 100644
--- a/mesalib/src/mesa/drivers/dri/common/depthtmp.h
+++ b/mesalib/src/mesa/drivers/dri/common/depthtmp.h
@@ -1,270 +1,270 @@
-
-/*
- * Notes:
- * 1. These functions plug into the gl_renderbuffer structure.
- * 2. The 'values' parameter always points to GLuint values, regardless of
- * the actual Z buffer depth.
- */
-
-
-#include "spantmp_common.h"
-
-#ifndef DBG
-#define DBG 0
-#endif
-
-#ifndef HAVE_HW_DEPTH_SPANS
-#define HAVE_HW_DEPTH_SPANS 0
-#endif
-
-#ifndef HAVE_HW_DEPTH_PIXELS
-#define HAVE_HW_DEPTH_PIXELS 0
-#endif
-
-static void TAG(WriteDepthSpan)( GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, GLint x, GLint y,
- const void *values,
- const GLubyte mask[] )
-{
- HW_WRITE_LOCK()
- {
- const VALUE_TYPE *depth = (const VALUE_TYPE *) values;
- GLint x1;
- GLint n1;
- LOCAL_DEPTH_VARS;
-
- y = Y_FLIP( y );
-
-#if HAVE_HW_DEPTH_SPANS
- (void) x1; (void) n1;
-
- if ( DBG ) fprintf( stderr, "WriteDepthSpan 0..%d (x1 %d)\n",
- (int)n, (int)x );
-
- WRITE_DEPTH_SPAN();
-#else
- HW_CLIPLOOP()
- {
- GLint i = 0;
- CLIPSPAN( x, y, n, x1, n1, i );
-
- if ( DBG ) fprintf( stderr, "WriteDepthSpan %d..%d (x1 %d) (mask %p)\n",
- (int)i, (int)n1, (int)x1, mask );
-
- if ( mask ) {
- for ( ; n1>0 ; i++, x1++, n1-- ) {
- if ( mask[i] ) WRITE_DEPTH( x1, y, depth[i] );
- }
- } else {
- for ( ; n1>0 ; i++, x1++, n1-- ) {
- WRITE_DEPTH( x1, y, depth[i] );
- }
- }
- }
- HW_ENDCLIPLOOP();
-#endif
- }
- HW_WRITE_UNLOCK();
-}
-
-
-#if HAVE_HW_DEPTH_SPANS
-/* implement MonoWriteDepthSpan() in terms of WriteDepthSpan() */
-static void
-TAG(WriteMonoDepthSpan)( GLcontext *ctx, struct gl_renderbuffer *rb,
- GLuint n, GLint x, GLint y,
- const void *value, const GLubyte mask[] )
-{
- const GLuint depthVal = *((GLuint *) value);
- GLuint depths[MAX_WIDTH];
- GLuint i;
- for (i = 0; i < n; i++)
- depths[i] = depthVal;
- TAG(WriteDepthSpan)(ctx, rb, n, x, y, depths, mask);
-}
-#else
-static void TAG(WriteMonoDepthSpan)( GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, GLint x, GLint y,
- const void *value,
- const GLubyte mask[] )
-{
- HW_WRITE_LOCK()
- {
- const GLuint depth = *((GLuint *) value);
- GLint x1;
- GLint n1;
- LOCAL_DEPTH_VARS;
-
- y = Y_FLIP( y );
-
- HW_CLIPLOOP()
- {
- GLint i = 0;
- CLIPSPAN( x, y, n, x1, n1, i );
-
- if ( DBG ) fprintf( stderr, "%s %d..%d (x1 %d) = %u\n",
- __FUNCTION__, (int)i, (int)n1, (int)x1, (GLuint)depth );
-
- if ( mask ) {
- for ( ; n1>0 ; i++, x1++, n1-- ) {
- if ( mask[i] ) WRITE_DEPTH( x1, y, depth );
- }
- } else {
- for ( ; n1>0 ; x1++, n1-- ) {
- WRITE_DEPTH( x1, y, depth );
- }
- }
- }
- HW_ENDCLIPLOOP();
- }
- HW_WRITE_UNLOCK();
-}
-#endif
-
-
-static void TAG(WriteDepthPixels)( GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n,
- const GLint x[],
- const GLint y[],
- const void *values,
- const GLubyte mask[] )
-{
- HW_WRITE_LOCK()
- {
- const VALUE_TYPE *depth = (const VALUE_TYPE *) values;
- GLuint i;
- LOCAL_DEPTH_VARS;
-
- if ( DBG ) fprintf( stderr, "WriteDepthPixels\n" );
-
-#if HAVE_HW_DEPTH_PIXELS
- (void) i;
-
- WRITE_DEPTH_PIXELS();
-#else
- HW_CLIPLOOP()
- {
- if ( mask ) {
- for ( i = 0 ; i < n ; i++ ) {
- if ( mask[i] ) {
- const int fy = Y_FLIP( y[i] );
- if ( CLIPPIXEL( x[i], fy ) )
- WRITE_DEPTH( x[i], fy, depth[i] );
- }
- }
- }
- else {
- for ( i = 0 ; i < n ; i++ ) {
- const int fy = Y_FLIP( y[i] );
- if ( CLIPPIXEL( x[i], fy ) )
- WRITE_DEPTH( x[i], fy, depth[i] );
- }
- }
- }
- HW_ENDCLIPLOOP();
-#endif
- }
- HW_WRITE_UNLOCK();
-}
-
-
-/* Read depth spans and pixels
- */
-static void TAG(ReadDepthSpan)( GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, GLint x, GLint y,
- void *values )
-{
- HW_READ_LOCK()
- {
- VALUE_TYPE *depth = (VALUE_TYPE *) values;
- GLint x1, n1;
- LOCAL_DEPTH_VARS;
-
- y = Y_FLIP( y );
-
- if ( DBG ) fprintf( stderr, "ReadDepthSpan\n" );
-
-#if HAVE_HW_DEPTH_SPANS
- (void) x1; (void) n1;
-
- READ_DEPTH_SPAN();
-#else
- HW_CLIPLOOP()
- {
- GLint i = 0;
- CLIPSPAN( x, y, n, x1, n1, i );
- for ( ; n1>0 ; i++, n1-- ) {
- READ_DEPTH( depth[i], x+i, y );
- }
- }
- HW_ENDCLIPLOOP();
-#endif
- }
- HW_READ_UNLOCK();
-}
-
-static void TAG(ReadDepthPixels)( GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n,
- const GLint x[], const GLint y[],
- void *values )
-{
- HW_READ_LOCK()
- {
- VALUE_TYPE *depth = (VALUE_TYPE *) values;
- GLuint i;
- LOCAL_DEPTH_VARS;
-
- if ( DBG ) fprintf( stderr, "ReadDepthPixels\n" );
-
-#if HAVE_HW_DEPTH_PIXELS
- (void) i;
-
- READ_DEPTH_PIXELS();
-#else
- HW_CLIPLOOP()
- {
- for ( i = 0 ; i < n ;i++ ) {
- int fy = Y_FLIP( y[i] );
- if ( CLIPPIXEL( x[i], fy ) )
- READ_DEPTH( depth[i], x[i], fy );
- }
- }
- HW_ENDCLIPLOOP();
-#endif
- }
- HW_READ_UNLOCK();
-}
-
-
-/**
- * Initialize the given renderbuffer's span routines to point to
- * the depth/z functions we generated above.
- */
-static void TAG(InitDepthPointers)(struct gl_renderbuffer *rb)
-{
- rb->GetRow = TAG(ReadDepthSpan);
- rb->GetValues = TAG(ReadDepthPixels);
- rb->PutRow = TAG(WriteDepthSpan);
- rb->PutRowRGB = NULL;
- rb->PutMonoRow = TAG(WriteMonoDepthSpan);
- rb->PutValues = TAG(WriteDepthPixels);
- rb->PutMonoValues = NULL;
-}
-
-
-#if HAVE_HW_DEPTH_SPANS
-#undef WRITE_DEPTH_SPAN
-#undef WRITE_DEPTH_PIXELS
-#undef READ_DEPTH_SPAN
-#undef READ_DEPTH_PIXELS
-#else
-#undef WRITE_DEPTH
-#undef READ_DEPTH
-#endif
-#undef TAG
-#undef VALUE_TYPE
+
+/*
+ * Notes:
+ * 1. These functions plug into the gl_renderbuffer structure.
+ * 2. The 'values' parameter always points to GLuint values, regardless of
+ * the actual Z buffer depth.
+ */
+
+
+#include "spantmp_common.h"
+
+#ifndef DBG
+#define DBG 0
+#endif
+
+#ifndef HAVE_HW_DEPTH_SPANS
+#define HAVE_HW_DEPTH_SPANS 0
+#endif
+
+#ifndef HAVE_HW_DEPTH_PIXELS
+#define HAVE_HW_DEPTH_PIXELS 0
+#endif
+
+static void TAG(WriteDepthSpan)( struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const void *values,
+ const GLubyte mask[] )
+{
+ HW_WRITE_LOCK()
+ {
+ const VALUE_TYPE *depth = (const VALUE_TYPE *) values;
+ GLint x1;
+ GLint n1;
+ LOCAL_DEPTH_VARS;
+
+ y = Y_FLIP( y );
+
+#if HAVE_HW_DEPTH_SPANS
+ (void) x1; (void) n1;
+
+ if ( DBG ) fprintf( stderr, "WriteDepthSpan 0..%d (x1 %d)\n",
+ (int)n, (int)x );
+
+ WRITE_DEPTH_SPAN();
+#else
+ HW_CLIPLOOP()
+ {
+ GLint i = 0;
+ CLIPSPAN( x, y, n, x1, n1, i );
+
+ if ( DBG ) fprintf( stderr, "WriteDepthSpan %d..%d (x1 %d) (mask %p)\n",
+ (int)i, (int)n1, (int)x1, mask );
+
+ if ( mask ) {
+ for ( ; n1>0 ; i++, x1++, n1-- ) {
+ if ( mask[i] ) WRITE_DEPTH( x1, y, depth[i] );
+ }
+ } else {
+ for ( ; n1>0 ; i++, x1++, n1-- ) {
+ WRITE_DEPTH( x1, y, depth[i] );
+ }
+ }
+ }
+ HW_ENDCLIPLOOP();
+#endif
+ }
+ HW_WRITE_UNLOCK();
+}
+
+
+#if HAVE_HW_DEPTH_SPANS
+/* implement MonoWriteDepthSpan() in terms of WriteDepthSpan() */
+static void
+TAG(WriteMonoDepthSpan)( struct gl_context *ctx, struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const void *value, const GLubyte mask[] )
+{
+ const GLuint depthVal = *((GLuint *) value);
+ GLuint depths[MAX_WIDTH];
+ GLuint i;
+ for (i = 0; i < n; i++)
+ depths[i] = depthVal;
+ TAG(WriteDepthSpan)(ctx, rb, n, x, y, depths, mask);
+}
+#else
+static void TAG(WriteMonoDepthSpan)( struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const void *value,
+ const GLubyte mask[] )
+{
+ HW_WRITE_LOCK()
+ {
+ const GLuint depth = *((GLuint *) value);
+ GLint x1;
+ GLint n1;
+ LOCAL_DEPTH_VARS;
+
+ y = Y_FLIP( y );
+
+ HW_CLIPLOOP()
+ {
+ GLint i = 0;
+ CLIPSPAN( x, y, n, x1, n1, i );
+
+ if ( DBG ) fprintf( stderr, "%s %d..%d (x1 %d) = %u\n",
+ __FUNCTION__, (int)i, (int)n1, (int)x1, (GLuint)depth );
+
+ if ( mask ) {
+ for ( ; n1>0 ; i++, x1++, n1-- ) {
+ if ( mask[i] ) WRITE_DEPTH( x1, y, depth );
+ }
+ } else {
+ for ( ; n1>0 ; x1++, n1-- ) {
+ WRITE_DEPTH( x1, y, depth );
+ }
+ }
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_WRITE_UNLOCK();
+}
+#endif
+
+
+static void TAG(WriteDepthPixels)( struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n,
+ const GLint x[],
+ const GLint y[],
+ const void *values,
+ const GLubyte mask[] )
+{
+ HW_WRITE_LOCK()
+ {
+ const VALUE_TYPE *depth = (const VALUE_TYPE *) values;
+ GLuint i;
+ LOCAL_DEPTH_VARS;
+
+ if ( DBG ) fprintf( stderr, "WriteDepthPixels\n" );
+
+#if HAVE_HW_DEPTH_PIXELS
+ (void) i;
+
+ WRITE_DEPTH_PIXELS();
+#else
+ HW_CLIPLOOP()
+ {
+ if ( mask ) {
+ for ( i = 0 ; i < n ; i++ ) {
+ if ( mask[i] ) {
+ const int fy = Y_FLIP( y[i] );
+ if ( CLIPPIXEL( x[i], fy ) )
+ WRITE_DEPTH( x[i], fy, depth[i] );
+ }
+ }
+ }
+ else {
+ for ( i = 0 ; i < n ; i++ ) {
+ const int fy = Y_FLIP( y[i] );
+ if ( CLIPPIXEL( x[i], fy ) )
+ WRITE_DEPTH( x[i], fy, depth[i] );
+ }
+ }
+ }
+ HW_ENDCLIPLOOP();
+#endif
+ }
+ HW_WRITE_UNLOCK();
+}
+
+
+/* Read depth spans and pixels
+ */
+static void TAG(ReadDepthSpan)( struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ void *values )
+{
+ HW_READ_LOCK()
+ {
+ VALUE_TYPE *depth = (VALUE_TYPE *) values;
+ GLint x1, n1;
+ LOCAL_DEPTH_VARS;
+
+ y = Y_FLIP( y );
+
+ if ( DBG ) fprintf( stderr, "ReadDepthSpan\n" );
+
+#if HAVE_HW_DEPTH_SPANS
+ (void) x1; (void) n1;
+
+ READ_DEPTH_SPAN();
+#else
+ HW_CLIPLOOP()
+ {
+ GLint i = 0;
+ CLIPSPAN( x, y, n, x1, n1, i );
+ for ( ; n1>0 ; i++, n1-- ) {
+ READ_DEPTH( depth[i], x+i, y );
+ }
+ }
+ HW_ENDCLIPLOOP();
+#endif
+ }
+ HW_READ_UNLOCK();
+}
+
+static void TAG(ReadDepthPixels)( struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ void *values )
+{
+ HW_READ_LOCK()
+ {
+ VALUE_TYPE *depth = (VALUE_TYPE *) values;
+ GLuint i;
+ LOCAL_DEPTH_VARS;
+
+ if ( DBG ) fprintf( stderr, "ReadDepthPixels\n" );
+
+#if HAVE_HW_DEPTH_PIXELS
+ (void) i;
+
+ READ_DEPTH_PIXELS();
+#else
+ HW_CLIPLOOP()
+ {
+ for ( i = 0 ; i < n ;i++ ) {
+ int fy = Y_FLIP( y[i] );
+ if ( CLIPPIXEL( x[i], fy ) )
+ READ_DEPTH( depth[i], x[i], fy );
+ }
+ }
+ HW_ENDCLIPLOOP();
+#endif
+ }
+ HW_READ_UNLOCK();
+}
+
+
+/**
+ * Initialize the given renderbuffer's span routines to point to
+ * the depth/z functions we generated above.
+ */
+static void TAG(InitDepthPointers)(struct gl_renderbuffer *rb)
+{
+ rb->GetRow = TAG(ReadDepthSpan);
+ rb->GetValues = TAG(ReadDepthPixels);
+ rb->PutRow = TAG(WriteDepthSpan);
+ rb->PutRowRGB = NULL;
+ rb->PutMonoRow = TAG(WriteMonoDepthSpan);
+ rb->PutValues = TAG(WriteDepthPixels);
+ rb->PutMonoValues = NULL;
+}
+
+
+#if HAVE_HW_DEPTH_SPANS
+#undef WRITE_DEPTH_SPAN
+#undef WRITE_DEPTH_PIXELS
+#undef READ_DEPTH_SPAN
+#undef READ_DEPTH_PIXELS
+#else
+#undef WRITE_DEPTH
+#undef READ_DEPTH
+#endif
+#undef TAG
+#undef VALUE_TYPE
diff --git a/mesalib/src/mesa/drivers/dri/common/dri_metaops.c b/mesalib/src/mesa/drivers/dri/common/dri_metaops.c
index a2f404b61..e259f11df 100644
--- a/mesalib/src/mesa/drivers/dri/common/dri_metaops.c
+++ b/mesalib/src/mesa/drivers/dri/common/dri_metaops.c
@@ -1,291 +1,291 @@
-/**************************************************************************
- *
- * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
- * Copyright 2009 Intel Corporation.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
-#include "main/arbprogram.h"
-#include "main/arrayobj.h"
-#include "main/bufferobj.h"
-#include "main/context.h"
-#include "main/enable.h"
-#include "main/matrix.h"
-#include "main/texstate.h"
-#include "main/varray.h"
-#include "main/viewport.h"
-#include "program/program.h"
-#include "dri_metaops.h"
-
-void
-meta_set_passthrough_transform(struct dri_metaops *meta)
-{
- GLcontext *ctx = meta->ctx;
-
- meta->saved_vp_x = ctx->Viewport.X;
- meta->saved_vp_y = ctx->Viewport.Y;
- meta->saved_vp_width = ctx->Viewport.Width;
- meta->saved_vp_height = ctx->Viewport.Height;
- meta->saved_matrix_mode = ctx->Transform.MatrixMode;
-
- meta->internal_viewport_call = GL_TRUE;
- _mesa_Viewport(0, 0, ctx->DrawBuffer->Width, ctx->DrawBuffer->Height);
- meta->internal_viewport_call = GL_FALSE;
-
- _mesa_MatrixMode(GL_PROJECTION);
- _mesa_PushMatrix();
- _mesa_LoadIdentity();
- _mesa_Ortho(0, ctx->DrawBuffer->Width, 0, ctx->DrawBuffer->Height, 1, -1);
-
- _mesa_MatrixMode(GL_MODELVIEW);
- _mesa_PushMatrix();
- _mesa_LoadIdentity();
-}
-
-void
-meta_restore_transform(struct dri_metaops *meta)
-{
- _mesa_MatrixMode(GL_PROJECTION);
- _mesa_PopMatrix();
- _mesa_MatrixMode(GL_MODELVIEW);
- _mesa_PopMatrix();
-
- _mesa_MatrixMode(meta->saved_matrix_mode);
-
- meta->internal_viewport_call = GL_TRUE;
- _mesa_Viewport(meta->saved_vp_x, meta->saved_vp_y,
- meta->saved_vp_width, meta->saved_vp_height);
- meta->internal_viewport_call = GL_FALSE;
-}
-
-
-/**
- * Set up a vertex program to pass through the position and first texcoord
- * for pixel path.
- */
-void
-meta_set_passthrough_vertex_program(struct dri_metaops *meta)
-{
- GLcontext *ctx = meta->ctx;
- static const char *vp =
- "!!ARBvp1.0\n"
- "TEMP vertexClip;\n"
- "DP4 vertexClip.x, state.matrix.mvp.row[0], vertex.position;\n"
- "DP4 vertexClip.y, state.matrix.mvp.row[1], vertex.position;\n"
- "DP4 vertexClip.z, state.matrix.mvp.row[2], vertex.position;\n"
- "DP4 vertexClip.w, state.matrix.mvp.row[3], vertex.position;\n"
- "MOV result.position, vertexClip;\n"
- "MOV result.texcoord[0], vertex.texcoord[0];\n"
- "MOV result.color, vertex.color;\n"
- "END\n";
-
- assert(meta->saved_vp == NULL);
-
- _mesa_reference_vertprog(ctx, &meta->saved_vp,
- ctx->VertexProgram.Current);
- if (meta->passthrough_vp == NULL) {
- GLuint prog_name;
- _mesa_GenPrograms(1, &prog_name);
- _mesa_BindProgram(GL_VERTEX_PROGRAM_ARB, prog_name);
- _mesa_ProgramStringARB(GL_VERTEX_PROGRAM_ARB,
- GL_PROGRAM_FORMAT_ASCII_ARB,
- strlen(vp), (const GLubyte *)vp);
- _mesa_reference_vertprog(ctx, &meta->passthrough_vp,
- ctx->VertexProgram.Current);
- _mesa_DeletePrograms(1, &prog_name);
- }
-
- FLUSH_VERTICES(ctx, _NEW_PROGRAM);
- _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
- meta->passthrough_vp);
- ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB,
- &meta->passthrough_vp->Base);
-
- meta->saved_vp_enable = ctx->VertexProgram.Enabled;
- _mesa_Enable(GL_VERTEX_PROGRAM_ARB);
-}
-
-/**
- * Restores the previous vertex program after
- * meta_set_passthrough_vertex_program()
- */
-void
-meta_restore_vertex_program(struct dri_metaops *meta)
-{
- GLcontext *ctx = meta->ctx;
-
- FLUSH_VERTICES(ctx, _NEW_PROGRAM);
- _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
- meta->saved_vp);
- _mesa_reference_vertprog(ctx, &meta->saved_vp, NULL);
- ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB,
- &ctx->VertexProgram.Current->Base);
-
- if (!meta->saved_vp_enable)
- _mesa_Disable(GL_VERTEX_PROGRAM_ARB);
-}
-
-/**
- * Binds the given program string to GL_FRAGMENT_PROGRAM_ARB, caching the
- * program object.
- */
-void
-meta_set_fragment_program(struct dri_metaops *meta,
- struct gl_fragment_program **prog,
- const char *prog_string)
-{
- GLcontext *ctx = meta->ctx;
- assert(meta->saved_fp == NULL);
-
- _mesa_reference_fragprog(ctx, &meta->saved_fp,
- ctx->FragmentProgram.Current);
- if (*prog == NULL) {
- GLuint prog_name;
- _mesa_GenPrograms(1, &prog_name);
- _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, prog_name);
- _mesa_ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB,
- GL_PROGRAM_FORMAT_ASCII_ARB,
- strlen(prog_string), (const GLubyte *)prog_string);
- _mesa_reference_fragprog(ctx, prog, ctx->FragmentProgram.Current);
- /* Note that DeletePrograms unbinds the program on us */
- _mesa_DeletePrograms(1, &prog_name);
- }
-
- FLUSH_VERTICES(ctx, _NEW_PROGRAM);
- _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, *prog);
- ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, &((*prog)->Base));
-
- meta->saved_fp_enable = ctx->FragmentProgram.Enabled;
- _mesa_Enable(GL_FRAGMENT_PROGRAM_ARB);
-}
-
-/**
- * Restores the previous fragment program after
- * meta_set_fragment_program()
- */
-void
-meta_restore_fragment_program(struct dri_metaops *meta)
-{
- GLcontext *ctx = meta->ctx;
-
- FLUSH_VERTICES(ctx, _NEW_PROGRAM);
- _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current,
- meta->saved_fp);
- _mesa_reference_fragprog(ctx, &meta->saved_fp, NULL);
- ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB,
- &ctx->FragmentProgram.Current->Base);
-
- if (!meta->saved_fp_enable)
- _mesa_Disable(GL_FRAGMENT_PROGRAM_ARB);
-}
-
-static const float default_texcoords[4][2] = { { 0.0, 0.0 },
- { 1.0, 0.0 },
- { 1.0, 1.0 },
- { 0.0, 1.0 } };
-
-void
-meta_set_default_texrect(struct dri_metaops *meta)
-{
- GLcontext *ctx = meta->ctx;
- struct gl_client_array *old_texcoord_array;
-
- meta->saved_active_texture = ctx->Texture.CurrentUnit;
- if (meta->saved_array_vbo == NULL) {
- _mesa_reference_buffer_object(ctx, &meta->saved_array_vbo,
- ctx->Array.ArrayBufferObj);
- }
-
- old_texcoord_array = &ctx->Array.ArrayObj->TexCoord[0];
- meta->saved_texcoord_type = old_texcoord_array->Type;
- meta->saved_texcoord_size = old_texcoord_array->Size;
- meta->saved_texcoord_stride = old_texcoord_array->Stride;
- meta->saved_texcoord_enable = old_texcoord_array->Enabled;
- meta->saved_texcoord_ptr = old_texcoord_array->Ptr;
- _mesa_reference_buffer_object(ctx, &meta->saved_texcoord_vbo,
- old_texcoord_array->BufferObj);
-
- _mesa_ClientActiveTextureARB(GL_TEXTURE0);
-
- if (meta->texcoord_vbo == NULL) {
- GLuint vbo_name;
-
- _mesa_GenBuffersARB(1, &vbo_name);
- _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, vbo_name);
- _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(default_texcoords),
- default_texcoords, GL_STATIC_DRAW_ARB);
- _mesa_reference_buffer_object(ctx, &meta->texcoord_vbo,
- ctx->Array.ArrayBufferObj);
- } else {
- _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB,
- meta->texcoord_vbo->Name);
- }
- _mesa_TexCoordPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), NULL);
-
- _mesa_Enable(GL_TEXTURE_COORD_ARRAY);
-}
-
-void
-meta_restore_texcoords(struct dri_metaops *meta)
-{
- GLcontext *ctx = meta->ctx;
-
- /* Restore the old TexCoordPointer */
- if (meta->saved_texcoord_vbo) {
- _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB,
- meta->saved_texcoord_vbo->Name);
- _mesa_reference_buffer_object(ctx, &meta->saved_texcoord_vbo, NULL);
- } else {
- _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
- }
-
- _mesa_TexCoordPointer(meta->saved_texcoord_size,
- meta->saved_texcoord_type,
- meta->saved_texcoord_stride,
- meta->saved_texcoord_ptr);
- if (!meta->saved_texcoord_enable)
- _mesa_Disable(GL_TEXTURE_COORD_ARRAY);
-
- _mesa_ClientActiveTextureARB(GL_TEXTURE0 +
- meta->saved_active_texture);
-
- if (meta->saved_array_vbo) {
- _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB,
- meta->saved_array_vbo->Name);
- _mesa_reference_buffer_object(ctx, &meta->saved_array_vbo, NULL);
- } else {
- _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
- }
-}
-
-
-void meta_init_metaops(GLcontext *ctx, struct dri_metaops *meta)
-{
- meta->ctx = ctx;
-}
-
-void meta_destroy_metaops(struct dri_metaops *meta)
-{
-
-}
+/**************************************************************************
+ *
+ * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * Copyright 2009 Intel Corporation.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "main/arbprogram.h"
+#include "main/arrayobj.h"
+#include "main/bufferobj.h"
+#include "main/context.h"
+#include "main/enable.h"
+#include "main/matrix.h"
+#include "main/texstate.h"
+#include "main/varray.h"
+#include "main/viewport.h"
+#include "program/program.h"
+#include "dri_metaops.h"
+
+void
+meta_set_passthrough_transform(struct dri_metaops *meta)
+{
+ struct gl_context *ctx = meta->ctx;
+
+ meta->saved_vp_x = ctx->Viewport.X;
+ meta->saved_vp_y = ctx->Viewport.Y;
+ meta->saved_vp_width = ctx->Viewport.Width;
+ meta->saved_vp_height = ctx->Viewport.Height;
+ meta->saved_matrix_mode = ctx->Transform.MatrixMode;
+
+ meta->internal_viewport_call = GL_TRUE;
+ _mesa_Viewport(0, 0, ctx->DrawBuffer->Width, ctx->DrawBuffer->Height);
+ meta->internal_viewport_call = GL_FALSE;
+
+ _mesa_MatrixMode(GL_PROJECTION);
+ _mesa_PushMatrix();
+ _mesa_LoadIdentity();
+ _mesa_Ortho(0, ctx->DrawBuffer->Width, 0, ctx->DrawBuffer->Height, 1, -1);
+
+ _mesa_MatrixMode(GL_MODELVIEW);
+ _mesa_PushMatrix();
+ _mesa_LoadIdentity();
+}
+
+void
+meta_restore_transform(struct dri_metaops *meta)
+{
+ _mesa_MatrixMode(GL_PROJECTION);
+ _mesa_PopMatrix();
+ _mesa_MatrixMode(GL_MODELVIEW);
+ _mesa_PopMatrix();
+
+ _mesa_MatrixMode(meta->saved_matrix_mode);
+
+ meta->internal_viewport_call = GL_TRUE;
+ _mesa_Viewport(meta->saved_vp_x, meta->saved_vp_y,
+ meta->saved_vp_width, meta->saved_vp_height);
+ meta->internal_viewport_call = GL_FALSE;
+}
+
+
+/**
+ * Set up a vertex program to pass through the position and first texcoord
+ * for pixel path.
+ */
+void
+meta_set_passthrough_vertex_program(struct dri_metaops *meta)
+{
+ struct gl_context *ctx = meta->ctx;
+ static const char *vp =
+ "!!ARBvp1.0\n"
+ "TEMP vertexClip;\n"
+ "DP4 vertexClip.x, state.matrix.mvp.row[0], vertex.position;\n"
+ "DP4 vertexClip.y, state.matrix.mvp.row[1], vertex.position;\n"
+ "DP4 vertexClip.z, state.matrix.mvp.row[2], vertex.position;\n"
+ "DP4 vertexClip.w, state.matrix.mvp.row[3], vertex.position;\n"
+ "MOV result.position, vertexClip;\n"
+ "MOV result.texcoord[0], vertex.texcoord[0];\n"
+ "MOV result.color, vertex.color;\n"
+ "END\n";
+
+ assert(meta->saved_vp == NULL);
+
+ _mesa_reference_vertprog(ctx, &meta->saved_vp,
+ ctx->VertexProgram.Current);
+ if (meta->passthrough_vp == NULL) {
+ GLuint prog_name;
+ _mesa_GenPrograms(1, &prog_name);
+ _mesa_BindProgram(GL_VERTEX_PROGRAM_ARB, prog_name);
+ _mesa_ProgramStringARB(GL_VERTEX_PROGRAM_ARB,
+ GL_PROGRAM_FORMAT_ASCII_ARB,
+ strlen(vp), (const GLubyte *)vp);
+ _mesa_reference_vertprog(ctx, &meta->passthrough_vp,
+ ctx->VertexProgram.Current);
+ _mesa_DeletePrograms(1, &prog_name);
+ }
+
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+ _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
+ meta->passthrough_vp);
+ ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB,
+ &meta->passthrough_vp->Base);
+
+ meta->saved_vp_enable = ctx->VertexProgram.Enabled;
+ _mesa_Enable(GL_VERTEX_PROGRAM_ARB);
+}
+
+/**
+ * Restores the previous vertex program after
+ * meta_set_passthrough_vertex_program()
+ */
+void
+meta_restore_vertex_program(struct dri_metaops *meta)
+{
+ struct gl_context *ctx = meta->ctx;
+
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+ _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
+ meta->saved_vp);
+ _mesa_reference_vertprog(ctx, &meta->saved_vp, NULL);
+ ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB,
+ &ctx->VertexProgram.Current->Base);
+
+ if (!meta->saved_vp_enable)
+ _mesa_Disable(GL_VERTEX_PROGRAM_ARB);
+}
+
+/**
+ * Binds the given program string to GL_FRAGMENT_PROGRAM_ARB, caching the
+ * program object.
+ */
+void
+meta_set_fragment_program(struct dri_metaops *meta,
+ struct gl_fragment_program **prog,
+ const char *prog_string)
+{
+ struct gl_context *ctx = meta->ctx;
+ assert(meta->saved_fp == NULL);
+
+ _mesa_reference_fragprog(ctx, &meta->saved_fp,
+ ctx->FragmentProgram.Current);
+ if (*prog == NULL) {
+ GLuint prog_name;
+ _mesa_GenPrograms(1, &prog_name);
+ _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, prog_name);
+ _mesa_ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB,
+ GL_PROGRAM_FORMAT_ASCII_ARB,
+ strlen(prog_string), (const GLubyte *)prog_string);
+ _mesa_reference_fragprog(ctx, prog, ctx->FragmentProgram.Current);
+ /* Note that DeletePrograms unbinds the program on us */
+ _mesa_DeletePrograms(1, &prog_name);
+ }
+
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+ _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, *prog);
+ ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, &((*prog)->Base));
+
+ meta->saved_fp_enable = ctx->FragmentProgram.Enabled;
+ _mesa_Enable(GL_FRAGMENT_PROGRAM_ARB);
+}
+
+/**
+ * Restores the previous fragment program after
+ * meta_set_fragment_program()
+ */
+void
+meta_restore_fragment_program(struct dri_metaops *meta)
+{
+ struct gl_context *ctx = meta->ctx;
+
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+ _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current,
+ meta->saved_fp);
+ _mesa_reference_fragprog(ctx, &meta->saved_fp, NULL);
+ ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB,
+ &ctx->FragmentProgram.Current->Base);
+
+ if (!meta->saved_fp_enable)
+ _mesa_Disable(GL_FRAGMENT_PROGRAM_ARB);
+}
+
+static const float default_texcoords[4][2] = { { 0.0, 0.0 },
+ { 1.0, 0.0 },
+ { 1.0, 1.0 },
+ { 0.0, 1.0 } };
+
+void
+meta_set_default_texrect(struct dri_metaops *meta)
+{
+ struct gl_context *ctx = meta->ctx;
+ struct gl_client_array *old_texcoord_array;
+
+ meta->saved_active_texture = ctx->Texture.CurrentUnit;
+ if (meta->saved_array_vbo == NULL) {
+ _mesa_reference_buffer_object(ctx, &meta->saved_array_vbo,
+ ctx->Array.ArrayBufferObj);
+ }
+
+ old_texcoord_array = &ctx->Array.ArrayObj->TexCoord[0];
+ meta->saved_texcoord_type = old_texcoord_array->Type;
+ meta->saved_texcoord_size = old_texcoord_array->Size;
+ meta->saved_texcoord_stride = old_texcoord_array->Stride;
+ meta->saved_texcoord_enable = old_texcoord_array->Enabled;
+ meta->saved_texcoord_ptr = old_texcoord_array->Ptr;
+ _mesa_reference_buffer_object(ctx, &meta->saved_texcoord_vbo,
+ old_texcoord_array->BufferObj);
+
+ _mesa_ClientActiveTextureARB(GL_TEXTURE0);
+
+ if (meta->texcoord_vbo == NULL) {
+ GLuint vbo_name;
+
+ _mesa_GenBuffersARB(1, &vbo_name);
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, vbo_name);
+ _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(default_texcoords),
+ default_texcoords, GL_STATIC_DRAW_ARB);
+ _mesa_reference_buffer_object(ctx, &meta->texcoord_vbo,
+ ctx->Array.ArrayBufferObj);
+ } else {
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB,
+ meta->texcoord_vbo->Name);
+ }
+ _mesa_TexCoordPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), NULL);
+
+ _mesa_Enable(GL_TEXTURE_COORD_ARRAY);
+}
+
+void
+meta_restore_texcoords(struct dri_metaops *meta)
+{
+ struct gl_context *ctx = meta->ctx;
+
+ /* Restore the old TexCoordPointer */
+ if (meta->saved_texcoord_vbo) {
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB,
+ meta->saved_texcoord_vbo->Name);
+ _mesa_reference_buffer_object(ctx, &meta->saved_texcoord_vbo, NULL);
+ } else {
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
+ }
+
+ _mesa_TexCoordPointer(meta->saved_texcoord_size,
+ meta->saved_texcoord_type,
+ meta->saved_texcoord_stride,
+ meta->saved_texcoord_ptr);
+ if (!meta->saved_texcoord_enable)
+ _mesa_Disable(GL_TEXTURE_COORD_ARRAY);
+
+ _mesa_ClientActiveTextureARB(GL_TEXTURE0 +
+ meta->saved_active_texture);
+
+ if (meta->saved_array_vbo) {
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB,
+ meta->saved_array_vbo->Name);
+ _mesa_reference_buffer_object(ctx, &meta->saved_array_vbo, NULL);
+ } else {
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
+ }
+}
+
+
+void meta_init_metaops(struct gl_context *ctx, struct dri_metaops *meta)
+{
+ meta->ctx = ctx;
+}
+
+void meta_destroy_metaops(struct dri_metaops *meta)
+{
+
+}
diff --git a/mesalib/src/mesa/drivers/dri/common/dri_metaops.h b/mesalib/src/mesa/drivers/dri/common/dri_metaops.h
index 248714532..e72094e62 100644
--- a/mesalib/src/mesa/drivers/dri/common/dri_metaops.h
+++ b/mesalib/src/mesa/drivers/dri/common/dri_metaops.h
@@ -1,81 +1,81 @@
-/**************************************************************************
- *
- * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
- * Copyright 2009 Intel Corporation.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
-#ifndef DRI_METAOPS_H
-#define DRI_METAOPS_H
-
-
-struct dri_metaops {
- GLcontext *ctx;
- GLboolean internal_viewport_call;
- struct gl_fragment_program *bitmap_fp;
- struct gl_vertex_program *passthrough_vp;
- struct gl_buffer_object *texcoord_vbo;
-
- struct gl_fragment_program *saved_fp;
- GLboolean saved_fp_enable;
- struct gl_vertex_program *saved_vp;
- GLboolean saved_vp_enable;
-
- struct gl_fragment_program *tex2d_fp;
-
- GLboolean saved_texcoord_enable;
- struct gl_buffer_object *saved_array_vbo, *saved_texcoord_vbo;
- GLenum saved_texcoord_type;
- GLsizei saved_texcoord_size, saved_texcoord_stride;
- const void *saved_texcoord_ptr;
- int saved_active_texture;
-
- GLint saved_vp_x, saved_vp_y;
- GLsizei saved_vp_width, saved_vp_height;
- GLenum saved_matrix_mode;
-};
-
-
-void meta_set_passthrough_transform(struct dri_metaops *meta);
-
-void meta_restore_transform(struct dri_metaops *meta);
-
-void meta_set_passthrough_vertex_program(struct dri_metaops *meta);
-
-void meta_restore_vertex_program(struct dri_metaops *meta);
-
-void meta_set_fragment_program(struct dri_metaops *meta,
- struct gl_fragment_program **prog,
- const char *prog_string);
-
-void meta_restore_fragment_program(struct dri_metaops *meta);
-
-void meta_set_default_texrect(struct dri_metaops *meta);
-
-void meta_restore_texcoords(struct dri_metaops *meta);
-
-void meta_init_metaops(GLcontext *ctx, struct dri_metaops *meta);
-void meta_destroy_metaops(struct dri_metaops *meta);
-
-#endif
+/**************************************************************************
+ *
+ * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * Copyright 2009 Intel Corporation.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef DRI_METAOPS_H
+#define DRI_METAOPS_H
+
+
+struct dri_metaops {
+ struct gl_context *ctx;
+ GLboolean internal_viewport_call;
+ struct gl_fragment_program *bitmap_fp;
+ struct gl_vertex_program *passthrough_vp;
+ struct gl_buffer_object *texcoord_vbo;
+
+ struct gl_fragment_program *saved_fp;
+ GLboolean saved_fp_enable;
+ struct gl_vertex_program *saved_vp;
+ GLboolean saved_vp_enable;
+
+ struct gl_fragment_program *tex2d_fp;
+
+ GLboolean saved_texcoord_enable;
+ struct gl_buffer_object *saved_array_vbo, *saved_texcoord_vbo;
+ GLenum saved_texcoord_type;
+ GLsizei saved_texcoord_size, saved_texcoord_stride;
+ const void *saved_texcoord_ptr;
+ int saved_active_texture;
+
+ GLint saved_vp_x, saved_vp_y;
+ GLsizei saved_vp_width, saved_vp_height;
+ GLenum saved_matrix_mode;
+};
+
+
+void meta_set_passthrough_transform(struct dri_metaops *meta);
+
+void meta_restore_transform(struct dri_metaops *meta);
+
+void meta_set_passthrough_vertex_program(struct dri_metaops *meta);
+
+void meta_restore_vertex_program(struct dri_metaops *meta);
+
+void meta_set_fragment_program(struct dri_metaops *meta,
+ struct gl_fragment_program **prog,
+ const char *prog_string);
+
+void meta_restore_fragment_program(struct dri_metaops *meta);
+
+void meta_set_default_texrect(struct dri_metaops *meta);
+
+void meta_restore_texcoords(struct dri_metaops *meta);
+
+void meta_init_metaops(struct gl_context *ctx, struct dri_metaops *meta);
+void meta_destroy_metaops(struct dri_metaops *meta);
+
+#endif
diff --git a/mesalib/src/mesa/drivers/dri/common/dri_util.c b/mesalib/src/mesa/drivers/dri/common/dri_util.c
index d46f622d5..3bf782a1b 100644
--- a/mesalib/src/mesa/drivers/dri/common/dri_util.c
+++ b/mesalib/src/mesa/drivers/dri/common/dri_util.c
@@ -1,1010 +1,1009 @@
-/**
- * \file dri_util.c
- * DRI utility functions.
- *
- * This module acts as glue between GLX and the actual hardware driver. A DRI
- * driver doesn't really \e have to use any of this - it's optional. But, some
- * useful stuff is done here that otherwise would have to be duplicated in most
- * drivers.
- *
- * Basically, these utility functions take care of some of the dirty details of
- * screen initialization, context creation, context binding, DRM setup, etc.
- *
- * These functions are compiled into each DRI driver so libGL.so knows nothing
- * about them.
- */
-
-
-#include <assert.h>
-#include <stdarg.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#include <stdio.h>
-
-#ifndef MAP_FAILED
-#define MAP_FAILED ((void *)-1)
-#endif
-
-#include "main/imports.h"
-#define None 0
-
-#include "dri_util.h"
-#include "drm_sarea.h"
-#include "utils.h"
-#include "xmlpool.h"
-#include "../glsl/glsl_parser_extras.h"
-
-PUBLIC const char __dri2ConfigOptions[] =
- DRI_CONF_BEGIN
- DRI_CONF_SECTION_PERFORMANCE
- DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_1)
- DRI_CONF_SECTION_END
- DRI_CONF_END;
-
-static const uint __dri2NConfigOptions = 1;
-
-#ifndef GLX_OML_sync_control
-typedef GLboolean ( * PFNGLXGETMSCRATEOMLPROC) (__DRIdrawable *drawable, int32_t *numerator, int32_t *denominator);
-#endif
-
-static void dri_get_drawable(__DRIdrawable *pdp);
-static void dri_put_drawable(__DRIdrawable *pdp);
-
-/**
- * This is just a token extension used to signal that the driver
- * supports setting a read drawable.
- */
-const __DRIextension driReadDrawableExtension = {
- __DRI_READ_DRAWABLE, __DRI_READ_DRAWABLE_VERSION
-};
-
-GLint
-driIntersectArea( drm_clip_rect_t rect1, drm_clip_rect_t rect2 )
-{
- if (rect2.x1 > rect1.x1) rect1.x1 = rect2.x1;
- if (rect2.x2 < rect1.x2) rect1.x2 = rect2.x2;
- if (rect2.y1 > rect1.y1) rect1.y1 = rect2.y1;
- if (rect2.y2 < rect1.y2) rect1.y2 = rect2.y2;
-
- if (rect1.x1 > rect1.x2 || rect1.y1 > rect1.y2) return 0;
-
- return (rect1.x2 - rect1.x1) * (rect1.y2 - rect1.y1);
-}
-
-/*****************************************************************/
-/** \name Context (un)binding functions */
-/*****************************************************************/
-/*@{*/
-
-/**
- * Unbind context.
- *
- * \param scrn the screen.
- * \param gc context.
- *
- * \return \c GL_TRUE on success, or \c GL_FALSE on failure.
- *
- * \internal
- * This function calls __DriverAPIRec::UnbindContext, and then decrements
- * __DRIdrawableRec::refcount which must be non-zero for a successful
- * return.
- *
- * While casting the opaque private pointers associated with the parameters
- * into their respective real types it also assures they are not \c NULL.
- */
-static int driUnbindContext(__DRIcontext *pcp)
-{
- __DRIscreen *psp;
- __DRIdrawable *pdp;
- __DRIdrawable *prp;
-
- /*
- ** Assume error checking is done properly in glXMakeCurrent before
- ** calling driUnbindContext.
- */
-
- if (pcp == NULL)
- return GL_FALSE;
-
- psp = pcp->driScreenPriv;
- pdp = pcp->driDrawablePriv;
- prp = pcp->driReadablePriv;
-
- /* already unbound */
- if (!pdp && !prp)
- return GL_TRUE;
- /* Let driver unbind drawable from context */
- (*psp->DriverAPI.UnbindContext)(pcp);
-
- assert(pdp);
- if (pdp->refcount == 0) {
- /* ERROR!!! */
- return GL_FALSE;
- }
-
- dri_put_drawable(pdp);
-
- if (prp != pdp) {
- if (prp->refcount == 0) {
- /* ERROR!!! */
- return GL_FALSE;
- }
-
- dri_put_drawable(prp);
- }
-
-
- /* XXX this is disabled so that if we call SwapBuffers on an unbound
- * window we can determine the last context bound to the window and
- * use that context's lock. (BrianP, 2-Dec-2000)
- */
- pcp->driDrawablePriv = pcp->driReadablePriv = NULL;
-
- return GL_TRUE;
-}
-
-/**
- * This function takes both a read buffer and a draw buffer. This is needed
- * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
- * function.
- */
-static int driBindContext(__DRIcontext *pcp,
- __DRIdrawable *pdp,
- __DRIdrawable *prp)
-{
- __DRIscreen *psp = NULL;
-
- /*
- ** Assume error checking is done properly in glXMakeCurrent before
- ** calling driUnbindContext.
- */
-
- if (!pcp)
- return GL_FALSE;
-
- /* Bind the drawable to the context */
- psp = pcp->driScreenPriv;
- pcp->driDrawablePriv = pdp;
- pcp->driReadablePriv = prp;
- if (pdp) {
- pdp->driContextPriv = pcp;
- dri_get_drawable(pdp);
- }
- if (prp && pdp != prp) {
- dri_get_drawable(prp);
- }
-
- /*
- ** Now that we have a context associated with this drawable, we can
- ** initialize the drawable information if has not been done before.
- */
-
- if (!psp->dri2.enabled) {
- if (pdp && !pdp->pStamp) {
- DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
- __driUtilUpdateDrawableInfo(pdp);
- DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
- }
- if (prp && pdp != prp && !prp->pStamp) {
- DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
- __driUtilUpdateDrawableInfo(prp);
- DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
- }
- }
-
- /* Call device-specific MakeCurrent */
- return (*psp->DriverAPI.MakeCurrent)(pcp, pdp, prp);
-}
-
-/*@}*/
-
-
-/*****************************************************************/
-/** \name Drawable handling functions */
-/*****************************************************************/
-/*@{*/
-
-/**
- * Update private drawable information.
- *
- * \param pdp pointer to the private drawable information to update.
- *
- * This function basically updates the __DRIdrawable struct's
- * cliprect information by calling \c __DRIinterfaceMethods::getDrawableInfo.
- * This is usually called by the DRI_VALIDATE_DRAWABLE_INFO macro which
- * compares the __DRIdrwablePrivate pStamp and lastStamp values. If
- * the values are different that means we have to update the clipping
- * info.
- */
-void
-__driUtilUpdateDrawableInfo(__DRIdrawable *pdp)
-{
- __DRIscreen *psp = pdp->driScreenPriv;
- __DRIcontext *pcp = pdp->driContextPriv;
-
- if (!pcp
- || ((pdp != pcp->driDrawablePriv) && (pdp != pcp->driReadablePriv))) {
- /* ERROR!!!
- * ...but we must ignore it. There can be many contexts bound to a
- * drawable.
- */
- }
-
- if (pdp->pClipRects) {
- free(pdp->pClipRects);
- pdp->pClipRects = NULL;
- }
-
- if (pdp->pBackClipRects) {
- free(pdp->pBackClipRects);
- pdp->pBackClipRects = NULL;
- }
-
- DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
-
- if (! (*psp->getDrawableInfo->getDrawableInfo)(pdp,
- &pdp->index, &pdp->lastStamp,
- &pdp->x, &pdp->y, &pdp->w, &pdp->h,
- &pdp->numClipRects, &pdp->pClipRects,
- &pdp->backX,
- &pdp->backY,
- &pdp->numBackClipRects,
- &pdp->pBackClipRects,
- pdp->loaderPrivate)) {
- /* Error -- eg the window may have been destroyed. Keep going
- * with no cliprects.
- */
- pdp->pStamp = &pdp->lastStamp; /* prevent endless loop */
- pdp->numClipRects = 0;
- pdp->pClipRects = NULL;
- pdp->numBackClipRects = 0;
- pdp->pBackClipRects = NULL;
- }
- else
- pdp->pStamp = &(psp->pSAREA->drawableTable[pdp->index].stamp);
-
- DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
-}
-
-/*@}*/
-
-/*****************************************************************/
-/** \name GLX callbacks */
-/*****************************************************************/
-/*@{*/
-
-static void driReportDamage(__DRIdrawable *pdp,
- struct drm_clip_rect *pClipRects, int numClipRects)
-{
- __DRIscreen *psp = pdp->driScreenPriv;
-
- /* Check that we actually have the new damage report method */
- if (psp->damage) {
- /* Report the damage. Currently, all our drivers draw
- * directly to the front buffer, so we report the damage there
- * rather than to the backing storein (if any).
- */
- (*psp->damage->reportDamage)(pdp,
- pdp->x, pdp->y,
- pClipRects, numClipRects,
- GL_TRUE, pdp->loaderPrivate);
- }
-}
-
-
-/**
- * Swap buffers.
- *
- * \param drawablePrivate opaque pointer to the per-drawable private info.
- *
- * \internal
- * This function calls __DRIdrawable::swapBuffers.
- *
- * Is called directly from glXSwapBuffers().
- */
-static void driSwapBuffers(__DRIdrawable *dPriv)
-{
- __DRIscreen *psp = dPriv->driScreenPriv;
- drm_clip_rect_t *rects;
- int i;
-
- psp->DriverAPI.SwapBuffers(dPriv);
-
- if (!dPriv->numClipRects)
- return;
-
- rects = malloc(sizeof(*rects) * dPriv->numClipRects);
-
- if (!rects)
- return;
-
- for (i = 0; i < dPriv->numClipRects; i++) {
- rects[i].x1 = dPriv->pClipRects[i].x1 - dPriv->x;
- rects[i].y1 = dPriv->pClipRects[i].y1 - dPriv->y;
- rects[i].x2 = dPriv->pClipRects[i].x2 - dPriv->x;
- rects[i].y2 = dPriv->pClipRects[i].y2 - dPriv->y;
- }
-
- driReportDamage(dPriv, rects, dPriv->numClipRects);
- free(rects);
-}
-
-static int driDrawableGetMSC( __DRIscreen *sPriv, __DRIdrawable *dPriv,
- int64_t *msc )
-{
- return sPriv->DriverAPI.GetDrawableMSC(sPriv, dPriv, msc);
-}
-
-
-static int driWaitForMSC(__DRIdrawable *dPriv, int64_t target_msc,
- int64_t divisor, int64_t remainder,
- int64_t * msc, int64_t * sbc)
-{
- __DRIswapInfo sInfo;
- int status;
-
- status = dPriv->driScreenPriv->DriverAPI.WaitForMSC( dPriv, target_msc,
- divisor, remainder,
- msc );
-
- /* GetSwapInfo() may not be provided by the driver if GLX_SGI_video_sync
- * is supported but GLX_OML_sync_control is not. Therefore, don't return
- * an error value if GetSwapInfo() is not implemented.
- */
- if ( status == 0
- && dPriv->driScreenPriv->DriverAPI.GetSwapInfo ) {
- status = dPriv->driScreenPriv->DriverAPI.GetSwapInfo( dPriv, & sInfo );
- *sbc = sInfo.swap_count;
- }
-
- return status;
-}
-
-
-const __DRImediaStreamCounterExtension driMediaStreamCounterExtension = {
- { __DRI_MEDIA_STREAM_COUNTER, __DRI_MEDIA_STREAM_COUNTER_VERSION },
- driWaitForMSC,
- driDrawableGetMSC,
-};
-
-
-static void driCopySubBuffer(__DRIdrawable *dPriv,
- int x, int y, int w, int h)
-{
- drm_clip_rect_t rect;
-
- rect.x1 = x;
- rect.y1 = dPriv->h - y - h;
- rect.x2 = x + w;
- rect.y2 = rect.y1 + h;
- driReportDamage(dPriv, &rect, 1);
-
- dPriv->driScreenPriv->DriverAPI.CopySubBuffer(dPriv, x, y, w, h);
-}
-
-const __DRIcopySubBufferExtension driCopySubBufferExtension = {
- { __DRI_COPY_SUB_BUFFER, __DRI_COPY_SUB_BUFFER_VERSION },
- driCopySubBuffer
-};
-
-static void driSetSwapInterval(__DRIdrawable *dPriv, unsigned int interval)
-{
- dPriv->swap_interval = interval;
-}
-
-static unsigned int driGetSwapInterval(__DRIdrawable *dPriv)
-{
- return dPriv->swap_interval;
-}
-
-const __DRIswapControlExtension driSwapControlExtension = {
- { __DRI_SWAP_CONTROL, __DRI_SWAP_CONTROL_VERSION },
- driSetSwapInterval,
- driGetSwapInterval
-};
-
-
-/**
- * This is called via __DRIscreenRec's createNewDrawable pointer.
- */
-static __DRIdrawable *
-driCreateNewDrawable(__DRIscreen *psp, const __DRIconfig *config,
- drm_drawable_t hwDrawable, int renderType,
- const int *attrs, void *data)
-{
- __DRIdrawable *pdp;
-
- /* Since pbuffers are not yet supported, no drawable attributes are
- * supported either.
- */
- (void) attrs;
-
- pdp = malloc(sizeof *pdp);
- if (!pdp) {
- return NULL;
- }
-
- pdp->driContextPriv = NULL;
- pdp->loaderPrivate = data;
- pdp->hHWDrawable = hwDrawable;
- pdp->refcount = 1;
- pdp->pStamp = NULL;
- pdp->lastStamp = 0;
- pdp->index = 0;
- pdp->x = 0;
- pdp->y = 0;
- pdp->w = 0;
- pdp->h = 0;
- pdp->numClipRects = 0;
- pdp->numBackClipRects = 0;
- pdp->pClipRects = NULL;
- pdp->pBackClipRects = NULL;
- pdp->vblSeq = 0;
- pdp->vblFlags = 0;
-
- pdp->driScreenPriv = psp;
-
- if (!(*psp->DriverAPI.CreateBuffer)(psp, pdp, &config->modes,
- renderType == GLX_PIXMAP_BIT)) {
- free(pdp);
- return NULL;
- }
-
- pdp->msc_base = 0;
-
- /* This special default value is replaced with the configured
- * default value when the drawable is first bound to a direct
- * rendering context.
- */
- pdp->swap_interval = (unsigned)-1;
-
- return pdp;
-}
-
-
-static __DRIdrawable *
-dri2CreateNewDrawable(__DRIscreen *screen,
- const __DRIconfig *config,
- void *loaderPrivate)
-{
- __DRIdrawable *pdraw;
-
- pdraw = driCreateNewDrawable(screen, config, 0, 0, NULL, loaderPrivate);
- if (!pdraw)
- return NULL;
-
- pdraw->pClipRects = &pdraw->dri2.clipRect;
- pdraw->pBackClipRects = &pdraw->dri2.clipRect;
-
- pdraw->pStamp = &pdraw->dri2.stamp;
- *pdraw->pStamp = pdraw->lastStamp + 1;
-
- return pdraw;
-}
-
-static int
-dri2ConfigQueryb(__DRIscreen *screen, const char *var, GLboolean *val)
-{
- if (!driCheckOption(&screen->optionCache, var, DRI_BOOL))
- return -1;
-
- *val = driQueryOptionb(&screen->optionCache, var);
-
- return 0;
-}
-
-static int
-dri2ConfigQueryi(__DRIscreen *screen, const char *var, GLint *val)
-{
- if (!driCheckOption(&screen->optionCache, var, DRI_INT) &&
- !driCheckOption(&screen->optionCache, var, DRI_ENUM))
- return -1;
-
- *val = driQueryOptioni(&screen->optionCache, var);
-
- return 0;
-}
-
-static int
-dri2ConfigQueryf(__DRIscreen *screen, const char *var, GLfloat *val)
-{
- if (!driCheckOption(&screen->optionCache, var, DRI_FLOAT))
- return -1;
-
- *val = driQueryOptionf(&screen->optionCache, var);
-
- return 0;
-}
-
-
-static void dri_get_drawable(__DRIdrawable *pdp)
-{
- pdp->refcount++;
-}
-
-static void dri_put_drawable(__DRIdrawable *pdp)
-{
- __DRIscreen *psp;
-
- if (pdp) {
- pdp->refcount--;
- if (pdp->refcount)
- return;
-
- psp = pdp->driScreenPriv;
- (*psp->DriverAPI.DestroyBuffer)(pdp);
- if (pdp->pClipRects && pdp->pClipRects != &pdp->dri2.clipRect) {
- free(pdp->pClipRects);
- pdp->pClipRects = NULL;
- }
- if (pdp->pBackClipRects && pdp->pClipRects != &pdp->dri2.clipRect) {
- free(pdp->pBackClipRects);
- pdp->pBackClipRects = NULL;
- }
- free(pdp);
- }
-}
-
-static void
-driDestroyDrawable(__DRIdrawable *pdp)
-{
- dri_put_drawable(pdp);
-}
-
-/*@}*/
-
-
-/*****************************************************************/
-/** \name Context handling functions */
-/*****************************************************************/
-/*@{*/
-
-/**
- * Destroy the per-context private information.
- *
- * \internal
- * This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls
- * drmDestroyContext(), and finally frees \p contextPrivate.
- */
-static void
-driDestroyContext(__DRIcontext *pcp)
-{
- if (pcp) {
- (*pcp->driScreenPriv->DriverAPI.DestroyContext)(pcp);
- free(pcp);
- }
-}
-
-
-/**
- * Create the per-drawable private driver information.
- *
- * \param render_type Type of rendering target. \c GLX_RGBA is the only
- * type likely to ever be supported for direct-rendering.
- * \param shared Context with which to share textures, etc. or NULL
- *
- * \returns An opaque pointer to the per-context private information on
- * success, or \c NULL on failure.
- *
- * \internal
- * This function allocates and fills a __DRIcontextRec structure. It
- * performs some device independent initialization and passes all the
- * relevent information to __DriverAPIRec::CreateContext to create the
- * context.
- *
- */
-static __DRIcontext *
-driCreateNewContext(__DRIscreen *psp, const __DRIconfig *config,
- int render_type, __DRIcontext *shared,
- drm_context_t hwContext, void *data)
-{
- __DRIcontext *pcp;
- void * const shareCtx = (shared != NULL) ? shared->driverPrivate : NULL;
-
- pcp = malloc(sizeof *pcp);
- if (!pcp)
- return NULL;
-
- pcp->driScreenPriv = psp;
- pcp->driDrawablePriv = NULL;
- pcp->loaderPrivate = data;
-
- pcp->dri2.draw_stamp = 0;
- pcp->dri2.read_stamp = 0;
-
- pcp->hHWContext = hwContext;
-
- if ( !(*psp->DriverAPI.CreateContext)(API_OPENGL,
- &config->modes, pcp, shareCtx) ) {
- free(pcp);
- return NULL;
- }
-
- return pcp;
-}
-
-static unsigned int
-dri2GetAPIMask(__DRIscreen *screen)
-{
- return screen->api_mask;
-}
-
-static __DRIcontext *
-dri2CreateNewContextForAPI(__DRIscreen *screen, int api,
- const __DRIconfig *config,
- __DRIcontext *shared, void *data)
-{
- __DRIcontext *context;
- const __GLcontextModes *modes = (config != NULL) ? &config->modes : NULL;
- void *shareCtx = (shared != NULL) ? shared->driverPrivate : NULL;
- gl_api mesa_api;
-
- if (!(screen->api_mask & (1 << api)))
- return NULL;
-
- switch (api) {
- case __DRI_API_OPENGL:
- mesa_api = API_OPENGL;
- break;
- case __DRI_API_GLES:
- mesa_api = API_OPENGLES;
- break;
- case __DRI_API_GLES2:
- mesa_api = API_OPENGLES2;
- break;
- default:
- return NULL;
- }
-
- context = malloc(sizeof *context);
- if (!context)
- return NULL;
-
- context->driScreenPriv = screen;
- context->driDrawablePriv = NULL;
- context->loaderPrivate = data;
-
- if (!(*screen->DriverAPI.CreateContext)(mesa_api, modes,
- context, shareCtx) ) {
- free(context);
- return NULL;
- }
-
- return context;
-}
-
-
-static __DRIcontext *
-dri2CreateNewContext(__DRIscreen *screen, const __DRIconfig *config,
- __DRIcontext *shared, void *data)
-{
- return dri2CreateNewContextForAPI(screen, __DRI_API_OPENGL,
- config, shared, data);
-}
-
-static int
-driCopyContext(__DRIcontext *dest, __DRIcontext *src, unsigned long mask)
-{
- return GL_FALSE;
-}
-
-/*@}*/
-
-
-/*****************************************************************/
-/** \name Screen handling functions */
-/*****************************************************************/
-/*@{*/
-
-/**
- * Destroy the per-screen private information.
- *
- * \internal
- * This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls
- * drmClose(), and finally frees \p screenPrivate.
- */
-static void driDestroyScreen(__DRIscreen *psp)
-{
- if (psp) {
- /* No interaction with the X-server is possible at this point. This
- * routine is called after XCloseDisplay, so there is no protocol
- * stream open to the X-server anymore.
- */
-
- _mesa_destroy_shader_compiler();
-
- if (psp->DriverAPI.DestroyScreen)
- (*psp->DriverAPI.DestroyScreen)(psp);
-
- if (!psp->dri2.enabled) {
- (void)drmUnmap((drmAddress)psp->pSAREA, SAREA_MAX);
- (void)drmUnmap((drmAddress)psp->pFB, psp->fbSize);
- (void)drmCloseOnce(psp->fd);
- } else {
- driDestroyOptionCache(&psp->optionCache);
- driDestroyOptionInfo(&psp->optionInfo);
- }
-
- free(psp);
- }
-}
-
-static void
-setupLoaderExtensions(__DRIscreen *psp,
- const __DRIextension **extensions)
-{
- int i;
-
- for (i = 0; extensions[i]; i++) {
- if (strcmp(extensions[i]->name, __DRI_GET_DRAWABLE_INFO) == 0)
- psp->getDrawableInfo = (__DRIgetDrawableInfoExtension *) extensions[i];
- if (strcmp(extensions[i]->name, __DRI_DAMAGE) == 0)
- psp->damage = (__DRIdamageExtension *) extensions[i];
- if (strcmp(extensions[i]->name, __DRI_SYSTEM_TIME) == 0)
- psp->systemTime = (__DRIsystemTimeExtension *) extensions[i];
- if (strcmp(extensions[i]->name, __DRI_DRI2_LOADER) == 0)
- psp->dri2.loader = (__DRIdri2LoaderExtension *) extensions[i];
- if (strcmp(extensions[i]->name, __DRI_IMAGE_LOOKUP) == 0)
- psp->dri2.image = (__DRIimageLookupExtension *) extensions[i];
- if (strcmp(extensions[i]->name, __DRI_USE_INVALIDATE) == 0)
- psp->dri2.useInvalidate = (__DRIuseInvalidateExtension *) extensions[i];
- }
-}
-
-/**
- * This is the bootstrap function for the driver. libGL supplies all of the
- * requisite information about the system, and the driver initializes itself.
- * This routine also fills in the linked list pointed to by \c driver_modes
- * with the \c __GLcontextModes that the driver can support for windows or
- * pbuffers.
- *
- * For legacy DRI.
- *
- * \param scrn Index of the screen
- * \param ddx_version Version of the 2D DDX. This may not be meaningful for
- * all drivers.
- * \param dri_version Version of the "server-side" DRI.
- * \param drm_version Version of the kernel DRM.
- * \param frame_buffer Data describing the location and layout of the
- * framebuffer.
- * \param pSAREA Pointer to the SAREA.
- * \param fd Device handle for the DRM.
- * \param extensions ??
- * \param driver_modes Returns modes suppoted by the driver
- * \param loaderPrivate ??
- *
- * \note There is no need to check the minimum API version in this
- * function. Since the name of this function is versioned, it is
- * impossible for a loader that is too old to even load this driver.
- */
-static __DRIscreen *
-driCreateNewScreen(int scrn,
- const __DRIversion *ddx_version,
- const __DRIversion *dri_version,
- const __DRIversion *drm_version,
- const __DRIframebuffer *frame_buffer,
- drmAddress pSAREA, int fd,
- const __DRIextension **extensions,
- const __DRIconfig ***driver_modes,
- void *loaderPrivate)
-{
- static const __DRIextension *emptyExtensionList[] = { NULL };
- __DRIscreen *psp;
-
- psp = calloc(1, sizeof *psp);
- if (!psp)
- return NULL;
-
- setupLoaderExtensions(psp, extensions);
-
- /*
- ** NOT_DONE: This is used by the X server to detect when the client
- ** has died while holding the drawable lock. The client sets the
- ** drawable lock to this value.
- */
- psp->drawLockID = 1;
-
- psp->drm_version = *drm_version;
- psp->ddx_version = *ddx_version;
- psp->dri_version = *dri_version;
-
- psp->pSAREA = pSAREA;
- psp->lock = (drmLock *) &psp->pSAREA->lock;
-
- psp->pFB = frame_buffer->base;
- psp->fbSize = frame_buffer->size;
- psp->fbStride = frame_buffer->stride;
- psp->fbWidth = frame_buffer->width;
- psp->fbHeight = frame_buffer->height;
- psp->devPrivSize = frame_buffer->dev_priv_size;
- psp->pDevPriv = frame_buffer->dev_priv;
- psp->fbBPP = psp->fbStride * 8 / frame_buffer->width;
-
- psp->extensions = emptyExtensionList;
- psp->fd = fd;
- psp->myNum = scrn;
- psp->dri2.enabled = GL_FALSE;
-
- psp->DriverAPI = driDriverAPI;
- psp->api_mask = (1 << __DRI_API_OPENGL);
-
- *driver_modes = driDriverAPI.InitScreen(psp);
- if (*driver_modes == NULL) {
- free(psp);
- return NULL;
- }
-
- return psp;
-}
-
-/**
- * DRI2
- */
-static __DRIscreen *
-dri2CreateNewScreen(int scrn, int fd,
- const __DRIextension **extensions,
- const __DRIconfig ***driver_configs, void *data)
-{
- static const __DRIextension *emptyExtensionList[] = { NULL };
- __DRIscreen *psp;
- drmVersionPtr version;
-
- if (driDriverAPI.InitScreen2 == NULL)
- return NULL;
-
- psp = calloc(1, sizeof(*psp));
- if (!psp)
- return NULL;
-
- setupLoaderExtensions(psp, extensions);
-
- version = drmGetVersion(fd);
- if (version) {
- psp->drm_version.major = version->version_major;
- psp->drm_version.minor = version->version_minor;
- psp->drm_version.patch = version->version_patchlevel;
- drmFreeVersion(version);
- }
-
- psp->extensions = emptyExtensionList;
- psp->fd = fd;
- psp->myNum = scrn;
- psp->dri2.enabled = GL_TRUE;
-
- psp->DriverAPI = driDriverAPI;
- psp->api_mask = (1 << __DRI_API_OPENGL);
- *driver_configs = driDriverAPI.InitScreen2(psp);
- if (*driver_configs == NULL) {
- free(psp);
- return NULL;
- }
-
- psp->DriverAPI = driDriverAPI;
- psp->loaderPrivate = data;
-
- driParseOptionInfo(&psp->optionInfo, __dri2ConfigOptions,
- __dri2NConfigOptions);
- driParseConfigFiles(&psp->optionCache, &psp->optionInfo, psp->myNum,
- "dri2");
-
- return psp;
-}
-
-static const __DRIextension **driGetExtensions(__DRIscreen *psp)
-{
- return psp->extensions;
-}
-
-/** Core interface */
-const __DRIcoreExtension driCoreExtension = {
- { __DRI_CORE, __DRI_CORE_VERSION },
- NULL,
- driDestroyScreen,
- driGetExtensions,
- driGetConfigAttrib,
- driIndexConfigAttrib,
- NULL,
- driDestroyDrawable,
- driSwapBuffers,
- NULL,
- driCopyContext,
- driDestroyContext,
- driBindContext,
- driUnbindContext
-};
-
-/** Legacy DRI interface */
-const __DRIlegacyExtension driLegacyExtension = {
- { __DRI_LEGACY, __DRI_LEGACY_VERSION },
- driCreateNewScreen,
- driCreateNewDrawable,
- driCreateNewContext,
-};
-
-/** DRI2 interface */
-const __DRIdri2Extension driDRI2Extension = {
- { __DRI_DRI2, __DRI_DRI2_VERSION },
- dri2CreateNewScreen,
- dri2CreateNewDrawable,
- dri2CreateNewContext,
- dri2GetAPIMask,
- dri2CreateNewContextForAPI
-};
-
-const __DRI2configQueryExtension dri2ConfigQueryExtension = {
- { __DRI2_CONFIG_QUERY, __DRI2_CONFIG_QUERY_VERSION },
- dri2ConfigQueryb,
- dri2ConfigQueryi,
- dri2ConfigQueryf,
-};
-
-/**
- * Calculate amount of swap interval used between GLX buffer swaps.
- *
- * The usage value, on the range [0,max], is the fraction of total swap
- * interval time used between GLX buffer swaps is calculated.
- *
- * \f$p = t_d / (i * t_r)\f$
- *
- * Where \f$t_d\f$ is the time since the last GLX buffer swap, \f$i\f$ is the
- * swap interval (as set by \c glXSwapIntervalSGI), and \f$t_r\f$ time
- * required for a single vertical refresh period (as returned by \c
- * glXGetMscRateOML).
- *
- * See the documentation for the GLX_MESA_swap_frame_usage extension for more
- * details.
- *
- * \param dPriv Pointer to the private drawable structure.
- * \return If less than a single swap interval time period was required
- * between GLX buffer swaps, a number greater than 0 and less than
- * 1.0 is returned. If exactly one swap interval time period is
- * required, 1.0 is returned, and if more than one is required then
- * a number greater than 1.0 will be returned.
- *
- * \sa glXSwapIntervalSGI glXGetMscRateOML
- *
- * \todo Instead of caching the \c glXGetMscRateOML function pointer, would it
- * be possible to cache the sync rate?
- */
-float
-driCalculateSwapUsage( __DRIdrawable *dPriv, int64_t last_swap_ust,
- int64_t current_ust )
-{
- int32_t n;
- int32_t d;
- int interval;
- float usage = 1.0;
- __DRIscreen *psp = dPriv->driScreenPriv;
-
- if ( (*psp->systemTime->getMSCRate)(dPriv, &n, &d, dPriv->loaderPrivate) ) {
- interval = (dPriv->swap_interval != 0) ? dPriv->swap_interval : 1;
-
-
- /* We want to calculate
- * (current_UST - last_swap_UST) / (interval * us_per_refresh). We get
- * current_UST by calling __glXGetUST. last_swap_UST is stored in
- * dPriv->swap_ust. interval has already been calculated.
- *
- * The only tricky part is us_per_refresh. us_per_refresh is
- * 1000000 / MSC_rate. We know the MSC_rate is n / d. We can flip it
- * around and say us_per_refresh = 1000000 * d / n. Since this goes in
- * the denominator of the final calculation, we calculate
- * (interval * 1000000 * d) and move n into the numerator.
- */
-
- usage = (current_ust - last_swap_ust);
- usage *= n;
- usage /= (interval * d);
- usage /= 1000000.0;
- }
-
- return usage;
-}
-
-void
-dri2InvalidateDrawable(__DRIdrawable *drawable)
-{
- drawable->dri2.stamp++;
-}
-
-/*@}*/
+/**
+ * \file dri_util.c
+ * DRI utility functions.
+ *
+ * This module acts as glue between GLX and the actual hardware driver. A DRI
+ * driver doesn't really \e have to use any of this - it's optional. But, some
+ * useful stuff is done here that otherwise would have to be duplicated in most
+ * drivers.
+ *
+ * Basically, these utility functions take care of some of the dirty details of
+ * screen initialization, context creation, context binding, DRM setup, etc.
+ *
+ * These functions are compiled into each DRI driver so libGL.so knows nothing
+ * about them.
+ */
+
+
+#include <assert.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <stdio.h>
+
+#ifndef MAP_FAILED
+#define MAP_FAILED ((void *)-1)
+#endif
+
+#include "main/imports.h"
+#define None 0
+
+#include "dri_util.h"
+#include "drm_sarea.h"
+#include "utils.h"
+#include "xmlpool.h"
+#include "../glsl/glsl_parser_extras.h"
+
+PUBLIC const char __dri2ConfigOptions[] =
+ DRI_CONF_BEGIN
+ DRI_CONF_SECTION_PERFORMANCE
+ DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_1)
+ DRI_CONF_SECTION_END
+ DRI_CONF_END;
+
+static const uint __dri2NConfigOptions = 1;
+
+#ifndef GLX_OML_sync_control
+typedef GLboolean ( * PFNGLXGETMSCRATEOMLPROC) (__DRIdrawable *drawable, int32_t *numerator, int32_t *denominator);
+#endif
+
+static void dri_get_drawable(__DRIdrawable *pdp);
+static void dri_put_drawable(__DRIdrawable *pdp);
+
+/**
+ * This is just a token extension used to signal that the driver
+ * supports setting a read drawable.
+ */
+const __DRIextension driReadDrawableExtension = {
+ __DRI_READ_DRAWABLE, __DRI_READ_DRAWABLE_VERSION
+};
+
+GLint
+driIntersectArea( drm_clip_rect_t rect1, drm_clip_rect_t rect2 )
+{
+ if (rect2.x1 > rect1.x1) rect1.x1 = rect2.x1;
+ if (rect2.x2 < rect1.x2) rect1.x2 = rect2.x2;
+ if (rect2.y1 > rect1.y1) rect1.y1 = rect2.y1;
+ if (rect2.y2 < rect1.y2) rect1.y2 = rect2.y2;
+
+ if (rect1.x1 > rect1.x2 || rect1.y1 > rect1.y2) return 0;
+
+ return (rect1.x2 - rect1.x1) * (rect1.y2 - rect1.y1);
+}
+
+/*****************************************************************/
+/** \name Context (un)binding functions */
+/*****************************************************************/
+/*@{*/
+
+/**
+ * Unbind context.
+ *
+ * \param scrn the screen.
+ * \param gc context.
+ *
+ * \return \c GL_TRUE on success, or \c GL_FALSE on failure.
+ *
+ * \internal
+ * This function calls __DriverAPIRec::UnbindContext, and then decrements
+ * __DRIdrawableRec::refcount which must be non-zero for a successful
+ * return.
+ *
+ * While casting the opaque private pointers associated with the parameters
+ * into their respective real types it also assures they are not \c NULL.
+ */
+static int driUnbindContext(__DRIcontext *pcp)
+{
+ __DRIscreen *psp;
+ __DRIdrawable *pdp;
+ __DRIdrawable *prp;
+
+ /*
+ ** Assume error checking is done properly in glXMakeCurrent before
+ ** calling driUnbindContext.
+ */
+
+ if (pcp == NULL)
+ return GL_FALSE;
+
+ psp = pcp->driScreenPriv;
+ pdp = pcp->driDrawablePriv;
+ prp = pcp->driReadablePriv;
+
+ /* already unbound */
+ if (!pdp && !prp)
+ return GL_TRUE;
+ /* Let driver unbind drawable from context */
+ (*psp->DriverAPI.UnbindContext)(pcp);
+
+ assert(pdp);
+ if (pdp->refcount == 0) {
+ /* ERROR!!! */
+ return GL_FALSE;
+ }
+
+ dri_put_drawable(pdp);
+
+ if (prp != pdp) {
+ if (prp->refcount == 0) {
+ /* ERROR!!! */
+ return GL_FALSE;
+ }
+
+ dri_put_drawable(prp);
+ }
+
+
+ /* XXX this is disabled so that if we call SwapBuffers on an unbound
+ * window we can determine the last context bound to the window and
+ * use that context's lock. (BrianP, 2-Dec-2000)
+ */
+ pcp->driDrawablePriv = pcp->driReadablePriv = NULL;
+
+ return GL_TRUE;
+}
+
+/**
+ * This function takes both a read buffer and a draw buffer. This is needed
+ * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
+ * function.
+ */
+static int driBindContext(__DRIcontext *pcp,
+ __DRIdrawable *pdp,
+ __DRIdrawable *prp)
+{
+ __DRIscreen *psp = NULL;
+
+ /*
+ ** Assume error checking is done properly in glXMakeCurrent before
+ ** calling driUnbindContext.
+ */
+
+ if (!pcp)
+ return GL_FALSE;
+
+ /* Bind the drawable to the context */
+ psp = pcp->driScreenPriv;
+ pcp->driDrawablePriv = pdp;
+ pcp->driReadablePriv = prp;
+ if (pdp) {
+ pdp->driContextPriv = pcp;
+ dri_get_drawable(pdp);
+ }
+ if (prp && pdp != prp) {
+ dri_get_drawable(prp);
+ }
+
+ /*
+ ** Now that we have a context associated with this drawable, we can
+ ** initialize the drawable information if has not been done before.
+ */
+
+ if (!psp->dri2.enabled) {
+ if (pdp && !pdp->pStamp) {
+ DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
+ __driUtilUpdateDrawableInfo(pdp);
+ DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
+ }
+ if (prp && pdp != prp && !prp->pStamp) {
+ DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
+ __driUtilUpdateDrawableInfo(prp);
+ DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
+ }
+ }
+
+ /* Call device-specific MakeCurrent */
+ return (*psp->DriverAPI.MakeCurrent)(pcp, pdp, prp);
+}
+
+/*@}*/
+
+
+/*****************************************************************/
+/** \name Drawable handling functions */
+/*****************************************************************/
+/*@{*/
+
+/**
+ * Update private drawable information.
+ *
+ * \param pdp pointer to the private drawable information to update.
+ *
+ * This function basically updates the __DRIdrawable struct's
+ * cliprect information by calling \c __DRIinterfaceMethods::getDrawableInfo.
+ * This is usually called by the DRI_VALIDATE_DRAWABLE_INFO macro which
+ * compares the __DRIdrwablePrivate pStamp and lastStamp values. If
+ * the values are different that means we have to update the clipping
+ * info.
+ */
+void
+__driUtilUpdateDrawableInfo(__DRIdrawable *pdp)
+{
+ __DRIscreen *psp = pdp->driScreenPriv;
+ __DRIcontext *pcp = pdp->driContextPriv;
+
+ if (!pcp
+ || ((pdp != pcp->driDrawablePriv) && (pdp != pcp->driReadablePriv))) {
+ /* ERROR!!!
+ * ...but we must ignore it. There can be many contexts bound to a
+ * drawable.
+ */
+ }
+
+ if (pdp->pClipRects) {
+ free(pdp->pClipRects);
+ pdp->pClipRects = NULL;
+ }
+
+ if (pdp->pBackClipRects) {
+ free(pdp->pBackClipRects);
+ pdp->pBackClipRects = NULL;
+ }
+
+ DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
+
+ if (! (*psp->getDrawableInfo->getDrawableInfo)(pdp,
+ &pdp->index, &pdp->lastStamp,
+ &pdp->x, &pdp->y, &pdp->w, &pdp->h,
+ &pdp->numClipRects, &pdp->pClipRects,
+ &pdp->backX,
+ &pdp->backY,
+ &pdp->numBackClipRects,
+ &pdp->pBackClipRects,
+ pdp->loaderPrivate)) {
+ /* Error -- eg the window may have been destroyed. Keep going
+ * with no cliprects.
+ */
+ pdp->pStamp = &pdp->lastStamp; /* prevent endless loop */
+ pdp->numClipRects = 0;
+ pdp->pClipRects = NULL;
+ pdp->numBackClipRects = 0;
+ pdp->pBackClipRects = NULL;
+ }
+ else
+ pdp->pStamp = &(psp->pSAREA->drawableTable[pdp->index].stamp);
+
+ DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
+}
+
+/*@}*/
+
+/*****************************************************************/
+/** \name GLX callbacks */
+/*****************************************************************/
+/*@{*/
+
+static void driReportDamage(__DRIdrawable *pdp,
+ struct drm_clip_rect *pClipRects, int numClipRects)
+{
+ __DRIscreen *psp = pdp->driScreenPriv;
+
+ /* Check that we actually have the new damage report method */
+ if (psp->damage) {
+ /* Report the damage. Currently, all our drivers draw
+ * directly to the front buffer, so we report the damage there
+ * rather than to the backing storein (if any).
+ */
+ (*psp->damage->reportDamage)(pdp,
+ pdp->x, pdp->y,
+ pClipRects, numClipRects,
+ GL_TRUE, pdp->loaderPrivate);
+ }
+}
+
+
+/**
+ * Swap buffers.
+ *
+ * \param drawablePrivate opaque pointer to the per-drawable private info.
+ *
+ * \internal
+ * This function calls __DRIdrawable::swapBuffers.
+ *
+ * Is called directly from glXSwapBuffers().
+ */
+static void driSwapBuffers(__DRIdrawable *dPriv)
+{
+ __DRIscreen *psp = dPriv->driScreenPriv;
+ drm_clip_rect_t *rects;
+ int i;
+
+ psp->DriverAPI.SwapBuffers(dPriv);
+
+ if (!dPriv->numClipRects)
+ return;
+
+ rects = malloc(sizeof(*rects) * dPriv->numClipRects);
+
+ if (!rects)
+ return;
+
+ for (i = 0; i < dPriv->numClipRects; i++) {
+ rects[i].x1 = dPriv->pClipRects[i].x1 - dPriv->x;
+ rects[i].y1 = dPriv->pClipRects[i].y1 - dPriv->y;
+ rects[i].x2 = dPriv->pClipRects[i].x2 - dPriv->x;
+ rects[i].y2 = dPriv->pClipRects[i].y2 - dPriv->y;
+ }
+
+ driReportDamage(dPriv, rects, dPriv->numClipRects);
+ free(rects);
+}
+
+static int driDrawableGetMSC( __DRIscreen *sPriv, __DRIdrawable *dPriv,
+ int64_t *msc )
+{
+ return sPriv->DriverAPI.GetDrawableMSC(sPriv, dPriv, msc);
+}
+
+
+static int driWaitForMSC(__DRIdrawable *dPriv, int64_t target_msc,
+ int64_t divisor, int64_t remainder,
+ int64_t * msc, int64_t * sbc)
+{
+ __DRIswapInfo sInfo;
+ int status;
+
+ status = dPriv->driScreenPriv->DriverAPI.WaitForMSC( dPriv, target_msc,
+ divisor, remainder,
+ msc );
+
+ /* GetSwapInfo() may not be provided by the driver if GLX_SGI_video_sync
+ * is supported but GLX_OML_sync_control is not. Therefore, don't return
+ * an error value if GetSwapInfo() is not implemented.
+ */
+ if ( status == 0
+ && dPriv->driScreenPriv->DriverAPI.GetSwapInfo ) {
+ status = dPriv->driScreenPriv->DriverAPI.GetSwapInfo( dPriv, & sInfo );
+ *sbc = sInfo.swap_count;
+ }
+
+ return status;
+}
+
+
+const __DRImediaStreamCounterExtension driMediaStreamCounterExtension = {
+ { __DRI_MEDIA_STREAM_COUNTER, __DRI_MEDIA_STREAM_COUNTER_VERSION },
+ driWaitForMSC,
+ driDrawableGetMSC,
+};
+
+
+static void driCopySubBuffer(__DRIdrawable *dPriv,
+ int x, int y, int w, int h)
+{
+ drm_clip_rect_t rect;
+
+ rect.x1 = x;
+ rect.y1 = dPriv->h - y - h;
+ rect.x2 = x + w;
+ rect.y2 = rect.y1 + h;
+ driReportDamage(dPriv, &rect, 1);
+
+ dPriv->driScreenPriv->DriverAPI.CopySubBuffer(dPriv, x, y, w, h);
+}
+
+const __DRIcopySubBufferExtension driCopySubBufferExtension = {
+ { __DRI_COPY_SUB_BUFFER, __DRI_COPY_SUB_BUFFER_VERSION },
+ driCopySubBuffer
+};
+
+static void driSetSwapInterval(__DRIdrawable *dPriv, unsigned int interval)
+{
+ dPriv->swap_interval = interval;
+}
+
+static unsigned int driGetSwapInterval(__DRIdrawable *dPriv)
+{
+ return dPriv->swap_interval;
+}
+
+const __DRIswapControlExtension driSwapControlExtension = {
+ { __DRI_SWAP_CONTROL, __DRI_SWAP_CONTROL_VERSION },
+ driSetSwapInterval,
+ driGetSwapInterval
+};
+
+
+/**
+ * This is called via __DRIscreenRec's createNewDrawable pointer.
+ */
+static __DRIdrawable *
+driCreateNewDrawable(__DRIscreen *psp, const __DRIconfig *config,
+ drm_drawable_t hwDrawable, int renderType,
+ const int *attrs, void *data)
+{
+ __DRIdrawable *pdp;
+
+ /* Since pbuffers are not yet supported, no drawable attributes are
+ * supported either.
+ */
+ (void) attrs;
+
+ pdp = malloc(sizeof *pdp);
+ if (!pdp) {
+ return NULL;
+ }
+
+ pdp->driContextPriv = NULL;
+ pdp->loaderPrivate = data;
+ pdp->hHWDrawable = hwDrawable;
+ pdp->refcount = 1;
+ pdp->pStamp = NULL;
+ pdp->lastStamp = 0;
+ pdp->index = 0;
+ pdp->x = 0;
+ pdp->y = 0;
+ pdp->w = 0;
+ pdp->h = 0;
+ pdp->numClipRects = 0;
+ pdp->numBackClipRects = 0;
+ pdp->pClipRects = NULL;
+ pdp->pBackClipRects = NULL;
+ pdp->vblSeq = 0;
+ pdp->vblFlags = 0;
+
+ pdp->driScreenPriv = psp;
+
+ if (!(*psp->DriverAPI.CreateBuffer)(psp, pdp, &config->modes, 0)) {
+ free(pdp);
+ return NULL;
+ }
+
+ pdp->msc_base = 0;
+
+ /* This special default value is replaced with the configured
+ * default value when the drawable is first bound to a direct
+ * rendering context.
+ */
+ pdp->swap_interval = (unsigned)-1;
+
+ return pdp;
+}
+
+
+static __DRIdrawable *
+dri2CreateNewDrawable(__DRIscreen *screen,
+ const __DRIconfig *config,
+ void *loaderPrivate)
+{
+ __DRIdrawable *pdraw;
+
+ pdraw = driCreateNewDrawable(screen, config, 0, 0, NULL, loaderPrivate);
+ if (!pdraw)
+ return NULL;
+
+ pdraw->pClipRects = &pdraw->dri2.clipRect;
+ pdraw->pBackClipRects = &pdraw->dri2.clipRect;
+
+ pdraw->pStamp = &pdraw->dri2.stamp;
+ *pdraw->pStamp = pdraw->lastStamp + 1;
+
+ return pdraw;
+}
+
+static int
+dri2ConfigQueryb(__DRIscreen *screen, const char *var, GLboolean *val)
+{
+ if (!driCheckOption(&screen->optionCache, var, DRI_BOOL))
+ return -1;
+
+ *val = driQueryOptionb(&screen->optionCache, var);
+
+ return 0;
+}
+
+static int
+dri2ConfigQueryi(__DRIscreen *screen, const char *var, GLint *val)
+{
+ if (!driCheckOption(&screen->optionCache, var, DRI_INT) &&
+ !driCheckOption(&screen->optionCache, var, DRI_ENUM))
+ return -1;
+
+ *val = driQueryOptioni(&screen->optionCache, var);
+
+ return 0;
+}
+
+static int
+dri2ConfigQueryf(__DRIscreen *screen, const char *var, GLfloat *val)
+{
+ if (!driCheckOption(&screen->optionCache, var, DRI_FLOAT))
+ return -1;
+
+ *val = driQueryOptionf(&screen->optionCache, var);
+
+ return 0;
+}
+
+
+static void dri_get_drawable(__DRIdrawable *pdp)
+{
+ pdp->refcount++;
+}
+
+static void dri_put_drawable(__DRIdrawable *pdp)
+{
+ __DRIscreen *psp;
+
+ if (pdp) {
+ pdp->refcount--;
+ if (pdp->refcount)
+ return;
+
+ psp = pdp->driScreenPriv;
+ (*psp->DriverAPI.DestroyBuffer)(pdp);
+ if (pdp->pClipRects && pdp->pClipRects != &pdp->dri2.clipRect) {
+ free(pdp->pClipRects);
+ pdp->pClipRects = NULL;
+ }
+ if (pdp->pBackClipRects && pdp->pClipRects != &pdp->dri2.clipRect) {
+ free(pdp->pBackClipRects);
+ pdp->pBackClipRects = NULL;
+ }
+ free(pdp);
+ }
+}
+
+static void
+driDestroyDrawable(__DRIdrawable *pdp)
+{
+ dri_put_drawable(pdp);
+}
+
+/*@}*/
+
+
+/*****************************************************************/
+/** \name Context handling functions */
+/*****************************************************************/
+/*@{*/
+
+/**
+ * Destroy the per-context private information.
+ *
+ * \internal
+ * This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls
+ * drmDestroyContext(), and finally frees \p contextPrivate.
+ */
+static void
+driDestroyContext(__DRIcontext *pcp)
+{
+ if (pcp) {
+ (*pcp->driScreenPriv->DriverAPI.DestroyContext)(pcp);
+ free(pcp);
+ }
+}
+
+
+/**
+ * Create the per-drawable private driver information.
+ *
+ * \param render_type Type of rendering target. \c GLX_RGBA is the only
+ * type likely to ever be supported for direct-rendering.
+ * \param shared Context with which to share textures, etc. or NULL
+ *
+ * \returns An opaque pointer to the per-context private information on
+ * success, or \c NULL on failure.
+ *
+ * \internal
+ * This function allocates and fills a __DRIcontextRec structure. It
+ * performs some device independent initialization and passes all the
+ * relevent information to __DriverAPIRec::CreateContext to create the
+ * context.
+ *
+ */
+static __DRIcontext *
+driCreateNewContext(__DRIscreen *psp, const __DRIconfig *config,
+ int render_type, __DRIcontext *shared,
+ drm_context_t hwContext, void *data)
+{
+ __DRIcontext *pcp;
+ void * const shareCtx = (shared != NULL) ? shared->driverPrivate : NULL;
+
+ pcp = malloc(sizeof *pcp);
+ if (!pcp)
+ return NULL;
+
+ pcp->driScreenPriv = psp;
+ pcp->driDrawablePriv = NULL;
+ pcp->loaderPrivate = data;
+
+ pcp->dri2.draw_stamp = 0;
+ pcp->dri2.read_stamp = 0;
+
+ pcp->hHWContext = hwContext;
+
+ if ( !(*psp->DriverAPI.CreateContext)(API_OPENGL,
+ &config->modes, pcp, shareCtx) ) {
+ free(pcp);
+ return NULL;
+ }
+
+ return pcp;
+}
+
+static unsigned int
+dri2GetAPIMask(__DRIscreen *screen)
+{
+ return screen->api_mask;
+}
+
+static __DRIcontext *
+dri2CreateNewContextForAPI(__DRIscreen *screen, int api,
+ const __DRIconfig *config,
+ __DRIcontext *shared, void *data)
+{
+ __DRIcontext *context;
+ const struct gl_config *modes = (config != NULL) ? &config->modes : NULL;
+ void *shareCtx = (shared != NULL) ? shared->driverPrivate : NULL;
+ gl_api mesa_api;
+
+ if (!(screen->api_mask & (1 << api)))
+ return NULL;
+
+ switch (api) {
+ case __DRI_API_OPENGL:
+ mesa_api = API_OPENGL;
+ break;
+ case __DRI_API_GLES:
+ mesa_api = API_OPENGLES;
+ break;
+ case __DRI_API_GLES2:
+ mesa_api = API_OPENGLES2;
+ break;
+ default:
+ return NULL;
+ }
+
+ context = malloc(sizeof *context);
+ if (!context)
+ return NULL;
+
+ context->driScreenPriv = screen;
+ context->driDrawablePriv = NULL;
+ context->loaderPrivate = data;
+
+ if (!(*screen->DriverAPI.CreateContext)(mesa_api, modes,
+ context, shareCtx) ) {
+ free(context);
+ return NULL;
+ }
+
+ return context;
+}
+
+
+static __DRIcontext *
+dri2CreateNewContext(__DRIscreen *screen, const __DRIconfig *config,
+ __DRIcontext *shared, void *data)
+{
+ return dri2CreateNewContextForAPI(screen, __DRI_API_OPENGL,
+ config, shared, data);
+}
+
+static int
+driCopyContext(__DRIcontext *dest, __DRIcontext *src, unsigned long mask)
+{
+ return GL_FALSE;
+}
+
+/*@}*/
+
+
+/*****************************************************************/
+/** \name Screen handling functions */
+/*****************************************************************/
+/*@{*/
+
+/**
+ * Destroy the per-screen private information.
+ *
+ * \internal
+ * This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls
+ * drmClose(), and finally frees \p screenPrivate.
+ */
+static void driDestroyScreen(__DRIscreen *psp)
+{
+ if (psp) {
+ /* No interaction with the X-server is possible at this point. This
+ * routine is called after XCloseDisplay, so there is no protocol
+ * stream open to the X-server anymore.
+ */
+
+ _mesa_destroy_shader_compiler();
+
+ if (psp->DriverAPI.DestroyScreen)
+ (*psp->DriverAPI.DestroyScreen)(psp);
+
+ if (!psp->dri2.enabled) {
+ (void)drmUnmap((drmAddress)psp->pSAREA, SAREA_MAX);
+ (void)drmUnmap((drmAddress)psp->pFB, psp->fbSize);
+ (void)drmCloseOnce(psp->fd);
+ } else {
+ driDestroyOptionCache(&psp->optionCache);
+ driDestroyOptionInfo(&psp->optionInfo);
+ }
+
+ free(psp);
+ }
+}
+
+static void
+setupLoaderExtensions(__DRIscreen *psp,
+ const __DRIextension **extensions)
+{
+ int i;
+
+ for (i = 0; extensions[i]; i++) {
+ if (strcmp(extensions[i]->name, __DRI_GET_DRAWABLE_INFO) == 0)
+ psp->getDrawableInfo = (__DRIgetDrawableInfoExtension *) extensions[i];
+ if (strcmp(extensions[i]->name, __DRI_DAMAGE) == 0)
+ psp->damage = (__DRIdamageExtension *) extensions[i];
+ if (strcmp(extensions[i]->name, __DRI_SYSTEM_TIME) == 0)
+ psp->systemTime = (__DRIsystemTimeExtension *) extensions[i];
+ if (strcmp(extensions[i]->name, __DRI_DRI2_LOADER) == 0)
+ psp->dri2.loader = (__DRIdri2LoaderExtension *) extensions[i];
+ if (strcmp(extensions[i]->name, __DRI_IMAGE_LOOKUP) == 0)
+ psp->dri2.image = (__DRIimageLookupExtension *) extensions[i];
+ if (strcmp(extensions[i]->name, __DRI_USE_INVALIDATE) == 0)
+ psp->dri2.useInvalidate = (__DRIuseInvalidateExtension *) extensions[i];
+ }
+}
+
+/**
+ * This is the bootstrap function for the driver. libGL supplies all of the
+ * requisite information about the system, and the driver initializes itself.
+ * This routine also fills in the linked list pointed to by \c driver_modes
+ * with the \c struct gl_config that the driver can support for windows or
+ * pbuffers.
+ *
+ * For legacy DRI.
+ *
+ * \param scrn Index of the screen
+ * \param ddx_version Version of the 2D DDX. This may not be meaningful for
+ * all drivers.
+ * \param dri_version Version of the "server-side" DRI.
+ * \param drm_version Version of the kernel DRM.
+ * \param frame_buffer Data describing the location and layout of the
+ * framebuffer.
+ * \param pSAREA Pointer to the SAREA.
+ * \param fd Device handle for the DRM.
+ * \param extensions ??
+ * \param driver_modes Returns modes suppoted by the driver
+ * \param loaderPrivate ??
+ *
+ * \note There is no need to check the minimum API version in this
+ * function. Since the name of this function is versioned, it is
+ * impossible for a loader that is too old to even load this driver.
+ */
+static __DRIscreen *
+driCreateNewScreen(int scrn,
+ const __DRIversion *ddx_version,
+ const __DRIversion *dri_version,
+ const __DRIversion *drm_version,
+ const __DRIframebuffer *frame_buffer,
+ drmAddress pSAREA, int fd,
+ const __DRIextension **extensions,
+ const __DRIconfig ***driver_modes,
+ void *loaderPrivate)
+{
+ static const __DRIextension *emptyExtensionList[] = { NULL };
+ __DRIscreen *psp;
+
+ psp = calloc(1, sizeof *psp);
+ if (!psp)
+ return NULL;
+
+ setupLoaderExtensions(psp, extensions);
+
+ /*
+ ** NOT_DONE: This is used by the X server to detect when the client
+ ** has died while holding the drawable lock. The client sets the
+ ** drawable lock to this value.
+ */
+ psp->drawLockID = 1;
+
+ psp->drm_version = *drm_version;
+ psp->ddx_version = *ddx_version;
+ psp->dri_version = *dri_version;
+
+ psp->pSAREA = pSAREA;
+ psp->lock = (drmLock *) &psp->pSAREA->lock;
+
+ psp->pFB = frame_buffer->base;
+ psp->fbSize = frame_buffer->size;
+ psp->fbStride = frame_buffer->stride;
+ psp->fbWidth = frame_buffer->width;
+ psp->fbHeight = frame_buffer->height;
+ psp->devPrivSize = frame_buffer->dev_priv_size;
+ psp->pDevPriv = frame_buffer->dev_priv;
+ psp->fbBPP = psp->fbStride * 8 / frame_buffer->width;
+
+ psp->extensions = emptyExtensionList;
+ psp->fd = fd;
+ psp->myNum = scrn;
+ psp->dri2.enabled = GL_FALSE;
+
+ psp->DriverAPI = driDriverAPI;
+ psp->api_mask = (1 << __DRI_API_OPENGL);
+
+ *driver_modes = driDriverAPI.InitScreen(psp);
+ if (*driver_modes == NULL) {
+ free(psp);
+ return NULL;
+ }
+
+ return psp;
+}
+
+/**
+ * DRI2
+ */
+static __DRIscreen *
+dri2CreateNewScreen(int scrn, int fd,
+ const __DRIextension **extensions,
+ const __DRIconfig ***driver_configs, void *data)
+{
+ static const __DRIextension *emptyExtensionList[] = { NULL };
+ __DRIscreen *psp;
+ drmVersionPtr version;
+
+ if (driDriverAPI.InitScreen2 == NULL)
+ return NULL;
+
+ psp = calloc(1, sizeof(*psp));
+ if (!psp)
+ return NULL;
+
+ setupLoaderExtensions(psp, extensions);
+
+ version = drmGetVersion(fd);
+ if (version) {
+ psp->drm_version.major = version->version_major;
+ psp->drm_version.minor = version->version_minor;
+ psp->drm_version.patch = version->version_patchlevel;
+ drmFreeVersion(version);
+ }
+
+ psp->extensions = emptyExtensionList;
+ psp->fd = fd;
+ psp->myNum = scrn;
+ psp->dri2.enabled = GL_TRUE;
+
+ psp->DriverAPI = driDriverAPI;
+ psp->api_mask = (1 << __DRI_API_OPENGL);
+ *driver_configs = driDriverAPI.InitScreen2(psp);
+ if (*driver_configs == NULL) {
+ free(psp);
+ return NULL;
+ }
+
+ psp->DriverAPI = driDriverAPI;
+ psp->loaderPrivate = data;
+
+ driParseOptionInfo(&psp->optionInfo, __dri2ConfigOptions,
+ __dri2NConfigOptions);
+ driParseConfigFiles(&psp->optionCache, &psp->optionInfo, psp->myNum,
+ "dri2");
+
+ return psp;
+}
+
+static const __DRIextension **driGetExtensions(__DRIscreen *psp)
+{
+ return psp->extensions;
+}
+
+/** Core interface */
+const __DRIcoreExtension driCoreExtension = {
+ { __DRI_CORE, __DRI_CORE_VERSION },
+ NULL,
+ driDestroyScreen,
+ driGetExtensions,
+ driGetConfigAttrib,
+ driIndexConfigAttrib,
+ NULL,
+ driDestroyDrawable,
+ driSwapBuffers,
+ NULL,
+ driCopyContext,
+ driDestroyContext,
+ driBindContext,
+ driUnbindContext
+};
+
+/** Legacy DRI interface */
+const __DRIlegacyExtension driLegacyExtension = {
+ { __DRI_LEGACY, __DRI_LEGACY_VERSION },
+ driCreateNewScreen,
+ driCreateNewDrawable,
+ driCreateNewContext,
+};
+
+/** DRI2 interface */
+const __DRIdri2Extension driDRI2Extension = {
+ { __DRI_DRI2, __DRI_DRI2_VERSION },
+ dri2CreateNewScreen,
+ dri2CreateNewDrawable,
+ dri2CreateNewContext,
+ dri2GetAPIMask,
+ dri2CreateNewContextForAPI
+};
+
+const __DRI2configQueryExtension dri2ConfigQueryExtension = {
+ { __DRI2_CONFIG_QUERY, __DRI2_CONFIG_QUERY_VERSION },
+ dri2ConfigQueryb,
+ dri2ConfigQueryi,
+ dri2ConfigQueryf,
+};
+
+/**
+ * Calculate amount of swap interval used between GLX buffer swaps.
+ *
+ * The usage value, on the range [0,max], is the fraction of total swap
+ * interval time used between GLX buffer swaps is calculated.
+ *
+ * \f$p = t_d / (i * t_r)\f$
+ *
+ * Where \f$t_d\f$ is the time since the last GLX buffer swap, \f$i\f$ is the
+ * swap interval (as set by \c glXSwapIntervalSGI), and \f$t_r\f$ time
+ * required for a single vertical refresh period (as returned by \c
+ * glXGetMscRateOML).
+ *
+ * See the documentation for the GLX_MESA_swap_frame_usage extension for more
+ * details.
+ *
+ * \param dPriv Pointer to the private drawable structure.
+ * \return If less than a single swap interval time period was required
+ * between GLX buffer swaps, a number greater than 0 and less than
+ * 1.0 is returned. If exactly one swap interval time period is
+ * required, 1.0 is returned, and if more than one is required then
+ * a number greater than 1.0 will be returned.
+ *
+ * \sa glXSwapIntervalSGI glXGetMscRateOML
+ *
+ * \todo Instead of caching the \c glXGetMscRateOML function pointer, would it
+ * be possible to cache the sync rate?
+ */
+float
+driCalculateSwapUsage( __DRIdrawable *dPriv, int64_t last_swap_ust,
+ int64_t current_ust )
+{
+ int32_t n;
+ int32_t d;
+ int interval;
+ float usage = 1.0;
+ __DRIscreen *psp = dPriv->driScreenPriv;
+
+ if ( (*psp->systemTime->getMSCRate)(dPriv, &n, &d, dPriv->loaderPrivate) ) {
+ interval = (dPriv->swap_interval != 0) ? dPriv->swap_interval : 1;
+
+
+ /* We want to calculate
+ * (current_UST - last_swap_UST) / (interval * us_per_refresh). We get
+ * current_UST by calling __glXGetUST. last_swap_UST is stored in
+ * dPriv->swap_ust. interval has already been calculated.
+ *
+ * The only tricky part is us_per_refresh. us_per_refresh is
+ * 1000000 / MSC_rate. We know the MSC_rate is n / d. We can flip it
+ * around and say us_per_refresh = 1000000 * d / n. Since this goes in
+ * the denominator of the final calculation, we calculate
+ * (interval * 1000000 * d) and move n into the numerator.
+ */
+
+ usage = (current_ust - last_swap_ust);
+ usage *= n;
+ usage /= (interval * d);
+ usage /= 1000000.0;
+ }
+
+ return usage;
+}
+
+void
+dri2InvalidateDrawable(__DRIdrawable *drawable)
+{
+ drawable->dri2.stamp++;
+}
+
+/*@}*/
diff --git a/mesalib/src/mesa/drivers/dri/common/dri_util.h b/mesalib/src/mesa/drivers/dri/common/dri_util.h
index 785beacd8..b6f04993e 100644
--- a/mesalib/src/mesa/drivers/dri/common/dri_util.h
+++ b/mesalib/src/mesa/drivers/dri/common/dri_util.h
@@ -1,558 +1,557 @@
-/*
- * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file dri_util.h
- * DRI utility functions definitions.
- *
- * This module acts as glue between GLX and the actual hardware driver. A DRI
- * driver doesn't really \e have to use any of this - it's optional. But, some
- * useful stuff is done here that otherwise would have to be duplicated in most
- * drivers.
- *
- * Basically, these utility functions take care of some of the dirty details of
- * screen initialization, context creation, context binding, DRM setup, etc.
- *
- * These functions are compiled into each DRI driver so libGL.so knows nothing
- * about them.
- *
- * \sa dri_util.c.
- *
- * \author Kevin E. Martin <kevin@precisioninsight.com>
- * \author Brian Paul <brian@precisioninsight.com>
- */
-
-#ifndef _DRI_UTIL_H_
-#define _DRI_UTIL_H_
-
-#include <GL/gl.h>
-#include <drm.h>
-#include <drm_sarea.h>
-#include <xf86drm.h>
-#include "xmlconfig.h"
-#include "main/glheader.h"
-#include "main/mtypes.h"
-#include "GL/internal/glcore.h"
-#include "GL/internal/dri_interface.h"
-
-#define GLX_BAD_CONTEXT 5
-
-typedef struct __DRIswapInfoRec __DRIswapInfo;
-
-/**
- * Extensions.
- */
-extern const __DRIlegacyExtension driLegacyExtension;
-extern const __DRIcoreExtension driCoreExtension;
-extern const __DRIdri2Extension driDRI2Extension;
-extern const __DRIextension driReadDrawableExtension;
-extern const __DRIcopySubBufferExtension driCopySubBufferExtension;
-extern const __DRIswapControlExtension driSwapControlExtension;
-extern const __DRImediaStreamCounterExtension driMediaStreamCounterExtension;
-extern const __DRI2configQueryExtension dri2ConfigQueryExtension;
-
-/**
- * Used by DRI_VALIDATE_DRAWABLE_INFO
- */
-#define DRI_VALIDATE_DRAWABLE_INFO_ONCE(pDrawPriv) \
- do { \
- if (*(pDrawPriv->pStamp) != pDrawPriv->lastStamp) { \
- __driUtilUpdateDrawableInfo(pDrawPriv); \
- } \
- } while (0)
-
-
-/**
- * Utility macro to validate the drawable information.
- *
- * See __DRIdrawable::pStamp and __DRIdrawable::lastStamp.
- */
-#define DRI_VALIDATE_DRAWABLE_INFO(psp, pdp) \
-do { \
- while (*(pdp->pStamp) != pdp->lastStamp) { \
- register unsigned int hwContext = psp->pSAREA->lock.lock & \
- ~(DRM_LOCK_HELD | DRM_LOCK_CONT); \
- DRM_UNLOCK(psp->fd, &psp->pSAREA->lock, hwContext); \
- \
- DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID); \
- DRI_VALIDATE_DRAWABLE_INFO_ONCE(pdp); \
- DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID); \
- \
- DRM_LIGHT_LOCK(psp->fd, &psp->pSAREA->lock, hwContext); \
- } \
-} while (0)
-
-/**
- * Same as above, but for two drawables simultaneously.
- *
- */
-
-#define DRI_VALIDATE_TWO_DRAWABLES_INFO(psp, pdp, prp) \
-do { \
- while (*((pdp)->pStamp) != (pdp)->lastStamp || \
- *((prp)->pStamp) != (prp)->lastStamp) { \
- register unsigned int hwContext = (psp)->pSAREA->lock.lock & \
- ~(DRM_LOCK_HELD | DRM_LOCK_CONT); \
- DRM_UNLOCK((psp)->fd, &(psp)->pSAREA->lock, hwContext); \
- \
- DRM_SPINLOCK(&(psp)->pSAREA->drawable_lock, (psp)->drawLockID); \
- DRI_VALIDATE_DRAWABLE_INFO_ONCE(pdp); \
- DRI_VALIDATE_DRAWABLE_INFO_ONCE(prp); \
- DRM_SPINUNLOCK(&(psp)->pSAREA->drawable_lock, (psp)->drawLockID); \
- \
- DRM_LIGHT_LOCK((psp)->fd, &(psp)->pSAREA->lock, hwContext); \
- } \
-} while (0)
-
-
-/**
- * Driver callback functions.
- *
- * Each DRI driver must have one of these structures with all the pointers set
- * to appropriate functions within the driver.
- *
- * When glXCreateContext() is called, for example, it'll call a helper function
- * dri_util.c which in turn will jump through the \a CreateContext pointer in
- * this structure.
- */
-struct __DriverAPIRec {
- const __DRIconfig **(*InitScreen) (__DRIscreen * priv);
-
- /**
- * Screen destruction callback
- */
- void (*DestroyScreen)(__DRIscreen *driScrnPriv);
-
- /**
- * Context creation callback
- */
- GLboolean (*CreateContext)(gl_api api,
- const __GLcontextModes *glVis,
- __DRIcontext *driContextPriv,
- void *sharedContextPrivate);
-
- /**
- * Context destruction callback
- */
- void (*DestroyContext)(__DRIcontext *driContextPriv);
-
- /**
- * Buffer (drawable) creation callback
- */
- GLboolean (*CreateBuffer)(__DRIscreen *driScrnPriv,
- __DRIdrawable *driDrawPriv,
- const __GLcontextModes *glVis,
- GLboolean pixmapBuffer);
-
- /**
- * Buffer (drawable) destruction callback
- */
- void (*DestroyBuffer)(__DRIdrawable *driDrawPriv);
-
- /**
- * Buffer swapping callback
- */
- void (*SwapBuffers)(__DRIdrawable *driDrawPriv);
-
- /**
- * Context activation callback
- */
- GLboolean (*MakeCurrent)(__DRIcontext *driContextPriv,
- __DRIdrawable *driDrawPriv,
- __DRIdrawable *driReadPriv);
-
- /**
- * Context unbinding callback
- */
- GLboolean (*UnbindContext)(__DRIcontext *driContextPriv);
-
- /**
- * Retrieves statistics about buffer swap operations. Required if
- * GLX_OML_sync_control or GLX_MESA_swap_frame_usage is supported.
- */
- int (*GetSwapInfo)( __DRIdrawable *dPriv, __DRIswapInfo * sInfo );
-
-
- /**
- * These are required if GLX_OML_sync_control is supported.
- */
- /*@{*/
- int (*WaitForMSC)( __DRIdrawable *priv, int64_t target_msc,
- int64_t divisor, int64_t remainder,
- int64_t * msc );
- int (*WaitForSBC)( __DRIdrawable *priv, int64_t target_sbc,
- int64_t * msc, int64_t * sbc );
-
- int64_t (*SwapBuffersMSC)( __DRIdrawable *priv, int64_t target_msc,
- int64_t divisor, int64_t remainder );
- /*@}*/
- void (*CopySubBuffer)(__DRIdrawable *driDrawPriv,
- int x, int y, int w, int h);
-
- /**
- * New version of GetMSC so we can pass drawable data to the low
- * level DRM driver (e.g. pipe info). Required if
- * GLX_SGI_video_sync or GLX_OML_sync_control is supported.
- */
- int (*GetDrawableMSC) ( __DRIscreen * priv,
- __DRIdrawable *drawablePrivate,
- int64_t *count);
-
-
-
- /* DRI2 Entry point */
- const __DRIconfig **(*InitScreen2) (__DRIscreen * priv);
-};
-
-extern const struct __DriverAPIRec driDriverAPI;
-
-
-struct __DRIswapInfoRec {
- /**
- * Number of swapBuffers operations that have been *completed*.
- */
- uint64_t swap_count;
-
- /**
- * Unadjusted system time of the last buffer swap. This is the time
- * when the swap completed, not the time when swapBuffers was called.
- */
- int64_t swap_ust;
-
- /**
- * Number of swap operations that occurred after the swap deadline. That
- * is if a swap happens more than swap_interval frames after the previous
- * swap, it has missed its deadline. If swap_interval is 0, then the
- * swap deadline is 1 frame after the previous swap.
- */
- uint64_t swap_missed_count;
-
- /**
- * Amount of time used by the last swap that missed its deadline. This
- * is calculated as (__glXGetUST() - swap_ust) / (swap_interval *
- * time_for_single_vrefresh)). If the actual value of swap_interval is
- * 0, then 1 is used instead. If swap_missed_count is non-zero, this
- * should be greater-than 1.0.
- */
- float swap_missed_usage;
-};
-
-
-/**
- * Per-drawable private DRI driver information.
- */
-struct __DRIdrawableRec {
- /**
- * Kernel drawable handle
- */
- drm_drawable_t hHWDrawable;
-
- /**
- * Driver's private drawable information.
- *
- * This structure is opaque.
- */
- void *driverPrivate;
-
- /**
- * Private data from the loader. We just hold on to it and pass
- * it back when calling into loader provided functions.
- */
- void *loaderPrivate;
-
- /**
- * Reference count for number of context's currently bound to this
- * drawable.
- *
- * Once it reaches zero, the drawable can be destroyed.
- *
- * \note This behavior will change with GLX 1.3.
- */
- int refcount;
-
- /**
- * Index of this drawable information in the SAREA.
- */
- unsigned int index;
-
- /**
- * Pointer to the "drawable has changed ID" stamp in the SAREA (or
- * to dri2.stamp if DRI2 is being used).
- */
- unsigned int *pStamp;
-
- /**
- * Last value of the stamp.
- *
- * If this differs from the value stored at __DRIdrawable::pStamp,
- * then the drawable information has been modified by the X server, and the
- * drawable information (below) should be retrieved from the X server.
- */
- unsigned int lastStamp;
-
- /**
- * \name Drawable
- *
- * Drawable information used in software fallbacks.
- */
- /*@{*/
- int x;
- int y;
- int w;
- int h;
- int numClipRects;
- drm_clip_rect_t *pClipRects;
- /*@}*/
-
- /**
- * \name Back and depthbuffer
- *
- * Information about the back and depthbuffer where different from above.
- */
- /*@{*/
- int backX;
- int backY;
- int backClipRectType;
- int numBackClipRects;
- drm_clip_rect_t *pBackClipRects;
- /*@}*/
-
- /**
- * \name Vertical blank tracking information
- * Used for waiting on vertical blank events.
- */
- /*@{*/
- unsigned int vblSeq;
- unsigned int vblFlags;
- /*@}*/
-
- /**
- * \name Monotonic MSC tracking
- *
- * Low level driver is responsible for updating msc_base and
- * vblSeq values so that higher level code can calculate
- * a new msc value or msc target for a WaitMSC call. The new value
- * will be:
- * msc = msc_base + get_vblank_count() - vblank_base;
- *
- * And for waiting on a value, core code will use:
- * actual_target = target_msc - msc_base + vblank_base;
- */
- /*@{*/
- int64_t vblank_base;
- int64_t msc_base;
- /*@}*/
-
- /**
- * Pointer to context to which this drawable is currently bound.
- */
- __DRIcontext *driContextPriv;
-
- /**
- * Pointer to screen on which this drawable was created.
- */
- __DRIscreen *driScreenPriv;
-
- /**
- * Controls swap interval as used by GLX_SGI_swap_control and
- * GLX_MESA_swap_control.
- */
- unsigned int swap_interval;
-
- struct {
- unsigned int stamp;
- drm_clip_rect_t clipRect;
- } dri2;
-};
-
-/**
- * Per-context private driver information.
- */
-struct __DRIcontextRec {
- /**
- * Kernel context handle used to access the device lock.
- */
- drm_context_t hHWContext;
-
- /**
- * Device driver's private context data. This structure is opaque.
- */
- void *driverPrivate;
-
- /**
- * Pointer to drawable currently bound to this context for drawing.
- */
- __DRIdrawable *driDrawablePriv;
-
- /**
- * Pointer to drawable currently bound to this context for reading.
- */
- __DRIdrawable *driReadablePriv;
-
- /**
- * Pointer to screen on which this context was created.
- */
- __DRIscreen *driScreenPriv;
-
- /**
- * The loaders's private context data. This structure is opaque.
- */
- void *loaderPrivate;
-
- struct {
- int draw_stamp;
- int read_stamp;
- } dri2;
-};
-
-/**
- * Per-screen private driver information.
- */
-struct __DRIscreenRec {
- /**
- * Current screen's number
- */
- int myNum;
-
- /**
- * Callback functions into the hardware-specific DRI driver code.
- */
- struct __DriverAPIRec DriverAPI;
-
- const __DRIextension **extensions;
- /**
- * DDX / 2D driver version information.
- */
- __DRIversion ddx_version;
-
- /**
- * DRI X extension version information.
- */
- __DRIversion dri_version;
-
- /**
- * DRM (kernel module) version information.
- */
- __DRIversion drm_version;
-
- /**
- * ID used when the client sets the drawable lock.
- *
- * The X server uses this value to detect if the client has died while
- * holding the drawable lock.
- */
- int drawLockID;
-
- /**
- * File descriptor returned when the kernel device driver is opened.
- *
- * Used to:
- * - authenticate client to kernel
- * - map the frame buffer, SAREA, etc.
- * - close the kernel device driver
- */
- int fd;
-
- /**
- * SAREA pointer
- *
- * Used to access:
- * - the device lock
- * - the device-independent per-drawable and per-context(?) information
- */
- drm_sarea_t *pSAREA;
-
- /**
- * \name Direct frame buffer access information
- * Used for software fallbacks.
- */
- /*@{*/
- unsigned char *pFB;
- int fbSize;
- int fbOrigin;
- int fbStride;
- int fbWidth;
- int fbHeight;
- int fbBPP;
- /*@}*/
-
- /**
- * \name Device-dependent private information (stored in the SAREA).
- *
- * This data is accessed by the client driver only.
- */
- /*@{*/
- void *pDevPriv;
- int devPrivSize;
- /*@}*/
-
- /**
- * Device-dependent private information (not stored in the SAREA).
- *
- * This pointer is never touched by the DRI layer.
- */
-#ifdef __cplusplus
- void *priv;
-#else
- void *private;
-#endif
-
- /* Extensions provided by the loader. */
- const __DRIgetDrawableInfoExtension *getDrawableInfo;
- const __DRIsystemTimeExtension *systemTime;
- const __DRIdamageExtension *damage;
-
- struct {
- /* Flag to indicate that this is a DRI2 screen. Many of the above
- * fields will not be valid or initializaed in that case. */
- int enabled;
- __DRIdri2LoaderExtension *loader;
- __DRIimageLookupExtension *image;
- __DRIuseInvalidateExtension *useInvalidate;
- } dri2;
-
- /* The lock actually in use, old sarea or DRI2 */
- drmLock *lock;
-
- driOptionCache optionInfo;
- driOptionCache optionCache;
- unsigned int api_mask;
- void *loaderPrivate;
-};
-
-extern void
-__driUtilUpdateDrawableInfo(__DRIdrawable *pdp);
-
-extern float
-driCalculateSwapUsage( __DRIdrawable *dPriv,
- int64_t last_swap_ust, int64_t current_ust );
-
-extern GLint
-driIntersectArea( drm_clip_rect_t rect1, drm_clip_rect_t rect2 );
-
-extern void
-dri2InvalidateDrawable(__DRIdrawable *drawable);
-
-#endif /* _DRI_UTIL_H_ */
+/*
+ * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file dri_util.h
+ * DRI utility functions definitions.
+ *
+ * This module acts as glue between GLX and the actual hardware driver. A DRI
+ * driver doesn't really \e have to use any of this - it's optional. But, some
+ * useful stuff is done here that otherwise would have to be duplicated in most
+ * drivers.
+ *
+ * Basically, these utility functions take care of some of the dirty details of
+ * screen initialization, context creation, context binding, DRM setup, etc.
+ *
+ * These functions are compiled into each DRI driver so libGL.so knows nothing
+ * about them.
+ *
+ * \sa dri_util.c.
+ *
+ * \author Kevin E. Martin <kevin@precisioninsight.com>
+ * \author Brian Paul <brian@precisioninsight.com>
+ */
+
+#ifndef _DRI_UTIL_H_
+#define _DRI_UTIL_H_
+
+#include <GL/gl.h>
+#include <drm.h>
+#include <drm_sarea.h>
+#include <xf86drm.h>
+#include "xmlconfig.h"
+#include "main/glheader.h"
+#include "main/mtypes.h"
+#include "GL/internal/dri_interface.h"
+
+#define GLX_BAD_CONTEXT 5
+
+typedef struct __DRIswapInfoRec __DRIswapInfo;
+
+/**
+ * Extensions.
+ */
+extern const __DRIlegacyExtension driLegacyExtension;
+extern const __DRIcoreExtension driCoreExtension;
+extern const __DRIdri2Extension driDRI2Extension;
+extern const __DRIextension driReadDrawableExtension;
+extern const __DRIcopySubBufferExtension driCopySubBufferExtension;
+extern const __DRIswapControlExtension driSwapControlExtension;
+extern const __DRImediaStreamCounterExtension driMediaStreamCounterExtension;
+extern const __DRI2configQueryExtension dri2ConfigQueryExtension;
+
+/**
+ * Used by DRI_VALIDATE_DRAWABLE_INFO
+ */
+#define DRI_VALIDATE_DRAWABLE_INFO_ONCE(pDrawPriv) \
+ do { \
+ if (*(pDrawPriv->pStamp) != pDrawPriv->lastStamp) { \
+ __driUtilUpdateDrawableInfo(pDrawPriv); \
+ } \
+ } while (0)
+
+
+/**
+ * Utility macro to validate the drawable information.
+ *
+ * See __DRIdrawable::pStamp and __DRIdrawable::lastStamp.
+ */
+#define DRI_VALIDATE_DRAWABLE_INFO(psp, pdp) \
+do { \
+ while (*(pdp->pStamp) != pdp->lastStamp) { \
+ register unsigned int hwContext = psp->pSAREA->lock.lock & \
+ ~(DRM_LOCK_HELD | DRM_LOCK_CONT); \
+ DRM_UNLOCK(psp->fd, &psp->pSAREA->lock, hwContext); \
+ \
+ DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID); \
+ DRI_VALIDATE_DRAWABLE_INFO_ONCE(pdp); \
+ DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID); \
+ \
+ DRM_LIGHT_LOCK(psp->fd, &psp->pSAREA->lock, hwContext); \
+ } \
+} while (0)
+
+/**
+ * Same as above, but for two drawables simultaneously.
+ *
+ */
+
+#define DRI_VALIDATE_TWO_DRAWABLES_INFO(psp, pdp, prp) \
+do { \
+ while (*((pdp)->pStamp) != (pdp)->lastStamp || \
+ *((prp)->pStamp) != (prp)->lastStamp) { \
+ register unsigned int hwContext = (psp)->pSAREA->lock.lock & \
+ ~(DRM_LOCK_HELD | DRM_LOCK_CONT); \
+ DRM_UNLOCK((psp)->fd, &(psp)->pSAREA->lock, hwContext); \
+ \
+ DRM_SPINLOCK(&(psp)->pSAREA->drawable_lock, (psp)->drawLockID); \
+ DRI_VALIDATE_DRAWABLE_INFO_ONCE(pdp); \
+ DRI_VALIDATE_DRAWABLE_INFO_ONCE(prp); \
+ DRM_SPINUNLOCK(&(psp)->pSAREA->drawable_lock, (psp)->drawLockID); \
+ \
+ DRM_LIGHT_LOCK((psp)->fd, &(psp)->pSAREA->lock, hwContext); \
+ } \
+} while (0)
+
+
+/**
+ * Driver callback functions.
+ *
+ * Each DRI driver must have one of these structures with all the pointers set
+ * to appropriate functions within the driver.
+ *
+ * When glXCreateContext() is called, for example, it'll call a helper function
+ * dri_util.c which in turn will jump through the \a CreateContext pointer in
+ * this structure.
+ */
+struct __DriverAPIRec {
+ const __DRIconfig **(*InitScreen) (__DRIscreen * priv);
+
+ /**
+ * Screen destruction callback
+ */
+ void (*DestroyScreen)(__DRIscreen *driScrnPriv);
+
+ /**
+ * Context creation callback
+ */
+ GLboolean (*CreateContext)(gl_api api,
+ const struct gl_config *glVis,
+ __DRIcontext *driContextPriv,
+ void *sharedContextPrivate);
+
+ /**
+ * Context destruction callback
+ */
+ void (*DestroyContext)(__DRIcontext *driContextPriv);
+
+ /**
+ * Buffer (drawable) creation callback
+ */
+ GLboolean (*CreateBuffer)(__DRIscreen *driScrnPriv,
+ __DRIdrawable *driDrawPriv,
+ const struct gl_config *glVis,
+ GLboolean pixmapBuffer);
+
+ /**
+ * Buffer (drawable) destruction callback
+ */
+ void (*DestroyBuffer)(__DRIdrawable *driDrawPriv);
+
+ /**
+ * Buffer swapping callback
+ */
+ void (*SwapBuffers)(__DRIdrawable *driDrawPriv);
+
+ /**
+ * Context activation callback
+ */
+ GLboolean (*MakeCurrent)(__DRIcontext *driContextPriv,
+ __DRIdrawable *driDrawPriv,
+ __DRIdrawable *driReadPriv);
+
+ /**
+ * Context unbinding callback
+ */
+ GLboolean (*UnbindContext)(__DRIcontext *driContextPriv);
+
+ /**
+ * Retrieves statistics about buffer swap operations. Required if
+ * GLX_OML_sync_control or GLX_MESA_swap_frame_usage is supported.
+ */
+ int (*GetSwapInfo)( __DRIdrawable *dPriv, __DRIswapInfo * sInfo );
+
+
+ /**
+ * These are required if GLX_OML_sync_control is supported.
+ */
+ /*@{*/
+ int (*WaitForMSC)( __DRIdrawable *priv, int64_t target_msc,
+ int64_t divisor, int64_t remainder,
+ int64_t * msc );
+ int (*WaitForSBC)( __DRIdrawable *priv, int64_t target_sbc,
+ int64_t * msc, int64_t * sbc );
+
+ int64_t (*SwapBuffersMSC)( __DRIdrawable *priv, int64_t target_msc,
+ int64_t divisor, int64_t remainder );
+ /*@}*/
+ void (*CopySubBuffer)(__DRIdrawable *driDrawPriv,
+ int x, int y, int w, int h);
+
+ /**
+ * New version of GetMSC so we can pass drawable data to the low
+ * level DRM driver (e.g. pipe info). Required if
+ * GLX_SGI_video_sync or GLX_OML_sync_control is supported.
+ */
+ int (*GetDrawableMSC) ( __DRIscreen * priv,
+ __DRIdrawable *drawablePrivate,
+ int64_t *count);
+
+
+
+ /* DRI2 Entry point */
+ const __DRIconfig **(*InitScreen2) (__DRIscreen * priv);
+};
+
+extern const struct __DriverAPIRec driDriverAPI;
+
+
+struct __DRIswapInfoRec {
+ /**
+ * Number of swapBuffers operations that have been *completed*.
+ */
+ uint64_t swap_count;
+
+ /**
+ * Unadjusted system time of the last buffer swap. This is the time
+ * when the swap completed, not the time when swapBuffers was called.
+ */
+ int64_t swap_ust;
+
+ /**
+ * Number of swap operations that occurred after the swap deadline. That
+ * is if a swap happens more than swap_interval frames after the previous
+ * swap, it has missed its deadline. If swap_interval is 0, then the
+ * swap deadline is 1 frame after the previous swap.
+ */
+ uint64_t swap_missed_count;
+
+ /**
+ * Amount of time used by the last swap that missed its deadline. This
+ * is calculated as (__glXGetUST() - swap_ust) / (swap_interval *
+ * time_for_single_vrefresh)). If the actual value of swap_interval is
+ * 0, then 1 is used instead. If swap_missed_count is non-zero, this
+ * should be greater-than 1.0.
+ */
+ float swap_missed_usage;
+};
+
+
+/**
+ * Per-drawable private DRI driver information.
+ */
+struct __DRIdrawableRec {
+ /**
+ * Kernel drawable handle
+ */
+ drm_drawable_t hHWDrawable;
+
+ /**
+ * Driver's private drawable information.
+ *
+ * This structure is opaque.
+ */
+ void *driverPrivate;
+
+ /**
+ * Private data from the loader. We just hold on to it and pass
+ * it back when calling into loader provided functions.
+ */
+ void *loaderPrivate;
+
+ /**
+ * Reference count for number of context's currently bound to this
+ * drawable.
+ *
+ * Once it reaches zero, the drawable can be destroyed.
+ *
+ * \note This behavior will change with GLX 1.3.
+ */
+ int refcount;
+
+ /**
+ * Index of this drawable information in the SAREA.
+ */
+ unsigned int index;
+
+ /**
+ * Pointer to the "drawable has changed ID" stamp in the SAREA (or
+ * to dri2.stamp if DRI2 is being used).
+ */
+ unsigned int *pStamp;
+
+ /**
+ * Last value of the stamp.
+ *
+ * If this differs from the value stored at __DRIdrawable::pStamp,
+ * then the drawable information has been modified by the X server, and the
+ * drawable information (below) should be retrieved from the X server.
+ */
+ unsigned int lastStamp;
+
+ /**
+ * \name Drawable
+ *
+ * Drawable information used in software fallbacks.
+ */
+ /*@{*/
+ int x;
+ int y;
+ int w;
+ int h;
+ int numClipRects;
+ drm_clip_rect_t *pClipRects;
+ /*@}*/
+
+ /**
+ * \name Back and depthbuffer
+ *
+ * Information about the back and depthbuffer where different from above.
+ */
+ /*@{*/
+ int backX;
+ int backY;
+ int backClipRectType;
+ int numBackClipRects;
+ drm_clip_rect_t *pBackClipRects;
+ /*@}*/
+
+ /**
+ * \name Vertical blank tracking information
+ * Used for waiting on vertical blank events.
+ */
+ /*@{*/
+ unsigned int vblSeq;
+ unsigned int vblFlags;
+ /*@}*/
+
+ /**
+ * \name Monotonic MSC tracking
+ *
+ * Low level driver is responsible for updating msc_base and
+ * vblSeq values so that higher level code can calculate
+ * a new msc value or msc target for a WaitMSC call. The new value
+ * will be:
+ * msc = msc_base + get_vblank_count() - vblank_base;
+ *
+ * And for waiting on a value, core code will use:
+ * actual_target = target_msc - msc_base + vblank_base;
+ */
+ /*@{*/
+ int64_t vblank_base;
+ int64_t msc_base;
+ /*@}*/
+
+ /**
+ * Pointer to context to which this drawable is currently bound.
+ */
+ __DRIcontext *driContextPriv;
+
+ /**
+ * Pointer to screen on which this drawable was created.
+ */
+ __DRIscreen *driScreenPriv;
+
+ /**
+ * Controls swap interval as used by GLX_SGI_swap_control and
+ * GLX_MESA_swap_control.
+ */
+ unsigned int swap_interval;
+
+ struct {
+ unsigned int stamp;
+ drm_clip_rect_t clipRect;
+ } dri2;
+};
+
+/**
+ * Per-context private driver information.
+ */
+struct __DRIcontextRec {
+ /**
+ * Kernel context handle used to access the device lock.
+ */
+ drm_context_t hHWContext;
+
+ /**
+ * Device driver's private context data. This structure is opaque.
+ */
+ void *driverPrivate;
+
+ /**
+ * Pointer to drawable currently bound to this context for drawing.
+ */
+ __DRIdrawable *driDrawablePriv;
+
+ /**
+ * Pointer to drawable currently bound to this context for reading.
+ */
+ __DRIdrawable *driReadablePriv;
+
+ /**
+ * Pointer to screen on which this context was created.
+ */
+ __DRIscreen *driScreenPriv;
+
+ /**
+ * The loaders's private context data. This structure is opaque.
+ */
+ void *loaderPrivate;
+
+ struct {
+ int draw_stamp;
+ int read_stamp;
+ } dri2;
+};
+
+/**
+ * Per-screen private driver information.
+ */
+struct __DRIscreenRec {
+ /**
+ * Current screen's number
+ */
+ int myNum;
+
+ /**
+ * Callback functions into the hardware-specific DRI driver code.
+ */
+ struct __DriverAPIRec DriverAPI;
+
+ const __DRIextension **extensions;
+ /**
+ * DDX / 2D driver version information.
+ */
+ __DRIversion ddx_version;
+
+ /**
+ * DRI X extension version information.
+ */
+ __DRIversion dri_version;
+
+ /**
+ * DRM (kernel module) version information.
+ */
+ __DRIversion drm_version;
+
+ /**
+ * ID used when the client sets the drawable lock.
+ *
+ * The X server uses this value to detect if the client has died while
+ * holding the drawable lock.
+ */
+ int drawLockID;
+
+ /**
+ * File descriptor returned when the kernel device driver is opened.
+ *
+ * Used to:
+ * - authenticate client to kernel
+ * - map the frame buffer, SAREA, etc.
+ * - close the kernel device driver
+ */
+ int fd;
+
+ /**
+ * SAREA pointer
+ *
+ * Used to access:
+ * - the device lock
+ * - the device-independent per-drawable and per-context(?) information
+ */
+ drm_sarea_t *pSAREA;
+
+ /**
+ * \name Direct frame buffer access information
+ * Used for software fallbacks.
+ */
+ /*@{*/
+ unsigned char *pFB;
+ int fbSize;
+ int fbOrigin;
+ int fbStride;
+ int fbWidth;
+ int fbHeight;
+ int fbBPP;
+ /*@}*/
+
+ /**
+ * \name Device-dependent private information (stored in the SAREA).
+ *
+ * This data is accessed by the client driver only.
+ */
+ /*@{*/
+ void *pDevPriv;
+ int devPrivSize;
+ /*@}*/
+
+ /**
+ * Device-dependent private information (not stored in the SAREA).
+ *
+ * This pointer is never touched by the DRI layer.
+ */
+#ifdef __cplusplus
+ void *priv;
+#else
+ void *private;
+#endif
+
+ /* Extensions provided by the loader. */
+ const __DRIgetDrawableInfoExtension *getDrawableInfo;
+ const __DRIsystemTimeExtension *systemTime;
+ const __DRIdamageExtension *damage;
+
+ struct {
+ /* Flag to indicate that this is a DRI2 screen. Many of the above
+ * fields will not be valid or initializaed in that case. */
+ int enabled;
+ __DRIdri2LoaderExtension *loader;
+ __DRIimageLookupExtension *image;
+ __DRIuseInvalidateExtension *useInvalidate;
+ } dri2;
+
+ /* The lock actually in use, old sarea or DRI2 */
+ drmLock *lock;
+
+ driOptionCache optionInfo;
+ driOptionCache optionCache;
+ unsigned int api_mask;
+ void *loaderPrivate;
+};
+
+extern void
+__driUtilUpdateDrawableInfo(__DRIdrawable *pdp);
+
+extern float
+driCalculateSwapUsage( __DRIdrawable *dPriv,
+ int64_t last_swap_ust, int64_t current_ust );
+
+extern GLint
+driIntersectArea( drm_clip_rect_t rect1, drm_clip_rect_t rect2 );
+
+extern void
+dri2InvalidateDrawable(__DRIdrawable *drawable);
+
+#endif /* _DRI_UTIL_H_ */
diff --git a/mesalib/src/mesa/drivers/dri/common/drirenderbuffer.c b/mesalib/src/mesa/drivers/dri/common/drirenderbuffer.c
index c9ce6e3cb..5e032bd15 100644
--- a/mesalib/src/mesa/drivers/dri/common/drirenderbuffer.c
+++ b/mesalib/src/mesa/drivers/dri/common/drirenderbuffer.c
@@ -1,200 +1,200 @@
-
-#include "main/mtypes.h"
-#include "main/formats.h"
-#include "main/renderbuffer.h"
-#include "main/imports.h"
-#include "drirenderbuffer.h"
-
-
-/**
- * This will get called when a window (gl_framebuffer) is resized (probably
- * via driUpdateFramebufferSize(), below).
- * Just update width, height and internal format fields for now.
- * There's usually no memory allocation above because the present
- * DRI drivers use statically-allocated full-screen buffers. If that's not
- * the case for a DRI driver, a different AllocStorage method should
- * be used.
- */
-static GLboolean
-driRenderbufferStorage(GLcontext *ctx, struct gl_renderbuffer *rb,
- GLenum internalFormat, GLuint width, GLuint height)
-{
- rb->Width = width;
- rb->Height = height;
- rb->InternalFormat = internalFormat;
- return GL_TRUE;
-}
-
-
-static void
-driDeleteRenderbuffer(struct gl_renderbuffer *rb)
-{
- /* don't free rb->Data Chances are it's a memory mapped region for
- * the dri drivers.
- */
- free(rb);
-}
-
-
-/**
- * Allocate a new driRenderbuffer object.
- * Individual drivers are free to implement different versions of
- * this function.
- *
- * At this time, this function can only be used for window-system
- * renderbuffers, not user-created RBOs.
- *
- * \param format Either GL_RGBA, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT24,
- * GL_DEPTH_COMPONENT32, or GL_STENCIL_INDEX8_EXT (for now).
- * \param addr address in main memory of the buffer. Probably a memory
- * mapped region.
- * \param cpp chars or bytes per pixel
- * \param offset start of renderbuffer with respect to start of framebuffer
- * \param pitch pixels per row
- */
-driRenderbuffer *
-driNewRenderbuffer(gl_format format, GLvoid *addr,
- GLint cpp, GLint offset, GLint pitch,
- __DRIdrawable *dPriv)
-{
- driRenderbuffer *drb;
-
- assert(cpp > 0);
- assert(pitch > 0);
-
- drb = calloc(1, sizeof(driRenderbuffer));
- if (drb) {
- const GLuint name = 0;
-
- _mesa_init_renderbuffer(&drb->Base, name);
-
- /* Make sure we're using a null-valued GetPointer routine */
- assert(drb->Base.GetPointer(NULL, &drb->Base, 0, 0) == NULL);
-
- switch (format) {
- case MESA_FORMAT_ARGB8888:
- if (cpp == 2) {
- /* override format */
- format = MESA_FORMAT_RGB565;
- }
- drb->Base.DataType = GL_UNSIGNED_BYTE;
- break;
- case MESA_FORMAT_Z16:
- /* Depth */
- /* we always Get/Put 32-bit Z values */
- drb->Base.DataType = GL_UNSIGNED_INT;
- assert(cpp == 2);
- break;
- case MESA_FORMAT_Z32:
- /* Depth */
- /* we always Get/Put 32-bit Z values */
- drb->Base.DataType = GL_UNSIGNED_INT;
- assert(cpp == 4);
- break;
- case MESA_FORMAT_Z24_S8:
- drb->Base.DataType = GL_UNSIGNED_INT_24_8_EXT;
- assert(cpp == 4);
- break;
- case MESA_FORMAT_S8_Z24:
- drb->Base.DataType = GL_UNSIGNED_INT_24_8_EXT;
- assert(cpp == 4);
- break;
- case MESA_FORMAT_S8:
- /* Stencil */
- drb->Base.DataType = GL_UNSIGNED_BYTE;
- break;
- default:
- _mesa_problem(NULL, "Bad format 0x%x in driNewRenderbuffer", format);
- return NULL;
- }
-
- drb->Base.Format = format;
-
- drb->Base.InternalFormat =
- drb->Base._BaseFormat = _mesa_get_format_base_format(format);
-
- drb->Base.AllocStorage = driRenderbufferStorage;
- drb->Base.Delete = driDeleteRenderbuffer;
-
- drb->Base.Data = addr;
-
- /* DRI renderbuffer-specific fields: */
- drb->dPriv = dPriv;
- drb->offset = offset;
- drb->pitch = pitch;
- drb->cpp = cpp;
-
- /* may be changed if page flipping is active: */
- drb->flippedOffset = offset;
- drb->flippedPitch = pitch;
- drb->flippedData = addr;
- }
- return drb;
-}
-
-
-/**
- * Update the front and back renderbuffers' flippedPitch/Offset/Data fields.
- * If stereo, flip both the left and right pairs.
- * This is used when we do double buffering via page flipping.
- * \param fb the framebuffer we're page flipping
- * \param flipped if true, set flipped values, else set non-flipped values
- */
-void
-driFlipRenderbuffers(struct gl_framebuffer *fb, GLboolean flipped)
-{
- const GLuint count = fb->Visual.stereoMode ? 2 : 1;
- GLuint lr; /* left or right */
-
- /* we shouldn't really call this function if single-buffered, but
- * play it safe.
- */
- if (!fb->Visual.doubleBufferMode)
- return;
-
- for (lr = 0; lr < count; lr++) {
- GLuint frontBuf = (lr == 0) ? BUFFER_FRONT_LEFT : BUFFER_FRONT_RIGHT;
- GLuint backBuf = (lr == 0) ? BUFFER_BACK_LEFT : BUFFER_BACK_RIGHT;
- driRenderbuffer *front_drb
- = (driRenderbuffer *) fb->Attachment[frontBuf].Renderbuffer;
- driRenderbuffer *back_drb
- = (driRenderbuffer *) fb->Attachment[backBuf].Renderbuffer;
-
- if (flipped) {
- front_drb->flippedOffset = back_drb->offset;
- front_drb->flippedPitch = back_drb->pitch;
- front_drb->flippedData = back_drb->Base.Data;
- back_drb->flippedOffset = front_drb->offset;
- back_drb->flippedPitch = front_drb->pitch;
- back_drb->flippedData = front_drb->Base.Data;
- }
- else {
- front_drb->flippedOffset = front_drb->offset;
- front_drb->flippedPitch = front_drb->pitch;
- front_drb->flippedData = front_drb->Base.Data;
- back_drb->flippedOffset = back_drb->offset;
- back_drb->flippedPitch = back_drb->pitch;
- back_drb->flippedData = back_drb->Base.Data;
- }
- }
-}
-
-
-/**
- * Check that the gl_framebuffer associated with dPriv is the right size.
- * Resize the gl_framebuffer if needed.
- * It's expected that the dPriv->driverPrivate member points to a
- * gl_framebuffer object.
- */
-void
-driUpdateFramebufferSize(GLcontext *ctx, const __DRIdrawable *dPriv)
-{
- struct gl_framebuffer *fb = (struct gl_framebuffer *) dPriv->driverPrivate;
- if (fb && (dPriv->w != fb->Width || dPriv->h != fb->Height)) {
- ctx->Driver.ResizeBuffers(ctx, fb, dPriv->w, dPriv->h);
- /* if the driver needs the hw lock for ResizeBuffers, the drawable
- might have changed again by now */
- assert(fb->Width == dPriv->w);
- assert(fb->Height == dPriv->h);
- }
-}
+
+#include "main/mtypes.h"
+#include "main/formats.h"
+#include "main/renderbuffer.h"
+#include "main/imports.h"
+#include "drirenderbuffer.h"
+
+
+/**
+ * This will get called when a window (gl_framebuffer) is resized (probably
+ * via driUpdateFramebufferSize(), below).
+ * Just update width, height and internal format fields for now.
+ * There's usually no memory allocation above because the present
+ * DRI drivers use statically-allocated full-screen buffers. If that's not
+ * the case for a DRI driver, a different AllocStorage method should
+ * be used.
+ */
+static GLboolean
+driRenderbufferStorage(struct gl_context *ctx, struct gl_renderbuffer *rb,
+ GLenum internalFormat, GLuint width, GLuint height)
+{
+ rb->Width = width;
+ rb->Height = height;
+ rb->InternalFormat = internalFormat;
+ return GL_TRUE;
+}
+
+
+static void
+driDeleteRenderbuffer(struct gl_renderbuffer *rb)
+{
+ /* don't free rb->Data Chances are it's a memory mapped region for
+ * the dri drivers.
+ */
+ free(rb);
+}
+
+
+/**
+ * Allocate a new driRenderbuffer object.
+ * Individual drivers are free to implement different versions of
+ * this function.
+ *
+ * At this time, this function can only be used for window-system
+ * renderbuffers, not user-created RBOs.
+ *
+ * \param format Either GL_RGBA, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT24,
+ * GL_DEPTH_COMPONENT32, or GL_STENCIL_INDEX8_EXT (for now).
+ * \param addr address in main memory of the buffer. Probably a memory
+ * mapped region.
+ * \param cpp chars or bytes per pixel
+ * \param offset start of renderbuffer with respect to start of framebuffer
+ * \param pitch pixels per row
+ */
+driRenderbuffer *
+driNewRenderbuffer(gl_format format, GLvoid *addr,
+ GLint cpp, GLint offset, GLint pitch,
+ __DRIdrawable *dPriv)
+{
+ driRenderbuffer *drb;
+
+ assert(cpp > 0);
+ assert(pitch > 0);
+
+ drb = calloc(1, sizeof(driRenderbuffer));
+ if (drb) {
+ const GLuint name = 0;
+
+ _mesa_init_renderbuffer(&drb->Base, name);
+
+ /* Make sure we're using a null-valued GetPointer routine */
+ assert(drb->Base.GetPointer(NULL, &drb->Base, 0, 0) == NULL);
+
+ switch (format) {
+ case MESA_FORMAT_ARGB8888:
+ if (cpp == 2) {
+ /* override format */
+ format = MESA_FORMAT_RGB565;
+ }
+ drb->Base.DataType = GL_UNSIGNED_BYTE;
+ break;
+ case MESA_FORMAT_Z16:
+ /* Depth */
+ /* we always Get/Put 32-bit Z values */
+ drb->Base.DataType = GL_UNSIGNED_INT;
+ assert(cpp == 2);
+ break;
+ case MESA_FORMAT_Z32:
+ /* Depth */
+ /* we always Get/Put 32-bit Z values */
+ drb->Base.DataType = GL_UNSIGNED_INT;
+ assert(cpp == 4);
+ break;
+ case MESA_FORMAT_Z24_S8:
+ drb->Base.DataType = GL_UNSIGNED_INT_24_8_EXT;
+ assert(cpp == 4);
+ break;
+ case MESA_FORMAT_S8_Z24:
+ drb->Base.DataType = GL_UNSIGNED_INT_24_8_EXT;
+ assert(cpp == 4);
+ break;
+ case MESA_FORMAT_S8:
+ /* Stencil */
+ drb->Base.DataType = GL_UNSIGNED_BYTE;
+ break;
+ default:
+ _mesa_problem(NULL, "Bad format 0x%x in driNewRenderbuffer", format);
+ return NULL;
+ }
+
+ drb->Base.Format = format;
+
+ drb->Base.InternalFormat =
+ drb->Base._BaseFormat = _mesa_get_format_base_format(format);
+
+ drb->Base.AllocStorage = driRenderbufferStorage;
+ drb->Base.Delete = driDeleteRenderbuffer;
+
+ drb->Base.Data = addr;
+
+ /* DRI renderbuffer-specific fields: */
+ drb->dPriv = dPriv;
+ drb->offset = offset;
+ drb->pitch = pitch;
+ drb->cpp = cpp;
+
+ /* may be changed if page flipping is active: */
+ drb->flippedOffset = offset;
+ drb->flippedPitch = pitch;
+ drb->flippedData = addr;
+ }
+ return drb;
+}
+
+
+/**
+ * Update the front and back renderbuffers' flippedPitch/Offset/Data fields.
+ * If stereo, flip both the left and right pairs.
+ * This is used when we do double buffering via page flipping.
+ * \param fb the framebuffer we're page flipping
+ * \param flipped if true, set flipped values, else set non-flipped values
+ */
+void
+driFlipRenderbuffers(struct gl_framebuffer *fb, GLboolean flipped)
+{
+ const GLuint count = fb->Visual.stereoMode ? 2 : 1;
+ GLuint lr; /* left or right */
+
+ /* we shouldn't really call this function if single-buffered, but
+ * play it safe.
+ */
+ if (!fb->Visual.doubleBufferMode)
+ return;
+
+ for (lr = 0; lr < count; lr++) {
+ GLuint frontBuf = (lr == 0) ? BUFFER_FRONT_LEFT : BUFFER_FRONT_RIGHT;
+ GLuint backBuf = (lr == 0) ? BUFFER_BACK_LEFT : BUFFER_BACK_RIGHT;
+ driRenderbuffer *front_drb
+ = (driRenderbuffer *) fb->Attachment[frontBuf].Renderbuffer;
+ driRenderbuffer *back_drb
+ = (driRenderbuffer *) fb->Attachment[backBuf].Renderbuffer;
+
+ if (flipped) {
+ front_drb->flippedOffset = back_drb->offset;
+ front_drb->flippedPitch = back_drb->pitch;
+ front_drb->flippedData = back_drb->Base.Data;
+ back_drb->flippedOffset = front_drb->offset;
+ back_drb->flippedPitch = front_drb->pitch;
+ back_drb->flippedData = front_drb->Base.Data;
+ }
+ else {
+ front_drb->flippedOffset = front_drb->offset;
+ front_drb->flippedPitch = front_drb->pitch;
+ front_drb->flippedData = front_drb->Base.Data;
+ back_drb->flippedOffset = back_drb->offset;
+ back_drb->flippedPitch = back_drb->pitch;
+ back_drb->flippedData = back_drb->Base.Data;
+ }
+ }
+}
+
+
+/**
+ * Check that the gl_framebuffer associated with dPriv is the right size.
+ * Resize the gl_framebuffer if needed.
+ * It's expected that the dPriv->driverPrivate member points to a
+ * gl_framebuffer object.
+ */
+void
+driUpdateFramebufferSize(struct gl_context *ctx, const __DRIdrawable *dPriv)
+{
+ struct gl_framebuffer *fb = (struct gl_framebuffer *) dPriv->driverPrivate;
+ if (fb && (dPriv->w != fb->Width || dPriv->h != fb->Height)) {
+ ctx->Driver.ResizeBuffers(ctx, fb, dPriv->w, dPriv->h);
+ /* if the driver needs the hw lock for ResizeBuffers, the drawable
+ might have changed again by now */
+ assert(fb->Width == dPriv->w);
+ assert(fb->Height == dPriv->h);
+ }
+}
diff --git a/mesalib/src/mesa/drivers/dri/common/drirenderbuffer.h b/mesalib/src/mesa/drivers/dri/common/drirenderbuffer.h
index 677511334..6c11d350d 100644
--- a/mesalib/src/mesa/drivers/dri/common/drirenderbuffer.h
+++ b/mesalib/src/mesa/drivers/dri/common/drirenderbuffer.h
@@ -1,79 +1,79 @@
-
-/**
- * A driRenderbuffer is dervied from gl_renderbuffer.
- * It describes a color buffer (front or back), a depth buffer, or stencil
- * buffer etc.
- * Specific to DRI drivers are the offset and pitch fields.
- */
-
-
-#ifndef DRIRENDERBUFFER_H
-#define DRIRENDERBUFFER_H
-
-#include "main/mtypes.h"
-#include "main/formats.h"
-#include "dri_util.h"
-
-
-typedef struct {
- struct gl_renderbuffer Base;
-
- /* Chars or bytes per pixel. If Z and Stencil are stored together this
- * will typically be 32 whether this a depth or stencil renderbuffer.
- */
- GLint cpp;
-
- /* Buffer position and pitch (row stride). Recall that for today's DRI
- * drivers, we have statically allocated color/depth/stencil buffers.
- * So this information describes the whole screen, not just a window.
- * To address pixels in a window, we need to know the window's position
- * and size with respect to the screen.
- */
- GLint offset; /* in bytes */
- GLint pitch; /* in pixels */
-
- /* If the driver can do page flipping (full-screen double buffering)
- * the current front/back buffers may get swapped.
- * If page flipping is disabled, these fields will be identical to
- * the offset/pitch/Data above.
- * If page flipping is enabled, and this is the front(back) renderbuffer,
- * flippedOffset/Pitch/Data will have the back(front) renderbuffer's values.
- */
- GLint flippedOffset;
- GLint flippedPitch;
- GLvoid *flippedData; /* mmap'd address of buffer memory, if used */
-
- /* Pointer to corresponding __DRIdrawable. This is used to compute
- * the window's position within the framebuffer.
- */
- __DRIdrawable *dPriv;
-
- /* XXX this is for radeon/r200 only. We should really create a new
- * r200Renderbuffer class, derived from this class... not a huge deal.
- */
- GLboolean depthHasSurface;
-
- /**
- * A handy flag to know if this is the back color buffer.
- *
- * \note
- * This is currently only used by tdfx.
- */
- GLboolean backBuffer;
-} driRenderbuffer;
-
-
-extern driRenderbuffer *
-driNewRenderbuffer(gl_format format, GLvoid *addr,
- GLint cpp, GLint offset, GLint pitch,
- __DRIdrawable *dPriv);
-
-extern void
-driFlipRenderbuffers(struct gl_framebuffer *fb, GLboolean flipped);
-
-
-extern void
-driUpdateFramebufferSize(GLcontext *ctx, const __DRIdrawable *dPriv);
-
-
-#endif /* DRIRENDERBUFFER_H */
+
+/**
+ * A driRenderbuffer is dervied from gl_renderbuffer.
+ * It describes a color buffer (front or back), a depth buffer, or stencil
+ * buffer etc.
+ * Specific to DRI drivers are the offset and pitch fields.
+ */
+
+
+#ifndef DRIRENDERBUFFER_H
+#define DRIRENDERBUFFER_H
+
+#include "main/mtypes.h"
+#include "main/formats.h"
+#include "dri_util.h"
+
+
+typedef struct {
+ struct gl_renderbuffer Base;
+
+ /* Chars or bytes per pixel. If Z and Stencil are stored together this
+ * will typically be 32 whether this a depth or stencil renderbuffer.
+ */
+ GLint cpp;
+
+ /* Buffer position and pitch (row stride). Recall that for today's DRI
+ * drivers, we have statically allocated color/depth/stencil buffers.
+ * So this information describes the whole screen, not just a window.
+ * To address pixels in a window, we need to know the window's position
+ * and size with respect to the screen.
+ */
+ GLint offset; /* in bytes */
+ GLint pitch; /* in pixels */
+
+ /* If the driver can do page flipping (full-screen double buffering)
+ * the current front/back buffers may get swapped.
+ * If page flipping is disabled, these fields will be identical to
+ * the offset/pitch/Data above.
+ * If page flipping is enabled, and this is the front(back) renderbuffer,
+ * flippedOffset/Pitch/Data will have the back(front) renderbuffer's values.
+ */
+ GLint flippedOffset;
+ GLint flippedPitch;
+ GLvoid *flippedData; /* mmap'd address of buffer memory, if used */
+
+ /* Pointer to corresponding __DRIdrawable. This is used to compute
+ * the window's position within the framebuffer.
+ */
+ __DRIdrawable *dPriv;
+
+ /* XXX this is for radeon/r200 only. We should really create a new
+ * r200Renderbuffer class, derived from this class... not a huge deal.
+ */
+ GLboolean depthHasSurface;
+
+ /**
+ * A handy flag to know if this is the back color buffer.
+ *
+ * \note
+ * This is currently only used by tdfx.
+ */
+ GLboolean backBuffer;
+} driRenderbuffer;
+
+
+extern driRenderbuffer *
+driNewRenderbuffer(gl_format format, GLvoid *addr,
+ GLint cpp, GLint offset, GLint pitch,
+ __DRIdrawable *dPriv);
+
+extern void
+driFlipRenderbuffers(struct gl_framebuffer *fb, GLboolean flipped);
+
+
+extern void
+driUpdateFramebufferSize(struct gl_context *ctx, const __DRIdrawable *dPriv);
+
+
+#endif /* DRIRENDERBUFFER_H */
diff --git a/mesalib/src/mesa/drivers/dri/common/drisw_util.h b/mesalib/src/mesa/drivers/dri/common/drisw_util.h
index 9c3d01c99..cae47e1f6 100644
--- a/mesalib/src/mesa/drivers/dri/common/drisw_util.h
+++ b/mesalib/src/mesa/drivers/dri/common/drisw_util.h
@@ -1,135 +1,134 @@
-/*
- * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- * Copyright 2010 George Sapountzis <gsapountzis@gmail.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * @file
- * Binding of the DRI interface (dri_interface.h) for DRISW.
- *
- * The DRISW structs are 'base classes' of the corresponding DRI1 / DRI2 (DRM)
- * structs. The bindings for SW and DRM can be unified by making the DRM structs
- * 'sub-classes' of the SW structs, either proper or with field re-ordering.
- *
- * The code can also be unified but that requires cluttering the common code
- * with ifdef's and guarding with (__DRIscreen::fd >= 0) for DRM.
- */
-
-#ifndef _DRISW_UTIL_H
-#define _DRISW_UTIL_H
-
-#include "main/mtypes.h"
-
-#include <GL/gl.h>
-#include <GL/internal/glcore.h>
-#include <GL/internal/dri_interface.h>
-typedef struct _drmLock drmLock;
-
-
-/**
- * Extensions
- */
-extern const __DRIcoreExtension driCoreExtension;
-extern const __DRIswrastExtension driSWRastExtension;
-
-
-/**
- * Driver callback functions
- */
-struct __DriverAPIRec {
- const __DRIconfig **(*InitScreen) (__DRIscreen * priv);
-
- void (*DestroyScreen)(__DRIscreen *driScrnPriv);
-
- GLboolean (*CreateContext)(gl_api glapi,
- const __GLcontextModes *glVis,
- __DRIcontext *driContextPriv,
- void *sharedContextPrivate);
-
- void (*DestroyContext)(__DRIcontext *driContextPriv);
-
- GLboolean (*CreateBuffer)(__DRIscreen *driScrnPriv,
- __DRIdrawable *driDrawPriv,
- const __GLcontextModes *glVis,
- GLboolean pixmapBuffer);
-
- void (*DestroyBuffer)(__DRIdrawable *driDrawPriv);
-
- void (*SwapBuffers)(__DRIdrawable *driDrawPriv);
-
- GLboolean (*MakeCurrent)(__DRIcontext *driContextPriv,
- __DRIdrawable *driDrawPriv,
- __DRIdrawable *driReadPriv);
-
- GLboolean (*UnbindContext)(__DRIcontext *driContextPriv);
-};
-
-extern const struct __DriverAPIRec driDriverAPI;
-
-
-/**
- * Data types
- */
-struct __DRIscreenRec {
- int myNum;
-
- int fd;
-
- void *private;
-
- const __DRIextension **extensions;
-
- const __DRIswrastLoaderExtension *swrast_loader;
-};
-
-struct __DRIcontextRec {
-
- void *driverPrivate;
-
- void *loaderPrivate;
-
- __DRIdrawable *driDrawablePriv;
-
- __DRIdrawable *driReadablePriv;
-
- __DRIscreen *driScreenPriv;
-};
-
-struct __DRIdrawableRec {
-
- void *driverPrivate;
-
- void *loaderPrivate;
-
- __DRIcontext *driContextPriv;
-
- __DRIscreen *driScreenPriv;
-
- int refcount;
-
- /* gallium */
- unsigned int lastStamp;
-
- int w;
- int h;
-};
-
-#endif /* _DRISW_UTIL_H */
+/*
+ * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * Copyright 2010 George Sapountzis <gsapountzis@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * @file
+ * Binding of the DRI interface (dri_interface.h) for DRISW.
+ *
+ * The DRISW structs are 'base classes' of the corresponding DRI1 / DRI2 (DRM)
+ * structs. The bindings for SW and DRM can be unified by making the DRM structs
+ * 'sub-classes' of the SW structs, either proper or with field re-ordering.
+ *
+ * The code can also be unified but that requires cluttering the common code
+ * with ifdef's and guarding with (__DRIscreen::fd >= 0) for DRM.
+ */
+
+#ifndef _DRISW_UTIL_H
+#define _DRISW_UTIL_H
+
+#include "main/mtypes.h"
+
+#include <GL/gl.h>
+#include <GL/internal/dri_interface.h>
+typedef struct _drmLock drmLock;
+
+
+/**
+ * Extensions
+ */
+extern const __DRIcoreExtension driCoreExtension;
+extern const __DRIswrastExtension driSWRastExtension;
+
+
+/**
+ * Driver callback functions
+ */
+struct __DriverAPIRec {
+ const __DRIconfig **(*InitScreen) (__DRIscreen * priv);
+
+ void (*DestroyScreen)(__DRIscreen *driScrnPriv);
+
+ GLboolean (*CreateContext)(gl_api glapi,
+ const struct gl_config *glVis,
+ __DRIcontext *driContextPriv,
+ void *sharedContextPrivate);
+
+ void (*DestroyContext)(__DRIcontext *driContextPriv);
+
+ GLboolean (*CreateBuffer)(__DRIscreen *driScrnPriv,
+ __DRIdrawable *driDrawPriv,
+ const struct gl_config *glVis,
+ GLboolean pixmapBuffer);
+
+ void (*DestroyBuffer)(__DRIdrawable *driDrawPriv);
+
+ void (*SwapBuffers)(__DRIdrawable *driDrawPriv);
+
+ GLboolean (*MakeCurrent)(__DRIcontext *driContextPriv,
+ __DRIdrawable *driDrawPriv,
+ __DRIdrawable *driReadPriv);
+
+ GLboolean (*UnbindContext)(__DRIcontext *driContextPriv);
+};
+
+extern const struct __DriverAPIRec driDriverAPI;
+
+
+/**
+ * Data types
+ */
+struct __DRIscreenRec {
+ int myNum;
+
+ int fd;
+
+ void *private;
+
+ const __DRIextension **extensions;
+
+ const __DRIswrastLoaderExtension *swrast_loader;
+};
+
+struct __DRIcontextRec {
+
+ void *driverPrivate;
+
+ void *loaderPrivate;
+
+ __DRIdrawable *driDrawablePriv;
+
+ __DRIdrawable *driReadablePriv;
+
+ __DRIscreen *driScreenPriv;
+};
+
+struct __DRIdrawableRec {
+
+ void *driverPrivate;
+
+ void *loaderPrivate;
+
+ __DRIcontext *driContextPriv;
+
+ __DRIscreen *driScreenPriv;
+
+ int refcount;
+
+ /* gallium */
+ unsigned int lastStamp;
+
+ int w;
+ int h;
+};
+
+#endif /* _DRISW_UTIL_H */
diff --git a/mesalib/src/mesa/drivers/dri/common/spantmp.h b/mesalib/src/mesa/drivers/dri/common/spantmp.h
index cdc4f422c..9aea3660c 100644
--- a/mesalib/src/mesa/drivers/dri/common/spantmp.h
+++ b/mesalib/src/mesa/drivers/dri/common/spantmp.h
@@ -1,325 +1,325 @@
-/*
- * Copyright 2000-2001 VA Linux Systems, Inc.
- * (C) Copyright IBM Corporation 2002, 2003
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * on the rights to use, copy, modify, merge, publish, distribute, sub
- * license, and/or sell copies of the Software, and to permit persons to whom
- * the Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Keith Whitwell <keithw@tungstengraphics.com>
- * Gareth Hughes <gareth@nvidia.com>
- */
-
-#include "spantmp_common.h"
-
-#ifndef DBG
-#define DBG 0
-#endif
-
-#ifndef HW_READ_CLIPLOOP
-#define HW_READ_CLIPLOOP() HW_CLIPLOOP()
-#endif
-
-#ifndef HW_WRITE_CLIPLOOP
-#define HW_WRITE_CLIPLOOP() HW_CLIPLOOP()
-#endif
-
-
-static void TAG(WriteRGBASpan)( GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, GLint x, GLint y,
- const void *values, const GLubyte mask[] )
-{
- HW_WRITE_LOCK()
- {
- const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
- GLint x1;
- GLint n1;
- LOCAL_VARS;
-
- y = Y_FLIP(y);
-
- HW_WRITE_CLIPLOOP()
- {
- GLint i = 0;
- CLIPSPAN(x,y,n,x1,n1,i);
-
- if (DBG) fprintf(stderr, "WriteRGBASpan %d..%d (x1 %d)\n",
- (int)i, (int)n1, (int)x1);
-
- if (mask)
- {
- for (;n1>0;i++,x1++,n1--)
- if (mask[i])
- WRITE_RGBA( x1, y,
- rgba[i][0], rgba[i][1],
- rgba[i][2], rgba[i][3] );
- }
- else
- {
- for (;n1>0;i++,x1++,n1--)
- WRITE_RGBA( x1, y,
- rgba[i][0], rgba[i][1],
- rgba[i][2], rgba[i][3] );
- }
- }
- HW_ENDCLIPLOOP();
- }
- HW_WRITE_UNLOCK();
-}
-
-static void TAG(WriteRGBSpan)( GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, GLint x, GLint y,
- const void *values, const GLubyte mask[] )
-{
- HW_WRITE_LOCK()
- {
- const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
- GLint x1;
- GLint n1;
- LOCAL_VARS;
-
- y = Y_FLIP(y);
-
- HW_WRITE_CLIPLOOP()
- {
- GLint i = 0;
- CLIPSPAN(x,y,n,x1,n1,i);
-
- if (DBG) fprintf(stderr, "WriteRGBSpan %d..%d (x1 %d)\n",
- (int)i, (int)n1, (int)x1);
-
- if (mask)
- {
- for (;n1>0;i++,x1++,n1--)
- if (mask[i])
- WRITE_RGBA( x1, y, rgb[i][0], rgb[i][1], rgb[i][2], 255 );
- }
- else
- {
- for (;n1>0;i++,x1++,n1--)
- WRITE_RGBA( x1, y, rgb[i][0], rgb[i][1], rgb[i][2], 255 );
- }
- }
- HW_ENDCLIPLOOP();
- }
- HW_WRITE_UNLOCK();
-}
-
-static void TAG(WriteRGBAPixels)( GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, const GLint x[], const GLint y[],
- const void *values, const GLubyte mask[] )
-{
- HW_WRITE_LOCK()
- {
- const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
- GLuint i;
- LOCAL_VARS;
-
- if (DBG) fprintf(stderr, "WriteRGBAPixels\n");
-
- HW_WRITE_CLIPLOOP()
- {
- if (mask)
- {
- for (i=0;i<n;i++)
- {
- if (mask[i]) {
- const int fy = Y_FLIP(y[i]);
- if (CLIPPIXEL(x[i],fy))
- WRITE_RGBA( x[i], fy,
- rgba[i][0], rgba[i][1],
- rgba[i][2], rgba[i][3] );
- }
- }
- }
- else
- {
- for (i=0;i<n;i++)
- {
- const int fy = Y_FLIP(y[i]);
- if (CLIPPIXEL(x[i],fy))
- WRITE_RGBA( x[i], fy,
- rgba[i][0], rgba[i][1],
- rgba[i][2], rgba[i][3] );
- }
- }
- }
- HW_ENDCLIPLOOP();
- }
- HW_WRITE_UNLOCK();
-}
-
-
-static void TAG(WriteMonoRGBASpan)( GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, GLint x, GLint y,
- const void *value,
- const GLubyte mask[] )
-{
- HW_WRITE_LOCK()
- {
- const GLubyte *color = (const GLubyte *) value;
- GLint x1;
- GLint n1;
- LOCAL_VARS;
- INIT_MONO_PIXEL(p, color);
-
- y = Y_FLIP( y );
-
- if (DBG) fprintf(stderr, "WriteMonoRGBASpan\n");
-
- HW_WRITE_CLIPLOOP()
- {
- GLint i = 0;
- CLIPSPAN(x,y,n,x1,n1,i);
- if (mask)
- {
- for (;n1>0;i++,x1++,n1--)
- if (mask[i])
- WRITE_PIXEL( x1, y, p );
- }
- else
- {
- for (;n1>0;i++,x1++,n1--)
- WRITE_PIXEL( x1, y, p );
- }
- }
- HW_ENDCLIPLOOP();
- }
- HW_WRITE_UNLOCK();
-}
-
-
-static void TAG(WriteMonoRGBAPixels)( GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n,
- const GLint x[], const GLint y[],
- const void *value,
- const GLubyte mask[] )
-{
- HW_WRITE_LOCK()
- {
- const GLubyte *color = (const GLubyte *) value;
- GLuint i;
- LOCAL_VARS;
- INIT_MONO_PIXEL(p, color);
-
- if (DBG) fprintf(stderr, "WriteMonoRGBAPixels\n");
-
- HW_WRITE_CLIPLOOP()
- {
- if (mask)
- {
- for (i=0;i<n;i++)
- if (mask[i]) {
- int fy = Y_FLIP(y[i]);
- if (CLIPPIXEL( x[i], fy ))
- WRITE_PIXEL( x[i], fy, p );
- }
- }
- else
- {
- for (i=0;i<n;i++) {
- int fy = Y_FLIP(y[i]);
- if (CLIPPIXEL( x[i], fy ))
- WRITE_PIXEL( x[i], fy, p );
- }
- }
- }
- HW_ENDCLIPLOOP();
- }
- HW_WRITE_UNLOCK();
-}
-
-
-static void TAG(ReadRGBASpan)( GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, GLint x, GLint y,
- void *values)
-{
- HW_READ_LOCK()
- {
- GLubyte (*rgba)[4] = (GLubyte (*)[4]) values;
- GLint x1,n1;
- LOCAL_VARS;
-
- y = Y_FLIP(y);
-
- if (DBG) fprintf(stderr, "ReadRGBASpan\n");
-
- HW_READ_CLIPLOOP()
- {
- GLint i = 0;
- CLIPSPAN(x,y,n,x1,n1,i);
- for (;n1>0;i++,x1++,n1--)
- READ_RGBA( rgba[i], x1, y );
- }
- HW_ENDCLIPLOOP();
- }
- HW_READ_UNLOCK();
-}
-
-
-static void TAG(ReadRGBAPixels)( GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, const GLint x[], const GLint y[],
- void *values )
-{
- HW_READ_LOCK()
- {
- GLubyte (*rgba)[4] = (GLubyte (*)[4]) values;
- GLuint i;
- LOCAL_VARS;
-
- if (DBG) fprintf(stderr, "ReadRGBAPixels\n");
-
- HW_READ_CLIPLOOP()
- {
- for (i=0;i<n;i++) {
- int fy = Y_FLIP( y[i] );
- if (CLIPPIXEL( x[i], fy ))
- READ_RGBA( rgba[i], x[i], fy );
- }
- }
- HW_ENDCLIPLOOP();
- }
- HW_READ_UNLOCK();
-}
-
-
-static void TAG(InitPointers)(struct gl_renderbuffer *rb)
-{
- rb->PutRow = TAG(WriteRGBASpan);
- rb->PutRowRGB = TAG(WriteRGBSpan);
- rb->PutMonoRow = TAG(WriteMonoRGBASpan);
- rb->PutValues = TAG(WriteRGBAPixels);
- rb->PutMonoValues = TAG(WriteMonoRGBAPixels);
- rb->GetValues = TAG(ReadRGBAPixels);
- rb->GetRow = TAG(ReadRGBASpan);
-}
-
-
-#undef WRITE_PIXEL
-#undef WRITE_RGBA
-#undef READ_RGBA
-#undef TAG
+/*
+ * Copyright 2000-2001 VA Linux Systems, Inc.
+ * (C) Copyright IBM Corporation 2002, 2003
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keithw@tungstengraphics.com>
+ * Gareth Hughes <gareth@nvidia.com>
+ */
+
+#include "spantmp_common.h"
+
+#ifndef DBG
+#define DBG 0
+#endif
+
+#ifndef HW_READ_CLIPLOOP
+#define HW_READ_CLIPLOOP() HW_CLIPLOOP()
+#endif
+
+#ifndef HW_WRITE_CLIPLOOP
+#define HW_WRITE_CLIPLOOP() HW_CLIPLOOP()
+#endif
+
+
+static void TAG(WriteRGBASpan)( struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const void *values, const GLubyte mask[] )
+{
+ HW_WRITE_LOCK()
+ {
+ const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+ GLint x1;
+ GLint n1;
+ LOCAL_VARS;
+
+ y = Y_FLIP(y);
+
+ HW_WRITE_CLIPLOOP()
+ {
+ GLint i = 0;
+ CLIPSPAN(x,y,n,x1,n1,i);
+
+ if (DBG) fprintf(stderr, "WriteRGBASpan %d..%d (x1 %d)\n",
+ (int)i, (int)n1, (int)x1);
+
+ if (mask)
+ {
+ for (;n1>0;i++,x1++,n1--)
+ if (mask[i])
+ WRITE_RGBA( x1, y,
+ rgba[i][0], rgba[i][1],
+ rgba[i][2], rgba[i][3] );
+ }
+ else
+ {
+ for (;n1>0;i++,x1++,n1--)
+ WRITE_RGBA( x1, y,
+ rgba[i][0], rgba[i][1],
+ rgba[i][2], rgba[i][3] );
+ }
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_WRITE_UNLOCK();
+}
+
+static void TAG(WriteRGBSpan)( struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const void *values, const GLubyte mask[] )
+{
+ HW_WRITE_LOCK()
+ {
+ const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
+ GLint x1;
+ GLint n1;
+ LOCAL_VARS;
+
+ y = Y_FLIP(y);
+
+ HW_WRITE_CLIPLOOP()
+ {
+ GLint i = 0;
+ CLIPSPAN(x,y,n,x1,n1,i);
+
+ if (DBG) fprintf(stderr, "WriteRGBSpan %d..%d (x1 %d)\n",
+ (int)i, (int)n1, (int)x1);
+
+ if (mask)
+ {
+ for (;n1>0;i++,x1++,n1--)
+ if (mask[i])
+ WRITE_RGBA( x1, y, rgb[i][0], rgb[i][1], rgb[i][2], 255 );
+ }
+ else
+ {
+ for (;n1>0;i++,x1++,n1--)
+ WRITE_RGBA( x1, y, rgb[i][0], rgb[i][1], rgb[i][2], 255 );
+ }
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_WRITE_UNLOCK();
+}
+
+static void TAG(WriteRGBAPixels)( struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, const GLint x[], const GLint y[],
+ const void *values, const GLubyte mask[] )
+{
+ HW_WRITE_LOCK()
+ {
+ const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+ GLuint i;
+ LOCAL_VARS;
+
+ if (DBG) fprintf(stderr, "WriteRGBAPixels\n");
+
+ HW_WRITE_CLIPLOOP()
+ {
+ if (mask)
+ {
+ for (i=0;i<n;i++)
+ {
+ if (mask[i]) {
+ const int fy = Y_FLIP(y[i]);
+ if (CLIPPIXEL(x[i],fy))
+ WRITE_RGBA( x[i], fy,
+ rgba[i][0], rgba[i][1],
+ rgba[i][2], rgba[i][3] );
+ }
+ }
+ }
+ else
+ {
+ for (i=0;i<n;i++)
+ {
+ const int fy = Y_FLIP(y[i]);
+ if (CLIPPIXEL(x[i],fy))
+ WRITE_RGBA( x[i], fy,
+ rgba[i][0], rgba[i][1],
+ rgba[i][2], rgba[i][3] );
+ }
+ }
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_WRITE_UNLOCK();
+}
+
+
+static void TAG(WriteMonoRGBASpan)( struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const void *value,
+ const GLubyte mask[] )
+{
+ HW_WRITE_LOCK()
+ {
+ const GLubyte *color = (const GLubyte *) value;
+ GLint x1;
+ GLint n1;
+ LOCAL_VARS;
+ INIT_MONO_PIXEL(p, color);
+
+ y = Y_FLIP( y );
+
+ if (DBG) fprintf(stderr, "WriteMonoRGBASpan\n");
+
+ HW_WRITE_CLIPLOOP()
+ {
+ GLint i = 0;
+ CLIPSPAN(x,y,n,x1,n1,i);
+ if (mask)
+ {
+ for (;n1>0;i++,x1++,n1--)
+ if (mask[i])
+ WRITE_PIXEL( x1, y, p );
+ }
+ else
+ {
+ for (;n1>0;i++,x1++,n1--)
+ WRITE_PIXEL( x1, y, p );
+ }
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_WRITE_UNLOCK();
+}
+
+
+static void TAG(WriteMonoRGBAPixels)( struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ const void *value,
+ const GLubyte mask[] )
+{
+ HW_WRITE_LOCK()
+ {
+ const GLubyte *color = (const GLubyte *) value;
+ GLuint i;
+ LOCAL_VARS;
+ INIT_MONO_PIXEL(p, color);
+
+ if (DBG) fprintf(stderr, "WriteMonoRGBAPixels\n");
+
+ HW_WRITE_CLIPLOOP()
+ {
+ if (mask)
+ {
+ for (i=0;i<n;i++)
+ if (mask[i]) {
+ int fy = Y_FLIP(y[i]);
+ if (CLIPPIXEL( x[i], fy ))
+ WRITE_PIXEL( x[i], fy, p );
+ }
+ }
+ else
+ {
+ for (i=0;i<n;i++) {
+ int fy = Y_FLIP(y[i]);
+ if (CLIPPIXEL( x[i], fy ))
+ WRITE_PIXEL( x[i], fy, p );
+ }
+ }
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_WRITE_UNLOCK();
+}
+
+
+static void TAG(ReadRGBASpan)( struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ void *values)
+{
+ HW_READ_LOCK()
+ {
+ GLubyte (*rgba)[4] = (GLubyte (*)[4]) values;
+ GLint x1,n1;
+ LOCAL_VARS;
+
+ y = Y_FLIP(y);
+
+ if (DBG) fprintf(stderr, "ReadRGBASpan\n");
+
+ HW_READ_CLIPLOOP()
+ {
+ GLint i = 0;
+ CLIPSPAN(x,y,n,x1,n1,i);
+ for (;n1>0;i++,x1++,n1--)
+ READ_RGBA( rgba[i], x1, y );
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_READ_UNLOCK();
+}
+
+
+static void TAG(ReadRGBAPixels)( struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, const GLint x[], const GLint y[],
+ void *values )
+{
+ HW_READ_LOCK()
+ {
+ GLubyte (*rgba)[4] = (GLubyte (*)[4]) values;
+ GLuint i;
+ LOCAL_VARS;
+
+ if (DBG) fprintf(stderr, "ReadRGBAPixels\n");
+
+ HW_READ_CLIPLOOP()
+ {
+ for (i=0;i<n;i++) {
+ int fy = Y_FLIP( y[i] );
+ if (CLIPPIXEL( x[i], fy ))
+ READ_RGBA( rgba[i], x[i], fy );
+ }
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_READ_UNLOCK();
+}
+
+
+static void TAG(InitPointers)(struct gl_renderbuffer *rb)
+{
+ rb->PutRow = TAG(WriteRGBASpan);
+ rb->PutRowRGB = TAG(WriteRGBSpan);
+ rb->PutMonoRow = TAG(WriteMonoRGBASpan);
+ rb->PutValues = TAG(WriteRGBAPixels);
+ rb->PutMonoValues = TAG(WriteMonoRGBAPixels);
+ rb->GetValues = TAG(ReadRGBAPixels);
+ rb->GetRow = TAG(ReadRGBASpan);
+}
+
+
+#undef WRITE_PIXEL
+#undef WRITE_RGBA
+#undef READ_RGBA
+#undef TAG
diff --git a/mesalib/src/mesa/drivers/dri/common/spantmp2.h b/mesalib/src/mesa/drivers/dri/common/spantmp2.h
index 1dab7336b..160836a77 100644
--- a/mesalib/src/mesa/drivers/dri/common/spantmp2.h
+++ b/mesalib/src/mesa/drivers/dri/common/spantmp2.h
@@ -1,916 +1,1038 @@
-/*
- * Copyright 2000-2001 VA Linux Systems, Inc.
- * (C) Copyright IBM Corporation 2004
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * on the rights to use, copy, modify, merge, publish, distribute, sub
- * license, and/or sell copies of the Software, and to permit persons to whom
- * the Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file spantmp2.h
- *
- * Template file of span read / write functions.
- *
- * \author Keith Whitwell <keithw@tungstengraphics.com>
- * \author Gareth Hughes <gareth@nvidia.com>
- * \author Ian Romanick <idr@us.ibm.com>
- */
-
-#include "main/colormac.h"
-#include "spantmp_common.h"
-
-#ifndef DBG
-#define DBG 0
-#endif
-
-#ifndef HW_READ_CLIPLOOP
-#define HW_READ_CLIPLOOP() HW_CLIPLOOP()
-#endif
-
-#ifndef HW_WRITE_CLIPLOOP
-#define HW_WRITE_CLIPLOOP() HW_CLIPLOOP()
-#endif
-
-#if (SPANTMP_PIXEL_FMT == GL_RGB) && (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_SHORT_5_6_5)
-
-/**
- ** GL_RGB, GL_UNSIGNED_SHORT_5_6_5
- **/
-
-#ifndef GET_VALUE
-#ifndef GET_PTR
-#define GET_PTR(_x, _y) (buf + (_x) * 2 + (_y) * pitch)
-#endif
-
-#define GET_VALUE(_x, _y) *(volatile GLushort *)(GET_PTR(_x, _y))
-#define PUT_VALUE(_x, _y, _v) *(volatile GLushort *)(GET_PTR(_x, _y)) = (_v)
-#endif /* GET_VALUE */
-
-#define INIT_MONO_PIXEL(p, color) \
- p = PACK_COLOR_565( color[0], color[1], color[2] )
-
-#define WRITE_RGBA( _x, _y, r, g, b, a ) \
- PUT_VALUE(_x, _y, ((((int)r & 0xf8) << 8) | \
- (((int)g & 0xfc) << 3) | \
- (((int)b & 0xf8) >> 3))) \
-
-#define WRITE_PIXEL( _x, _y, p ) PUT_VALUE(_x, _y, p)
-
-#define READ_RGBA( rgba, _x, _y ) \
- do { \
- GLushort p = GET_VALUE(_x, _y); \
- rgba[0] = ((p >> 8) & 0xf8) * 255 / 0xf8; \
- rgba[1] = ((p >> 3) & 0xfc) * 255 / 0xfc; \
- rgba[2] = ((p << 3) & 0xf8) * 255 / 0xf8; \
- rgba[3] = 0xff; \
- } while (0)
-
-#elif (SPANTMP_PIXEL_FMT == GL_RGB) && (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_SHORT_5_6_5_REV)
-
-/**
- ** GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV
- **/
-
-#ifndef GET_VALUE
-#ifndef GET_PTR
-#define GET_PTR(_x, _y) (buf + (_x) * 2 + (_y) * pitch)
-#endif
-
-#define GET_VALUE(_x, _y) *(volatile GLushort *)(GET_PTR(_x, _y))
-#define PUT_VALUE(_x, _y, _v) *(volatile GLushort *)(GET_PTR(_x, _y)) = (_v)
-#endif /* GET_VALUE */
-
-#define INIT_MONO_PIXEL(p, color) \
- p = PACK_COLOR_565_REV( color[0], color[1], color[2] )
-
-#define WRITE_RGBA( _x, _y, r, g, b, a ) \
- PUT_VALUE(_x, _y, PACK_COLOR_565_REV( r, g, b ))
-
-#define WRITE_PIXEL( _x, _y, p ) PUT_VALUE(_x, _y, p)
-
-#define READ_RGBA( rgba, _x, _y ) \
- do { \
- GLushort p = GET_VALUE(_x, _y); \
- p = p << 8 | p >> 8; \
- rgba[0] = ((p >> 8) & 0xf8) * 255 / 0xf8; \
- rgba[1] = ((p >> 3) & 0xfc) * 255 / 0xfc; \
- rgba[2] = ((p << 3) & 0xf8) * 255 / 0xf8; \
- rgba[3] = 0xff; \
- } while (0)
-
-#elif (SPANTMP_PIXEL_FMT == GL_BGRA) && (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_SHORT_4_4_4_4)
-
-/**
- ** GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4
- **/
-
-#ifndef GET_VALUE
-#ifndef GET_PTR
-#define GET_PTR(_x, _y) (buf + (_x) * 2 + (_y) * pitch)
-#endif
-
-#define GET_VALUE(_x, _y) *(volatile GLushort *)(GET_PTR(_x, _y))
-#define PUT_VALUE(_x, _y, _v) *(volatile GLushort *)(GET_PTR(_x, _y)) = (_v)
-#endif /* GET_VALUE */
-
-#define INIT_MONO_PIXEL(p, color) \
- p = PACK_COLOR_4444_REV(color[3], color[0], color[1], color[2])
-
-#define WRITE_RGBA( _x, _y, r, g, b, a ) \
- PUT_VALUE(_x, _y, PACK_COLOR_4444_REV(a, r, g, b)) \
-
-#define WRITE_PIXEL( _x, _y, p ) PUT_VALUE(_x, _y, p)
-
-#define READ_RGBA( rgba, _x, _y ) \
- do { \
- GLushort p = GET_VALUE(_x, _y); \
- rgba[0] = ((p >> 0) & 0xf) * 0x11; \
- rgba[1] = ((p >> 12) & 0xf) * 0x11; \
- rgba[2] = ((p >> 4) & 0xf) * 0x11; \
- rgba[3] = ((p >> 8) & 0xf) * 0x11; \
- } while (0)
-
-
-#elif (SPANTMP_PIXEL_FMT == GL_BGRA) && (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_SHORT_4_4_4_4_REV)
-
-/**
- ** GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV
- **/
-
-#ifndef GET_VALUE
-#ifndef GET_PTR
-#define GET_PTR(_x, _y) (buf + (_x) * 2 + (_y) * pitch)
-#endif
-
-#define GET_VALUE(_x, _y) *(volatile GLushort *)(GET_PTR(_x, _y))
-#define PUT_VALUE(_x, _y, _v) *(volatile GLushort *)(GET_PTR(_x, _y)) = (_v)
-#endif /* GET_VALUE */
-
-#define INIT_MONO_PIXEL(p, color) \
- p = PACK_COLOR_4444(color[3], color[0], color[1], color[2])
-
-#define WRITE_RGBA( _x, _y, r, g, b, a ) \
- PUT_VALUE(_x, _y, PACK_COLOR_4444(a, r, g, b)) \
-
-#define WRITE_PIXEL( _x, _y, p ) PUT_VALUE(_x, _y, p)
-
-#define READ_RGBA( rgba, _x, _y ) \
- do { \
- GLushort p = GET_VALUE(_x, _y); \
- rgba[0] = ((p >> 8) & 0xf) * 0x11; \
- rgba[1] = ((p >> 4) & 0xf) * 0x11; \
- rgba[2] = ((p >> 0) & 0xf) * 0x11; \
- rgba[3] = ((p >> 12) & 0xf) * 0x11; \
- } while (0)
-
-
-#elif (SPANTMP_PIXEL_FMT == GL_BGRA) && (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_SHORT_1_5_5_5_REV)
-
-/**
- ** GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV
- **/
-
-#ifndef GET_VALUE
-#ifndef GET_PTR
-#define GET_PTR(_x, _y) (buf + (_x) * 2 + (_y) * pitch)
-#endif
-
-#define GET_VALUE(_x, _y) *(volatile GLushort *)(GET_PTR(_x, _y))
-#define PUT_VALUE(_x, _y, _v) *(volatile GLushort *)(GET_PTR(_x, _y)) = (_v)
-#endif /* GET_VALUE */
-
-#define INIT_MONO_PIXEL(p, color) \
- p = PACK_COLOR_1555(color[3], color[0], color[1], color[2])
-
-#define WRITE_RGBA( _x, _y, r, g, b, a ) \
- PUT_VALUE(_x, _y, PACK_COLOR_1555(a, r, g, b)) \
-
-#define WRITE_PIXEL( _x, _y, p ) PUT_VALUE(_x, _y, p)
-
-#define READ_RGBA( rgba, _x, _y ) \
- do { \
- GLushort p = GET_VALUE(_x, _y); \
- rgba[0] = ((p >> 7) & 0xf8) * 255 / 0xf8; \
- rgba[1] = ((p >> 2) & 0xf8) * 255 / 0xf8; \
- rgba[2] = ((p << 3) & 0xf8) * 255 / 0xf8; \
- rgba[3] = ((p >> 15) & 0x1) * 0xff; \
- } while (0)
-
-#elif (SPANTMP_PIXEL_FMT == GL_BGRA) && (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_SHORT_1_5_5_5)
-
-/**
- ** GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5
- **/
-
-#ifndef GET_VALUE
-#ifndef GET_PTR
-#define GET_PTR(_x, _y) (buf + (_x) * 2 + (_y) * pitch)
-#endif
-
-#define GET_VALUE(_x, _y) *(volatile GLushort *)(GET_PTR(_x, _y))
-#define PUT_VALUE(_x, _y, _v) *(volatile GLushort *)(GET_PTR(_x, _y)) = (_v)
-#endif /* GET_VALUE */
-
-#define INIT_MONO_PIXEL(p, color) \
- p = PACK_COLOR_1555_REV(color[3], color[0], color[1], color[2])
-
-#define WRITE_RGBA( _x, _y, r, g, b, a ) \
- PUT_VALUE(_x, _y, PACK_COLOR_1555_REV(a, r, g, b)) \
-
-#define WRITE_PIXEL( _x, _y, p ) PUT_VALUE(_x, _y, p)
-
-#define READ_RGBA( rgba, _x, _y ) \
- do { \
- GLushort p = GET_VALUE(_x, _y); \
- p = p << 8 | p >> 8; \
- rgba[0] = ((p >> 7) & 0xf8) * 255 / 0xf8; \
- rgba[1] = ((p >> 2) & 0xf8) * 255 / 0xf8; \
- rgba[2] = ((p << 3) & 0xf8) * 255 / 0xf8; \
- rgba[3] = ((p >> 15) & 0x1) * 0xff; \
- } while (0)
-
-#elif (SPANTMP_PIXEL_FMT == GL_BGRA) && (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_INT_8_8_8_8_REV)
-
-/**
- ** GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV
- **/
-
-#ifndef GET_VALUE
-#ifndef GET_PTR
-#define GET_PTR(_x, _y) ( buf + (_x) * 4 + (_y) * pitch)
-#endif
-
-#define GET_VALUE(_x, _y) *(volatile GLuint *)(GET_PTR(_x, _y))
-#define PUT_VALUE(_x, _y, _v) *(volatile GLuint *)(GET_PTR(_x, _y)) = (_v)
-#endif /* GET_VALUE */
-
-# define INIT_MONO_PIXEL(p, color) \
- p = PACK_COLOR_8888(color[3], color[0], color[1], color[2])
-
-# define WRITE_RGBA(_x, _y, r, g, b, a) \
- PUT_VALUE(_x, _y, ((r << 16) | \
- (g << 8) | \
- (b << 0) | \
- (a << 24)))
-
-#define WRITE_PIXEL(_x, _y, p) PUT_VALUE(_x, _y, p)
-
-# if defined( USE_X86_ASM )
-# define READ_RGBA(rgba, _x, _y) \
- do { \
- GLuint p = GET_VALUE(_x, _y); \
- __asm__ __volatile__( "bswap %0; rorl $8, %0" \
- : "=r" (p) : "0" (p) ); \
- ((GLuint *)rgba)[0] = p; \
- } while (0)
-# elif defined( MESA_BIG_ENDIAN )
- /* On PowerPC with GCC 3.4.2 the shift madness below becomes a single
- * rotlwi instruction. It also produces good code on SPARC.
- */
-# define READ_RGBA( rgba, _x, _y ) \
- do { \
- GLuint p = GET_VALUE(_x, _y); \
- GLuint t = p; \
- *((uint32_t *) rgba) = (t >> 24) | (p << 8); \
- } while (0)
-# else
-# define READ_RGBA( rgba, _x, _y ) \
- do { \
- GLuint p = GET_VALUE(_x, _y); \
- rgba[0] = (p >> 16) & 0xff; \
- rgba[1] = (p >> 8) & 0xff; \
- rgba[2] = (p >> 0) & 0xff; \
- rgba[3] = (p >> 24) & 0xff; \
- } while (0)
-# endif
-
-#elif (SPANTMP_PIXEL_FMT == GL_BGRA) && (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_INT_8_8_8_8)
-
-/**
- ** GL_BGRA, GL_UNSIGNED_INT_8_8_8_8
- **/
-
-#ifndef GET_VALUE
-#ifndef GET_PTR
-#define GET_PTR(_x, _y) ( buf + (_x) * 4 + (_y) * pitch)
-#endif
-
-#define GET_VALUE(_x, _y) *(volatile GLuint *)(GET_PTR(_x, _y))
-#define PUT_VALUE(_x, _y, _v) *(volatile GLuint *)(GET_PTR(_x, _y)) = (_v)
-#endif /* GET_VALUE */
-
-# define INIT_MONO_PIXEL(p, color) \
- p = PACK_COLOR_8888(color[2], color[1], color[0], color[3])
-
-# define WRITE_RGBA(_x, _y, r, g, b, a) \
- PUT_VALUE(_x, _y, ((r << 8) | \
- (g << 16) | \
- (b << 24) | \
- (a << 0)))
-
-#define WRITE_PIXEL(_x, _y, p) PUT_VALUE(_x, _y, p)
-
-# if defined( USE_X86_ASM )
-# define READ_RGBA(rgba, _x, _y) \
- do { \
- GLuint p = GET_VALUE(_x, _y); \
- __asm__ __volatile__( "rorl $8, %0" \
- : "=r" (p) : "0" (p) ); \
- ((GLuint *)rgba)[0] = p; \
- } while (0)
-# elif defined( MESA_BIG_ENDIAN )
- /* On PowerPC with GCC 3.4.2 the shift madness below becomes a single
- * rotlwi instruction. It also produces good code on SPARC.
- */
-# define READ_RGBA( rgba, _x, _y ) \
- do { \
- GLuint p = CPU_TO_LE32(GET_VALUE(_x, _y)); \
- GLuint t = p; \
- *((uint32_t *) rgba) = (t >> 24) | (p << 8); \
- } while (0)
-# else
-# define READ_RGBA( rgba, _x, _y ) \
- do { \
- GLuint p = GET_VALUE(_x, _y); \
- rgba[0] = (p >> 8) & 0xff; \
- rgba[1] = (p >> 16) & 0xff; \
- rgba[2] = (p >> 24) & 0xff; \
- rgba[3] = (p >> 0) & 0xff; \
- } while (0)
-# endif
-
-#elif (SPANTMP_PIXEL_FMT == GL_BGR) && (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_INT_8_8_8_8_REV)
-
-/**
- ** GL_BGR, GL_UNSIGNED_INT_8_8_8_8_REV
- **
- ** This is really for MESA_FORMAT_XRGB8888. The spantmp code needs to be
- ** kicked to the curb, and we need to just code-gen this.
- **/
-
-#ifndef GET_VALUE
-#ifndef GET_PTR
-#define GET_PTR(_x, _y) ( buf + (_x) * 4 + (_y) * pitch)
-#endif
-
-#define GET_VALUE(_x, _y) *(volatile GLuint *)(GET_PTR(_x, _y))
-#define PUT_VALUE(_x, _y, _v) *(volatile GLuint *)(GET_PTR(_x, _y)) = (_v)
-#endif /* GET_VALUE */
-
-# define INIT_MONO_PIXEL(p, color) \
- p = PACK_COLOR_8888(0xff, color[0], color[1], color[2])
-
-# define WRITE_RGBA(_x, _y, r, g, b, a) \
- PUT_VALUE(_x, _y, ((r << 16) | \
- (g << 8) | \
- (b << 0) | \
- (0xff << 24)))
-
-#define WRITE_PIXEL(_x, _y, p) PUT_VALUE(_x, _y, p)
-
-# if defined( USE_X86_ASM )
-# define READ_RGBA(rgba, _x, _y) \
- do { \
- GLuint p = GET_VALUE(_x, _y); \
- __asm__ __volatile__( "bswap %0; rorl $8, %0" \
- : "=r" (p) : "0" (p) ); \
- ((GLuint *)rgba)[0] = p | 0xff000000; \
- } while (0)
-# elif defined( MESA_BIG_ENDIAN )
- /* On PowerPC with GCC 3.4.2 the shift madness below becomes a single
- * rotlwi instruction. It also produces good code on SPARC.
- */
-# define READ_RGBA( rgba, _x, _y ) \
- do { \
- GLuint p = GET_VALUE(_x, _y); \
- *((uint32_t *) rgba) = (p << 8) | 0xff; \
- } while (0)
-# else
-# define READ_RGBA( rgba, _x, _y ) \
- do { \
- GLuint p = GET_VALUE(_x, _y); \
- rgba[0] = (p >> 16) & 0xff; \
- rgba[1] = (p >> 8) & 0xff; \
- rgba[2] = (p >> 0) & 0xff; \
- rgba[3] = 0xff; \
- } while (0)
-# endif
-
-#elif (SPANTMP_PIXEL_FMT == GL_ALPHA) && (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_BYTE)
-
-/**
- ** GL_ALPHA, GL_UNSIGNED_BYTE
- **/
-
-#ifndef GET_VALUE
-#ifndef GET_PTR
-#define GET_PTR(_x, _y) ( buf + (_x) + (_y) * pitch)
-#endif
-
-#define GET_VALUE(_x, _y) *(volatile GLubyte *)(GET_PTR(_x, _y))
-#define PUT_VALUE(_x, _y, _v) *(volatile GLubyte *)(GET_PTR(_x, _y)) = (_v)
-#endif /* GET_VALUE */
-
-# define INIT_MONO_PIXEL(p, color) \
- p = color[3]
-
-# define WRITE_RGBA(_x, _y, r, g, b, a) \
- PUT_VALUE(_x, _y, a | (r & 0 /* quiet warnings */))
-
-#define WRITE_PIXEL(_x, _y, p) PUT_VALUE(_x, _y, p)
-
-#define READ_RGBA( rgba, _x, _y ) \
- do { \
- GLubyte p = GET_VALUE(_x, _y); \
- rgba[0] = 0; \
- rgba[1] = 0; \
- rgba[2] = 0; \
- rgba[3] = p; \
- } while (0)
-
-#else
-#error SPANTMP_PIXEL_FMT must be set to a valid value!
-#endif
-
-
-
-/**
- ** Assembly routines.
- **/
-
-#if defined( USE_MMX_ASM ) || defined( USE_SSE_ASM )
-#include "x86/read_rgba_span_x86.h"
-#include "x86/common_x86_asm.h"
-#endif
-
-static void TAG(WriteRGBASpan)( GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, GLint x, GLint y,
- const void *values, const GLubyte mask[] )
-{
- HW_WRITE_LOCK()
- {
- const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
- GLint x1;
- GLint n1;
- LOCAL_VARS;
-
- y = Y_FLIP(y);
-
- HW_WRITE_CLIPLOOP()
- {
- GLint i = 0;
- CLIPSPAN(x,y,n,x1,n1,i);
-
- if (DBG) fprintf(stderr, "WriteRGBASpan %d..%d (x1 %d)\n",
- (int)i, (int)n1, (int)x1);
-
- if (mask)
- {
- for (;n1>0;i++,x1++,n1--)
- if (mask[i])
- WRITE_RGBA( x1, y,
- rgba[i][0], rgba[i][1],
- rgba[i][2], rgba[i][3] );
- }
- else
- {
- for (;n1>0;i++,x1++,n1--)
- WRITE_RGBA( x1, y,
- rgba[i][0], rgba[i][1],
- rgba[i][2], rgba[i][3] );
- }
- }
- HW_ENDCLIPLOOP();
- }
- HW_WRITE_UNLOCK();
-}
-
-static void TAG(WriteRGBSpan)( GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, GLint x, GLint y,
- const void *values, const GLubyte mask[] )
-{
- HW_WRITE_LOCK()
- {
- const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
- GLint x1;
- GLint n1;
- LOCAL_VARS;
-
- y = Y_FLIP(y);
-
- HW_WRITE_CLIPLOOP()
- {
- GLint i = 0;
- CLIPSPAN(x,y,n,x1,n1,i);
-
- if (DBG) fprintf(stderr, "WriteRGBSpan %d..%d (x1 %d)\n",
- (int)i, (int)n1, (int)x1);
-
- if (mask)
- {
- for (;n1>0;i++,x1++,n1--)
- if (mask[i])
- WRITE_RGBA( x1, y, rgb[i][0], rgb[i][1], rgb[i][2], 255 );
- }
- else
- {
- for (;n1>0;i++,x1++,n1--)
- WRITE_RGBA( x1, y, rgb[i][0], rgb[i][1], rgb[i][2], 255 );
- }
- }
- HW_ENDCLIPLOOP();
- }
- HW_WRITE_UNLOCK();
-}
-
-static void TAG(WriteRGBAPixels)( GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, const GLint x[], const GLint y[],
- const void *values, const GLubyte mask[] )
-{
- HW_WRITE_LOCK()
- {
- const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
- GLint i;
- LOCAL_VARS;
-
- if (DBG) fprintf(stderr, "WriteRGBAPixels\n");
-
- HW_WRITE_CLIPLOOP()
- {
- if (mask)
- {
- for (i=0;i<n;i++)
- {
- if (mask[i]) {
- const int fy = Y_FLIP(y[i]);
- if (CLIPPIXEL(x[i],fy))
- WRITE_RGBA( x[i], fy,
- rgba[i][0], rgba[i][1],
- rgba[i][2], rgba[i][3] );
- }
- }
- }
- else
- {
- for (i=0;i<n;i++)
- {
- const int fy = Y_FLIP(y[i]);
- if (CLIPPIXEL(x[i],fy))
- WRITE_RGBA( x[i], fy,
- rgba[i][0], rgba[i][1],
- rgba[i][2], rgba[i][3] );
- }
- }
- }
- HW_ENDCLIPLOOP();
- }
- HW_WRITE_UNLOCK();
-}
-
-
-static void TAG(WriteMonoRGBASpan)( GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, GLint x, GLint y,
- const void *value, const GLubyte mask[] )
-{
- HW_WRITE_LOCK()
- {
- const GLubyte *color = (const GLubyte *) value;
- GLint x1;
- GLint n1;
- LOCAL_VARS;
- INIT_MONO_PIXEL(p, color);
-
- y = Y_FLIP( y );
-
- if (DBG) fprintf(stderr, "WriteMonoRGBASpan\n");
-
- HW_WRITE_CLIPLOOP()
- {
- GLint i = 0;
- CLIPSPAN(x,y,n,x1,n1,i);
- if (mask)
- {
- for (;n1>0;i++,x1++,n1--)
- if (mask[i])
- WRITE_PIXEL( x1, y, p );
- }
- else
- {
- for (;n1>0;i++,x1++,n1--)
- WRITE_PIXEL( x1, y, p );
- }
- }
- HW_ENDCLIPLOOP();
- }
- HW_WRITE_UNLOCK();
-}
-
-
-static void TAG(WriteMonoRGBAPixels)( GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n,
- const GLint x[], const GLint y[],
- const void *value,
- const GLubyte mask[] )
-{
- HW_WRITE_LOCK()
- {
- const GLubyte *color = (const GLubyte *) value;
- GLint i;
- LOCAL_VARS;
- INIT_MONO_PIXEL(p, color);
-
- if (DBG) fprintf(stderr, "WriteMonoRGBAPixels\n");
-
- HW_WRITE_CLIPLOOP()
- {
- if (mask)
- {
- for (i=0;i<n;i++)
- if (mask[i]) {
- int fy = Y_FLIP(y[i]);
- if (CLIPPIXEL( x[i], fy ))
- WRITE_PIXEL( x[i], fy, p );
- }
- }
- else
- {
- for (i=0;i<n;i++) {
- int fy = Y_FLIP(y[i]);
- if (CLIPPIXEL( x[i], fy ))
- WRITE_PIXEL( x[i], fy, p );
- }
- }
- }
- HW_ENDCLIPLOOP();
- }
- HW_WRITE_UNLOCK();
-}
-
-
-static void TAG(ReadRGBASpan)( GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, GLint x, GLint y, void *values)
-{
- HW_READ_LOCK()
- {
- GLubyte (*rgba)[4] = (GLubyte (*)[4]) values;
- GLint x1,n1;
- LOCAL_VARS;
-
- y = Y_FLIP(y);
-
- if (DBG) fprintf(stderr, "ReadRGBASpan\n");
-
- HW_READ_CLIPLOOP()
- {
- GLint i = 0;
- CLIPSPAN(x,y,n,x1,n1,i);
- for (;n1>0;i++,x1++,n1--)
- READ_RGBA( rgba[i], x1, y );
- }
- HW_ENDCLIPLOOP();
- }
- HW_READ_UNLOCK();
-}
-
-
-#if defined(GET_PTR) && \
- defined(USE_MMX_ASM) && \
- (((SPANTMP_PIXEL_FMT == GL_BGRA) && \
- (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_INT_8_8_8_8_REV)) || \
- ((SPANTMP_PIXEL_FMT == GL_RGB) && \
- (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_SHORT_5_6_5)))
-static void TAG2(ReadRGBASpan,_MMX)( GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, GLint x, GLint y, void *values)
-{
-#ifndef USE_INNER_EMMS
- /* The EMMS instruction is directly in-lined here because using GCC's
- * built-in _mm_empty function was found to utterly destroy performance.
- */
- __asm__ __volatile__( "emms" );
-#endif
-
- HW_READ_LOCK()
- {
- GLubyte (*rgba)[4] = (GLubyte (*)[4]) values;
- GLint x1,n1;
- LOCAL_VARS;
-
- y = Y_FLIP(y);
-
- if (DBG) fprintf(stderr, "ReadRGBASpan\n");
-
- HW_READ_CLIPLOOP()
- {
- GLint i = 0;
- CLIPSPAN(x,y,n,x1,n1,i);
-
- {
- const void * src = GET_PTR( x1, y );
-#if (SPANTMP_PIXEL_FMT == GL_RGB) && \
- (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_SHORT_5_6_5)
- _generic_read_RGBA_span_RGB565_MMX( src, rgba[i], n1 );
-#else
- _generic_read_RGBA_span_BGRA8888_REV_MMX( src, rgba[i], n1 );
-#endif
- }
- }
- HW_ENDCLIPLOOP();
- }
- HW_READ_UNLOCK();
-#ifndef USE_INNER_EMMS
- __asm__ __volatile__( "emms" );
-#endif
-}
-#endif
-
-
-#if defined(GET_PTR) && \
- defined(USE_SSE_ASM) && \
- (SPANTMP_PIXEL_FMT == GL_BGRA) && \
- (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_INT_8_8_8_8_REV)
-static void TAG2(ReadRGBASpan,_SSE2)( GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, GLint x, GLint y,
- void *values)
-{
- HW_READ_LOCK()
- {
- GLubyte (*rgba)[4] = (GLubyte (*)[4]) values;
- GLint x1,n1;
- LOCAL_VARS;
-
- y = Y_FLIP(y);
-
- if (DBG) fprintf(stderr, "ReadRGBASpan\n");
-
- HW_READ_CLIPLOOP()
- {
- GLint i = 0;
- CLIPSPAN(x,y,n,x1,n1,i);
-
- {
- const void * src = GET_PTR( x1, y );
- _generic_read_RGBA_span_BGRA8888_REV_SSE2( src, rgba[i], n1 );
- }
- }
- HW_ENDCLIPLOOP();
- }
- HW_READ_UNLOCK();
-}
-#endif
-
-#if defined(GET_PTR) && \
- defined(USE_SSE_ASM) && \
- (SPANTMP_PIXEL_FMT == GL_BGRA) && \
- (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_INT_8_8_8_8_REV)
-static void TAG2(ReadRGBASpan,_SSE)( GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, GLint x, GLint y,
- void *values)
-{
-#ifndef USE_INNER_EMMS
- /* The EMMS instruction is directly in-lined here because using GCC's
- * built-in _mm_empty function was found to utterly destroy performance.
- */
- __asm__ __volatile__( "emms" );
-#endif
-
- HW_READ_LOCK()
- {
- GLubyte (*rgba)[4] = (GLubyte (*)[4]) values;
- GLint x1,n1;
- LOCAL_VARS;
-
- y = Y_FLIP(y);
-
- if (DBG) fprintf(stderr, "ReadRGBASpan\n");
-
- HW_READ_CLIPLOOP()
- {
- GLint i = 0;
- CLIPSPAN(x,y,n,x1,n1,i);
-
- {
- const void * src = GET_PTR( x1, y );
- _generic_read_RGBA_span_BGRA8888_REV_SSE( src, rgba[i], n1 );
- }
- }
- HW_ENDCLIPLOOP();
- }
- HW_READ_UNLOCK();
-#ifndef USE_INNER_EMMS
- __asm__ __volatile__( "emms" );
-#endif
-}
-#endif
-
-
-static void TAG(ReadRGBAPixels)( GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, const GLint x[], const GLint y[],
- void *values )
-{
- HW_READ_LOCK()
- {
- GLubyte (*rgba)[4] = (GLubyte (*)[4]) values;
- GLint i;
- LOCAL_VARS;
-
- if (DBG) fprintf(stderr, "ReadRGBAPixels\n");
-
- HW_READ_CLIPLOOP()
- {
- for (i=0;i<n;i++) {
- int fy = Y_FLIP( y[i] );
- if (CLIPPIXEL( x[i], fy ))
- READ_RGBA( rgba[i], x[i], fy );
- }
- }
- HW_ENDCLIPLOOP();
- }
- HW_READ_UNLOCK();
-}
-
-static void TAG(InitPointers)(struct gl_renderbuffer *rb)
-{
- rb->PutRow = TAG(WriteRGBASpan);
- rb->PutRowRGB = TAG(WriteRGBSpan);
- rb->PutMonoRow = TAG(WriteMonoRGBASpan);
- rb->PutValues = TAG(WriteRGBAPixels);
- rb->PutMonoValues = TAG(WriteMonoRGBAPixels);
- rb->GetValues = TAG(ReadRGBAPixels);
-
-#if defined(GET_PTR)
-#if defined(USE_SSE_ASM) && \
- (SPANTMP_PIXEL_FMT == GL_BGRA) && \
- (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_INT_8_8_8_8_REV)
- if ( cpu_has_xmm2 ) {
- if (DBG) fprintf( stderr, "Using %s version of GetRow\n", "SSE2" );
- rb->GetRow = TAG2(ReadRGBASpan, _SSE2);
- }
- else
-#endif
-#if defined(USE_SSE_ASM) && \
- (SPANTMP_PIXEL_FMT == GL_BGRA) && \
- (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_INT_8_8_8_8_REV)
- if ( cpu_has_xmm ) {
- if (DBG) fprintf( stderr, "Using %s version of GetRow\n", "SSE" );
- rb->GetRow = TAG2(ReadRGBASpan, _SSE);
- }
- else
-#endif
-#if defined(USE_MMX_ASM) && \
- (((SPANTMP_PIXEL_FMT == GL_BGRA) && \
- (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_INT_8_8_8_8_REV)) || \
- ((SPANTMP_PIXEL_FMT == GL_RGB) && \
- (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_SHORT_5_6_5)))
- if ( cpu_has_mmx ) {
- if (DBG) fprintf( stderr, "Using %s version of GetRow\n", "MMX" );
- rb->GetRow = TAG2(ReadRGBASpan, _MMX);
- }
- else
-#endif
-#endif /* GET_PTR */
- {
- if (DBG) fprintf( stderr, "Using %s version of GetRow\n", "C" );
- rb->GetRow = TAG(ReadRGBASpan);
- }
-
-}
-
-
-#undef INIT_MONO_PIXEL
-#undef WRITE_PIXEL
-#undef WRITE_RGBA
-#undef READ_RGBA
-#undef TAG
-#undef TAG2
-#undef GET_VALUE
-#undef PUT_VALUE
-#undef GET_PTR
-#undef SPANTMP_PIXEL_FMT
-#undef SPANTMP_PIXEL_TYPE
+/*
+ * Copyright 2000-2001 VA Linux Systems, Inc.
+ * (C) Copyright IBM Corporation 2004
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file spantmp2.h
+ *
+ * Template file of span read / write functions.
+ *
+ * \author Keith Whitwell <keithw@tungstengraphics.com>
+ * \author Gareth Hughes <gareth@nvidia.com>
+ * \author Ian Romanick <idr@us.ibm.com>
+ */
+
+#include "main/colormac.h"
+#include "spantmp_common.h"
+
+#ifndef DBG
+#define DBG 0
+#endif
+
+#ifndef HW_READ_CLIPLOOP
+#define HW_READ_CLIPLOOP() HW_CLIPLOOP()
+#endif
+
+#ifndef HW_WRITE_CLIPLOOP
+#define HW_WRITE_CLIPLOOP() HW_CLIPLOOP()
+#endif
+
+#ifdef SPANTMP_MESA_FMT
+#define SPANTMP_PIXEL_FMT GL_NONE
+#define SPANTMP_PIXEL_TYPE GL_NONE
+#endif
+
+#ifndef SPANTMP_MESA_FMT
+#define SPANTMP_MESA_FMT MESA_FORMAT_COUNT
+#endif
+
+#if (SPANTMP_PIXEL_FMT == GL_RGB) && (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_SHORT_5_6_5)
+
+/**
+ ** GL_RGB, GL_UNSIGNED_SHORT_5_6_5
+ **/
+
+#ifndef GET_VALUE
+#ifndef GET_PTR
+#define GET_PTR(_x, _y) (buf + (_x) * 2 + (_y) * pitch)
+#endif
+
+#define GET_VALUE(_x, _y) *(volatile GLushort *)(GET_PTR(_x, _y))
+#define PUT_VALUE(_x, _y, _v) *(volatile GLushort *)(GET_PTR(_x, _y)) = (_v)
+#endif /* GET_VALUE */
+
+#define INIT_MONO_PIXEL(p, color) \
+ p = PACK_COLOR_565( color[0], color[1], color[2] )
+
+#define WRITE_RGBA( _x, _y, r, g, b, a ) \
+ PUT_VALUE(_x, _y, ((((int)r & 0xf8) << 8) | \
+ (((int)g & 0xfc) << 3) | \
+ (((int)b & 0xf8) >> 3))) \
+
+#define WRITE_PIXEL( _x, _y, p ) PUT_VALUE(_x, _y, p)
+
+#define READ_RGBA( rgba, _x, _y ) \
+ do { \
+ GLushort p = GET_VALUE(_x, _y); \
+ rgba[0] = ((p >> 8) & 0xf8) * 255 / 0xf8; \
+ rgba[1] = ((p >> 3) & 0xfc) * 255 / 0xfc; \
+ rgba[2] = ((p << 3) & 0xf8) * 255 / 0xf8; \
+ rgba[3] = 0xff; \
+ } while (0)
+
+#elif (SPANTMP_PIXEL_FMT == GL_RGB) && (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_SHORT_5_6_5_REV)
+
+/**
+ ** GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV
+ **/
+
+#ifndef GET_VALUE
+#ifndef GET_PTR
+#define GET_PTR(_x, _y) (buf + (_x) * 2 + (_y) * pitch)
+#endif
+
+#define GET_VALUE(_x, _y) *(volatile GLushort *)(GET_PTR(_x, _y))
+#define PUT_VALUE(_x, _y, _v) *(volatile GLushort *)(GET_PTR(_x, _y)) = (_v)
+#endif /* GET_VALUE */
+
+#define INIT_MONO_PIXEL(p, color) \
+ p = PACK_COLOR_565_REV( color[0], color[1], color[2] )
+
+#define WRITE_RGBA( _x, _y, r, g, b, a ) \
+ PUT_VALUE(_x, _y, PACK_COLOR_565_REV( r, g, b ))
+
+#define WRITE_PIXEL( _x, _y, p ) PUT_VALUE(_x, _y, p)
+
+#define READ_RGBA( rgba, _x, _y ) \
+ do { \
+ GLushort p = GET_VALUE(_x, _y); \
+ p = p << 8 | p >> 8; \
+ rgba[0] = ((p >> 8) & 0xf8) * 255 / 0xf8; \
+ rgba[1] = ((p >> 3) & 0xfc) * 255 / 0xfc; \
+ rgba[2] = ((p << 3) & 0xf8) * 255 / 0xf8; \
+ rgba[3] = 0xff; \
+ } while (0)
+
+#elif (SPANTMP_PIXEL_FMT == GL_BGRA) && (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_SHORT_4_4_4_4)
+
+/**
+ ** GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4
+ **/
+
+#ifndef GET_VALUE
+#ifndef GET_PTR
+#define GET_PTR(_x, _y) (buf + (_x) * 2 + (_y) * pitch)
+#endif
+
+#define GET_VALUE(_x, _y) *(volatile GLushort *)(GET_PTR(_x, _y))
+#define PUT_VALUE(_x, _y, _v) *(volatile GLushort *)(GET_PTR(_x, _y)) = (_v)
+#endif /* GET_VALUE */
+
+#define INIT_MONO_PIXEL(p, color) \
+ p = PACK_COLOR_4444_REV(color[3], color[0], color[1], color[2])
+
+#define WRITE_RGBA( _x, _y, r, g, b, a ) \
+ PUT_VALUE(_x, _y, PACK_COLOR_4444_REV(a, r, g, b)) \
+
+#define WRITE_PIXEL( _x, _y, p ) PUT_VALUE(_x, _y, p)
+
+#define READ_RGBA( rgba, _x, _y ) \
+ do { \
+ GLushort p = GET_VALUE(_x, _y); \
+ rgba[0] = ((p >> 0) & 0xf) * 0x11; \
+ rgba[1] = ((p >> 12) & 0xf) * 0x11; \
+ rgba[2] = ((p >> 4) & 0xf) * 0x11; \
+ rgba[3] = ((p >> 8) & 0xf) * 0x11; \
+ } while (0)
+
+
+#elif (SPANTMP_PIXEL_FMT == GL_BGRA) && (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_SHORT_4_4_4_4_REV)
+
+/**
+ ** GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV
+ **/
+
+#ifndef GET_VALUE
+#ifndef GET_PTR
+#define GET_PTR(_x, _y) (buf + (_x) * 2 + (_y) * pitch)
+#endif
+
+#define GET_VALUE(_x, _y) *(volatile GLushort *)(GET_PTR(_x, _y))
+#define PUT_VALUE(_x, _y, _v) *(volatile GLushort *)(GET_PTR(_x, _y)) = (_v)
+#endif /* GET_VALUE */
+
+#define INIT_MONO_PIXEL(p, color) \
+ p = PACK_COLOR_4444(color[3], color[0], color[1], color[2])
+
+#define WRITE_RGBA( _x, _y, r, g, b, a ) \
+ PUT_VALUE(_x, _y, PACK_COLOR_4444(a, r, g, b)) \
+
+#define WRITE_PIXEL( _x, _y, p ) PUT_VALUE(_x, _y, p)
+
+#define READ_RGBA( rgba, _x, _y ) \
+ do { \
+ GLushort p = GET_VALUE(_x, _y); \
+ rgba[0] = ((p >> 8) & 0xf) * 0x11; \
+ rgba[1] = ((p >> 4) & 0xf) * 0x11; \
+ rgba[2] = ((p >> 0) & 0xf) * 0x11; \
+ rgba[3] = ((p >> 12) & 0xf) * 0x11; \
+ } while (0)
+
+
+#elif (SPANTMP_PIXEL_FMT == GL_BGRA) && (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_SHORT_1_5_5_5_REV)
+
+/**
+ ** GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV
+ **/
+
+#ifndef GET_VALUE
+#ifndef GET_PTR
+#define GET_PTR(_x, _y) (buf + (_x) * 2 + (_y) * pitch)
+#endif
+
+#define GET_VALUE(_x, _y) *(volatile GLushort *)(GET_PTR(_x, _y))
+#define PUT_VALUE(_x, _y, _v) *(volatile GLushort *)(GET_PTR(_x, _y)) = (_v)
+#endif /* GET_VALUE */
+
+#define INIT_MONO_PIXEL(p, color) \
+ p = PACK_COLOR_1555(color[3], color[0], color[1], color[2])
+
+#define WRITE_RGBA( _x, _y, r, g, b, a ) \
+ PUT_VALUE(_x, _y, PACK_COLOR_1555(a, r, g, b)) \
+
+#define WRITE_PIXEL( _x, _y, p ) PUT_VALUE(_x, _y, p)
+
+#define READ_RGBA( rgba, _x, _y ) \
+ do { \
+ GLushort p = GET_VALUE(_x, _y); \
+ rgba[0] = ((p >> 7) & 0xf8) * 255 / 0xf8; \
+ rgba[1] = ((p >> 2) & 0xf8) * 255 / 0xf8; \
+ rgba[2] = ((p << 3) & 0xf8) * 255 / 0xf8; \
+ rgba[3] = ((p >> 15) & 0x1) * 0xff; \
+ } while (0)
+
+#elif (SPANTMP_PIXEL_FMT == GL_BGRA) && (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_SHORT_1_5_5_5)
+
+/**
+ ** GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5
+ **/
+
+#ifndef GET_VALUE
+#ifndef GET_PTR
+#define GET_PTR(_x, _y) (buf + (_x) * 2 + (_y) * pitch)
+#endif
+
+#define GET_VALUE(_x, _y) *(volatile GLushort *)(GET_PTR(_x, _y))
+#define PUT_VALUE(_x, _y, _v) *(volatile GLushort *)(GET_PTR(_x, _y)) = (_v)
+#endif /* GET_VALUE */
+
+#define INIT_MONO_PIXEL(p, color) \
+ p = PACK_COLOR_1555_REV(color[3], color[0], color[1], color[2])
+
+#define WRITE_RGBA( _x, _y, r, g, b, a ) \
+ PUT_VALUE(_x, _y, PACK_COLOR_1555_REV(a, r, g, b)) \
+
+#define WRITE_PIXEL( _x, _y, p ) PUT_VALUE(_x, _y, p)
+
+#define READ_RGBA( rgba, _x, _y ) \
+ do { \
+ GLushort p = GET_VALUE(_x, _y); \
+ p = p << 8 | p >> 8; \
+ rgba[0] = ((p >> 7) & 0xf8) * 255 / 0xf8; \
+ rgba[1] = ((p >> 2) & 0xf8) * 255 / 0xf8; \
+ rgba[2] = ((p << 3) & 0xf8) * 255 / 0xf8; \
+ rgba[3] = ((p >> 15) & 0x1) * 0xff; \
+ } while (0)
+
+#elif (SPANTMP_PIXEL_FMT == GL_BGRA) && (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_INT_8_8_8_8_REV)
+
+/**
+ ** GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV
+ **/
+
+#ifndef GET_VALUE
+#ifndef GET_PTR
+#define GET_PTR(_x, _y) ( buf + (_x) * 4 + (_y) * pitch)
+#endif
+
+#define GET_VALUE(_x, _y) *(volatile GLuint *)(GET_PTR(_x, _y))
+#define PUT_VALUE(_x, _y, _v) *(volatile GLuint *)(GET_PTR(_x, _y)) = (_v)
+#endif /* GET_VALUE */
+
+# define INIT_MONO_PIXEL(p, color) \
+ p = PACK_COLOR_8888(color[3], color[0], color[1], color[2])
+
+# define WRITE_RGBA(_x, _y, r, g, b, a) \
+ PUT_VALUE(_x, _y, ((r << 16) | \
+ (g << 8) | \
+ (b << 0) | \
+ (a << 24)))
+
+#define WRITE_PIXEL(_x, _y, p) PUT_VALUE(_x, _y, p)
+
+# if defined( USE_X86_ASM )
+# define READ_RGBA(rgba, _x, _y) \
+ do { \
+ GLuint p = GET_VALUE(_x, _y); \
+ __asm__ __volatile__( "bswap %0; rorl $8, %0" \
+ : "=r" (p) : "0" (p) ); \
+ ((GLuint *)rgba)[0] = p; \
+ } while (0)
+# elif defined( MESA_BIG_ENDIAN )
+ /* On PowerPC with GCC 3.4.2 the shift madness below becomes a single
+ * rotlwi instruction. It also produces good code on SPARC.
+ */
+# define READ_RGBA( rgba, _x, _y ) \
+ do { \
+ GLuint p = GET_VALUE(_x, _y); \
+ GLuint t = p; \
+ *((uint32_t *) rgba) = (t >> 24) | (p << 8); \
+ } while (0)
+# else
+# define READ_RGBA( rgba, _x, _y ) \
+ do { \
+ GLuint p = GET_VALUE(_x, _y); \
+ rgba[0] = (p >> 16) & 0xff; \
+ rgba[1] = (p >> 8) & 0xff; \
+ rgba[2] = (p >> 0) & 0xff; \
+ rgba[3] = (p >> 24) & 0xff; \
+ } while (0)
+# endif
+
+#elif (SPANTMP_PIXEL_FMT == GL_BGRA) && (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_INT_8_8_8_8)
+
+/**
+ ** GL_BGRA, GL_UNSIGNED_INT_8_8_8_8
+ **/
+
+#ifndef GET_VALUE
+#ifndef GET_PTR
+#define GET_PTR(_x, _y) ( buf + (_x) * 4 + (_y) * pitch)
+#endif
+
+#define GET_VALUE(_x, _y) *(volatile GLuint *)(GET_PTR(_x, _y))
+#define PUT_VALUE(_x, _y, _v) *(volatile GLuint *)(GET_PTR(_x, _y)) = (_v)
+#endif /* GET_VALUE */
+
+# define INIT_MONO_PIXEL(p, color) \
+ p = PACK_COLOR_8888(color[2], color[1], color[0], color[3])
+
+# define WRITE_RGBA(_x, _y, r, g, b, a) \
+ PUT_VALUE(_x, _y, ((r << 8) | \
+ (g << 16) | \
+ (b << 24) | \
+ (a << 0)))
+
+#define WRITE_PIXEL(_x, _y, p) PUT_VALUE(_x, _y, p)
+
+# if defined( USE_X86_ASM )
+# define READ_RGBA(rgba, _x, _y) \
+ do { \
+ GLuint p = GET_VALUE(_x, _y); \
+ __asm__ __volatile__( "rorl $8, %0" \
+ : "=r" (p) : "0" (p) ); \
+ ((GLuint *)rgba)[0] = p; \
+ } while (0)
+# elif defined( MESA_BIG_ENDIAN )
+ /* On PowerPC with GCC 3.4.2 the shift madness below becomes a single
+ * rotlwi instruction. It also produces good code on SPARC.
+ */
+# define READ_RGBA( rgba, _x, _y ) \
+ do { \
+ GLuint p = CPU_TO_LE32(GET_VALUE(_x, _y)); \
+ GLuint t = p; \
+ *((uint32_t *) rgba) = (t >> 24) | (p << 8); \
+ } while (0)
+# else
+# define READ_RGBA( rgba, _x, _y ) \
+ do { \
+ GLuint p = GET_VALUE(_x, _y); \
+ rgba[0] = (p >> 8) & 0xff; \
+ rgba[1] = (p >> 16) & 0xff; \
+ rgba[2] = (p >> 24) & 0xff; \
+ rgba[3] = (p >> 0) & 0xff; \
+ } while (0)
+# endif
+
+#elif (SPANTMP_PIXEL_FMT == GL_BGR) && (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_INT_8_8_8_8_REV)
+
+/**
+ ** GL_BGR, GL_UNSIGNED_INT_8_8_8_8_REV
+ **
+ ** This is really for MESA_FORMAT_XRGB8888. The spantmp code needs to be
+ ** kicked to the curb, and we need to just code-gen this.
+ **/
+
+#ifndef GET_VALUE
+#ifndef GET_PTR
+#define GET_PTR(_x, _y) ( buf + (_x) * 4 + (_y) * pitch)
+#endif
+
+#define GET_VALUE(_x, _y) *(volatile GLuint *)(GET_PTR(_x, _y))
+#define PUT_VALUE(_x, _y, _v) *(volatile GLuint *)(GET_PTR(_x, _y)) = (_v)
+#endif /* GET_VALUE */
+
+# define INIT_MONO_PIXEL(p, color) \
+ p = PACK_COLOR_8888(0xff, color[0], color[1], color[2])
+
+# define WRITE_RGBA(_x, _y, r, g, b, a) \
+ PUT_VALUE(_x, _y, ((r << 16) | \
+ (g << 8) | \
+ (b << 0) | \
+ (0xff << 24)))
+
+#define WRITE_PIXEL(_x, _y, p) PUT_VALUE(_x, _y, p)
+
+# if defined( USE_X86_ASM )
+# define READ_RGBA(rgba, _x, _y) \
+ do { \
+ GLuint p = GET_VALUE(_x, _y); \
+ __asm__ __volatile__( "bswap %0; rorl $8, %0" \
+ : "=r" (p) : "0" (p) ); \
+ ((GLuint *)rgba)[0] = p | 0xff000000; \
+ } while (0)
+# elif defined( MESA_BIG_ENDIAN )
+ /* On PowerPC with GCC 3.4.2 the shift madness below becomes a single
+ * rotlwi instruction. It also produces good code on SPARC.
+ */
+# define READ_RGBA( rgba, _x, _y ) \
+ do { \
+ GLuint p = GET_VALUE(_x, _y); \
+ *((uint32_t *) rgba) = (p << 8) | 0xff; \
+ } while (0)
+# else
+# define READ_RGBA( rgba, _x, _y ) \
+ do { \
+ GLuint p = GET_VALUE(_x, _y); \
+ rgba[0] = (p >> 16) & 0xff; \
+ rgba[1] = (p >> 8) & 0xff; \
+ rgba[2] = (p >> 0) & 0xff; \
+ rgba[3] = 0xff; \
+ } while (0)
+# endif
+
+#elif (SPANTMP_PIXEL_FMT == GL_ALPHA) && (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_BYTE)
+
+/**
+ ** GL_ALPHA, GL_UNSIGNED_BYTE
+ **/
+
+#ifndef GET_VALUE
+#ifndef GET_PTR
+#define GET_PTR(_x, _y) ( buf + (_x) + (_y) * pitch)
+#endif
+
+#define GET_VALUE(_x, _y) *(volatile GLubyte *)(GET_PTR(_x, _y))
+#define PUT_VALUE(_x, _y, _v) *(volatile GLubyte *)(GET_PTR(_x, _y)) = (_v)
+#endif /* GET_VALUE */
+
+# define INIT_MONO_PIXEL(p, color) \
+ p = color[3]
+
+# define WRITE_RGBA(_x, _y, r, g, b, a) \
+ PUT_VALUE(_x, _y, a | (r & 0 /* quiet warnings */))
+
+#define WRITE_PIXEL(_x, _y, p) PUT_VALUE(_x, _y, p)
+
+#define READ_RGBA( rgba, _x, _y ) \
+ do { \
+ GLubyte p = GET_VALUE(_x, _y); \
+ rgba[0] = 0; \
+ rgba[1] = 0; \
+ rgba[2] = 0; \
+ rgba[3] = p; \
+ } while (0)
+
+#elif (SPANTMP_MESA_FMT == MESA_FORMAT_R8)
+
+#ifndef GET_VALUE
+#ifndef GET_PTR
+#define GET_PTR(_x, _y) ( buf + (_x) + (_y) * pitch)
+#endif
+
+#define GET_VALUE(_x, _y) *(volatile GLubyte *)(GET_PTR(_x, _y))
+#define PUT_VALUE(_x, _y, _v) *(volatile GLubyte *)(GET_PTR(_x, _y)) = (_v)
+#endif /* GET_VALUE */
+
+# define INIT_MONO_PIXEL(p, color) \
+ p = color[0]
+
+# define WRITE_RGBA(_x, _y, r, g, b, a) \
+ PUT_VALUE(_x, _y, r)
+
+#define WRITE_PIXEL(_x, _y, p) PUT_VALUE(_x, _y, p)
+
+#define READ_RGBA( rgba, _x, _y ) \
+ do { \
+ GLubyte p = GET_VALUE(_x, _y); \
+ rgba[0] = p; \
+ rgba[1] = 0; \
+ rgba[2] = 0; \
+ rgba[3] = 0; \
+ } while (0)
+
+#elif (SPANTMP_MESA_FMT == MESA_FORMAT_RG88)
+
+#ifndef GET_VALUE
+#ifndef GET_PTR
+#define GET_PTR(_x, _y) ( buf + (_x) * 2 + (_y) * pitch)
+#endif
+
+#define GET_VALUE(_x, _y) *(volatile GLushort *)(GET_PTR(_x, _y))
+#define PUT_VALUE(_x, _y, _v) *(volatile GLushort *)(GET_PTR(_x, _y)) = (_v)
+#endif /* GET_VALUE */
+
+# define INIT_MONO_PIXEL(p, color) \
+ PACK_COLOR_8888(color[0], color[1], 0, 0)
+
+# define WRITE_RGBA(_x, _y, r, g, b, a) \
+ PUT_VALUE(_x, _y, r)
+
+#define WRITE_PIXEL(_x, _y, p) PUT_VALUE(_x, _y, p)
+
+#define READ_RGBA( rgba, _x, _y ) \
+ do { \
+ GLushort p = GET_VALUE(_x, _y); \
+ rgba[0] = p & 0xff; \
+ rgba[1] = (p >> 8) & 0xff; \
+ rgba[2] = 0; \
+ rgba[3] = 0; \
+ } while (0)
+
+#elif (SPANTMP_MESA_FMT == MESA_FORMAT_R16)
+
+#ifndef GET_VALUE
+#ifndef GET_PTR
+#define GET_PTR(_x, _y) ( buf + (_x) * 2 + (_y) * pitch)
+#endif
+
+#define GET_VALUE(_x, _y) *(volatile GLushort *)(GET_PTR(_x, _y))
+#define PUT_VALUE(_x, _y, _v) *(volatile GLushort *)(GET_PTR(_x, _y)) = (_v)
+#endif /* GET_VALUE */
+
+# define INIT_MONO_PIXEL(p, color) \
+ p = color[0]
+
+# define WRITE_RGBA(_x, _y, r, g, b, a) \
+ PUT_VALUE(_x, _y, r)
+
+#define WRITE_PIXEL(_x, _y, p) PUT_VALUE(_x, _y, p)
+
+#define READ_RGBA( rgba, _x, _y ) \
+ do { \
+ GLushort p = GET_VALUE(_x, _y); \
+ rgba[0] = p; \
+ rgba[1] = 0; \
+ rgba[2] = 0; \
+ rgba[3] = 0; \
+ } while (0)
+
+#elif (SPANTMP_MESA_FMT == MESA_FORMAT_RG1616)
+
+#ifndef GET_VALUE
+#ifndef GET_PTR
+#define GET_PTR(_x, _y) ( buf + (_x) * 4 + (_y) * pitch)
+#endif
+
+#define GET_VALUE(_x, _y) *(volatile GLuint *)(GET_PTR(_x, _y))
+#define PUT_VALUE(_x, _y, _v) *(volatile GLuint *)(GET_PTR(_x, _y)) = (_v)
+#endif /* GET_VALUE */
+
+# define INIT_MONO_PIXEL(p, color) \
+ ((color[1] << 16) | (color[0]))
+
+# define WRITE_RGBA(_x, _y, r, g, b, a) \
+ PUT_VALUE(_x, _y, r)
+
+#define WRITE_PIXEL(_x, _y, p) PUT_VALUE(_x, _y, p)
+
+#define READ_RGBA( rgba, _x, _y ) \
+ do { \
+ GLuint p = GET_VALUE(_x, _y); \
+ rgba[0] = p & 0xffff; \
+ rgba[1] = (p >> 16) & 0xffff; \
+ rgba[2] = 0; \
+ rgba[3] = 0; \
+ } while (0)
+
+#else
+#error SPANTMP_PIXEL_FMT must be set to a valid value!
+#endif
+
+
+
+/**
+ ** Assembly routines.
+ **/
+
+#if defined( USE_MMX_ASM ) || defined( USE_SSE_ASM )
+#include "x86/read_rgba_span_x86.h"
+#include "x86/common_x86_asm.h"
+#endif
+
+static void TAG(WriteRGBASpan)( struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const void *values, const GLubyte mask[] )
+{
+ HW_WRITE_LOCK()
+ {
+ const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+ GLint x1;
+ GLint n1;
+ LOCAL_VARS;
+
+ y = Y_FLIP(y);
+
+ HW_WRITE_CLIPLOOP()
+ {
+ GLint i = 0;
+ CLIPSPAN(x,y,n,x1,n1,i);
+
+ if (DBG) fprintf(stderr, "WriteRGBASpan %d..%d (x1 %d)\n",
+ (int)i, (int)n1, (int)x1);
+
+ if (mask)
+ {
+ for (;n1>0;i++,x1++,n1--)
+ if (mask[i])
+ WRITE_RGBA( x1, y,
+ rgba[i][0], rgba[i][1],
+ rgba[i][2], rgba[i][3] );
+ }
+ else
+ {
+ for (;n1>0;i++,x1++,n1--)
+ WRITE_RGBA( x1, y,
+ rgba[i][0], rgba[i][1],
+ rgba[i][2], rgba[i][3] );
+ }
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_WRITE_UNLOCK();
+}
+
+static void TAG(WriteRGBSpan)( struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const void *values, const GLubyte mask[] )
+{
+ HW_WRITE_LOCK()
+ {
+ const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
+ GLint x1;
+ GLint n1;
+ LOCAL_VARS;
+
+ y = Y_FLIP(y);
+
+ HW_WRITE_CLIPLOOP()
+ {
+ GLint i = 0;
+ CLIPSPAN(x,y,n,x1,n1,i);
+
+ if (DBG) fprintf(stderr, "WriteRGBSpan %d..%d (x1 %d)\n",
+ (int)i, (int)n1, (int)x1);
+
+ if (mask)
+ {
+ for (;n1>0;i++,x1++,n1--)
+ if (mask[i])
+ WRITE_RGBA( x1, y, rgb[i][0], rgb[i][1], rgb[i][2], 255 );
+ }
+ else
+ {
+ for (;n1>0;i++,x1++,n1--)
+ WRITE_RGBA( x1, y, rgb[i][0], rgb[i][1], rgb[i][2], 255 );
+ }
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_WRITE_UNLOCK();
+}
+
+static void TAG(WriteRGBAPixels)( struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, const GLint x[], const GLint y[],
+ const void *values, const GLubyte mask[] )
+{
+ HW_WRITE_LOCK()
+ {
+ const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+ GLint i;
+ LOCAL_VARS;
+
+ if (DBG) fprintf(stderr, "WriteRGBAPixels\n");
+
+ HW_WRITE_CLIPLOOP()
+ {
+ if (mask)
+ {
+ for (i=0;i<n;i++)
+ {
+ if (mask[i]) {
+ const int fy = Y_FLIP(y[i]);
+ if (CLIPPIXEL(x[i],fy))
+ WRITE_RGBA( x[i], fy,
+ rgba[i][0], rgba[i][1],
+ rgba[i][2], rgba[i][3] );
+ }
+ }
+ }
+ else
+ {
+ for (i=0;i<n;i++)
+ {
+ const int fy = Y_FLIP(y[i]);
+ if (CLIPPIXEL(x[i],fy))
+ WRITE_RGBA( x[i], fy,
+ rgba[i][0], rgba[i][1],
+ rgba[i][2], rgba[i][3] );
+ }
+ }
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_WRITE_UNLOCK();
+}
+
+
+static void TAG(WriteMonoRGBASpan)( struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const void *value, const GLubyte mask[] )
+{
+ HW_WRITE_LOCK()
+ {
+ const GLubyte *color = (const GLubyte *) value;
+ GLint x1;
+ GLint n1;
+ LOCAL_VARS;
+ INIT_MONO_PIXEL(p, color);
+
+ y = Y_FLIP( y );
+
+ if (DBG) fprintf(stderr, "WriteMonoRGBASpan\n");
+
+ HW_WRITE_CLIPLOOP()
+ {
+ GLint i = 0;
+ CLIPSPAN(x,y,n,x1,n1,i);
+ if (mask)
+ {
+ for (;n1>0;i++,x1++,n1--)
+ if (mask[i])
+ WRITE_PIXEL( x1, y, p );
+ }
+ else
+ {
+ for (;n1>0;i++,x1++,n1--)
+ WRITE_PIXEL( x1, y, p );
+ }
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_WRITE_UNLOCK();
+}
+
+
+static void TAG(WriteMonoRGBAPixels)( struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ const void *value,
+ const GLubyte mask[] )
+{
+ HW_WRITE_LOCK()
+ {
+ const GLubyte *color = (const GLubyte *) value;
+ GLint i;
+ LOCAL_VARS;
+ INIT_MONO_PIXEL(p, color);
+
+ if (DBG) fprintf(stderr, "WriteMonoRGBAPixels\n");
+
+ HW_WRITE_CLIPLOOP()
+ {
+ if (mask)
+ {
+ for (i=0;i<n;i++)
+ if (mask[i]) {
+ int fy = Y_FLIP(y[i]);
+ if (CLIPPIXEL( x[i], fy ))
+ WRITE_PIXEL( x[i], fy, p );
+ }
+ }
+ else
+ {
+ for (i=0;i<n;i++) {
+ int fy = Y_FLIP(y[i]);
+ if (CLIPPIXEL( x[i], fy ))
+ WRITE_PIXEL( x[i], fy, p );
+ }
+ }
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_WRITE_UNLOCK();
+}
+
+
+static void TAG(ReadRGBASpan)( struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y, void *values)
+{
+ HW_READ_LOCK()
+ {
+ GLubyte (*rgba)[4] = (GLubyte (*)[4]) values;
+ GLint x1,n1;
+ LOCAL_VARS;
+
+ y = Y_FLIP(y);
+
+ if (DBG) fprintf(stderr, "ReadRGBASpan\n");
+
+ HW_READ_CLIPLOOP()
+ {
+ GLint i = 0;
+ CLIPSPAN(x,y,n,x1,n1,i);
+ for (;n1>0;i++,x1++,n1--)
+ READ_RGBA( rgba[i], x1, y );
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_READ_UNLOCK();
+}
+
+
+#if defined(GET_PTR) && \
+ defined(USE_MMX_ASM) && \
+ (((SPANTMP_PIXEL_FMT == GL_BGRA) && \
+ (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_INT_8_8_8_8_REV)) || \
+ ((SPANTMP_PIXEL_FMT == GL_RGB) && \
+ (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_SHORT_5_6_5)))
+static void TAG2(ReadRGBASpan,_MMX)( struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y, void *values)
+{
+#ifndef USE_INNER_EMMS
+ /* The EMMS instruction is directly in-lined here because using GCC's
+ * built-in _mm_empty function was found to utterly destroy performance.
+ */
+ __asm__ __volatile__( "emms" );
+#endif
+
+ HW_READ_LOCK()
+ {
+ GLubyte (*rgba)[4] = (GLubyte (*)[4]) values;
+ GLint x1,n1;
+ LOCAL_VARS;
+
+ y = Y_FLIP(y);
+
+ if (DBG) fprintf(stderr, "ReadRGBASpan\n");
+
+ HW_READ_CLIPLOOP()
+ {
+ GLint i = 0;
+ CLIPSPAN(x,y,n,x1,n1,i);
+
+ {
+ const void * src = GET_PTR( x1, y );
+#if (SPANTMP_PIXEL_FMT == GL_RGB) && \
+ (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_SHORT_5_6_5)
+ _generic_read_RGBA_span_RGB565_MMX( src, rgba[i], n1 );
+#else
+ _generic_read_RGBA_span_BGRA8888_REV_MMX( src, rgba[i], n1 );
+#endif
+ }
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_READ_UNLOCK();
+#ifndef USE_INNER_EMMS
+ __asm__ __volatile__( "emms" );
+#endif
+}
+#endif
+
+
+#if defined(GET_PTR) && \
+ defined(USE_SSE_ASM) && \
+ (SPANTMP_PIXEL_FMT == GL_BGRA) && \
+ (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_INT_8_8_8_8_REV)
+static void TAG2(ReadRGBASpan,_SSE2)( struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ void *values)
+{
+ HW_READ_LOCK()
+ {
+ GLubyte (*rgba)[4] = (GLubyte (*)[4]) values;
+ GLint x1,n1;
+ LOCAL_VARS;
+
+ y = Y_FLIP(y);
+
+ if (DBG) fprintf(stderr, "ReadRGBASpan\n");
+
+ HW_READ_CLIPLOOP()
+ {
+ GLint i = 0;
+ CLIPSPAN(x,y,n,x1,n1,i);
+
+ {
+ const void * src = GET_PTR( x1, y );
+ _generic_read_RGBA_span_BGRA8888_REV_SSE2( src, rgba[i], n1 );
+ }
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_READ_UNLOCK();
+}
+#endif
+
+#if defined(GET_PTR) && \
+ defined(USE_SSE_ASM) && \
+ (SPANTMP_PIXEL_FMT == GL_BGRA) && \
+ (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_INT_8_8_8_8_REV)
+static void TAG2(ReadRGBASpan,_SSE)( struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ void *values)
+{
+#ifndef USE_INNER_EMMS
+ /* The EMMS instruction is directly in-lined here because using GCC's
+ * built-in _mm_empty function was found to utterly destroy performance.
+ */
+ __asm__ __volatile__( "emms" );
+#endif
+
+ HW_READ_LOCK()
+ {
+ GLubyte (*rgba)[4] = (GLubyte (*)[4]) values;
+ GLint x1,n1;
+ LOCAL_VARS;
+
+ y = Y_FLIP(y);
+
+ if (DBG) fprintf(stderr, "ReadRGBASpan\n");
+
+ HW_READ_CLIPLOOP()
+ {
+ GLint i = 0;
+ CLIPSPAN(x,y,n,x1,n1,i);
+
+ {
+ const void * src = GET_PTR( x1, y );
+ _generic_read_RGBA_span_BGRA8888_REV_SSE( src, rgba[i], n1 );
+ }
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_READ_UNLOCK();
+#ifndef USE_INNER_EMMS
+ __asm__ __volatile__( "emms" );
+#endif
+}
+#endif
+
+
+static void TAG(ReadRGBAPixels)( struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, const GLint x[], const GLint y[],
+ void *values )
+{
+ HW_READ_LOCK()
+ {
+ GLubyte (*rgba)[4] = (GLubyte (*)[4]) values;
+ GLint i;
+ LOCAL_VARS;
+
+ if (DBG) fprintf(stderr, "ReadRGBAPixels\n");
+
+ HW_READ_CLIPLOOP()
+ {
+ for (i=0;i<n;i++) {
+ int fy = Y_FLIP( y[i] );
+ if (CLIPPIXEL( x[i], fy ))
+ READ_RGBA( rgba[i], x[i], fy );
+ }
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_READ_UNLOCK();
+}
+
+static void TAG(InitPointers)(struct gl_renderbuffer *rb)
+{
+ rb->PutRow = TAG(WriteRGBASpan);
+ rb->PutRowRGB = TAG(WriteRGBSpan);
+ rb->PutMonoRow = TAG(WriteMonoRGBASpan);
+ rb->PutValues = TAG(WriteRGBAPixels);
+ rb->PutMonoValues = TAG(WriteMonoRGBAPixels);
+ rb->GetValues = TAG(ReadRGBAPixels);
+
+#if defined(GET_PTR)
+#if defined(USE_SSE_ASM) && \
+ (SPANTMP_PIXEL_FMT == GL_BGRA) && \
+ (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_INT_8_8_8_8_REV)
+ if ( cpu_has_xmm2 ) {
+ if (DBG) fprintf( stderr, "Using %s version of GetRow\n", "SSE2" );
+ rb->GetRow = TAG2(ReadRGBASpan, _SSE2);
+ }
+ else
+#endif
+#if defined(USE_SSE_ASM) && \
+ (SPANTMP_PIXEL_FMT == GL_BGRA) && \
+ (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_INT_8_8_8_8_REV)
+ if ( cpu_has_xmm ) {
+ if (DBG) fprintf( stderr, "Using %s version of GetRow\n", "SSE" );
+ rb->GetRow = TAG2(ReadRGBASpan, _SSE);
+ }
+ else
+#endif
+#if defined(USE_MMX_ASM) && \
+ (((SPANTMP_PIXEL_FMT == GL_BGRA) && \
+ (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_INT_8_8_8_8_REV)) || \
+ ((SPANTMP_PIXEL_FMT == GL_RGB) && \
+ (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_SHORT_5_6_5)))
+ if ( cpu_has_mmx ) {
+ if (DBG) fprintf( stderr, "Using %s version of GetRow\n", "MMX" );
+ rb->GetRow = TAG2(ReadRGBASpan, _MMX);
+ }
+ else
+#endif
+#endif /* GET_PTR */
+ {
+ if (DBG) fprintf( stderr, "Using %s version of GetRow\n", "C" );
+ rb->GetRow = TAG(ReadRGBASpan);
+ }
+
+}
+
+
+#undef INIT_MONO_PIXEL
+#undef WRITE_PIXEL
+#undef WRITE_RGBA
+#undef READ_RGBA
+#undef TAG
+#undef TAG2
+#undef GET_VALUE
+#undef PUT_VALUE
+#undef GET_PTR
+#undef SPANTMP_PIXEL_FMT
+#undef SPANTMP_PIXEL_TYPE
+#undef SPANTMP_MESA_FMT
diff --git a/mesalib/src/mesa/drivers/dri/common/stenciltmp.h b/mesalib/src/mesa/drivers/dri/common/stenciltmp.h
index 2b10b9ecf..2ea2e207a 100644
--- a/mesalib/src/mesa/drivers/dri/common/stenciltmp.h
+++ b/mesalib/src/mesa/drivers/dri/common/stenciltmp.h
@@ -1,245 +1,245 @@
-
-#include "spantmp_common.h"
-
-#ifndef DBG
-#define DBG 0
-#endif
-
-#ifndef HAVE_HW_STENCIL_SPANS
-#define HAVE_HW_STENCIL_SPANS 0
-#endif
-
-#ifndef HAVE_HW_STENCIL_PIXELS
-#define HAVE_HW_STENCIL_PIXELS 0
-#endif
-
-static void TAG(WriteStencilSpan)( GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, GLint x, GLint y,
- const void *values, const GLubyte mask[] )
-{
- HW_WRITE_LOCK()
- {
- const GLubyte *stencil = (const GLubyte *) values;
- GLint x1;
- GLint n1;
- LOCAL_STENCIL_VARS;
-
- y = Y_FLIP(y);
-
-#if HAVE_HW_STENCIL_SPANS
- (void) x1; (void) n1;
-
- if (DBG) fprintf(stderr, "WriteStencilSpan 0..%d (x1 %d)\n",
- (int)n1, (int)x1);
-
- WRITE_STENCIL_SPAN();
-#else /* HAVE_HW_STENCIL_SPANS */
- HW_CLIPLOOP()
- {
- GLint i = 0;
- CLIPSPAN(x,y,n,x1,n1,i);
-
- if (DBG) fprintf(stderr, "WriteStencilSpan %d..%d (x1 %d)\n",
- (int)i, (int)n1, (int)x1);
-
- if (mask)
- {
- for (;n1>0;i++,x1++,n1--)
- if (mask[i])
- WRITE_STENCIL( x1, y, stencil[i] );
- }
- else
- {
- for (;n1>0;i++,x1++,n1--)
- WRITE_STENCIL( x1, y, stencil[i] );
- }
- }
- HW_ENDCLIPLOOP();
-#endif /* !HAVE_HW_STENCIL_SPANS */
- }
- HW_WRITE_UNLOCK();
-}
-
-#if HAVE_HW_STENCIL_SPANS
-/* implement MonoWriteDepthSpan() in terms of WriteDepthSpan() */
-static void
-TAG(WriteMonoStencilSpan)( GLcontext *ctx, struct gl_renderbuffer *rb,
- GLuint n, GLint x, GLint y,
- const void *value, const GLubyte mask[] )
-{
- const GLuint stenVal = *((GLuint *) value);
- GLuint stens[MAX_WIDTH];
- GLuint i;
- for (i = 0; i < n; i++)
- stens[i] = stenVal;
- TAG(WriteStencilSpan)(ctx, rb, n, x, y, stens, mask);
-}
-#else /* HAVE_HW_STENCIL_SPANS */
-static void TAG(WriteMonoStencilSpan)( GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, GLint x, GLint y,
- const void *value,
- const GLubyte mask[] )
-{
- HW_WRITE_LOCK()
- {
- const GLubyte stencil = *((const GLubyte *) value);
- GLint x1;
- GLint n1;
- LOCAL_STENCIL_VARS;
-
- y = Y_FLIP(y);
-
- HW_CLIPLOOP()
- {
- GLint i = 0;
- CLIPSPAN(x,y,n,x1,n1,i);
-
- if (DBG) fprintf(stderr, "WriteStencilSpan %d..%d (x1 %d)\n",
- (int)i, (int)n1, (int)x1);
-
- if (mask)
- {
- for (;n1>0;i++,x1++,n1--)
- if (mask[i])
- WRITE_STENCIL( x1, y, stencil );
- }
- else
- {
- for (;n1>0;i++,x1++,n1--)
- WRITE_STENCIL( x1, y, stencil );
- }
- }
- HW_ENDCLIPLOOP();
- }
- HW_WRITE_UNLOCK();
-}
-#endif /* !HAVE_HW_STENCIL_SPANS */
-
-
-static void TAG(WriteStencilPixels)( GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n,
- const GLint x[], const GLint y[],
- const void *values, const GLubyte mask[] )
-{
- HW_WRITE_LOCK()
- {
- const GLubyte *stencil = (const GLubyte *) values;
- GLuint i;
- LOCAL_STENCIL_VARS;
-
- if (DBG) fprintf(stderr, "WriteStencilPixels\n");
-
-#if HAVE_HW_STENCIL_PIXELS
- (void) i;
-
- WRITE_STENCIL_PIXELS();
-#else /* HAVE_HW_STENCIL_PIXELS */
- HW_CLIPLOOP()
- {
- for (i=0;i<n;i++)
- {
- if (mask[i]) {
- const int fy = Y_FLIP(y[i]);
- if (CLIPPIXEL(x[i],fy))
- WRITE_STENCIL( x[i], fy, stencil[i] );
- }
- }
- }
- HW_ENDCLIPLOOP();
-#endif /* !HAVE_HW_STENCIL_PIXELS */
- }
- HW_WRITE_UNLOCK();
-}
-
-
-/* Read stencil spans and pixels
- */
-static void TAG(ReadStencilSpan)( GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, GLint x, GLint y,
- void *values)
-{
- HW_READ_LOCK()
- {
- GLubyte *stencil = (GLubyte *) values;
- GLint x1,n1;
- LOCAL_STENCIL_VARS;
-
- y = Y_FLIP(y);
-
- if (DBG) fprintf(stderr, "ReadStencilSpan\n");
-
-#if HAVE_HW_STENCIL_SPANS
- (void) x1; (void) n1;
-
- READ_STENCIL_SPAN();
-#else /* HAVE_HW_STENCIL_SPANS */
- HW_CLIPLOOP()
- {
- GLint i = 0;
- CLIPSPAN(x,y,n,x1,n1,i);
- for (;n1>0;i++,n1--)
- READ_STENCIL( stencil[i], (x+i), y );
- }
- HW_ENDCLIPLOOP();
-#endif /* !HAVE_HW_STENCIL_SPANS */
- }
- HW_READ_UNLOCK();
-}
-
-static void TAG(ReadStencilPixels)( GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, const GLint x[], const GLint y[],
- void *values )
-{
- HW_READ_LOCK()
- {
- GLubyte *stencil = (GLubyte *) values;
- GLuint i;
- LOCAL_STENCIL_VARS;
-
- if (DBG) fprintf(stderr, "ReadStencilPixels\n");
-
-#if HAVE_HW_STENCIL_PIXELS
- (void) i;
-
- READ_STENCIL_PIXELS();
-#else /* HAVE_HW_STENCIL_PIXELS */
- HW_CLIPLOOP()
- {
- for (i=0;i<n;i++) {
- int fy = Y_FLIP( y[i] );
- if (CLIPPIXEL( x[i], fy ))
- READ_STENCIL( stencil[i], x[i], fy );
- }
- }
- HW_ENDCLIPLOOP();
-#endif /* !HAVE_HW_STENCIL_PIXELS */
- }
- HW_READ_UNLOCK();
-}
-
-
-
-/**
- * Initialize the given renderbuffer's span routines to point to
- * the stencil functions we generated above.
- */
-static void TAG(InitStencilPointers)(struct gl_renderbuffer *rb)
-{
- rb->GetRow = TAG(ReadStencilSpan);
- rb->GetValues = TAG(ReadStencilPixels);
- rb->PutRow = TAG(WriteStencilSpan);
- rb->PutRowRGB = NULL;
- rb->PutMonoRow = TAG(WriteMonoStencilSpan);
- rb->PutValues = TAG(WriteStencilPixels);
- rb->PutMonoValues = NULL;
-}
-
-
-#undef WRITE_STENCIL
-#undef READ_STENCIL
-#undef TAG
+
+#include "spantmp_common.h"
+
+#ifndef DBG
+#define DBG 0
+#endif
+
+#ifndef HAVE_HW_STENCIL_SPANS
+#define HAVE_HW_STENCIL_SPANS 0
+#endif
+
+#ifndef HAVE_HW_STENCIL_PIXELS
+#define HAVE_HW_STENCIL_PIXELS 0
+#endif
+
+static void TAG(WriteStencilSpan)( struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const void *values, const GLubyte mask[] )
+{
+ HW_WRITE_LOCK()
+ {
+ const GLubyte *stencil = (const GLubyte *) values;
+ GLint x1;
+ GLint n1;
+ LOCAL_STENCIL_VARS;
+
+ y = Y_FLIP(y);
+
+#if HAVE_HW_STENCIL_SPANS
+ (void) x1; (void) n1;
+
+ if (DBG) fprintf(stderr, "WriteStencilSpan 0..%d (x1 %d)\n",
+ (int)n1, (int)x1);
+
+ WRITE_STENCIL_SPAN();
+#else /* HAVE_HW_STENCIL_SPANS */
+ HW_CLIPLOOP()
+ {
+ GLint i = 0;
+ CLIPSPAN(x,y,n,x1,n1,i);
+
+ if (DBG) fprintf(stderr, "WriteStencilSpan %d..%d (x1 %d)\n",
+ (int)i, (int)n1, (int)x1);
+
+ if (mask)
+ {
+ for (;n1>0;i++,x1++,n1--)
+ if (mask[i])
+ WRITE_STENCIL( x1, y, stencil[i] );
+ }
+ else
+ {
+ for (;n1>0;i++,x1++,n1--)
+ WRITE_STENCIL( x1, y, stencil[i] );
+ }
+ }
+ HW_ENDCLIPLOOP();
+#endif /* !HAVE_HW_STENCIL_SPANS */
+ }
+ HW_WRITE_UNLOCK();
+}
+
+#if HAVE_HW_STENCIL_SPANS
+/* implement MonoWriteDepthSpan() in terms of WriteDepthSpan() */
+static void
+TAG(WriteMonoStencilSpan)( struct gl_context *ctx, struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const void *value, const GLubyte mask[] )
+{
+ const GLuint stenVal = *((GLuint *) value);
+ GLuint stens[MAX_WIDTH];
+ GLuint i;
+ for (i = 0; i < n; i++)
+ stens[i] = stenVal;
+ TAG(WriteStencilSpan)(ctx, rb, n, x, y, stens, mask);
+}
+#else /* HAVE_HW_STENCIL_SPANS */
+static void TAG(WriteMonoStencilSpan)( struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const void *value,
+ const GLubyte mask[] )
+{
+ HW_WRITE_LOCK()
+ {
+ const GLubyte stencil = *((const GLubyte *) value);
+ GLint x1;
+ GLint n1;
+ LOCAL_STENCIL_VARS;
+
+ y = Y_FLIP(y);
+
+ HW_CLIPLOOP()
+ {
+ GLint i = 0;
+ CLIPSPAN(x,y,n,x1,n1,i);
+
+ if (DBG) fprintf(stderr, "WriteStencilSpan %d..%d (x1 %d)\n",
+ (int)i, (int)n1, (int)x1);
+
+ if (mask)
+ {
+ for (;n1>0;i++,x1++,n1--)
+ if (mask[i])
+ WRITE_STENCIL( x1, y, stencil );
+ }
+ else
+ {
+ for (;n1>0;i++,x1++,n1--)
+ WRITE_STENCIL( x1, y, stencil );
+ }
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_WRITE_UNLOCK();
+}
+#endif /* !HAVE_HW_STENCIL_SPANS */
+
+
+static void TAG(WriteStencilPixels)( struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ const void *values, const GLubyte mask[] )
+{
+ HW_WRITE_LOCK()
+ {
+ const GLubyte *stencil = (const GLubyte *) values;
+ GLuint i;
+ LOCAL_STENCIL_VARS;
+
+ if (DBG) fprintf(stderr, "WriteStencilPixels\n");
+
+#if HAVE_HW_STENCIL_PIXELS
+ (void) i;
+
+ WRITE_STENCIL_PIXELS();
+#else /* HAVE_HW_STENCIL_PIXELS */
+ HW_CLIPLOOP()
+ {
+ for (i=0;i<n;i++)
+ {
+ if (mask[i]) {
+ const int fy = Y_FLIP(y[i]);
+ if (CLIPPIXEL(x[i],fy))
+ WRITE_STENCIL( x[i], fy, stencil[i] );
+ }
+ }
+ }
+ HW_ENDCLIPLOOP();
+#endif /* !HAVE_HW_STENCIL_PIXELS */
+ }
+ HW_WRITE_UNLOCK();
+}
+
+
+/* Read stencil spans and pixels
+ */
+static void TAG(ReadStencilSpan)( struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ void *values)
+{
+ HW_READ_LOCK()
+ {
+ GLubyte *stencil = (GLubyte *) values;
+ GLint x1,n1;
+ LOCAL_STENCIL_VARS;
+
+ y = Y_FLIP(y);
+
+ if (DBG) fprintf(stderr, "ReadStencilSpan\n");
+
+#if HAVE_HW_STENCIL_SPANS
+ (void) x1; (void) n1;
+
+ READ_STENCIL_SPAN();
+#else /* HAVE_HW_STENCIL_SPANS */
+ HW_CLIPLOOP()
+ {
+ GLint i = 0;
+ CLIPSPAN(x,y,n,x1,n1,i);
+ for (;n1>0;i++,n1--)
+ READ_STENCIL( stencil[i], (x+i), y );
+ }
+ HW_ENDCLIPLOOP();
+#endif /* !HAVE_HW_STENCIL_SPANS */
+ }
+ HW_READ_UNLOCK();
+}
+
+static void TAG(ReadStencilPixels)( struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, const GLint x[], const GLint y[],
+ void *values )
+{
+ HW_READ_LOCK()
+ {
+ GLubyte *stencil = (GLubyte *) values;
+ GLuint i;
+ LOCAL_STENCIL_VARS;
+
+ if (DBG) fprintf(stderr, "ReadStencilPixels\n");
+
+#if HAVE_HW_STENCIL_PIXELS
+ (void) i;
+
+ READ_STENCIL_PIXELS();
+#else /* HAVE_HW_STENCIL_PIXELS */
+ HW_CLIPLOOP()
+ {
+ for (i=0;i<n;i++) {
+ int fy = Y_FLIP( y[i] );
+ if (CLIPPIXEL( x[i], fy ))
+ READ_STENCIL( stencil[i], x[i], fy );
+ }
+ }
+ HW_ENDCLIPLOOP();
+#endif /* !HAVE_HW_STENCIL_PIXELS */
+ }
+ HW_READ_UNLOCK();
+}
+
+
+
+/**
+ * Initialize the given renderbuffer's span routines to point to
+ * the stencil functions we generated above.
+ */
+static void TAG(InitStencilPointers)(struct gl_renderbuffer *rb)
+{
+ rb->GetRow = TAG(ReadStencilSpan);
+ rb->GetValues = TAG(ReadStencilPixels);
+ rb->PutRow = TAG(WriteStencilSpan);
+ rb->PutRowRGB = NULL;
+ rb->PutMonoRow = TAG(WriteMonoStencilSpan);
+ rb->PutValues = TAG(WriteStencilPixels);
+ rb->PutMonoValues = NULL;
+}
+
+
+#undef WRITE_STENCIL
+#undef READ_STENCIL
+#undef TAG
diff --git a/mesalib/src/mesa/drivers/dri/common/texmem.c b/mesalib/src/mesa/drivers/dri/common/texmem.c
index 895139b55..3c4f3373f 100644
--- a/mesalib/src/mesa/drivers/dri/common/texmem.c
+++ b/mesalib/src/mesa/drivers/dri/common/texmem.c
@@ -1,1341 +1,1341 @@
-/*
- * Copyright 2000-2001 VA Linux Systems, Inc.
- * (C) Copyright IBM Corporation 2002, 2003
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * on the rights to use, copy, modify, merge, publish, distribute, sub
- * license, and/or sell copies of the Software, and to permit persons to whom
- * the Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Ian Romanick <idr@us.ibm.com>
- * Keith Whitwell <keithw@tungstengraphics.com>
- * Kevin E. Martin <kem@users.sourceforge.net>
- * Gareth Hughes <gareth@nvidia.com>
- */
-
-/** \file texmem.c
- * Implements all of the device-independent texture memory management.
- *
- * Currently, only a simple LRU texture memory management policy is
- * implemented. In the (hopefully very near) future, better policies will be
- * implemented. The idea is that the DRI should be able to run in one of two
- * modes. In the default mode the DRI will dynamically attempt to discover
- * the best texture management policy for the running application. In the
- * other mode, the user (via some sort of as yet TBD mechanism) will select
- * a texture management policy that is known to work well with the
- * application.
- */
-
-#include "main/imports.h"
-#include "main/macros.h"
-#include "main/simple_list.h"
-#include "texmem.h"
-
-
-static unsigned dummy_swap_counter;
-
-
-/**
- * Calculate \f$\log_2\f$ of a value. This is a particularly poor
- * implementation of this function. However, since system performance is in
- * no way dependent on this function, the slowness of the implementation is
- * irrelevent.
- *
- * \param n Value whose \f$\log_2\f$ is to be calculated
- */
-
-static GLuint
-driLog2( GLuint n )
-{
- GLuint log2;
-
- for ( log2 = 1 ; n > 1 ; log2++ ) {
- n >>= 1;
- }
-
- return log2;
-}
-
-
-
-
-/**
- * Determine if a texture is resident in textureable memory. Depending on
- * the driver, this may or may not be on-card memory. It could be AGP memory
- * or anyother type of memory from which the hardware can directly read
- * texels.
- *
- * This function is intended to be used as the \c IsTextureResident function
- * in the device's \c dd_function_table.
- *
- * \param ctx GL context pointer (currently unused)
- * \param texObj Texture object to be tested
- */
-
-GLboolean
-driIsTextureResident( GLcontext * ctx,
- struct gl_texture_object * texObj )
-{
- driTextureObject * t;
-
-
- t = (driTextureObject *) texObj->DriverData;
- return( (t != NULL) && (t->memBlock != NULL) );
-}
-
-
-
-
-/**
- * (Re)initialize the global circular LRU list. The last element
- * in the array (\a heap->nrRegions) is the sentinal. Keeping it
- * at the end of the array allows the other elements of the array
- * to be addressed rationally when looking up objects at a particular
- * location in texture memory.
- *
- * \param heap Texture heap to be reset
- */
-
-static void resetGlobalLRU( driTexHeap * heap )
-{
- drmTextureRegionPtr list = heap->global_regions;
- unsigned sz = 1U << heap->logGranularity;
- unsigned i;
-
- for (i = 0 ; (i+1) * sz <= heap->size ; i++) {
- list[i].prev = i-1;
- list[i].next = i+1;
- list[i].age = 0;
- }
-
- i--;
- list[0].prev = heap->nrRegions;
- list[i].prev = i-1;
- list[i].next = heap->nrRegions;
- list[heap->nrRegions].prev = i;
- list[heap->nrRegions].next = 0;
- heap->global_age[0] = 0;
-}
-
-/**
- * Print out debugging information about the local texture LRU.
- *
- * \param heap Texture heap to be printed
- * \param callername Name of calling function
- */
-static void printLocalLRU( driTexHeap * heap, const char *callername )
-{
- driTextureObject *t;
- unsigned sz = 1U << heap->logGranularity;
-
- fprintf( stderr, "%s in %s:\nLocal LRU, heap %d:\n",
- __FUNCTION__, callername, heap->heapId );
-
- foreach ( t, &heap->texture_objects ) {
- if (!t->memBlock)
- continue;
- if (!t->tObj) {
- fprintf( stderr, "Placeholder (%p) %d at 0x%x sz 0x%x\n",
- (void *)t,
- t->memBlock->ofs / sz,
- t->memBlock->ofs,
- t->memBlock->size );
- } else {
- fprintf( stderr, "Texture (%p) at 0x%x sz 0x%x\n",
- (void *)t,
- t->memBlock->ofs,
- t->memBlock->size );
- }
- }
- foreach ( t, heap->swapped_objects ) {
- if (!t->tObj) {
- fprintf( stderr, "Swapped Placeholder (%p)\n", (void *)t );
- } else {
- fprintf( stderr, "Swapped Texture (%p)\n", (void *)t );
- }
- }
-
- fprintf( stderr, "\n" );
-}
-
-/**
- * Print out debugging information about the global texture LRU.
- *
- * \param heap Texture heap to be printed
- * \param callername Name of calling function
- */
-static void printGlobalLRU( driTexHeap * heap, const char *callername )
-{
- drmTextureRegionPtr list = heap->global_regions;
- unsigned int i, j;
-
- fprintf( stderr, "%s in %s:\nGlobal LRU, heap %d list %p:\n",
- __FUNCTION__, callername, heap->heapId, (void *)list );
-
- for ( i = 0, j = heap->nrRegions ; i < heap->nrRegions ; i++ ) {
- fprintf( stderr, "list[%d] age %d next %d prev %d in_use %d\n",
- j, list[j].age, list[j].next, list[j].prev, list[j].in_use );
- j = list[j].next;
- if ( j == heap->nrRegions ) break;
- }
-
- if ( j != heap->nrRegions ) {
- fprintf( stderr, "Loop detected in global LRU\n" );
- for ( i = 0 ; i < heap->nrRegions ; i++ ) {
- fprintf( stderr, "list[%d] age %d next %d prev %d in_use %d\n",
- i, list[i].age, list[i].next, list[i].prev, list[i].in_use );
- }
- }
-
- fprintf( stderr, "\n" );
-}
-
-
-/**
- * Called by the client whenever it touches a local texture.
- *
- * \param t Texture object that the client has accessed
- */
-
-void driUpdateTextureLRU( driTextureObject * t )
-{
- driTexHeap * heap;
- drmTextureRegionPtr list;
- unsigned shift;
- unsigned start;
- unsigned end;
- unsigned i;
-
-
- heap = t->heap;
- if ( heap != NULL ) {
- shift = heap->logGranularity;
- start = t->memBlock->ofs >> shift;
- end = (t->memBlock->ofs + t->memBlock->size - 1) >> shift;
-
-
- heap->local_age = ++heap->global_age[0];
- list = heap->global_regions;
-
-
- /* Update the context's local LRU
- */
-
- move_to_head( & heap->texture_objects, t );
-
-
- for (i = start ; i <= end ; i++) {
- list[i].age = heap->local_age;
-
- /* remove_from_list(i)
- */
- list[(unsigned)list[i].next].prev = list[i].prev;
- list[(unsigned)list[i].prev].next = list[i].next;
-
- /* insert_at_head(list, i)
- */
- list[i].prev = heap->nrRegions;
- list[i].next = list[heap->nrRegions].next;
- list[(unsigned)list[heap->nrRegions].next].prev = i;
- list[heap->nrRegions].next = i;
- }
-
- if ( 0 ) {
- printGlobalLRU( heap, __FUNCTION__ );
- printLocalLRU( heap, __FUNCTION__ );
- }
- }
-}
-
-
-
-
-/**
- * Keep track of swapped out texture objects.
- *
- * \param t Texture object to be "swapped" out of its texture heap
- */
-
-void driSwapOutTextureObject( driTextureObject * t )
-{
- unsigned face;
-
-
- if ( t->memBlock != NULL ) {
- assert( t->heap != NULL );
- mmFreeMem( t->memBlock );
- t->memBlock = NULL;
-
- if (t->timestamp > t->heap->timestamp)
- t->heap->timestamp = t->timestamp;
-
- t->heap->texture_swaps[0]++;
- move_to_tail( t->heap->swapped_objects, t );
- t->heap = NULL;
- }
- else {
- assert( t->heap == NULL );
- }
-
-
- for ( face = 0 ; face < 6 ; face++ ) {
- t->dirty_images[face] = ~0;
- }
-}
-
-
-
-
-/**
- * Destroy hardware state associated with texture \a t. Calls the
- * \a destroy_texture_object method associated with the heap from which
- * \a t was allocated.
- *
- * \param t Texture object to be destroyed
- */
-
-void driDestroyTextureObject( driTextureObject * t )
-{
- driTexHeap * heap;
-
-
- if ( 0 ) {
- fprintf( stderr, "[%s:%d] freeing %p (tObj = %p, DriverData = %p)\n",
- __FILE__, __LINE__,
- (void *)t,
- (void *)((t != NULL) ? t->tObj : NULL),
- (void *)((t != NULL && t->tObj != NULL) ? t->tObj->DriverData : NULL ));
- }
-
- if ( t != NULL ) {
- if ( t->memBlock ) {
- heap = t->heap;
- assert( heap != NULL );
-
- heap->texture_swaps[0]++;
-
- mmFreeMem( t->memBlock );
- t->memBlock = NULL;
-
- if (t->timestamp > t->heap->timestamp)
- t->heap->timestamp = t->timestamp;
-
- heap->destroy_texture_object( heap->driverContext, t );
- t->heap = NULL;
- }
-
- if ( t->tObj != NULL ) {
- assert( t->tObj->DriverData == t );
- t->tObj->DriverData = NULL;
- }
-
- remove_from_list( t );
- FREE( t );
- }
-
- if ( 0 ) {
- fprintf( stderr, "[%s:%d] done freeing %p\n", __FILE__, __LINE__, (void *)t );
- }
-}
-
-
-
-
-/**
- * Update the local heap's representation of texture memory based on
- * data in the SAREA. This is done each time it is detected that some other
- * direct rendering client has held the lock. This pertains to both our local
- * textures and the textures belonging to other clients. Keep track of other
- * client's textures by pushing a placeholder texture onto the LRU list --
- * these are denoted by \a tObj being \a NULL.
- *
- * \param heap Heap whose state is to be updated
- * \param offset Byte offset in the heap that has been stolen
- * \param size Size, in bytes, of the stolen block
- * \param in_use Non-zero if the block is pinned/reserved by the kernel
- */
-
-static void driTexturesGone( driTexHeap * heap, int offset, int size,
- int in_use )
-{
- driTextureObject * t;
- driTextureObject * tmp;
-
-
- foreach_s ( t, tmp, & heap->texture_objects ) {
- if ( (t->memBlock->ofs < (offset + size))
- && ((t->memBlock->ofs + t->memBlock->size) > offset) ) {
- /* It overlaps - kick it out. If the texture object is just a
- * place holder, then destroy it all together. Otherwise, mark
- * it as being swapped out.
- */
-
- if ( t->tObj != NULL ) {
- driSwapOutTextureObject( t );
- }
- else {
- driDestroyTextureObject( t );
- }
- }
- }
-
-
- {
- t = (driTextureObject *) CALLOC( heap->texture_object_size );
- if ( t == NULL ) return;
-
- t->memBlock = mmAllocMem( heap->memory_heap, size, 0, offset );
- if ( t->memBlock == NULL ) {
- fprintf( stderr, "Couldn't alloc placeholder: heap %u sz %x ofs %x\n", heap->heapId,
- (int)size, (int)offset );
- mmDumpMemInfo( heap->memory_heap );
- FREE(t);
- return;
- }
- t->heap = heap;
- if (in_use)
- t->reserved = 1;
- insert_at_head( & heap->texture_objects, t );
- }
-}
-
-
-
-
-/**
- * Called by the client on lock contention to determine whether textures have
- * been stolen. If another client has modified a region in which we have
- * textures, then we need to figure out which of our textures have been
- * removed and update our global LRU.
- *
- * \param heap Texture heap to be updated
- */
-
-void driAgeTextures( driTexHeap * heap )
-{
- drmTextureRegionPtr list = heap->global_regions;
- unsigned sz = 1U << (heap->logGranularity);
- unsigned i, nr = 0;
-
-
- /* Have to go right round from the back to ensure stuff ends up
- * LRU in the local list... Fix with a cursor pointer.
- */
-
- for (i = list[heap->nrRegions].prev ;
- i != heap->nrRegions && nr < heap->nrRegions ;
- i = list[i].prev, nr++) {
- /* If switching texturing schemes, then the SAREA might not have been
- * properly cleared, so we need to reset the global texture LRU.
- */
-
- if ( (i * sz) > heap->size ) {
- nr = heap->nrRegions;
- break;
- }
-
- if (list[i].age > heap->local_age)
- driTexturesGone( heap, i * sz, sz, list[i].in_use);
- }
-
- /* Loop or uninitialized heap detected. Reset.
- */
-
- if (nr == heap->nrRegions) {
- driTexturesGone( heap, 0, heap->size, 0);
- resetGlobalLRU( heap );
- }
-
- if ( 0 ) {
- printGlobalLRU( heap, __FUNCTION__ );
- printLocalLRU( heap, __FUNCTION__ );
- }
-
- heap->local_age = heap->global_age[0];
-}
-
-
-
-
-#define INDEX_ARRAY_SIZE 6 /* I'm not aware of driver with more than 2 heaps */
-
-/**
- * Allocate memory from a texture heap to hold a texture object. This
- * routine will attempt to allocate memory for the texture from the heaps
- * specified by \c heap_array in order. That is, first it will try to
- * allocate from \c heap_array[0], then \c heap_array[1], and so on.
- *
- * \param heap_array Array of pointers to texture heaps to use
- * \param nr_heaps Number of heap pointer in \a heap_array
- * \param t Texture object for which space is needed
- * \return The ID of the heap from which memory was allocated, or -1 if
- * memory could not be allocated.
- *
- * \bug The replacement policy implemented by this function is horrible.
- */
-
-
-int
-driAllocateTexture( driTexHeap * const * heap_array, unsigned nr_heaps,
- driTextureObject * t )
-{
- driTexHeap * heap;
- driTextureObject * temp;
- driTextureObject * cursor;
- unsigned id;
-
-
- /* In case it already has texture space, initialize heap. This also
- * prevents GCC from issuing a warning that heap might be used
- * uninitialized.
- */
-
- heap = t->heap;
-
-
- /* Run through each of the existing heaps and try to allocate a buffer
- * to hold the texture.
- */
-
- for ( id = 0 ; (t->memBlock == NULL) && (id < nr_heaps) ; id++ ) {
- heap = heap_array[ id ];
- if ( heap != NULL ) {
- t->memBlock = mmAllocMem( heap->memory_heap, t->totalSize,
- heap->alignmentShift, 0 );
- }
- }
-
-
- /* Kick textures out until the requested texture fits.
- */
-
- if ( t->memBlock == NULL ) {
- unsigned index[INDEX_ARRAY_SIZE];
- unsigned nrGoodHeaps = 0;
-
- /* Trying to avoid dynamic memory allocation. If you have more
- * heaps, increase INDEX_ARRAY_SIZE. I'm not aware of any
- * drivers with more than 2 tex heaps. */
- assert( nr_heaps < INDEX_ARRAY_SIZE );
-
- /* Sort large enough heaps by duty. Insertion sort should be
- * fast enough for such a short array. */
- for ( id = 0 ; id < nr_heaps ; id++ ) {
- heap = heap_array[ id ];
-
- if ( heap != NULL && t->totalSize <= heap->size ) {
- unsigned j;
-
- for ( j = 0 ; j < nrGoodHeaps; j++ ) {
- if ( heap->duty > heap_array[ index[ j ] ]->duty )
- break;
- }
-
- if ( j < nrGoodHeaps ) {
- memmove( &index[ j+1 ], &index[ j ],
- sizeof(index[ 0 ]) * (nrGoodHeaps - j) );
- }
-
- index[ j ] = id;
-
- nrGoodHeaps++;
- }
- }
-
- for ( id = 0 ; (t->memBlock == NULL) && (id < nrGoodHeaps) ; id++ ) {
- heap = heap_array[ index[ id ] ];
-
- for ( cursor = heap->texture_objects.prev, temp = cursor->prev;
- cursor != &heap->texture_objects ;
- cursor = temp, temp = cursor->prev ) {
-
- /* The the LRU element. If the texture is bound to one of
- * the texture units, then we cannot kick it out.
- */
- if ( cursor->bound || cursor->reserved ) {
- continue;
- }
-
- if ( cursor->memBlock )
- heap->duty -= cursor->memBlock->size;
-
- /* If this is a placeholder, there's no need to keep it */
- if (cursor->tObj)
- driSwapOutTextureObject( cursor );
- else
- driDestroyTextureObject( cursor );
-
- t->memBlock = mmAllocMem( heap->memory_heap, t->totalSize,
- heap->alignmentShift, 0 );
-
- if (t->memBlock)
- break;
- }
- }
-
- /* Rebalance duties. If a heap kicked more data than its duty,
- * then all other heaps get that amount multiplied with their
- * relative weight added to their duty. The negative duty is
- * reset to 0. In the end all heaps have a duty >= 0.
- *
- * CAUTION: we must not change the heap pointer here, because it
- * is used below to update the texture object.
- */
- for ( id = 0 ; id < nr_heaps ; id++ )
- if ( heap_array[ id ] != NULL && heap_array[ id ]->duty < 0) {
- int duty = -heap_array[ id ]->duty;
- double weight = heap_array[ id ]->weight;
- unsigned j;
-
- for ( j = 0 ; j < nr_heaps ; j++ )
- if ( j != id && heap_array[ j ] != NULL ) {
- heap_array[ j ]->duty += (double) duty *
- heap_array[ j ]->weight / weight;
- }
-
- heap_array[ id ]->duty = 0;
- }
- }
-
-
- if ( t->memBlock != NULL ) {
- /* id and heap->heapId may or may not be the same value here.
- */
-
- assert( heap != NULL );
- assert( (t->heap == NULL) || (t->heap == heap) );
-
- t->heap = heap;
- return heap->heapId;
- }
- else {
- assert( t->heap == NULL );
-
- fprintf( stderr, "[%s:%d] unable to allocate texture\n",
- __FUNCTION__, __LINE__ );
- return -1;
- }
-}
-
-
-
-
-
-
-/**
- * Set the location where the texture-swap counter is stored.
- */
-
-void
-driSetTextureSwapCounterLocation( driTexHeap * heap, unsigned * counter )
-{
- heap->texture_swaps = (counter == NULL) ? & dummy_swap_counter : counter;
-}
-
-
-
-
-/**
- * Create a new heap for texture data.
- *
- * \param heap_id Device-dependent heap identifier. This value
- * will returned by driAllocateTexture when memory
- * is allocated from this heap.
- * \param context Device-dependent driver context. This is
- * supplied as the first parameter to the
- * \c destroy_tex_obj function.
- * \param size Size, in bytes, of the texture region
- * \param alignmentShift Alignment requirement for textures. If textures
- * must be allocated on a 4096 byte boundry, this
- * would be 12.
- * \param nr_regions Number of regions into which this texture space
- * should be partitioned
- * \param global_regions Array of \c drmTextureRegion structures in the SAREA
- * \param global_age Pointer to the global texture age in the SAREA
- * \param swapped_objects Pointer to the list of texture objects that are
- * not in texture memory (i.e., have been swapped
- * out).
- * \param texture_object_size Size, in bytes, of a device-dependent texture
- * object
- * \param destroy_tex_obj Function used to destroy a device-dependent
- * texture object
- *
- * \sa driDestroyTextureHeap
- */
-
-driTexHeap *
-driCreateTextureHeap( unsigned heap_id, void * context, unsigned size,
- unsigned alignmentShift, unsigned nr_regions,
- drmTextureRegionPtr global_regions, unsigned * global_age,
- driTextureObject * swapped_objects,
- unsigned texture_object_size,
- destroy_texture_object_t * destroy_tex_obj
- )
-{
- driTexHeap * heap;
- unsigned l;
-
-
- if ( 0 )
- fprintf( stderr, "%s( %u, %p, %u, %u, %u )\n",
- __FUNCTION__,
- heap_id, (void *)context, size, alignmentShift, nr_regions );
-
- heap = (driTexHeap *) CALLOC( sizeof( driTexHeap ) );
- if ( heap != NULL ) {
- l = driLog2( (size - 1) / nr_regions );
- if ( l < alignmentShift )
- {
- l = alignmentShift;
- }
-
- heap->logGranularity = l;
- heap->size = size & ~((1L << l) - 1);
-
- heap->memory_heap = mmInit( 0, heap->size );
- if ( heap->memory_heap != NULL ) {
- heap->heapId = heap_id;
- heap->driverContext = context;
-
- heap->alignmentShift = alignmentShift;
- heap->nrRegions = nr_regions;
- heap->global_regions = global_regions;
- heap->global_age = global_age;
- heap->swapped_objects = swapped_objects;
- heap->texture_object_size = texture_object_size;
- heap->destroy_texture_object = destroy_tex_obj;
-
- /* Force global heap init */
- if (heap->global_age[0] == 0)
- heap->local_age = ~0;
- else
- heap->local_age = 0;
-
- make_empty_list( & heap->texture_objects );
- driSetTextureSwapCounterLocation( heap, NULL );
-
- heap->weight = heap->size;
- heap->duty = 0;
- }
- else {
- FREE( heap );
- heap = NULL;
- }
- }
-
-
- if ( 0 )
- fprintf( stderr, "%s returning %p\n", __FUNCTION__, (void *)heap );
-
- return heap;
-}
-
-
-
-
-/** Destroys a texture heap
- *
- * \param heap Texture heap to be destroyed
- */
-
-void
-driDestroyTextureHeap( driTexHeap * heap )
-{
- driTextureObject * t;
- driTextureObject * temp;
-
-
- if ( heap != NULL ) {
- foreach_s( t, temp, & heap->texture_objects ) {
- driDestroyTextureObject( t );
- }
- foreach_s( t, temp, heap->swapped_objects ) {
- driDestroyTextureObject( t );
- }
-
- mmDestroy( heap->memory_heap );
- FREE( heap );
- }
-}
-
-
-
-
-/****************************************************************************/
-/**
- * Determine how many texels (including all mipmap levels) would be required
- * for a texture map of size \f$2^^\c base_size_log2\f$ would require.
- *
- * \param base_size_log2 \f$log_2\f$ of the size of a side of the texture
- * \param dimensions Number of dimensions of the texture. Either 2 or 3.
- * \param faces Number of faces of the texture. Either 1 or 6 (for cube maps).
- * \return Number of texels
- */
-
-static unsigned
-texels_this_map_size( int base_size_log2, unsigned dimensions, unsigned faces )
-{
- unsigned texels;
-
-
- assert( (faces == 1) || (faces == 6) );
- assert( (dimensions == 2) || (dimensions == 3) );
-
- texels = 0;
- if ( base_size_log2 >= 0 ) {
- texels = (1U << (dimensions * base_size_log2));
-
- /* See http://www.mail-archive.com/dri-devel@lists.sourceforge.net/msg03636.html
- * for the complete explaination of why this formulation is used.
- * Basically, the smaller mipmap levels sum to 0.333 the size of the
- * level 0 map. The total size is therefore the size of the map
- * multipled by 1.333. The +2 is there to round up.
- */
-
- texels = (texels * 4 * faces + 2) / 3;
- }
-
- return texels;
-}
-
-
-
-
-struct maps_per_heap {
- unsigned c[32];
-};
-
-static void
-fill_in_maximums( driTexHeap * const * heaps, unsigned nr_heaps,
- unsigned max_bytes_per_texel, unsigned max_size,
- unsigned mipmaps_at_once, unsigned dimensions,
- unsigned faces, struct maps_per_heap * max_textures )
-{
- unsigned heap;
- unsigned log2_size;
- unsigned mask;
-
-
- /* Determine how many textures of each size can be stored in each
- * texture heap.
- */
-
- for ( heap = 0 ; heap < nr_heaps ; heap++ ) {
- if ( heaps[ heap ] == NULL ) {
- (void) memset( max_textures[ heap ].c, 0,
- sizeof( max_textures[ heap ].c ) );
- continue;
- }
-
- mask = (1U << heaps[ heap ]->logGranularity) - 1;
-
- if ( 0 ) {
- fprintf( stderr, "[%s:%d] heap[%u] = %u bytes, mask = 0x%08x\n",
- __FILE__, __LINE__,
- heap, heaps[ heap ]->size, mask );
- }
-
- for ( log2_size = max_size ; log2_size > 0 ; log2_size-- ) {
- unsigned total;
-
-
- /* Determine the total number of bytes required by a texture of
- * size log2_size.
- */
-
- total = texels_this_map_size( log2_size, dimensions, faces )
- - texels_this_map_size( log2_size - mipmaps_at_once,
- dimensions, faces );
- total *= max_bytes_per_texel;
- total = (total + mask) & ~mask;
-
- /* The number of textures of a given size that will fit in a heap
- * is equal to the size of the heap divided by the size of the
- * texture.
- */
-
- max_textures[ heap ].c[ log2_size ] = heaps[ heap ]->size / total;
-
- if ( 0 ) {
- fprintf( stderr, "[%s:%d] max_textures[%u].c[%02u] "
- "= 0x%08x / 0x%08x "
- "= %u (%u)\n",
- __FILE__, __LINE__,
- heap, log2_size,
- heaps[ heap ]->size, total,
- heaps[ heap ]->size / total,
- max_textures[ heap ].c[ log2_size ] );
- }
- }
- }
-}
-
-
-static unsigned
-get_max_size( unsigned nr_heaps,
- unsigned texture_units,
- unsigned max_size,
- int all_textures_one_heap,
- struct maps_per_heap * max_textures )
-{
- unsigned heap;
- unsigned log2_size;
-
-
- /* Determine the largest texture size such that a texture of that size
- * can be bound to each texture unit at the same time. Some hardware
- * may require that all textures be in the same texture heap for
- * multitexturing.
- */
-
- for ( log2_size = max_size ; log2_size > 0 ; log2_size-- ) {
- unsigned total = 0;
-
- for ( heap = 0 ; heap < nr_heaps ; heap++ )
- {
- total += max_textures[ heap ].c[ log2_size ];
-
- if ( 0 ) {
- fprintf( stderr, "[%s:%d] max_textures[%u].c[%02u] = %u, "
- "total = %u\n", __FILE__, __LINE__, heap, log2_size,
- max_textures[ heap ].c[ log2_size ], total );
- }
-
- if ( (max_textures[ heap ].c[ log2_size ] >= texture_units)
- || (!all_textures_one_heap && (total >= texture_units)) ) {
- /* The number of mipmap levels is the log-base-2 of the
- * maximum texture size plus 1. If the maximum texture size
- * is 1x1, the log-base-2 is 0 and 1 mipmap level (the base
- * level) is available.
- */
-
- return log2_size + 1;
- }
- }
- }
-
- /* This should NEVER happen. It should always be possible to have at
- * *least* a 1x1 texture in memory!
- */
- assert( log2_size != 0 );
- return 0;
-}
-
-#define SET_MAX(f,v) \
- do { if ( max_sizes[v] != 0 ) { limits-> f = max_sizes[v]; } } while( 0 )
-
-#define SET_MAX_RECT(f,v) \
- do { if ( max_sizes[v] != 0 ) { limits-> f = 1 << (max_sizes[v] - 1); } } while( 0 )
-
-
-/**
- * Given the amount of texture memory, the number of texture units, and the
- * maximum size of a texel, calculate the maximum texture size the driver can
- * advertise.
- *
- * \param heaps Texture heaps for this card
- * \param nr_heap Number of texture heaps
- * \param limits OpenGL contants. MaxTextureUnits must be set.
- * \param max_bytes_per_texel Maximum size of a single texel, in bytes
- * \param max_2D_size \f$\log_2\f$ of the maximum 2D texture size (i.e.,
- * 1024x1024 textures, this would be 10)
- * \param max_3D_size \f$\log_2\f$ of the maximum 3D texture size (i.e.,
- * 1024x1024x1024 textures, this would be 10)
- * \param max_cube_size \f$\log_2\f$ of the maximum cube texture size (i.e.,
- * 1024x1024 textures, this would be 10)
- * \param max_rect_size \f$\log_2\f$ of the maximum texture rectangle size
- * (i.e., 1024x1024 textures, this would be 10). This is a power-of-2
- * even though texture rectangles need not be a power-of-2.
- * \param mipmaps_at_once Total number of mipmaps that can be used
- * at one time. For most hardware this will be \f$\c max_size + 1\f$.
- * For hardware that does not support mipmapping, this will be 1.
- * \param all_textures_one_heap True if the hardware requires that all
- * textures be in a single texture heap for multitexturing.
- * \param allow_larger_textures 0 conservative, 1 calculate limits
- * so at least one worst-case texture can fit, 2 just use hw limits.
- */
-
-void
-driCalculateMaxTextureLevels( driTexHeap * const * heaps,
- unsigned nr_heaps,
- struct gl_constants * limits,
- unsigned max_bytes_per_texel,
- unsigned max_2D_size,
- unsigned max_3D_size,
- unsigned max_cube_size,
- unsigned max_rect_size,
- unsigned mipmaps_at_once,
- int all_textures_one_heap,
- int allow_larger_textures )
-{
- struct maps_per_heap max_textures[8];
- unsigned i;
- const unsigned dimensions[4] = { 2, 3, 2, 2 };
- const unsigned faces[4] = { 1, 1, 6, 1 };
- unsigned max_sizes[4];
- unsigned mipmaps[4];
-
-
- max_sizes[0] = max_2D_size;
- max_sizes[1] = max_3D_size;
- max_sizes[2] = max_cube_size;
- max_sizes[3] = max_rect_size;
-
- mipmaps[0] = mipmaps_at_once;
- mipmaps[1] = mipmaps_at_once;
- mipmaps[2] = mipmaps_at_once;
- mipmaps[3] = 1;
-
-
- /* Calculate the maximum number of texture levels in two passes. The
- * first pass determines how many textures of each power-of-two size
- * (including all mipmap levels for that size) can fit in each texture
- * heap. The second pass finds the largest texture size that allows
- * a texture of that size to be bound to every texture unit.
- */
-
- for ( i = 0 ; i < 4 ; i++ ) {
- if ( (allow_larger_textures != 2) && (max_sizes[ i ] != 0) ) {
- fill_in_maximums( heaps, nr_heaps, max_bytes_per_texel,
- max_sizes[ i ], mipmaps[ i ],
- dimensions[ i ], faces[ i ],
- max_textures );
-
- max_sizes[ i ] = get_max_size( nr_heaps,
- allow_larger_textures == 1 ?
- 1 : limits->MaxTextureUnits,
- max_sizes[ i ],
- all_textures_one_heap,
- max_textures );
- }
- else if (max_sizes[ i ] != 0) {
- max_sizes[ i ] += 1;
- }
- }
-
- SET_MAX( MaxTextureLevels, 0 );
- SET_MAX( Max3DTextureLevels, 1 );
- SET_MAX( MaxCubeTextureLevels, 2 );
- SET_MAX_RECT( MaxTextureRectSize, 3 );
-}
-
-
-
-
-/**
- * Perform initial binding of default textures objects on a per unit, per
- * texture target basis.
- *
- * \param ctx Current OpenGL context
- * \param swapped List of swapped-out textures
- * \param targets Bit-mask of value texture targets
- */
-
-void driInitTextureObjects( GLcontext *ctx, driTextureObject * swapped,
- GLuint targets )
-{
- struct gl_texture_object *texObj;
- GLuint tmp = ctx->Texture.CurrentUnit;
- unsigned i;
-
-
- for ( i = 0 ; i < ctx->Const.MaxTextureUnits ; i++ ) {
- ctx->Texture.CurrentUnit = i;
-
- if ( (targets & DRI_TEXMGR_DO_TEXTURE_1D) != 0 ) {
- texObj = ctx->Texture.Unit[i].CurrentTex[TEXTURE_1D_INDEX];
- ctx->Driver.BindTexture( ctx, GL_TEXTURE_1D, texObj );
- move_to_tail( swapped, (driTextureObject *) texObj->DriverData );
- }
-
- if ( (targets & DRI_TEXMGR_DO_TEXTURE_2D) != 0 ) {
- texObj = ctx->Texture.Unit[i].CurrentTex[TEXTURE_2D_INDEX];
- ctx->Driver.BindTexture( ctx, GL_TEXTURE_2D, texObj );
- move_to_tail( swapped, (driTextureObject *) texObj->DriverData );
- }
-
- if ( (targets & DRI_TEXMGR_DO_TEXTURE_3D) != 0 ) {
- texObj = ctx->Texture.Unit[i].CurrentTex[TEXTURE_3D_INDEX];
- ctx->Driver.BindTexture( ctx, GL_TEXTURE_3D, texObj );
- move_to_tail( swapped, (driTextureObject *) texObj->DriverData );
- }
-
- if ( (targets & DRI_TEXMGR_DO_TEXTURE_CUBE) != 0 ) {
- texObj = ctx->Texture.Unit[i].CurrentTex[TEXTURE_CUBE_INDEX];
- ctx->Driver.BindTexture( ctx, GL_TEXTURE_CUBE_MAP_ARB, texObj );
- move_to_tail( swapped, (driTextureObject *) texObj->DriverData );
- }
-
- if ( (targets & DRI_TEXMGR_DO_TEXTURE_RECT) != 0 ) {
- texObj = ctx->Texture.Unit[i].CurrentTex[TEXTURE_RECT_INDEX];
- ctx->Driver.BindTexture( ctx, GL_TEXTURE_RECTANGLE_NV, texObj );
- move_to_tail( swapped, (driTextureObject *) texObj->DriverData );
- }
- }
-
- ctx->Texture.CurrentUnit = tmp;
-}
-
-
-
-
-/**
- * Verify that the specified texture is in the specificed heap.
- *
- * \param tex Texture to be tested.
- * \param heap Texture memory heap to be tested.
- * \return True if the texture is in the heap, false otherwise.
- */
-
-static GLboolean
-check_in_heap( const driTextureObject * tex, const driTexHeap * heap )
-{
-#if 1
- return tex->heap == heap;
-#else
- driTextureObject * curr;
-
- foreach( curr, & heap->texture_objects ) {
- if ( curr == tex ) {
- break;
- }
- }
-
- return curr == tex;
-#endif
-}
-
-
-
-/****************************************************************************/
-/**
- * Validate the consistency of a set of texture heaps.
- * Original version by Keith Whitwell in r200/r200_sanity.c.
- */
-
-GLboolean
-driValidateTextureHeaps( driTexHeap * const * texture_heaps,
- unsigned nr_heaps, const driTextureObject * swapped )
-{
- driTextureObject *t;
- unsigned i;
-
- for ( i = 0 ; i < nr_heaps ; i++ ) {
- int last_end = 0;
- unsigned textures_in_heap = 0;
- unsigned blocks_in_mempool = 0;
- const driTexHeap * heap = texture_heaps[i];
- const struct mem_block *p = heap->memory_heap;
-
- /* Check each texture object has a MemBlock, and is linked into
- * the correct heap.
- *
- * Check the texobj base address corresponds to the MemBlock
- * range. Check the texobj size (recalculate?) fits within
- * the MemBlock.
- *
- * Count the number of texobj's using this heap.
- */
-
- foreach ( t, &heap->texture_objects ) {
- if ( !check_in_heap( t, heap ) ) {
- fprintf( stderr, "%s memory block for texture object @ %p not "
- "found in heap #%d\n",
- __FUNCTION__, (void *)t, i );
- return GL_FALSE;
- }
-
-
- if ( t->totalSize > t->memBlock->size ) {
- fprintf( stderr, "%s: Memory block for texture object @ %p is "
- "only %u bytes, but %u are required\n",
- __FUNCTION__, (void *)t, t->totalSize, t->memBlock->size );
- return GL_FALSE;
- }
-
- textures_in_heap++;
- }
-
- /* Validate the contents of the heap:
- * - Ordering
- * - Overlaps
- * - Bounds
- */
-
- while ( p != NULL ) {
- if (p->reserved) {
- fprintf( stderr, "%s: Block (%08x,%x), is reserved?!\n",
- __FUNCTION__, p->ofs, p->size );
- return GL_FALSE;
- }
-
- if (p->ofs != last_end) {
- fprintf( stderr, "%s: blocks_in_mempool = %d, last_end = %d, p->ofs = %d\n",
- __FUNCTION__, blocks_in_mempool, last_end, p->ofs );
- return GL_FALSE;
- }
-
- if (!p->reserved && !p->free) {
- blocks_in_mempool++;
- }
-
- last_end = p->ofs + p->size;
- p = p->next;
- }
-
- if (textures_in_heap != blocks_in_mempool) {
- fprintf( stderr, "%s: Different number of textures objects (%u) and "
- "inuse memory blocks (%u)\n",
- __FUNCTION__, textures_in_heap, blocks_in_mempool );
- return GL_FALSE;
- }
-
-#if 0
- fprintf( stderr, "%s: textures_in_heap = %u\n",
- __FUNCTION__, textures_in_heap );
-#endif
- }
-
-
- /* Check swapped texobj's have zero memblocks
- */
- i = 0;
- foreach ( t, swapped ) {
- if ( t->memBlock != NULL ) {
- fprintf( stderr, "%s: Swapped texobj %p has non-NULL memblock %p\n",
- __FUNCTION__, (void *)t, (void *)t->memBlock );
- return GL_FALSE;
- }
- i++;
- }
-
-#if 0
- fprintf( stderr, "%s: swapped texture count = %u\n", __FUNCTION__, i );
-#endif
-
- return GL_TRUE;
-}
-
-
-
-
-/****************************************************************************/
-/**
- * Compute which mipmap levels that really need to be sent to the hardware.
- * This depends on the base image size, GL_TEXTURE_MIN_LOD,
- * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL.
- */
-
-void
-driCalculateTextureFirstLastLevel( driTextureObject * t )
-{
- struct gl_texture_object * const tObj = t->tObj;
- const struct gl_texture_image * const baseImage =
- tObj->Image[0][tObj->BaseLevel];
-
- /* These must be signed values. MinLod and MaxLod can be negative numbers,
- * and having firstLevel and lastLevel as signed prevents the need for
- * extra sign checks.
- */
- int firstLevel;
- int lastLevel;
-
- /* Yes, this looks overly complicated, but it's all needed.
- */
-
- switch (tObj->Target) {
- case GL_TEXTURE_1D:
- case GL_TEXTURE_2D:
- case GL_TEXTURE_3D:
- case GL_TEXTURE_CUBE_MAP:
- if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) {
- /* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL.
- */
-
- firstLevel = lastLevel = tObj->BaseLevel;
- }
- else {
- firstLevel = tObj->BaseLevel + (GLint)(tObj->MinLod + 0.5);
- firstLevel = MAX2(firstLevel, tObj->BaseLevel);
- firstLevel = MIN2(firstLevel, tObj->BaseLevel + baseImage->MaxLog2);
- lastLevel = tObj->BaseLevel + (GLint)(tObj->MaxLod + 0.5);
- lastLevel = MAX2(lastLevel, t->tObj->BaseLevel);
- lastLevel = MIN2(lastLevel, t->tObj->BaseLevel + baseImage->MaxLog2);
- lastLevel = MIN2(lastLevel, t->tObj->MaxLevel);
- lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */
- }
- break;
- case GL_TEXTURE_RECTANGLE_NV:
- case GL_TEXTURE_4D_SGIS:
- firstLevel = lastLevel = 0;
- break;
- default:
- return;
- }
-
- /* save these values */
- t->firstLevel = firstLevel;
- t->lastLevel = lastLevel;
-}
-
-
-
-
-/**
- * \name DRI texture formats. These vars are initialized to either the
- * big- or little-endian Mesa formats.
- */
-/*@{*/
-gl_format _dri_texformat_rgba8888 = MESA_FORMAT_NONE;
-gl_format _dri_texformat_argb8888 = MESA_FORMAT_NONE;
-gl_format _dri_texformat_rgb565 = MESA_FORMAT_NONE;
-gl_format _dri_texformat_argb4444 = MESA_FORMAT_NONE;
-gl_format _dri_texformat_argb1555 = MESA_FORMAT_NONE;
-gl_format _dri_texformat_al88 = MESA_FORMAT_NONE;
-gl_format _dri_texformat_a8 = MESA_FORMAT_A8;
-gl_format _dri_texformat_ci8 = MESA_FORMAT_CI8;
-gl_format _dri_texformat_i8 = MESA_FORMAT_I8;
-gl_format _dri_texformat_l8 = MESA_FORMAT_L8;
-/*@}*/
-
-
-/**
- * Initialize _dri_texformat_* vars according to whether we're on
- * a big or little endian system.
- */
-void
-driInitTextureFormats(void)
-{
- if (_mesa_little_endian()) {
- _dri_texformat_rgba8888 = MESA_FORMAT_RGBA8888;
- _dri_texformat_argb8888 = MESA_FORMAT_ARGB8888;
- _dri_texformat_rgb565 = MESA_FORMAT_RGB565;
- _dri_texformat_argb4444 = MESA_FORMAT_ARGB4444;
- _dri_texformat_argb1555 = MESA_FORMAT_ARGB1555;
- _dri_texformat_al88 = MESA_FORMAT_AL88;
- }
- else {
- _dri_texformat_rgba8888 = MESA_FORMAT_RGBA8888_REV;
- _dri_texformat_argb8888 = MESA_FORMAT_ARGB8888_REV;
- _dri_texformat_rgb565 = MESA_FORMAT_RGB565_REV;
- _dri_texformat_argb4444 = MESA_FORMAT_ARGB4444_REV;
- _dri_texformat_argb1555 = MESA_FORMAT_ARGB1555_REV;
- _dri_texformat_al88 = MESA_FORMAT_AL88_REV;
- }
-}
+/*
+ * Copyright 2000-2001 VA Linux Systems, Inc.
+ * (C) Copyright IBM Corporation 2002, 2003
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Ian Romanick <idr@us.ibm.com>
+ * Keith Whitwell <keithw@tungstengraphics.com>
+ * Kevin E. Martin <kem@users.sourceforge.net>
+ * Gareth Hughes <gareth@nvidia.com>
+ */
+
+/** \file texmem.c
+ * Implements all of the device-independent texture memory management.
+ *
+ * Currently, only a simple LRU texture memory management policy is
+ * implemented. In the (hopefully very near) future, better policies will be
+ * implemented. The idea is that the DRI should be able to run in one of two
+ * modes. In the default mode the DRI will dynamically attempt to discover
+ * the best texture management policy for the running application. In the
+ * other mode, the user (via some sort of as yet TBD mechanism) will select
+ * a texture management policy that is known to work well with the
+ * application.
+ */
+
+#include "main/imports.h"
+#include "main/macros.h"
+#include "main/simple_list.h"
+#include "texmem.h"
+
+
+static unsigned dummy_swap_counter;
+
+
+/**
+ * Calculate \f$\log_2\f$ of a value. This is a particularly poor
+ * implementation of this function. However, since system performance is in
+ * no way dependent on this function, the slowness of the implementation is
+ * irrelevent.
+ *
+ * \param n Value whose \f$\log_2\f$ is to be calculated
+ */
+
+static GLuint
+driLog2( GLuint n )
+{
+ GLuint log2;
+
+ for ( log2 = 1 ; n > 1 ; log2++ ) {
+ n >>= 1;
+ }
+
+ return log2;
+}
+
+
+
+
+/**
+ * Determine if a texture is resident in textureable memory. Depending on
+ * the driver, this may or may not be on-card memory. It could be AGP memory
+ * or anyother type of memory from which the hardware can directly read
+ * texels.
+ *
+ * This function is intended to be used as the \c IsTextureResident function
+ * in the device's \c dd_function_table.
+ *
+ * \param ctx GL context pointer (currently unused)
+ * \param texObj Texture object to be tested
+ */
+
+GLboolean
+driIsTextureResident( struct gl_context * ctx,
+ struct gl_texture_object * texObj )
+{
+ driTextureObject * t;
+
+
+ t = (driTextureObject *) texObj->DriverData;
+ return( (t != NULL) && (t->memBlock != NULL) );
+}
+
+
+
+
+/**
+ * (Re)initialize the global circular LRU list. The last element
+ * in the array (\a heap->nrRegions) is the sentinal. Keeping it
+ * at the end of the array allows the other elements of the array
+ * to be addressed rationally when looking up objects at a particular
+ * location in texture memory.
+ *
+ * \param heap Texture heap to be reset
+ */
+
+static void resetGlobalLRU( driTexHeap * heap )
+{
+ drmTextureRegionPtr list = heap->global_regions;
+ unsigned sz = 1U << heap->logGranularity;
+ unsigned i;
+
+ for (i = 0 ; (i+1) * sz <= heap->size ; i++) {
+ list[i].prev = i-1;
+ list[i].next = i+1;
+ list[i].age = 0;
+ }
+
+ i--;
+ list[0].prev = heap->nrRegions;
+ list[i].prev = i-1;
+ list[i].next = heap->nrRegions;
+ list[heap->nrRegions].prev = i;
+ list[heap->nrRegions].next = 0;
+ heap->global_age[0] = 0;
+}
+
+/**
+ * Print out debugging information about the local texture LRU.
+ *
+ * \param heap Texture heap to be printed
+ * \param callername Name of calling function
+ */
+static void printLocalLRU( driTexHeap * heap, const char *callername )
+{
+ driTextureObject *t;
+ unsigned sz = 1U << heap->logGranularity;
+
+ fprintf( stderr, "%s in %s:\nLocal LRU, heap %d:\n",
+ __FUNCTION__, callername, heap->heapId );
+
+ foreach ( t, &heap->texture_objects ) {
+ if (!t->memBlock)
+ continue;
+ if (!t->tObj) {
+ fprintf( stderr, "Placeholder (%p) %d at 0x%x sz 0x%x\n",
+ (void *)t,
+ t->memBlock->ofs / sz,
+ t->memBlock->ofs,
+ t->memBlock->size );
+ } else {
+ fprintf( stderr, "Texture (%p) at 0x%x sz 0x%x\n",
+ (void *)t,
+ t->memBlock->ofs,
+ t->memBlock->size );
+ }
+ }
+ foreach ( t, heap->swapped_objects ) {
+ if (!t->tObj) {
+ fprintf( stderr, "Swapped Placeholder (%p)\n", (void *)t );
+ } else {
+ fprintf( stderr, "Swapped Texture (%p)\n", (void *)t );
+ }
+ }
+
+ fprintf( stderr, "\n" );
+}
+
+/**
+ * Print out debugging information about the global texture LRU.
+ *
+ * \param heap Texture heap to be printed
+ * \param callername Name of calling function
+ */
+static void printGlobalLRU( driTexHeap * heap, const char *callername )
+{
+ drmTextureRegionPtr list = heap->global_regions;
+ unsigned int i, j;
+
+ fprintf( stderr, "%s in %s:\nGlobal LRU, heap %d list %p:\n",
+ __FUNCTION__, callername, heap->heapId, (void *)list );
+
+ for ( i = 0, j = heap->nrRegions ; i < heap->nrRegions ; i++ ) {
+ fprintf( stderr, "list[%d] age %d next %d prev %d in_use %d\n",
+ j, list[j].age, list[j].next, list[j].prev, list[j].in_use );
+ j = list[j].next;
+ if ( j == heap->nrRegions ) break;
+ }
+
+ if ( j != heap->nrRegions ) {
+ fprintf( stderr, "Loop detected in global LRU\n" );
+ for ( i = 0 ; i < heap->nrRegions ; i++ ) {
+ fprintf( stderr, "list[%d] age %d next %d prev %d in_use %d\n",
+ i, list[i].age, list[i].next, list[i].prev, list[i].in_use );
+ }
+ }
+
+ fprintf( stderr, "\n" );
+}
+
+
+/**
+ * Called by the client whenever it touches a local texture.
+ *
+ * \param t Texture object that the client has accessed
+ */
+
+void driUpdateTextureLRU( driTextureObject * t )
+{
+ driTexHeap * heap;
+ drmTextureRegionPtr list;
+ unsigned shift;
+ unsigned start;
+ unsigned end;
+ unsigned i;
+
+
+ heap = t->heap;
+ if ( heap != NULL ) {
+ shift = heap->logGranularity;
+ start = t->memBlock->ofs >> shift;
+ end = (t->memBlock->ofs + t->memBlock->size - 1) >> shift;
+
+
+ heap->local_age = ++heap->global_age[0];
+ list = heap->global_regions;
+
+
+ /* Update the context's local LRU
+ */
+
+ move_to_head( & heap->texture_objects, t );
+
+
+ for (i = start ; i <= end ; i++) {
+ list[i].age = heap->local_age;
+
+ /* remove_from_list(i)
+ */
+ list[(unsigned)list[i].next].prev = list[i].prev;
+ list[(unsigned)list[i].prev].next = list[i].next;
+
+ /* insert_at_head(list, i)
+ */
+ list[i].prev = heap->nrRegions;
+ list[i].next = list[heap->nrRegions].next;
+ list[(unsigned)list[heap->nrRegions].next].prev = i;
+ list[heap->nrRegions].next = i;
+ }
+
+ if ( 0 ) {
+ printGlobalLRU( heap, __FUNCTION__ );
+ printLocalLRU( heap, __FUNCTION__ );
+ }
+ }
+}
+
+
+
+
+/**
+ * Keep track of swapped out texture objects.
+ *
+ * \param t Texture object to be "swapped" out of its texture heap
+ */
+
+void driSwapOutTextureObject( driTextureObject * t )
+{
+ unsigned face;
+
+
+ if ( t->memBlock != NULL ) {
+ assert( t->heap != NULL );
+ mmFreeMem( t->memBlock );
+ t->memBlock = NULL;
+
+ if (t->timestamp > t->heap->timestamp)
+ t->heap->timestamp = t->timestamp;
+
+ t->heap->texture_swaps[0]++;
+ move_to_tail( t->heap->swapped_objects, t );
+ t->heap = NULL;
+ }
+ else {
+ assert( t->heap == NULL );
+ }
+
+
+ for ( face = 0 ; face < 6 ; face++ ) {
+ t->dirty_images[face] = ~0;
+ }
+}
+
+
+
+
+/**
+ * Destroy hardware state associated with texture \a t. Calls the
+ * \a destroy_texture_object method associated with the heap from which
+ * \a t was allocated.
+ *
+ * \param t Texture object to be destroyed
+ */
+
+void driDestroyTextureObject( driTextureObject * t )
+{
+ driTexHeap * heap;
+
+
+ if ( 0 ) {
+ fprintf( stderr, "[%s:%d] freeing %p (tObj = %p, DriverData = %p)\n",
+ __FILE__, __LINE__,
+ (void *)t,
+ (void *)((t != NULL) ? t->tObj : NULL),
+ (void *)((t != NULL && t->tObj != NULL) ? t->tObj->DriverData : NULL ));
+ }
+
+ if ( t != NULL ) {
+ if ( t->memBlock ) {
+ heap = t->heap;
+ assert( heap != NULL );
+
+ heap->texture_swaps[0]++;
+
+ mmFreeMem( t->memBlock );
+ t->memBlock = NULL;
+
+ if (t->timestamp > t->heap->timestamp)
+ t->heap->timestamp = t->timestamp;
+
+ heap->destroy_texture_object( heap->driverContext, t );
+ t->heap = NULL;
+ }
+
+ if ( t->tObj != NULL ) {
+ assert( t->tObj->DriverData == t );
+ t->tObj->DriverData = NULL;
+ }
+
+ remove_from_list( t );
+ FREE( t );
+ }
+
+ if ( 0 ) {
+ fprintf( stderr, "[%s:%d] done freeing %p\n", __FILE__, __LINE__, (void *)t );
+ }
+}
+
+
+
+
+/**
+ * Update the local heap's representation of texture memory based on
+ * data in the SAREA. This is done each time it is detected that some other
+ * direct rendering client has held the lock. This pertains to both our local
+ * textures and the textures belonging to other clients. Keep track of other
+ * client's textures by pushing a placeholder texture onto the LRU list --
+ * these are denoted by \a tObj being \a NULL.
+ *
+ * \param heap Heap whose state is to be updated
+ * \param offset Byte offset in the heap that has been stolen
+ * \param size Size, in bytes, of the stolen block
+ * \param in_use Non-zero if the block is pinned/reserved by the kernel
+ */
+
+static void driTexturesGone( driTexHeap * heap, int offset, int size,
+ int in_use )
+{
+ driTextureObject * t;
+ driTextureObject * tmp;
+
+
+ foreach_s ( t, tmp, & heap->texture_objects ) {
+ if ( (t->memBlock->ofs < (offset + size))
+ && ((t->memBlock->ofs + t->memBlock->size) > offset) ) {
+ /* It overlaps - kick it out. If the texture object is just a
+ * place holder, then destroy it all together. Otherwise, mark
+ * it as being swapped out.
+ */
+
+ if ( t->tObj != NULL ) {
+ driSwapOutTextureObject( t );
+ }
+ else {
+ driDestroyTextureObject( t );
+ }
+ }
+ }
+
+
+ {
+ t = (driTextureObject *) CALLOC( heap->texture_object_size );
+ if ( t == NULL ) return;
+
+ t->memBlock = mmAllocMem( heap->memory_heap, size, 0, offset );
+ if ( t->memBlock == NULL ) {
+ fprintf( stderr, "Couldn't alloc placeholder: heap %u sz %x ofs %x\n", heap->heapId,
+ (int)size, (int)offset );
+ mmDumpMemInfo( heap->memory_heap );
+ FREE(t);
+ return;
+ }
+ t->heap = heap;
+ if (in_use)
+ t->reserved = 1;
+ insert_at_head( & heap->texture_objects, t );
+ }
+}
+
+
+
+
+/**
+ * Called by the client on lock contention to determine whether textures have
+ * been stolen. If another client has modified a region in which we have
+ * textures, then we need to figure out which of our textures have been
+ * removed and update our global LRU.
+ *
+ * \param heap Texture heap to be updated
+ */
+
+void driAgeTextures( driTexHeap * heap )
+{
+ drmTextureRegionPtr list = heap->global_regions;
+ unsigned sz = 1U << (heap->logGranularity);
+ unsigned i, nr = 0;
+
+
+ /* Have to go right round from the back to ensure stuff ends up
+ * LRU in the local list... Fix with a cursor pointer.
+ */
+
+ for (i = list[heap->nrRegions].prev ;
+ i != heap->nrRegions && nr < heap->nrRegions ;
+ i = list[i].prev, nr++) {
+ /* If switching texturing schemes, then the SAREA might not have been
+ * properly cleared, so we need to reset the global texture LRU.
+ */
+
+ if ( (i * sz) > heap->size ) {
+ nr = heap->nrRegions;
+ break;
+ }
+
+ if (list[i].age > heap->local_age)
+ driTexturesGone( heap, i * sz, sz, list[i].in_use);
+ }
+
+ /* Loop or uninitialized heap detected. Reset.
+ */
+
+ if (nr == heap->nrRegions) {
+ driTexturesGone( heap, 0, heap->size, 0);
+ resetGlobalLRU( heap );
+ }
+
+ if ( 0 ) {
+ printGlobalLRU( heap, __FUNCTION__ );
+ printLocalLRU( heap, __FUNCTION__ );
+ }
+
+ heap->local_age = heap->global_age[0];
+}
+
+
+
+
+#define INDEX_ARRAY_SIZE 6 /* I'm not aware of driver with more than 2 heaps */
+
+/**
+ * Allocate memory from a texture heap to hold a texture object. This
+ * routine will attempt to allocate memory for the texture from the heaps
+ * specified by \c heap_array in order. That is, first it will try to
+ * allocate from \c heap_array[0], then \c heap_array[1], and so on.
+ *
+ * \param heap_array Array of pointers to texture heaps to use
+ * \param nr_heaps Number of heap pointer in \a heap_array
+ * \param t Texture object for which space is needed
+ * \return The ID of the heap from which memory was allocated, or -1 if
+ * memory could not be allocated.
+ *
+ * \bug The replacement policy implemented by this function is horrible.
+ */
+
+
+int
+driAllocateTexture( driTexHeap * const * heap_array, unsigned nr_heaps,
+ driTextureObject * t )
+{
+ driTexHeap * heap;
+ driTextureObject * temp;
+ driTextureObject * cursor;
+ unsigned id;
+
+
+ /* In case it already has texture space, initialize heap. This also
+ * prevents GCC from issuing a warning that heap might be used
+ * uninitialized.
+ */
+
+ heap = t->heap;
+
+
+ /* Run through each of the existing heaps and try to allocate a buffer
+ * to hold the texture.
+ */
+
+ for ( id = 0 ; (t->memBlock == NULL) && (id < nr_heaps) ; id++ ) {
+ heap = heap_array[ id ];
+ if ( heap != NULL ) {
+ t->memBlock = mmAllocMem( heap->memory_heap, t->totalSize,
+ heap->alignmentShift, 0 );
+ }
+ }
+
+
+ /* Kick textures out until the requested texture fits.
+ */
+
+ if ( t->memBlock == NULL ) {
+ unsigned index[INDEX_ARRAY_SIZE];
+ unsigned nrGoodHeaps = 0;
+
+ /* Trying to avoid dynamic memory allocation. If you have more
+ * heaps, increase INDEX_ARRAY_SIZE. I'm not aware of any
+ * drivers with more than 2 tex heaps. */
+ assert( nr_heaps < INDEX_ARRAY_SIZE );
+
+ /* Sort large enough heaps by duty. Insertion sort should be
+ * fast enough for such a short array. */
+ for ( id = 0 ; id < nr_heaps ; id++ ) {
+ heap = heap_array[ id ];
+
+ if ( heap != NULL && t->totalSize <= heap->size ) {
+ unsigned j;
+
+ for ( j = 0 ; j < nrGoodHeaps; j++ ) {
+ if ( heap->duty > heap_array[ index[ j ] ]->duty )
+ break;
+ }
+
+ if ( j < nrGoodHeaps ) {
+ memmove( &index[ j+1 ], &index[ j ],
+ sizeof(index[ 0 ]) * (nrGoodHeaps - j) );
+ }
+
+ index[ j ] = id;
+
+ nrGoodHeaps++;
+ }
+ }
+
+ for ( id = 0 ; (t->memBlock == NULL) && (id < nrGoodHeaps) ; id++ ) {
+ heap = heap_array[ index[ id ] ];
+
+ for ( cursor = heap->texture_objects.prev, temp = cursor->prev;
+ cursor != &heap->texture_objects ;
+ cursor = temp, temp = cursor->prev ) {
+
+ /* The the LRU element. If the texture is bound to one of
+ * the texture units, then we cannot kick it out.
+ */
+ if ( cursor->bound || cursor->reserved ) {
+ continue;
+ }
+
+ if ( cursor->memBlock )
+ heap->duty -= cursor->memBlock->size;
+
+ /* If this is a placeholder, there's no need to keep it */
+ if (cursor->tObj)
+ driSwapOutTextureObject( cursor );
+ else
+ driDestroyTextureObject( cursor );
+
+ t->memBlock = mmAllocMem( heap->memory_heap, t->totalSize,
+ heap->alignmentShift, 0 );
+
+ if (t->memBlock)
+ break;
+ }
+ }
+
+ /* Rebalance duties. If a heap kicked more data than its duty,
+ * then all other heaps get that amount multiplied with their
+ * relative weight added to their duty. The negative duty is
+ * reset to 0. In the end all heaps have a duty >= 0.
+ *
+ * CAUTION: we must not change the heap pointer here, because it
+ * is used below to update the texture object.
+ */
+ for ( id = 0 ; id < nr_heaps ; id++ )
+ if ( heap_array[ id ] != NULL && heap_array[ id ]->duty < 0) {
+ int duty = -heap_array[ id ]->duty;
+ double weight = heap_array[ id ]->weight;
+ unsigned j;
+
+ for ( j = 0 ; j < nr_heaps ; j++ )
+ if ( j != id && heap_array[ j ] != NULL ) {
+ heap_array[ j ]->duty += (double) duty *
+ heap_array[ j ]->weight / weight;
+ }
+
+ heap_array[ id ]->duty = 0;
+ }
+ }
+
+
+ if ( t->memBlock != NULL ) {
+ /* id and heap->heapId may or may not be the same value here.
+ */
+
+ assert( heap != NULL );
+ assert( (t->heap == NULL) || (t->heap == heap) );
+
+ t->heap = heap;
+ return heap->heapId;
+ }
+ else {
+ assert( t->heap == NULL );
+
+ fprintf( stderr, "[%s:%d] unable to allocate texture\n",
+ __FUNCTION__, __LINE__ );
+ return -1;
+ }
+}
+
+
+
+
+
+
+/**
+ * Set the location where the texture-swap counter is stored.
+ */
+
+void
+driSetTextureSwapCounterLocation( driTexHeap * heap, unsigned * counter )
+{
+ heap->texture_swaps = (counter == NULL) ? & dummy_swap_counter : counter;
+}
+
+
+
+
+/**
+ * Create a new heap for texture data.
+ *
+ * \param heap_id Device-dependent heap identifier. This value
+ * will returned by driAllocateTexture when memory
+ * is allocated from this heap.
+ * \param context Device-dependent driver context. This is
+ * supplied as the first parameter to the
+ * \c destroy_tex_obj function.
+ * \param size Size, in bytes, of the texture region
+ * \param alignmentShift Alignment requirement for textures. If textures
+ * must be allocated on a 4096 byte boundry, this
+ * would be 12.
+ * \param nr_regions Number of regions into which this texture space
+ * should be partitioned
+ * \param global_regions Array of \c drmTextureRegion structures in the SAREA
+ * \param global_age Pointer to the global texture age in the SAREA
+ * \param swapped_objects Pointer to the list of texture objects that are
+ * not in texture memory (i.e., have been swapped
+ * out).
+ * \param texture_object_size Size, in bytes, of a device-dependent texture
+ * object
+ * \param destroy_tex_obj Function used to destroy a device-dependent
+ * texture object
+ *
+ * \sa driDestroyTextureHeap
+ */
+
+driTexHeap *
+driCreateTextureHeap( unsigned heap_id, void * context, unsigned size,
+ unsigned alignmentShift, unsigned nr_regions,
+ drmTextureRegionPtr global_regions, unsigned * global_age,
+ driTextureObject * swapped_objects,
+ unsigned texture_object_size,
+ destroy_texture_object_t * destroy_tex_obj
+ )
+{
+ driTexHeap * heap;
+ unsigned l;
+
+
+ if ( 0 )
+ fprintf( stderr, "%s( %u, %p, %u, %u, %u )\n",
+ __FUNCTION__,
+ heap_id, (void *)context, size, alignmentShift, nr_regions );
+
+ heap = (driTexHeap *) CALLOC( sizeof( driTexHeap ) );
+ if ( heap != NULL ) {
+ l = driLog2( (size - 1) / nr_regions );
+ if ( l < alignmentShift )
+ {
+ l = alignmentShift;
+ }
+
+ heap->logGranularity = l;
+ heap->size = size & ~((1L << l) - 1);
+
+ heap->memory_heap = mmInit( 0, heap->size );
+ if ( heap->memory_heap != NULL ) {
+ heap->heapId = heap_id;
+ heap->driverContext = context;
+
+ heap->alignmentShift = alignmentShift;
+ heap->nrRegions = nr_regions;
+ heap->global_regions = global_regions;
+ heap->global_age = global_age;
+ heap->swapped_objects = swapped_objects;
+ heap->texture_object_size = texture_object_size;
+ heap->destroy_texture_object = destroy_tex_obj;
+
+ /* Force global heap init */
+ if (heap->global_age[0] == 0)
+ heap->local_age = ~0;
+ else
+ heap->local_age = 0;
+
+ make_empty_list( & heap->texture_objects );
+ driSetTextureSwapCounterLocation( heap, NULL );
+
+ heap->weight = heap->size;
+ heap->duty = 0;
+ }
+ else {
+ FREE( heap );
+ heap = NULL;
+ }
+ }
+
+
+ if ( 0 )
+ fprintf( stderr, "%s returning %p\n", __FUNCTION__, (void *)heap );
+
+ return heap;
+}
+
+
+
+
+/** Destroys a texture heap
+ *
+ * \param heap Texture heap to be destroyed
+ */
+
+void
+driDestroyTextureHeap( driTexHeap * heap )
+{
+ driTextureObject * t;
+ driTextureObject * temp;
+
+
+ if ( heap != NULL ) {
+ foreach_s( t, temp, & heap->texture_objects ) {
+ driDestroyTextureObject( t );
+ }
+ foreach_s( t, temp, heap->swapped_objects ) {
+ driDestroyTextureObject( t );
+ }
+
+ mmDestroy( heap->memory_heap );
+ FREE( heap );
+ }
+}
+
+
+
+
+/****************************************************************************/
+/**
+ * Determine how many texels (including all mipmap levels) would be required
+ * for a texture map of size \f$2^^\c base_size_log2\f$ would require.
+ *
+ * \param base_size_log2 \f$log_2\f$ of the size of a side of the texture
+ * \param dimensions Number of dimensions of the texture. Either 2 or 3.
+ * \param faces Number of faces of the texture. Either 1 or 6 (for cube maps).
+ * \return Number of texels
+ */
+
+static unsigned
+texels_this_map_size( int base_size_log2, unsigned dimensions, unsigned faces )
+{
+ unsigned texels;
+
+
+ assert( (faces == 1) || (faces == 6) );
+ assert( (dimensions == 2) || (dimensions == 3) );
+
+ texels = 0;
+ if ( base_size_log2 >= 0 ) {
+ texels = (1U << (dimensions * base_size_log2));
+
+ /* See http://www.mail-archive.com/dri-devel@lists.sourceforge.net/msg03636.html
+ * for the complete explaination of why this formulation is used.
+ * Basically, the smaller mipmap levels sum to 0.333 the size of the
+ * level 0 map. The total size is therefore the size of the map
+ * multipled by 1.333. The +2 is there to round up.
+ */
+
+ texels = (texels * 4 * faces + 2) / 3;
+ }
+
+ return texels;
+}
+
+
+
+
+struct maps_per_heap {
+ unsigned c[32];
+};
+
+static void
+fill_in_maximums( driTexHeap * const * heaps, unsigned nr_heaps,
+ unsigned max_bytes_per_texel, unsigned max_size,
+ unsigned mipmaps_at_once, unsigned dimensions,
+ unsigned faces, struct maps_per_heap * max_textures )
+{
+ unsigned heap;
+ unsigned log2_size;
+ unsigned mask;
+
+
+ /* Determine how many textures of each size can be stored in each
+ * texture heap.
+ */
+
+ for ( heap = 0 ; heap < nr_heaps ; heap++ ) {
+ if ( heaps[ heap ] == NULL ) {
+ (void) memset( max_textures[ heap ].c, 0,
+ sizeof( max_textures[ heap ].c ) );
+ continue;
+ }
+
+ mask = (1U << heaps[ heap ]->logGranularity) - 1;
+
+ if ( 0 ) {
+ fprintf( stderr, "[%s:%d] heap[%u] = %u bytes, mask = 0x%08x\n",
+ __FILE__, __LINE__,
+ heap, heaps[ heap ]->size, mask );
+ }
+
+ for ( log2_size = max_size ; log2_size > 0 ; log2_size-- ) {
+ unsigned total;
+
+
+ /* Determine the total number of bytes required by a texture of
+ * size log2_size.
+ */
+
+ total = texels_this_map_size( log2_size, dimensions, faces )
+ - texels_this_map_size( log2_size - mipmaps_at_once,
+ dimensions, faces );
+ total *= max_bytes_per_texel;
+ total = (total + mask) & ~mask;
+
+ /* The number of textures of a given size that will fit in a heap
+ * is equal to the size of the heap divided by the size of the
+ * texture.
+ */
+
+ max_textures[ heap ].c[ log2_size ] = heaps[ heap ]->size / total;
+
+ if ( 0 ) {
+ fprintf( stderr, "[%s:%d] max_textures[%u].c[%02u] "
+ "= 0x%08x / 0x%08x "
+ "= %u (%u)\n",
+ __FILE__, __LINE__,
+ heap, log2_size,
+ heaps[ heap ]->size, total,
+ heaps[ heap ]->size / total,
+ max_textures[ heap ].c[ log2_size ] );
+ }
+ }
+ }
+}
+
+
+static unsigned
+get_max_size( unsigned nr_heaps,
+ unsigned texture_units,
+ unsigned max_size,
+ int all_textures_one_heap,
+ struct maps_per_heap * max_textures )
+{
+ unsigned heap;
+ unsigned log2_size;
+
+
+ /* Determine the largest texture size such that a texture of that size
+ * can be bound to each texture unit at the same time. Some hardware
+ * may require that all textures be in the same texture heap for
+ * multitexturing.
+ */
+
+ for ( log2_size = max_size ; log2_size > 0 ; log2_size-- ) {
+ unsigned total = 0;
+
+ for ( heap = 0 ; heap < nr_heaps ; heap++ )
+ {
+ total += max_textures[ heap ].c[ log2_size ];
+
+ if ( 0 ) {
+ fprintf( stderr, "[%s:%d] max_textures[%u].c[%02u] = %u, "
+ "total = %u\n", __FILE__, __LINE__, heap, log2_size,
+ max_textures[ heap ].c[ log2_size ], total );
+ }
+
+ if ( (max_textures[ heap ].c[ log2_size ] >= texture_units)
+ || (!all_textures_one_heap && (total >= texture_units)) ) {
+ /* The number of mipmap levels is the log-base-2 of the
+ * maximum texture size plus 1. If the maximum texture size
+ * is 1x1, the log-base-2 is 0 and 1 mipmap level (the base
+ * level) is available.
+ */
+
+ return log2_size + 1;
+ }
+ }
+ }
+
+ /* This should NEVER happen. It should always be possible to have at
+ * *least* a 1x1 texture in memory!
+ */
+ assert( log2_size != 0 );
+ return 0;
+}
+
+#define SET_MAX(f,v) \
+ do { if ( max_sizes[v] != 0 ) { limits-> f = max_sizes[v]; } } while( 0 )
+
+#define SET_MAX_RECT(f,v) \
+ do { if ( max_sizes[v] != 0 ) { limits-> f = 1 << (max_sizes[v] - 1); } } while( 0 )
+
+
+/**
+ * Given the amount of texture memory, the number of texture units, and the
+ * maximum size of a texel, calculate the maximum texture size the driver can
+ * advertise.
+ *
+ * \param heaps Texture heaps for this card
+ * \param nr_heap Number of texture heaps
+ * \param limits OpenGL contants. MaxTextureUnits must be set.
+ * \param max_bytes_per_texel Maximum size of a single texel, in bytes
+ * \param max_2D_size \f$\log_2\f$ of the maximum 2D texture size (i.e.,
+ * 1024x1024 textures, this would be 10)
+ * \param max_3D_size \f$\log_2\f$ of the maximum 3D texture size (i.e.,
+ * 1024x1024x1024 textures, this would be 10)
+ * \param max_cube_size \f$\log_2\f$ of the maximum cube texture size (i.e.,
+ * 1024x1024 textures, this would be 10)
+ * \param max_rect_size \f$\log_2\f$ of the maximum texture rectangle size
+ * (i.e., 1024x1024 textures, this would be 10). This is a power-of-2
+ * even though texture rectangles need not be a power-of-2.
+ * \param mipmaps_at_once Total number of mipmaps that can be used
+ * at one time. For most hardware this will be \f$\c max_size + 1\f$.
+ * For hardware that does not support mipmapping, this will be 1.
+ * \param all_textures_one_heap True if the hardware requires that all
+ * textures be in a single texture heap for multitexturing.
+ * \param allow_larger_textures 0 conservative, 1 calculate limits
+ * so at least one worst-case texture can fit, 2 just use hw limits.
+ */
+
+void
+driCalculateMaxTextureLevels( driTexHeap * const * heaps,
+ unsigned nr_heaps,
+ struct gl_constants * limits,
+ unsigned max_bytes_per_texel,
+ unsigned max_2D_size,
+ unsigned max_3D_size,
+ unsigned max_cube_size,
+ unsigned max_rect_size,
+ unsigned mipmaps_at_once,
+ int all_textures_one_heap,
+ int allow_larger_textures )
+{
+ struct maps_per_heap max_textures[8];
+ unsigned i;
+ const unsigned dimensions[4] = { 2, 3, 2, 2 };
+ const unsigned faces[4] = { 1, 1, 6, 1 };
+ unsigned max_sizes[4];
+ unsigned mipmaps[4];
+
+
+ max_sizes[0] = max_2D_size;
+ max_sizes[1] = max_3D_size;
+ max_sizes[2] = max_cube_size;
+ max_sizes[3] = max_rect_size;
+
+ mipmaps[0] = mipmaps_at_once;
+ mipmaps[1] = mipmaps_at_once;
+ mipmaps[2] = mipmaps_at_once;
+ mipmaps[3] = 1;
+
+
+ /* Calculate the maximum number of texture levels in two passes. The
+ * first pass determines how many textures of each power-of-two size
+ * (including all mipmap levels for that size) can fit in each texture
+ * heap. The second pass finds the largest texture size that allows
+ * a texture of that size to be bound to every texture unit.
+ */
+
+ for ( i = 0 ; i < 4 ; i++ ) {
+ if ( (allow_larger_textures != 2) && (max_sizes[ i ] != 0) ) {
+ fill_in_maximums( heaps, nr_heaps, max_bytes_per_texel,
+ max_sizes[ i ], mipmaps[ i ],
+ dimensions[ i ], faces[ i ],
+ max_textures );
+
+ max_sizes[ i ] = get_max_size( nr_heaps,
+ allow_larger_textures == 1 ?
+ 1 : limits->MaxTextureUnits,
+ max_sizes[ i ],
+ all_textures_one_heap,
+ max_textures );
+ }
+ else if (max_sizes[ i ] != 0) {
+ max_sizes[ i ] += 1;
+ }
+ }
+
+ SET_MAX( MaxTextureLevels, 0 );
+ SET_MAX( Max3DTextureLevels, 1 );
+ SET_MAX( MaxCubeTextureLevels, 2 );
+ SET_MAX_RECT( MaxTextureRectSize, 3 );
+}
+
+
+
+
+/**
+ * Perform initial binding of default textures objects on a per unit, per
+ * texture target basis.
+ *
+ * \param ctx Current OpenGL context
+ * \param swapped List of swapped-out textures
+ * \param targets Bit-mask of value texture targets
+ */
+
+void driInitTextureObjects( struct gl_context *ctx, driTextureObject * swapped,
+ GLuint targets )
+{
+ struct gl_texture_object *texObj;
+ GLuint tmp = ctx->Texture.CurrentUnit;
+ unsigned i;
+
+
+ for ( i = 0 ; i < ctx->Const.MaxTextureUnits ; i++ ) {
+ ctx->Texture.CurrentUnit = i;
+
+ if ( (targets & DRI_TEXMGR_DO_TEXTURE_1D) != 0 ) {
+ texObj = ctx->Texture.Unit[i].CurrentTex[TEXTURE_1D_INDEX];
+ ctx->Driver.BindTexture( ctx, GL_TEXTURE_1D, texObj );
+ move_to_tail( swapped, (driTextureObject *) texObj->DriverData );
+ }
+
+ if ( (targets & DRI_TEXMGR_DO_TEXTURE_2D) != 0 ) {
+ texObj = ctx->Texture.Unit[i].CurrentTex[TEXTURE_2D_INDEX];
+ ctx->Driver.BindTexture( ctx, GL_TEXTURE_2D, texObj );
+ move_to_tail( swapped, (driTextureObject *) texObj->DriverData );
+ }
+
+ if ( (targets & DRI_TEXMGR_DO_TEXTURE_3D) != 0 ) {
+ texObj = ctx->Texture.Unit[i].CurrentTex[TEXTURE_3D_INDEX];
+ ctx->Driver.BindTexture( ctx, GL_TEXTURE_3D, texObj );
+ move_to_tail( swapped, (driTextureObject *) texObj->DriverData );
+ }
+
+ if ( (targets & DRI_TEXMGR_DO_TEXTURE_CUBE) != 0 ) {
+ texObj = ctx->Texture.Unit[i].CurrentTex[TEXTURE_CUBE_INDEX];
+ ctx->Driver.BindTexture( ctx, GL_TEXTURE_CUBE_MAP_ARB, texObj );
+ move_to_tail( swapped, (driTextureObject *) texObj->DriverData );
+ }
+
+ if ( (targets & DRI_TEXMGR_DO_TEXTURE_RECT) != 0 ) {
+ texObj = ctx->Texture.Unit[i].CurrentTex[TEXTURE_RECT_INDEX];
+ ctx->Driver.BindTexture( ctx, GL_TEXTURE_RECTANGLE_NV, texObj );
+ move_to_tail( swapped, (driTextureObject *) texObj->DriverData );
+ }
+ }
+
+ ctx->Texture.CurrentUnit = tmp;
+}
+
+
+
+
+/**
+ * Verify that the specified texture is in the specificed heap.
+ *
+ * \param tex Texture to be tested.
+ * \param heap Texture memory heap to be tested.
+ * \return True if the texture is in the heap, false otherwise.
+ */
+
+static GLboolean
+check_in_heap( const driTextureObject * tex, const driTexHeap * heap )
+{
+#if 1
+ return tex->heap == heap;
+#else
+ driTextureObject * curr;
+
+ foreach( curr, & heap->texture_objects ) {
+ if ( curr == tex ) {
+ break;
+ }
+ }
+
+ return curr == tex;
+#endif
+}
+
+
+
+/****************************************************************************/
+/**
+ * Validate the consistency of a set of texture heaps.
+ * Original version by Keith Whitwell in r200/r200_sanity.c.
+ */
+
+GLboolean
+driValidateTextureHeaps( driTexHeap * const * texture_heaps,
+ unsigned nr_heaps, const driTextureObject * swapped )
+{
+ driTextureObject *t;
+ unsigned i;
+
+ for ( i = 0 ; i < nr_heaps ; i++ ) {
+ int last_end = 0;
+ unsigned textures_in_heap = 0;
+ unsigned blocks_in_mempool = 0;
+ const driTexHeap * heap = texture_heaps[i];
+ const struct mem_block *p = heap->memory_heap;
+
+ /* Check each texture object has a MemBlock, and is linked into
+ * the correct heap.
+ *
+ * Check the texobj base address corresponds to the MemBlock
+ * range. Check the texobj size (recalculate?) fits within
+ * the MemBlock.
+ *
+ * Count the number of texobj's using this heap.
+ */
+
+ foreach ( t, &heap->texture_objects ) {
+ if ( !check_in_heap( t, heap ) ) {
+ fprintf( stderr, "%s memory block for texture object @ %p not "
+ "found in heap #%d\n",
+ __FUNCTION__, (void *)t, i );
+ return GL_FALSE;
+ }
+
+
+ if ( t->totalSize > t->memBlock->size ) {
+ fprintf( stderr, "%s: Memory block for texture object @ %p is "
+ "only %u bytes, but %u are required\n",
+ __FUNCTION__, (void *)t, t->totalSize, t->memBlock->size );
+ return GL_FALSE;
+ }
+
+ textures_in_heap++;
+ }
+
+ /* Validate the contents of the heap:
+ * - Ordering
+ * - Overlaps
+ * - Bounds
+ */
+
+ while ( p != NULL ) {
+ if (p->reserved) {
+ fprintf( stderr, "%s: Block (%08x,%x), is reserved?!\n",
+ __FUNCTION__, p->ofs, p->size );
+ return GL_FALSE;
+ }
+
+ if (p->ofs != last_end) {
+ fprintf( stderr, "%s: blocks_in_mempool = %d, last_end = %d, p->ofs = %d\n",
+ __FUNCTION__, blocks_in_mempool, last_end, p->ofs );
+ return GL_FALSE;
+ }
+
+ if (!p->reserved && !p->free) {
+ blocks_in_mempool++;
+ }
+
+ last_end = p->ofs + p->size;
+ p = p->next;
+ }
+
+ if (textures_in_heap != blocks_in_mempool) {
+ fprintf( stderr, "%s: Different number of textures objects (%u) and "
+ "inuse memory blocks (%u)\n",
+ __FUNCTION__, textures_in_heap, blocks_in_mempool );
+ return GL_FALSE;
+ }
+
+#if 0
+ fprintf( stderr, "%s: textures_in_heap = %u\n",
+ __FUNCTION__, textures_in_heap );
+#endif
+ }
+
+
+ /* Check swapped texobj's have zero memblocks
+ */
+ i = 0;
+ foreach ( t, swapped ) {
+ if ( t->memBlock != NULL ) {
+ fprintf( stderr, "%s: Swapped texobj %p has non-NULL memblock %p\n",
+ __FUNCTION__, (void *)t, (void *)t->memBlock );
+ return GL_FALSE;
+ }
+ i++;
+ }
+
+#if 0
+ fprintf( stderr, "%s: swapped texture count = %u\n", __FUNCTION__, i );
+#endif
+
+ return GL_TRUE;
+}
+
+
+
+
+/****************************************************************************/
+/**
+ * Compute which mipmap levels that really need to be sent to the hardware.
+ * This depends on the base image size, GL_TEXTURE_MIN_LOD,
+ * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL.
+ */
+
+void
+driCalculateTextureFirstLastLevel( driTextureObject * t )
+{
+ struct gl_texture_object * const tObj = t->tObj;
+ const struct gl_texture_image * const baseImage =
+ tObj->Image[0][tObj->BaseLevel];
+
+ /* These must be signed values. MinLod and MaxLod can be negative numbers,
+ * and having firstLevel and lastLevel as signed prevents the need for
+ * extra sign checks.
+ */
+ int firstLevel;
+ int lastLevel;
+
+ /* Yes, this looks overly complicated, but it's all needed.
+ */
+
+ switch (tObj->Target) {
+ case GL_TEXTURE_1D:
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_3D:
+ case GL_TEXTURE_CUBE_MAP:
+ if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) {
+ /* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL.
+ */
+
+ firstLevel = lastLevel = tObj->BaseLevel;
+ }
+ else {
+ firstLevel = tObj->BaseLevel + (GLint)(tObj->MinLod + 0.5);
+ firstLevel = MAX2(firstLevel, tObj->BaseLevel);
+ firstLevel = MIN2(firstLevel, tObj->BaseLevel + baseImage->MaxLog2);
+ lastLevel = tObj->BaseLevel + (GLint)(tObj->MaxLod + 0.5);
+ lastLevel = MAX2(lastLevel, t->tObj->BaseLevel);
+ lastLevel = MIN2(lastLevel, t->tObj->BaseLevel + baseImage->MaxLog2);
+ lastLevel = MIN2(lastLevel, t->tObj->MaxLevel);
+ lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */
+ }
+ break;
+ case GL_TEXTURE_RECTANGLE_NV:
+ case GL_TEXTURE_4D_SGIS:
+ firstLevel = lastLevel = 0;
+ break;
+ default:
+ return;
+ }
+
+ /* save these values */
+ t->firstLevel = firstLevel;
+ t->lastLevel = lastLevel;
+}
+
+
+
+
+/**
+ * \name DRI texture formats. These vars are initialized to either the
+ * big- or little-endian Mesa formats.
+ */
+/*@{*/
+gl_format _dri_texformat_rgba8888 = MESA_FORMAT_NONE;
+gl_format _dri_texformat_argb8888 = MESA_FORMAT_NONE;
+gl_format _dri_texformat_rgb565 = MESA_FORMAT_NONE;
+gl_format _dri_texformat_argb4444 = MESA_FORMAT_NONE;
+gl_format _dri_texformat_argb1555 = MESA_FORMAT_NONE;
+gl_format _dri_texformat_al88 = MESA_FORMAT_NONE;
+gl_format _dri_texformat_a8 = MESA_FORMAT_A8;
+gl_format _dri_texformat_ci8 = MESA_FORMAT_CI8;
+gl_format _dri_texformat_i8 = MESA_FORMAT_I8;
+gl_format _dri_texformat_l8 = MESA_FORMAT_L8;
+/*@}*/
+
+
+/**
+ * Initialize _dri_texformat_* vars according to whether we're on
+ * a big or little endian system.
+ */
+void
+driInitTextureFormats(void)
+{
+ if (_mesa_little_endian()) {
+ _dri_texformat_rgba8888 = MESA_FORMAT_RGBA8888;
+ _dri_texformat_argb8888 = MESA_FORMAT_ARGB8888;
+ _dri_texformat_rgb565 = MESA_FORMAT_RGB565;
+ _dri_texformat_argb4444 = MESA_FORMAT_ARGB4444;
+ _dri_texformat_argb1555 = MESA_FORMAT_ARGB1555;
+ _dri_texformat_al88 = MESA_FORMAT_AL88;
+ }
+ else {
+ _dri_texformat_rgba8888 = MESA_FORMAT_RGBA8888_REV;
+ _dri_texformat_argb8888 = MESA_FORMAT_ARGB8888_REV;
+ _dri_texformat_rgb565 = MESA_FORMAT_RGB565_REV;
+ _dri_texformat_argb4444 = MESA_FORMAT_ARGB4444_REV;
+ _dri_texformat_argb1555 = MESA_FORMAT_ARGB1555_REV;
+ _dri_texformat_al88 = MESA_FORMAT_AL88_REV;
+ }
+}
diff --git a/mesalib/src/mesa/drivers/dri/common/texmem.h b/mesalib/src/mesa/drivers/dri/common/texmem.h
index 725ba2e11..3815c4107 100644
--- a/mesalib/src/mesa/drivers/dri/common/texmem.h
+++ b/mesalib/src/mesa/drivers/dri/common/texmem.h
@@ -1,334 +1,334 @@
-/*
- * Copyright 2000-2001 VA Linux Systems, Inc.
- * (c) Copyright IBM Corporation 2002
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * on the rights to use, copy, modify, merge, publish, distribute, sub
- * license, and/or sell copies of the Software, and to permit persons to whom
- * the Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Ian Romanick <idr@us.ibm.com>
- * Keith Whitwell <keithw@tungstengraphics.com>
- * Kevin E. Martin <kem@users.sourceforge.net>
- * Gareth Hughes <gareth@nvidia.com>
- */
-
-/** \file texmem.h
- * Public interface to the DRI texture memory management routines.
- *
- * \sa texmem.c
- */
-
-#ifndef DRI_TEXMEM_H
-#define DRI_TEXMEM_H
-
-#include "main/mtypes.h"
-#include "main/formats.h"
-#include "main/mm.h"
-#include "xf86drm.h"
-
-struct dri_tex_heap;
-typedef struct dri_tex_heap driTexHeap;
-
-struct dri_texture_object;
-typedef struct dri_texture_object driTextureObject;
-
-
-/**
- * Base texture object type. Each driver will extend this type with its own
- * private data members.
- */
-
-struct dri_texture_object {
- struct dri_texture_object * next;
- struct dri_texture_object * prev;
-
- driTexHeap * heap; /**< Texture heap currently stored in */
- struct gl_texture_object * tObj;/**< Pointer to Mesa texture object
- * If NULL, this texture object is a
- * "placeholder" object representing
- * texture memory in use by another context.
- * A placeholder should have a heap and a memBlock.
- */
- struct mem_block *memBlock; /**< Memory block containing texture */
-
- unsigned reserved; /**< Cannot be swapped out by user contexts. */
-
- unsigned bound; /**< Bitmask indicating which tex units
- * this texture object is bound to.
- * Bit 0 = unit 0, Bit 1 = unit 1, etc
- */
-
- unsigned totalSize; /**< Total size of the texture,
- * including all mipmap levels
- */
-
- unsigned dirty_images[6]; /**< Flags for whether or not images
- * need to be uploaded to local or
- * AGP texture space. One flag set
- * for each cube face for cubic
- * textures. Bit zero corresponds to
- * the base-level, which may or may
- * not be the level zero mipmap.
- */
-
- unsigned timestamp; /**< Timestamp used to
- * synchronize with 3d engine
- * in hardware where textures
- * are uploaded directly to
- * the framebuffer.
- */
-
- unsigned firstLevel; /**< Image in \c tObj->Image[0] that
- * corresponds to the base-level of
- * this texture object.
- */
-
- unsigned lastLevel; /**< Last image in \c tObj->Image[0]
- * used by the
- * current LOD settings of
- * this texture object. This
- * value must be greater than
- * or equal to \c firstLevel.
- */
-};
-
-
-typedef void (destroy_texture_object_t)( void * driverContext,
- driTextureObject * t );
-
-/**
- * Client-private representation of texture memory state.
- *
- * Clients will place one or more of these structs in their driver
- * context struct to manage one or more global texture heaps.
- */
-
-struct dri_tex_heap {
-
- /** Client-supplied heap identifier
- */
- unsigned heapId;
-
- /** Pointer to the client's private context
- */
- void *driverContext;
-
- /** Total size of the heap, in bytes
- */
- unsigned size;
-
- /** \brief \f$log_2\f$ of size of single heap region
- *
- * Each context takes memory from the global texture heap in
- * \f$2^{logGranularity}\f$ byte blocks. The value of
- * \a logGranularity is based on the amount of memory represented
- * by the heap and the maximum number of regions in the SAREA. Given
- * \a b bytes of texture memory an \a n regions in the SAREA,
- * \a logGranularity will be \f$\lfloor\log_2( b / n )\rfloor\f$.
- */
- unsigned logGranularity;
-
- /** \brief Required alignment of allocations in this heap
- *
- * The alignment shift is supplied to \a mmAllocMem when memory is
- * allocated from this heap. The value of \a alignmentShift will
- * typically reflect some require of the hardware. This value has
- * \b no \b relation to \a logGranularity. \a alignmentShift is a
- * per-context value.
- *
- * \sa mmAllocMem
- */
- unsigned alignmentShift;
-
- /** Number of elements in global list (the SAREA).
- */
- unsigned nrRegions;
-
- /** Pointer to SAREA \a driTexRegion array
- */
- drmTextureRegionPtr global_regions;
-
- /** Pointer to the texture state age (generation number) in the SAREA
- */
- unsigned * global_age;
-
- /** Local age (generation number) of texture state
- */
- unsigned local_age;
-
- /** Memory heap used to manage texture memory represented by
- * this texture heap.
- */
- struct mem_block * memory_heap;
-
- /** List of objects that we currently believe to be in texture
- * memory.
- */
- driTextureObject texture_objects;
-
- /** Pointer to the list of texture objects that are not in
- * texture memory.
- */
- driTextureObject * swapped_objects;
-
- /** Size of the driver-speicific texture object.
- */
- unsigned texture_object_size;
-
-
- /**
- * \brief Function to destroy driver-specific texture object data.
- *
- * This function is supplied by the driver so that the texture manager
- * can release all resources associated with a texture object. This
- * function should only release driver-specific data. That is,
- * \a driDestroyTextureObject will release the texture memory
- * associated with the texture object, it will release the memory
- * for the texture object itself, and it will unlink the texture
- * object from the texture object lists.
- *
- * \param driverContext Pointer to the driver supplied context
- * \param t Texture object that is to be destroyed
- * \sa driDestroyTextureObject
- */
-
- destroy_texture_object_t * destroy_texture_object;
-
-
- /**
- */
- unsigned * texture_swaps;
-
- /**
- * Timestamp used to synchronize with 3d engine in hardware
- * where textures are uploaded directly to the
- * framebuffer.
- */
- unsigned timestamp;
-
- /** \brief Kick/upload weight
- *
- * When not enough free space is available this weight
- * influences the choice of the heap from which textures are
- * kicked. By default the weight is equal to the heap size.
- */
- double weight;
-
- /** \brief Kick/upload duty
- *
- * The heap with the highest duty will be chosen for kicking
- * textures if not enough free space is available. The duty is
- * reduced by the amount of data kicked. Rebalancing of
- * negative duties takes the weights into account.
- */
- int duty;
-};
-
-
-
-
-/**
- * Called by the client on lock contention to determine whether textures have
- * been stolen. If another client has modified a region in which we have
- * textures, then we need to figure out which of our textures have been
- * removed and update our global LRU.
- *
- * \param heap Texture heap to be updated
- * \hideinitializer
- */
-
-#define DRI_AGE_TEXTURES( heap ) \
- do { \
- if ( ((heap) != NULL) \
- && ((heap)->local_age != (heap)->global_age[0]) ) \
- driAgeTextures( heap ); \
- } while( 0 )
-
-
-
-
-/* This should be called whenever there has been contention on the hardware
- * lock. driAgeTextures should not be called directly. Instead, clients
- * should use DRI_AGE_TEXTURES, above.
- */
-
-void driAgeTextures( driTexHeap * heap );
-
-void driUpdateTextureLRU( driTextureObject * t );
-void driSwapOutTextureObject( driTextureObject * t );
-void driDestroyTextureObject( driTextureObject * t );
-int driAllocateTexture( driTexHeap * const * heap_array, unsigned nr_heaps,
- driTextureObject * t );
-
-GLboolean driIsTextureResident( GLcontext * ctx,
- struct gl_texture_object * texObj );
-
-driTexHeap * driCreateTextureHeap( unsigned heap_id, void * context,
- unsigned size, unsigned alignmentShift, unsigned nr_regions,
- drmTextureRegionPtr global_regions, unsigned * global_age,
- driTextureObject * swapped_objects, unsigned texture_object_size,
- destroy_texture_object_t * destroy_tex_obj );
-void driDestroyTextureHeap( driTexHeap * heap );
-
-void
-driCalculateMaxTextureLevels( driTexHeap * const * heaps,
- unsigned nr_heaps,
- struct gl_constants * limits,
- unsigned max_bytes_per_texel,
- unsigned max_2D_size,
- unsigned max_3D_size,
- unsigned max_cube_size,
- unsigned max_rect_size,
- unsigned mipmaps_at_once,
- int all_textures_one_heap,
- int allow_larger_textures );
-
-void
-driSetTextureSwapCounterLocation( driTexHeap * heap, unsigned * counter );
-
-#define DRI_TEXMGR_DO_TEXTURE_1D 0x0001
-#define DRI_TEXMGR_DO_TEXTURE_2D 0x0002
-#define DRI_TEXMGR_DO_TEXTURE_3D 0x0004
-#define DRI_TEXMGR_DO_TEXTURE_CUBE 0x0008
-#define DRI_TEXMGR_DO_TEXTURE_RECT 0x0010
-
-void driInitTextureObjects( GLcontext *ctx, driTextureObject * swapped,
- GLuint targets );
-
-GLboolean driValidateTextureHeaps( driTexHeap * const * texture_heaps,
- unsigned nr_heaps, const driTextureObject * swapped );
-
-extern void driCalculateTextureFirstLastLevel( driTextureObject * t );
-
-
-extern gl_format _dri_texformat_rgba8888;
-extern gl_format _dri_texformat_argb8888;
-extern gl_format _dri_texformat_rgb565;
-extern gl_format _dri_texformat_argb4444;
-extern gl_format _dri_texformat_argb1555;
-extern gl_format _dri_texformat_al88;
-extern gl_format _dri_texformat_a8;
-extern gl_format _dri_texformat_ci8;
-extern gl_format _dri_texformat_i8;
-extern gl_format _dri_texformat_l8;
-
-extern void driInitTextureFormats( void );
-
-#endif /* DRI_TEXMEM_H */
+/*
+ * Copyright 2000-2001 VA Linux Systems, Inc.
+ * (c) Copyright IBM Corporation 2002
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Ian Romanick <idr@us.ibm.com>
+ * Keith Whitwell <keithw@tungstengraphics.com>
+ * Kevin E. Martin <kem@users.sourceforge.net>
+ * Gareth Hughes <gareth@nvidia.com>
+ */
+
+/** \file texmem.h
+ * Public interface to the DRI texture memory management routines.
+ *
+ * \sa texmem.c
+ */
+
+#ifndef DRI_TEXMEM_H
+#define DRI_TEXMEM_H
+
+#include "main/mtypes.h"
+#include "main/formats.h"
+#include "main/mm.h"
+#include "xf86drm.h"
+
+struct dri_tex_heap;
+typedef struct dri_tex_heap driTexHeap;
+
+struct dri_texture_object;
+typedef struct dri_texture_object driTextureObject;
+
+
+/**
+ * Base texture object type. Each driver will extend this type with its own
+ * private data members.
+ */
+
+struct dri_texture_object {
+ struct dri_texture_object * next;
+ struct dri_texture_object * prev;
+
+ driTexHeap * heap; /**< Texture heap currently stored in */
+ struct gl_texture_object * tObj;/**< Pointer to Mesa texture object
+ * If NULL, this texture object is a
+ * "placeholder" object representing
+ * texture memory in use by another context.
+ * A placeholder should have a heap and a memBlock.
+ */
+ struct mem_block *memBlock; /**< Memory block containing texture */
+
+ unsigned reserved; /**< Cannot be swapped out by user contexts. */
+
+ unsigned bound; /**< Bitmask indicating which tex units
+ * this texture object is bound to.
+ * Bit 0 = unit 0, Bit 1 = unit 1, etc
+ */
+
+ unsigned totalSize; /**< Total size of the texture,
+ * including all mipmap levels
+ */
+
+ unsigned dirty_images[6]; /**< Flags for whether or not images
+ * need to be uploaded to local or
+ * AGP texture space. One flag set
+ * for each cube face for cubic
+ * textures. Bit zero corresponds to
+ * the base-level, which may or may
+ * not be the level zero mipmap.
+ */
+
+ unsigned timestamp; /**< Timestamp used to
+ * synchronize with 3d engine
+ * in hardware where textures
+ * are uploaded directly to
+ * the framebuffer.
+ */
+
+ unsigned firstLevel; /**< Image in \c tObj->Image[0] that
+ * corresponds to the base-level of
+ * this texture object.
+ */
+
+ unsigned lastLevel; /**< Last image in \c tObj->Image[0]
+ * used by the
+ * current LOD settings of
+ * this texture object. This
+ * value must be greater than
+ * or equal to \c firstLevel.
+ */
+};
+
+
+typedef void (destroy_texture_object_t)( void * driverContext,
+ driTextureObject * t );
+
+/**
+ * Client-private representation of texture memory state.
+ *
+ * Clients will place one or more of these structs in their driver
+ * context struct to manage one or more global texture heaps.
+ */
+
+struct dri_tex_heap {
+
+ /** Client-supplied heap identifier
+ */
+ unsigned heapId;
+
+ /** Pointer to the client's private context
+ */
+ void *driverContext;
+
+ /** Total size of the heap, in bytes
+ */
+ unsigned size;
+
+ /** \brief \f$log_2\f$ of size of single heap region
+ *
+ * Each context takes memory from the global texture heap in
+ * \f$2^{logGranularity}\f$ byte blocks. The value of
+ * \a logGranularity is based on the amount of memory represented
+ * by the heap and the maximum number of regions in the SAREA. Given
+ * \a b bytes of texture memory an \a n regions in the SAREA,
+ * \a logGranularity will be \f$\lfloor\log_2( b / n )\rfloor\f$.
+ */
+ unsigned logGranularity;
+
+ /** \brief Required alignment of allocations in this heap
+ *
+ * The alignment shift is supplied to \a mmAllocMem when memory is
+ * allocated from this heap. The value of \a alignmentShift will
+ * typically reflect some require of the hardware. This value has
+ * \b no \b relation to \a logGranularity. \a alignmentShift is a
+ * per-context value.
+ *
+ * \sa mmAllocMem
+ */
+ unsigned alignmentShift;
+
+ /** Number of elements in global list (the SAREA).
+ */
+ unsigned nrRegions;
+
+ /** Pointer to SAREA \a driTexRegion array
+ */
+ drmTextureRegionPtr global_regions;
+
+ /** Pointer to the texture state age (generation number) in the SAREA
+ */
+ unsigned * global_age;
+
+ /** Local age (generation number) of texture state
+ */
+ unsigned local_age;
+
+ /** Memory heap used to manage texture memory represented by
+ * this texture heap.
+ */
+ struct mem_block * memory_heap;
+
+ /** List of objects that we currently believe to be in texture
+ * memory.
+ */
+ driTextureObject texture_objects;
+
+ /** Pointer to the list of texture objects that are not in
+ * texture memory.
+ */
+ driTextureObject * swapped_objects;
+
+ /** Size of the driver-speicific texture object.
+ */
+ unsigned texture_object_size;
+
+
+ /**
+ * \brief Function to destroy driver-specific texture object data.
+ *
+ * This function is supplied by the driver so that the texture manager
+ * can release all resources associated with a texture object. This
+ * function should only release driver-specific data. That is,
+ * \a driDestroyTextureObject will release the texture memory
+ * associated with the texture object, it will release the memory
+ * for the texture object itself, and it will unlink the texture
+ * object from the texture object lists.
+ *
+ * \param driverContext Pointer to the driver supplied context
+ * \param t Texture object that is to be destroyed
+ * \sa driDestroyTextureObject
+ */
+
+ destroy_texture_object_t * destroy_texture_object;
+
+
+ /**
+ */
+ unsigned * texture_swaps;
+
+ /**
+ * Timestamp used to synchronize with 3d engine in hardware
+ * where textures are uploaded directly to the
+ * framebuffer.
+ */
+ unsigned timestamp;
+
+ /** \brief Kick/upload weight
+ *
+ * When not enough free space is available this weight
+ * influences the choice of the heap from which textures are
+ * kicked. By default the weight is equal to the heap size.
+ */
+ double weight;
+
+ /** \brief Kick/upload duty
+ *
+ * The heap with the highest duty will be chosen for kicking
+ * textures if not enough free space is available. The duty is
+ * reduced by the amount of data kicked. Rebalancing of
+ * negative duties takes the weights into account.
+ */
+ int duty;
+};
+
+
+
+
+/**
+ * Called by the client on lock contention to determine whether textures have
+ * been stolen. If another client has modified a region in which we have
+ * textures, then we need to figure out which of our textures have been
+ * removed and update our global LRU.
+ *
+ * \param heap Texture heap to be updated
+ * \hideinitializer
+ */
+
+#define DRI_AGE_TEXTURES( heap ) \
+ do { \
+ if ( ((heap) != NULL) \
+ && ((heap)->local_age != (heap)->global_age[0]) ) \
+ driAgeTextures( heap ); \
+ } while( 0 )
+
+
+
+
+/* This should be called whenever there has been contention on the hardware
+ * lock. driAgeTextures should not be called directly. Instead, clients
+ * should use DRI_AGE_TEXTURES, above.
+ */
+
+void driAgeTextures( driTexHeap * heap );
+
+void driUpdateTextureLRU( driTextureObject * t );
+void driSwapOutTextureObject( driTextureObject * t );
+void driDestroyTextureObject( driTextureObject * t );
+int driAllocateTexture( driTexHeap * const * heap_array, unsigned nr_heaps,
+ driTextureObject * t );
+
+GLboolean driIsTextureResident( struct gl_context * ctx,
+ struct gl_texture_object * texObj );
+
+driTexHeap * driCreateTextureHeap( unsigned heap_id, void * context,
+ unsigned size, unsigned alignmentShift, unsigned nr_regions,
+ drmTextureRegionPtr global_regions, unsigned * global_age,
+ driTextureObject * swapped_objects, unsigned texture_object_size,
+ destroy_texture_object_t * destroy_tex_obj );
+void driDestroyTextureHeap( driTexHeap * heap );
+
+void
+driCalculateMaxTextureLevels( driTexHeap * const * heaps,
+ unsigned nr_heaps,
+ struct gl_constants * limits,
+ unsigned max_bytes_per_texel,
+ unsigned max_2D_size,
+ unsigned max_3D_size,
+ unsigned max_cube_size,
+ unsigned max_rect_size,
+ unsigned mipmaps_at_once,
+ int all_textures_one_heap,
+ int allow_larger_textures );
+
+void
+driSetTextureSwapCounterLocation( driTexHeap * heap, unsigned * counter );
+
+#define DRI_TEXMGR_DO_TEXTURE_1D 0x0001
+#define DRI_TEXMGR_DO_TEXTURE_2D 0x0002
+#define DRI_TEXMGR_DO_TEXTURE_3D 0x0004
+#define DRI_TEXMGR_DO_TEXTURE_CUBE 0x0008
+#define DRI_TEXMGR_DO_TEXTURE_RECT 0x0010
+
+void driInitTextureObjects( struct gl_context *ctx, driTextureObject * swapped,
+ GLuint targets );
+
+GLboolean driValidateTextureHeaps( driTexHeap * const * texture_heaps,
+ unsigned nr_heaps, const driTextureObject * swapped );
+
+extern void driCalculateTextureFirstLastLevel( driTextureObject * t );
+
+
+extern gl_format _dri_texformat_rgba8888;
+extern gl_format _dri_texformat_argb8888;
+extern gl_format _dri_texformat_rgb565;
+extern gl_format _dri_texformat_argb4444;
+extern gl_format _dri_texformat_argb1555;
+extern gl_format _dri_texformat_al88;
+extern gl_format _dri_texformat_a8;
+extern gl_format _dri_texformat_ci8;
+extern gl_format _dri_texformat_i8;
+extern gl_format _dri_texformat_l8;
+
+extern void driInitTextureFormats( void );
+
+#endif /* DRI_TEXMEM_H */
diff --git a/mesalib/src/mesa/drivers/dri/common/utils.c b/mesalib/src/mesa/drivers/dri/common/utils.c
index 0dd879abc..a2b0b4e94 100644
--- a/mesalib/src/mesa/drivers/dri/common/utils.c
+++ b/mesalib/src/mesa/drivers/dri/common/utils.c
@@ -1,798 +1,821 @@
-/*
- * (C) Copyright IBM Corporation 2002, 2004
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * on the rights to use, copy, modify, merge, publish, distribute, sub
- * license, and/or sell copies of the Software, and to permit persons to whom
- * the Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file utils.c
- * Utility functions for DRI drivers.
- *
- * \author Ian Romanick <idr@us.ibm.com>
- */
-
-#include <string.h>
-#include <stdlib.h>
-#include "main/mtypes.h"
-#include "main/cpuinfo.h"
-#include "main/extensions.h"
-#include "utils.h"
-
-
-/**
- * Print message to \c stderr if the \c LIBGL_DEBUG environment variable
- * is set.
- *
- * Is called from the drivers.
- *
- * \param f \c printf like format string.
- */
-void
-__driUtilMessage(const char *f, ...)
-{
- va_list args;
-
- if (getenv("LIBGL_DEBUG")) {
- fprintf(stderr, "libGL: ");
- va_start(args, f);
- vfprintf(stderr, f, args);
- va_end(args);
- fprintf(stderr, "\n");
- }
-}
-
-
-unsigned
-driParseDebugString( const char * debug,
- const struct dri_debug_control * control )
-{
- unsigned flag;
-
-
- flag = 0;
- if ( debug != NULL ) {
- while( control->string != NULL ) {
- if ( !strcmp( debug, "all" ) ||
- strstr( debug, control->string ) != NULL ) {
- flag |= control->flag;
- }
-
- control++;
- }
- }
-
- return flag;
-}
-
-
-
-/**
- * Create the \c GL_RENDERER string for DRI drivers.
- *
- * Almost all DRI drivers use a \c GL_RENDERER string of the form:
- *
- * "Mesa DRI <chip> <driver date> <AGP speed) <CPU information>"
- *
- * Using the supplied chip name, driver data, and AGP speed, this function
- * creates the string.
- *
- * \param buffer Buffer to hold the \c GL_RENDERER string.
- * \param hardware_name Name of the hardware.
- * \param driver_date Driver date.
- * \param agp_mode AGP mode (speed).
- *
- * \returns
- * The length of the string stored in \c buffer. This does \b not include
- * the terminating \c NUL character.
- */
-unsigned
-driGetRendererString( char * buffer, const char * hardware_name,
- const char * driver_date, GLuint agp_mode )
-{
- unsigned offset;
- char *cpu;
-
- offset = sprintf( buffer, "Mesa DRI %s %s", hardware_name, driver_date );
-
- /* Append any AGP-specific information.
- */
- switch ( agp_mode ) {
- case 1:
- case 2:
- case 4:
- case 8:
- offset += sprintf( & buffer[ offset ], " AGP %ux", agp_mode );
- break;
-
- default:
- break;
- }
-
- /* Append any CPU-specific information.
- */
- cpu = _mesa_get_cpu_string();
- if (cpu) {
- offset += sprintf(buffer + offset, " %s", cpu);
- free(cpu);
- }
-
- return offset;
-}
-
-
-
-
-#define need_GL_ARB_draw_buffers
-#define need_GL_ARB_multisample
-#define need_GL_ARB_texture_compression
-#define need_GL_ARB_transpose_matrix
-#define need_GL_ARB_vertex_buffer_object
-#define need_GL_ARB_window_pos
-#define need_GL_EXT_compiled_vertex_array
-#define need_GL_EXT_multi_draw_arrays
-#define need_GL_EXT_polygon_offset
-#define need_GL_EXT_texture_object
-#define need_GL_EXT_vertex_array
-#define need_GL_IBM_multimode_draw_arrays
-#define need_GL_MESA_window_pos
-
-/* These are needed in *all* drivers because Mesa internally implements
- * certain functionality in terms of functions provided by these extensions.
- * For example, glBlendFunc is implemented by calling glBlendFuncSeparateEXT.
- */
-#define need_GL_EXT_blend_func_separate
-#define need_GL_NV_vertex_program
-
-#include "main/remap_helper.h"
-
-static const struct dri_extension all_mesa_extensions[] = {
- { "GL_ARB_draw_buffers", GL_ARB_draw_buffers_functions },
- { "GL_ARB_multisample", GL_ARB_multisample_functions },
- { "GL_ARB_texture_compression", GL_ARB_texture_compression_functions },
- { "GL_ARB_transpose_matrix", GL_ARB_transpose_matrix_functions },
- { "GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions},
- { "GL_ARB_window_pos", GL_ARB_window_pos_functions },
- { "GL_EXT_blend_func_separate", GL_EXT_blend_func_separate_functions },
- { "GL_EXT_compiled_vertex_array", GL_EXT_compiled_vertex_array_functions },
- { "GL_EXT_multi_draw_arrays", GL_EXT_multi_draw_arrays_functions },
- { "GL_EXT_polygon_offset", GL_EXT_polygon_offset_functions },
- { "GL_EXT_texture_object", GL_EXT_texture_object_functions },
- { "GL_EXT_vertex_array", GL_EXT_vertex_array_functions },
- { "GL_IBM_multimode_draw_arrays", GL_IBM_multimode_draw_arrays_functions },
- { "GL_MESA_window_pos", GL_MESA_window_pos_functions },
- { "GL_NV_vertex_program", GL_NV_vertex_program_functions },
- { NULL, NULL }
-};
-
-
-/**
- * Enable and map extensions supported by the driver.
- *
- * When ctx is NULL, extensions are not enabled, but their functions
- * are still mapped. When extensions_to_enable is NULL, all static
- * functions known to mesa core are mapped.
- *
- * \bug
- * ARB_imaging isn't handled properly. In Mesa, enabling ARB_imaging also
- * enables all the sub-extensions that are folded into it. This means that
- * we need to add entry-points (via \c driInitSingleExtension) for those
- * new functions here.
- */
-void driInitExtensions( GLcontext * ctx,
- const struct dri_extension * extensions_to_enable,
- GLboolean enable_imaging )
-{
- static int first_time = 1;
- unsigned i;
-
- if ( first_time ) {
- first_time = 0;
- driInitExtensions( NULL, all_mesa_extensions, GL_FALSE );
- }
-
- if ( (ctx != NULL) && enable_imaging ) {
- _mesa_enable_imaging_extensions( ctx );
- }
-
- /* The caller is too lazy to list any extension */
- if ( extensions_to_enable == NULL ) {
- /* Map the static functions. Together with those mapped by remap
- * table, this should cover everything mesa core knows.
- */
- _mesa_map_static_functions();
- return;
- }
-
- for ( i = 0 ; extensions_to_enable[i].name != NULL ; i++ ) {
- driInitSingleExtension( ctx, & extensions_to_enable[i] );
- }
-}
-
-
-
-
-/**
- * Enable and map functions for a single extension
- *
- * \param ctx Context where extension is to be enabled.
- * \param ext Extension that is to be enabled.
- *
- * \sa driInitExtensions, _mesa_enable_extension, _mesa_map_function_array
- */
-void driInitSingleExtension( GLcontext * ctx,
- const struct dri_extension * ext )
-{
- if ( ext->functions != NULL ) {
- _mesa_map_function_array(ext->functions);
- }
-
- if ( ctx != NULL ) {
- _mesa_enable_extension( ctx, ext->name );
- }
-}
-
-
-/**
- * Utility function used by drivers to test the verions of other components.
- *
- * \param driver_name Name of the driver. Used in error messages.
- * \param driActual Actual DRI version supplied __driCreateNewScreen.
- * \param driExpected Minimum DRI version required by the driver.
- * \param ddxActual Actual DDX version supplied __driCreateNewScreen.
- * \param ddxExpected Minimum DDX minor and range of DDX major version required by the driver.
- * \param drmActual Actual DRM version supplied __driCreateNewScreen.
- * \param drmExpected Minimum DRM version required by the driver.
- *
- * \returns \c GL_TRUE if all version requirements are met. Otherwise,
- * \c GL_FALSE is returned.
- *
- * \sa __driCreateNewScreen, driCheckDriDdxDrmVersions2
- *
- * \todo
- * Now that the old \c driCheckDriDdxDrmVersions function is gone, this
- * function and \c driCheckDriDdxDrmVersions2 should be renamed.
- */
-GLboolean
-driCheckDriDdxDrmVersions3(const char * driver_name,
- const __DRIversion * driActual,
- const __DRIversion * driExpected,
- const __DRIversion * ddxActual,
- const __DRIutilversion2 * ddxExpected,
- const __DRIversion * drmActual,
- const __DRIversion * drmExpected)
-{
- static const char format[] = "%s DRI driver expected %s version %d.%d.x "
- "but got version %d.%d.%d\n";
- static const char format2[] = "%s DRI driver expected %s version %d-%d.%d.x "
- "but got version %d.%d.%d\n";
-
-
- /* Check the DRI version */
- if ( (driActual->major != driExpected->major)
- || (driActual->minor < driExpected->minor) ) {
- fprintf(stderr, format, driver_name, "DRI",
- driExpected->major, driExpected->minor,
- driActual->major, driActual->minor, driActual->patch);
- return GL_FALSE;
- }
-
- /* Check that the DDX driver version is compatible */
- if ( (ddxActual->major < ddxExpected->major_min)
- || (ddxActual->major > ddxExpected->major_max)
- || (ddxActual->minor < ddxExpected->minor) ) {
- fprintf(stderr, format2, driver_name, "DDX",
- ddxExpected->major_min, ddxExpected->major_max, ddxExpected->minor,
- ddxActual->major, ddxActual->minor, ddxActual->patch);
- return GL_FALSE;
- }
-
- /* Check that the DRM driver version is compatible */
- if ( (drmActual->major != drmExpected->major)
- || (drmActual->minor < drmExpected->minor) ) {
- fprintf(stderr, format, driver_name, "DRM",
- drmExpected->major, drmExpected->minor,
- drmActual->major, drmActual->minor, drmActual->patch);
- return GL_FALSE;
- }
-
- return GL_TRUE;
-}
-
-GLboolean
-driCheckDriDdxDrmVersions2(const char * driver_name,
- const __DRIversion * driActual,
- const __DRIversion * driExpected,
- const __DRIversion * ddxActual,
- const __DRIversion * ddxExpected,
- const __DRIversion * drmActual,
- const __DRIversion * drmExpected)
-{
- __DRIutilversion2 ddx_expected;
- ddx_expected.major_min = ddxExpected->major;
- ddx_expected.major_max = ddxExpected->major;
- ddx_expected.minor = ddxExpected->minor;
- ddx_expected.patch = ddxExpected->patch;
- return driCheckDriDdxDrmVersions3(driver_name, driActual,
- driExpected, ddxActual, & ddx_expected,
- drmActual, drmExpected);
-}
-
-GLboolean driClipRectToFramebuffer( const GLframebuffer *buffer,
- GLint *x, GLint *y,
- GLsizei *width, GLsizei *height )
-{
- /* left clipping */
- if (*x < buffer->_Xmin) {
- *width -= (buffer->_Xmin - *x);
- *x = buffer->_Xmin;
- }
-
- /* right clipping */
- if (*x + *width > buffer->_Xmax)
- *width -= (*x + *width - buffer->_Xmax - 1);
-
- if (*width <= 0)
- return GL_FALSE;
-
- /* bottom clipping */
- if (*y < buffer->_Ymin) {
- *height -= (buffer->_Ymin - *y);
- *y = buffer->_Ymin;
- }
-
- /* top clipping */
- if (*y + *height > buffer->_Ymax)
- *height -= (*y + *height - buffer->_Ymax - 1);
-
- if (*height <= 0)
- return GL_FALSE;
-
- return GL_TRUE;
-}
-
-/**
- * Creates a set of \c __GLcontextModes that a driver will expose.
- *
- * A set of \c __GLcontextModes will be created based on the supplied
- * parameters. The number of modes processed will be 2 *
- * \c num_depth_stencil_bits * \c num_db_modes.
- *
- * For the most part, data is just copied from \c depth_bits, \c stencil_bits,
- * \c db_modes, and \c visType into each \c __GLcontextModes element.
- * However, the meanings of \c fb_format and \c fb_type require further
- * explanation. The \c fb_format specifies which color components are in
- * each pixel and what the default order is. For example, \c GL_RGB specifies
- * that red, green, blue are available and red is in the "most significant"
- * position and blue is in the "least significant". The \c fb_type specifies
- * the bit sizes of each component and the actual ordering. For example, if
- * \c GL_UNSIGNED_SHORT_5_6_5_REV is specified with \c GL_RGB, bits [15:11]
- * are the blue value, bits [10:5] are the green value, and bits [4:0] are
- * the red value.
- *
- * One sublte issue is the combination of \c GL_RGB or \c GL_BGR and either
- * of the \c GL_UNSIGNED_INT_8_8_8_8 modes. The resulting mask values in the
- * \c __GLcontextModes structure is \b identical to the \c GL_RGBA or
- * \c GL_BGRA case, except the \c alphaMask is zero. This means that, as
- * far as this routine is concerned, \c GL_RGB with \c GL_UNSIGNED_INT_8_8_8_8
- * still uses 32-bits.
- *
- * If in doubt, look at the tables used in the function.
- *
- * \param ptr_to_modes Pointer to a pointer to a linked list of
- * \c __GLcontextModes. Upon completion, a pointer to
- * the next element to be process will be stored here.
- * If the function fails and returns \c GL_FALSE, this
- * value will be unmodified, but some elements in the
- * linked list may be modified.
- * \param fb_format Format of the framebuffer. Currently only \c GL_RGB,
- * \c GL_RGBA, \c GL_BGR, and \c GL_BGRA are supported.
- * \param fb_type Type of the pixels in the framebuffer. Currently only
- * \c GL_UNSIGNED_SHORT_5_6_5,
- * \c GL_UNSIGNED_SHORT_5_6_5_REV,
- * \c GL_UNSIGNED_INT_8_8_8_8, and
- * \c GL_UNSIGNED_INT_8_8_8_8_REV are supported.
- * \param depth_bits Array of depth buffer sizes to be exposed.
- * \param stencil_bits Array of stencil buffer sizes to be exposed.
- * \param num_depth_stencil_bits Number of entries in both \c depth_bits and
- * \c stencil_bits.
- * \param db_modes Array of buffer swap modes. If an element has a
- * value of \c GLX_NONE, then it represents a
- * single-buffered mode. Other valid values are
- * \c GLX_SWAP_EXCHANGE_OML, \c GLX_SWAP_COPY_OML, and
- * \c GLX_SWAP_UNDEFINED_OML. See the
- * GLX_OML_swap_method extension spec for more details.
- * \param num_db_modes Number of entries in \c db_modes.
- * \param msaa_samples Array of msaa sample count. 0 represents a visual
- * without a multisample buffer.
- * \param num_msaa_modes Number of entries in \c msaa_samples.
- * \param visType GLX visual type. Usually either \c GLX_TRUE_COLOR or
- * \c GLX_DIRECT_COLOR.
- *
- * \returns
- * \c GL_TRUE on success or \c GL_FALSE on failure. Currently the only
- * cause of failure is a bad parameter (i.e., unsupported \c fb_format or
- * \c fb_type).
- *
- * \todo
- * There is currently no way to support packed RGB modes (i.e., modes with
- * exactly 3 bytes per pixel) or floating-point modes. This could probably
- * be done by creating some new, private enums with clever names likes
- * \c GL_UNSIGNED_3BYTE_8_8_8, \c GL_4FLOAT_32_32_32_32,
- * \c GL_4HALF_16_16_16_16, etc. We can cross that bridge when we come to it.
- */
-__DRIconfig **
-driCreateConfigs(GLenum fb_format, GLenum fb_type,
- const uint8_t * depth_bits, const uint8_t * stencil_bits,
- unsigned num_depth_stencil_bits,
- const GLenum * db_modes, unsigned num_db_modes,
- const uint8_t * msaa_samples, unsigned num_msaa_modes,
- GLboolean enable_accum)
-{
- static const uint8_t bits_table[4][4] = {
- /* R G B A */
- { 3, 3, 2, 0 }, /* Any GL_UNSIGNED_BYTE_3_3_2 */
- { 5, 6, 5, 0 }, /* Any GL_UNSIGNED_SHORT_5_6_5 */
- { 8, 8, 8, 0 }, /* Any RGB with any GL_UNSIGNED_INT_8_8_8_8 */
- { 8, 8, 8, 8 } /* Any RGBA with any GL_UNSIGNED_INT_8_8_8_8 */
- };
-
- static const uint32_t masks_table_rgb[6][4] = {
- { 0x000000E0, 0x0000001C, 0x00000003, 0x00000000 }, /* 3_3_2 */
- { 0x00000007, 0x00000038, 0x000000C0, 0x00000000 }, /* 2_3_3_REV */
- { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5 */
- { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5_REV */
- { 0xFF000000, 0x00FF0000, 0x0000FF00, 0x00000000 }, /* 8_8_8_8 */
- { 0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000 } /* 8_8_8_8_REV */
- };
-
- static const uint32_t masks_table_rgba[6][4] = {
- { 0x000000E0, 0x0000001C, 0x00000003, 0x00000000 }, /* 3_3_2 */
- { 0x00000007, 0x00000038, 0x000000C0, 0x00000000 }, /* 2_3_3_REV */
- { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5 */
- { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5_REV */
- { 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF }, /* 8_8_8_8 */
- { 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 }, /* 8_8_8_8_REV */
- };
-
- static const uint32_t masks_table_bgr[6][4] = {
- { 0x00000007, 0x00000038, 0x000000C0, 0x00000000 }, /* 3_3_2 */
- { 0x000000E0, 0x0000001C, 0x00000003, 0x00000000 }, /* 2_3_3_REV */
- { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5 */
- { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5_REV */
- { 0x0000FF00, 0x00FF0000, 0xFF000000, 0x00000000 }, /* 8_8_8_8 */
- { 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000 }, /* 8_8_8_8_REV */
- };
-
- static const uint32_t masks_table_bgra[6][4] = {
- { 0x00000007, 0x00000038, 0x000000C0, 0x00000000 }, /* 3_3_2 */
- { 0x000000E0, 0x0000001C, 0x00000003, 0x00000000 }, /* 2_3_3_REV */
- { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5 */
- { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5_REV */
- { 0x0000FF00, 0x00FF0000, 0xFF000000, 0x000000FF }, /* 8_8_8_8 */
- { 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000 }, /* 8_8_8_8_REV */
- };
-
- static const uint8_t bytes_per_pixel[6] = {
- 1, /* 3_3_2 */
- 1, /* 2_3_3_REV */
- 2, /* 5_6_5 */
- 2, /* 5_6_5_REV */
- 4, /* 8_8_8_8 */
- 4 /* 8_8_8_8_REV */
- };
-
- const uint8_t * bits;
- const uint32_t * masks;
- int index;
- __DRIconfig **configs, **c;
- __GLcontextModes *modes;
- unsigned i, j, k, h;
- unsigned num_modes;
- unsigned num_accum_bits = (enable_accum) ? 2 : 1;
-
- switch ( fb_type ) {
- case GL_UNSIGNED_BYTE_3_3_2:
- index = 0;
- break;
- case GL_UNSIGNED_BYTE_2_3_3_REV:
- index = 1;
- break;
- case GL_UNSIGNED_SHORT_5_6_5:
- index = 2;
- break;
- case GL_UNSIGNED_SHORT_5_6_5_REV:
- index = 3;
- break;
- case GL_UNSIGNED_INT_8_8_8_8:
- index = 4;
- break;
- case GL_UNSIGNED_INT_8_8_8_8_REV:
- index = 5;
- break;
- default:
- fprintf( stderr, "[%s:%u] Unknown framebuffer type 0x%04x.\n",
- __FUNCTION__, __LINE__, fb_type );
- return NULL;
- }
-
-
- /* Valid types are GL_UNSIGNED_SHORT_5_6_5 and GL_UNSIGNED_INT_8_8_8_8 and
- * the _REV versions.
- *
- * Valid formats are GL_RGBA, GL_RGB, and GL_BGRA.
- */
-
- switch ( fb_format ) {
- case GL_RGB:
- masks = masks_table_rgb[ index ];
- break;
-
- case GL_RGBA:
- masks = masks_table_rgba[ index ];
- break;
-
- case GL_BGR:
- masks = masks_table_bgr[ index ];
- break;
-
- case GL_BGRA:
- masks = masks_table_bgra[ index ];
- break;
-
- default:
- fprintf( stderr, "[%s:%u] Unknown framebuffer format 0x%04x.\n",
- __FUNCTION__, __LINE__, fb_format );
- return NULL;
- }
-
- switch ( bytes_per_pixel[ index ] ) {
- case 1:
- bits = bits_table[0];
- break;
- case 2:
- bits = bits_table[1];
- break;
- default:
- bits = ((fb_format == GL_RGB) || (fb_format == GL_BGR))
- ? bits_table[2]
- : bits_table[3];
- break;
- }
-
- num_modes = num_depth_stencil_bits * num_db_modes * num_accum_bits * num_msaa_modes;
- configs = calloc(1, (num_modes + 1) * sizeof *configs);
- if (configs == NULL)
- return NULL;
-
- c = configs;
- for ( k = 0 ; k < num_depth_stencil_bits ; k++ ) {
- for ( i = 0 ; i < num_db_modes ; i++ ) {
- for ( h = 0 ; h < num_msaa_modes; h++ ) {
- for ( j = 0 ; j < num_accum_bits ; j++ ) {
- *c = malloc (sizeof **c);
- modes = &(*c)->modes;
- c++;
-
- memset(modes, 0, sizeof *modes);
- modes->redBits = bits[0];
- modes->greenBits = bits[1];
- modes->blueBits = bits[2];
- modes->alphaBits = bits[3];
- modes->redMask = masks[0];
- modes->greenMask = masks[1];
- modes->blueMask = masks[2];
- modes->alphaMask = masks[3];
- modes->rgbBits = modes->redBits + modes->greenBits
- + modes->blueBits + modes->alphaBits;
-
- modes->accumRedBits = 16 * j;
- modes->accumGreenBits = 16 * j;
- modes->accumBlueBits = 16 * j;
- modes->accumAlphaBits = (masks[3] != 0) ? 16 * j : 0;
- modes->visualRating = (j == 0) ? GLX_NONE : GLX_SLOW_CONFIG;
-
- modes->stencilBits = stencil_bits[k];
- modes->depthBits = depth_bits[k];
-
- modes->transparentPixel = GLX_NONE;
- modes->transparentRed = GLX_DONT_CARE;
- modes->transparentGreen = GLX_DONT_CARE;
- modes->transparentBlue = GLX_DONT_CARE;
- modes->transparentAlpha = GLX_DONT_CARE;
- modes->transparentIndex = GLX_DONT_CARE;
- modes->visualType = GLX_DONT_CARE;
- modes->renderType = GLX_RGBA_BIT;
- modes->drawableType = GLX_WINDOW_BIT;
- modes->rgbMode = GL_TRUE;
-
- if ( db_modes[i] == GLX_NONE ) {
- modes->doubleBufferMode = GL_FALSE;
- }
- else {
- modes->doubleBufferMode = GL_TRUE;
- modes->swapMethod = db_modes[i];
- }
-
- modes->samples = msaa_samples[h];
- modes->sampleBuffers = modes->samples ? 1 : 0;
-
-
- modes->haveAccumBuffer = ((modes->accumRedBits +
- modes->accumGreenBits +
- modes->accumBlueBits +
- modes->accumAlphaBits) > 0);
- modes->haveDepthBuffer = (modes->depthBits > 0);
- modes->haveStencilBuffer = (modes->stencilBits > 0);
-
- modes->bindToTextureRgb = GL_TRUE;
- modes->bindToTextureRgba = GL_TRUE;
- modes->bindToMipmapTexture = GL_FALSE;
- modes->bindToTextureTargets =
- __DRI_ATTRIB_TEXTURE_1D_BIT |
- __DRI_ATTRIB_TEXTURE_2D_BIT |
- __DRI_ATTRIB_TEXTURE_RECTANGLE_BIT;
- }
- }
- }
- }
- *c = NULL;
-
- return configs;
-}
-
-__DRIconfig **driConcatConfigs(__DRIconfig **a,
- __DRIconfig **b)
-{
- __DRIconfig **all;
- int i, j, index;
-
- i = 0;
- while (a[i] != NULL)
- i++;
- j = 0;
- while (b[j] != NULL)
- j++;
-
- all = malloc((i + j + 1) * sizeof *all);
- index = 0;
- for (i = 0; a[i] != NULL; i++)
- all[index++] = a[i];
- for (j = 0; b[j] != NULL; j++)
- all[index++] = b[j];
- all[index++] = NULL;
-
- free(a);
- free(b);
-
- return all;
-}
-
-#define __ATTRIB(attrib, field) \
- { attrib, offsetof(__GLcontextModes, field) }
-
-static const struct { unsigned int attrib, offset; } attribMap[] = {
- __ATTRIB(__DRI_ATTRIB_BUFFER_SIZE, rgbBits),
- __ATTRIB(__DRI_ATTRIB_LEVEL, level),
- __ATTRIB(__DRI_ATTRIB_RED_SIZE, redBits),
- __ATTRIB(__DRI_ATTRIB_GREEN_SIZE, greenBits),
- __ATTRIB(__DRI_ATTRIB_BLUE_SIZE, blueBits),
- __ATTRIB(__DRI_ATTRIB_ALPHA_SIZE, alphaBits),
- __ATTRIB(__DRI_ATTRIB_DEPTH_SIZE, depthBits),
- __ATTRIB(__DRI_ATTRIB_STENCIL_SIZE, stencilBits),
- __ATTRIB(__DRI_ATTRIB_ACCUM_RED_SIZE, accumRedBits),
- __ATTRIB(__DRI_ATTRIB_ACCUM_GREEN_SIZE, accumGreenBits),
- __ATTRIB(__DRI_ATTRIB_ACCUM_BLUE_SIZE, accumBlueBits),
- __ATTRIB(__DRI_ATTRIB_ACCUM_ALPHA_SIZE, accumAlphaBits),
- __ATTRIB(__DRI_ATTRIB_SAMPLE_BUFFERS, sampleBuffers),
- __ATTRIB(__DRI_ATTRIB_SAMPLES, samples),
- __ATTRIB(__DRI_ATTRIB_DOUBLE_BUFFER, doubleBufferMode),
- __ATTRIB(__DRI_ATTRIB_STEREO, stereoMode),
- __ATTRIB(__DRI_ATTRIB_AUX_BUFFERS, numAuxBuffers),
- __ATTRIB(__DRI_ATTRIB_TRANSPARENT_TYPE, transparentPixel),
- __ATTRIB(__DRI_ATTRIB_TRANSPARENT_INDEX_VALUE, transparentPixel),
- __ATTRIB(__DRI_ATTRIB_TRANSPARENT_RED_VALUE, transparentRed),
- __ATTRIB(__DRI_ATTRIB_TRANSPARENT_GREEN_VALUE, transparentGreen),
- __ATTRIB(__DRI_ATTRIB_TRANSPARENT_BLUE_VALUE, transparentBlue),
- __ATTRIB(__DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE, transparentAlpha),
- __ATTRIB(__DRI_ATTRIB_FLOAT_MODE, floatMode),
- __ATTRIB(__DRI_ATTRIB_RED_MASK, redMask),
- __ATTRIB(__DRI_ATTRIB_GREEN_MASK, greenMask),
- __ATTRIB(__DRI_ATTRIB_BLUE_MASK, blueMask),
- __ATTRIB(__DRI_ATTRIB_ALPHA_MASK, alphaMask),
- __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_WIDTH, maxPbufferWidth),
- __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_HEIGHT, maxPbufferHeight),
- __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_PIXELS, maxPbufferPixels),
- __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH, optimalPbufferWidth),
- __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT, optimalPbufferHeight),
- __ATTRIB(__DRI_ATTRIB_SWAP_METHOD, swapMethod),
- __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGB, bindToTextureRgb),
- __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGBA, bindToTextureRgba),
- __ATTRIB(__DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE, bindToMipmapTexture),
- __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS, bindToTextureTargets),
- __ATTRIB(__DRI_ATTRIB_YINVERTED, yInverted),
-
- /* The struct field doesn't matter here, these are handled by the
- * switch in driGetConfigAttribIndex. We need them in the array
- * so the iterator includes them though.*/
- __ATTRIB(__DRI_ATTRIB_RENDER_TYPE, level),
- __ATTRIB(__DRI_ATTRIB_CONFIG_CAVEAT, level),
- __ATTRIB(__DRI_ATTRIB_SWAP_METHOD, level)
-};
-
-#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
-
-static int
-driGetConfigAttribIndex(const __DRIconfig *config,
- unsigned int index, unsigned int *value)
-{
- switch (attribMap[index].attrib) {
- case __DRI_ATTRIB_RENDER_TYPE:
- *value = __DRI_ATTRIB_RGBA_BIT;
- break;
- case __DRI_ATTRIB_CONFIG_CAVEAT:
- if (config->modes.visualRating == GLX_NON_CONFORMANT_CONFIG)
- *value = __DRI_ATTRIB_NON_CONFORMANT_CONFIG;
- else if (config->modes.visualRating == GLX_SLOW_CONFIG)
- *value = __DRI_ATTRIB_SLOW_BIT;
- else
- *value = 0;
- break;
- case __DRI_ATTRIB_SWAP_METHOD:
- break;
-
- case __DRI_ATTRIB_FLOAT_MODE:
- *value = config->modes.floatMode;
- break;
-
- default:
- *value = *(unsigned int *)
- ((char *) &config->modes + attribMap[index].offset);
-
- break;
- }
-
- return GL_TRUE;
-}
-
-int
-driGetConfigAttrib(const __DRIconfig *config,
- unsigned int attrib, unsigned int *value)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(attribMap); i++)
- if (attribMap[i].attrib == attrib)
- return driGetConfigAttribIndex(config, i, value);
-
- return GL_FALSE;
-}
-
-int
-driIndexConfigAttrib(const __DRIconfig *config, int index,
- unsigned int *attrib, unsigned int *value)
-{
- if (index >= 0 && index < ARRAY_SIZE(attribMap)) {
- *attrib = attribMap[index].attrib;
- return driGetConfigAttribIndex(config, index, value);
- }
-
- return GL_FALSE;
-}
+/*
+ * (C) Copyright IBM Corporation 2002, 2004
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file utils.c
+ * Utility functions for DRI drivers.
+ *
+ * \author Ian Romanick <idr@us.ibm.com>
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include "main/mtypes.h"
+#include "main/cpuinfo.h"
+#include "main/extensions.h"
+#include "utils.h"
+
+
+/**
+ * Print message to \c stderr if the \c LIBGL_DEBUG environment variable
+ * is set.
+ *
+ * Is called from the drivers.
+ *
+ * \param f \c printf like format string.
+ */
+void
+__driUtilMessage(const char *f, ...)
+{
+ va_list args;
+
+ if (getenv("LIBGL_DEBUG")) {
+ fprintf(stderr, "libGL: ");
+ va_start(args, f);
+ vfprintf(stderr, f, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+ }
+}
+
+
+unsigned
+driParseDebugString( const char * debug,
+ const struct dri_debug_control * control )
+{
+ unsigned flag;
+
+
+ flag = 0;
+ if ( debug != NULL ) {
+ while( control->string != NULL ) {
+ if ( !strcmp( debug, "all" ) ||
+ strstr( debug, control->string ) != NULL ) {
+ flag |= control->flag;
+ }
+
+ control++;
+ }
+ }
+
+ return flag;
+}
+
+
+
+/**
+ * Create the \c GL_RENDERER string for DRI drivers.
+ *
+ * Almost all DRI drivers use a \c GL_RENDERER string of the form:
+ *
+ * "Mesa DRI <chip> <driver date> <AGP speed) <CPU information>"
+ *
+ * Using the supplied chip name, driver data, and AGP speed, this function
+ * creates the string.
+ *
+ * \param buffer Buffer to hold the \c GL_RENDERER string.
+ * \param hardware_name Name of the hardware.
+ * \param driver_date Driver date.
+ * \param agp_mode AGP mode (speed).
+ *
+ * \returns
+ * The length of the string stored in \c buffer. This does \b not include
+ * the terminating \c NUL character.
+ */
+unsigned
+driGetRendererString( char * buffer, const char * hardware_name,
+ const char * driver_date, GLuint agp_mode )
+{
+ unsigned offset;
+ char *cpu;
+
+ offset = sprintf( buffer, "Mesa DRI %s %s", hardware_name, driver_date );
+
+ /* Append any AGP-specific information.
+ */
+ switch ( agp_mode ) {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ offset += sprintf( & buffer[ offset ], " AGP %ux", agp_mode );
+ break;
+
+ default:
+ break;
+ }
+
+ /* Append any CPU-specific information.
+ */
+ cpu = _mesa_get_cpu_string();
+ if (cpu) {
+ offset += sprintf(buffer + offset, " %s", cpu);
+ free(cpu);
+ }
+
+ return offset;
+}
+
+
+
+
+#define need_GL_ARB_copy_buffer
+#define need_GL_ARB_draw_buffers
+#define need_GL_ARB_multisample
+#define need_GL_ARB_texture_compression
+#define need_GL_ARB_transpose_matrix
+#define need_GL_ARB_vertex_buffer_object
+#define need_GL_ARB_window_pos
+#define need_GL_EXT_compiled_vertex_array
+#define need_GL_EXT_multi_draw_arrays
+#define need_GL_EXT_polygon_offset
+#define need_GL_EXT_texture_object
+#define need_GL_EXT_vertex_array
+#define need_GL_IBM_multimode_draw_arrays
+#define need_GL_MESA_window_pos
+
+/* These are needed in *all* drivers because Mesa internally implements
+ * certain functionality in terms of functions provided by these extensions.
+ * For example, glBlendFunc is implemented by calling glBlendFuncSeparateEXT.
+ */
+#define need_GL_EXT_blend_func_separate
+#define need_GL_NV_vertex_program
+
+#include "main/remap_helper.h"
+
+static const struct dri_extension all_mesa_extensions[] = {
+ { "GL_ARB_copy_buffer", GL_ARB_copy_buffer_functions },
+ { "GL_ARB_draw_buffers", GL_ARB_draw_buffers_functions },
+ { "GL_ARB_multisample", GL_ARB_multisample_functions },
+ { "GL_ARB_texture_compression", GL_ARB_texture_compression_functions },
+ { "GL_ARB_transpose_matrix", GL_ARB_transpose_matrix_functions },
+ { "GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions},
+ { "GL_ARB_window_pos", GL_ARB_window_pos_functions },
+ { "GL_EXT_blend_func_separate", GL_EXT_blend_func_separate_functions },
+ { "GL_EXT_compiled_vertex_array", GL_EXT_compiled_vertex_array_functions },
+ { "GL_EXT_multi_draw_arrays", GL_EXT_multi_draw_arrays_functions },
+ { "GL_EXT_polygon_offset", GL_EXT_polygon_offset_functions },
+ { "GL_EXT_texture_object", GL_EXT_texture_object_functions },
+ { "GL_EXT_vertex_array", GL_EXT_vertex_array_functions },
+ { "GL_IBM_multimode_draw_arrays", GL_IBM_multimode_draw_arrays_functions },
+ { "GL_MESA_window_pos", GL_MESA_window_pos_functions },
+ { "GL_NV_vertex_program", GL_NV_vertex_program_functions },
+ { NULL, NULL }
+};
+
+
+/**
+ * Enable and map extensions supported by the driver.
+ *
+ * When ctx is NULL, extensions are not enabled, but their functions
+ * are still mapped. When extensions_to_enable is NULL, all static
+ * functions known to mesa core are mapped.
+ *
+ * \bug
+ * ARB_imaging isn't handled properly. In Mesa, enabling ARB_imaging also
+ * enables all the sub-extensions that are folded into it. This means that
+ * we need to add entry-points (via \c driInitSingleExtension) for those
+ * new functions here.
+ */
+void driInitExtensions( struct gl_context * ctx,
+ const struct dri_extension * extensions_to_enable,
+ GLboolean enable_imaging )
+{
+ static int first_time = 1;
+ unsigned i;
+
+ if ( first_time ) {
+ first_time = 0;
+ driInitExtensions( NULL, all_mesa_extensions, GL_FALSE );
+ }
+
+ if ( (ctx != NULL) && enable_imaging ) {
+ _mesa_enable_imaging_extensions( ctx );
+ }
+
+ /* The caller is too lazy to list any extension */
+ if ( extensions_to_enable == NULL ) {
+ /* Map the static functions. Together with those mapped by remap
+ * table, this should cover everything mesa core knows.
+ */
+ _mesa_map_static_functions();
+ return;
+ }
+
+ for ( i = 0 ; extensions_to_enable[i].name != NULL ; i++ ) {
+ driInitSingleExtension( ctx, & extensions_to_enable[i] );
+ }
+}
+
+
+
+
+/**
+ * Enable and map functions for a single extension
+ *
+ * \param ctx Context where extension is to be enabled.
+ * \param ext Extension that is to be enabled.
+ *
+ * \sa driInitExtensions, _mesa_enable_extension, _mesa_map_function_array
+ */
+void driInitSingleExtension( struct gl_context * ctx,
+ const struct dri_extension * ext )
+{
+ if ( ext->functions != NULL ) {
+ _mesa_map_function_array(ext->functions);
+ }
+
+ if ( ctx != NULL ) {
+ _mesa_enable_extension( ctx, ext->name );
+ }
+}
+
+
+/**
+ * Utility function used by drivers to test the verions of other components.
+ *
+ * \param driver_name Name of the driver. Used in error messages.
+ * \param driActual Actual DRI version supplied __driCreateNewScreen.
+ * \param driExpected Minimum DRI version required by the driver.
+ * \param ddxActual Actual DDX version supplied __driCreateNewScreen.
+ * \param ddxExpected Minimum DDX minor and range of DDX major version required by the driver.
+ * \param drmActual Actual DRM version supplied __driCreateNewScreen.
+ * \param drmExpected Minimum DRM version required by the driver.
+ *
+ * \returns \c GL_TRUE if all version requirements are met. Otherwise,
+ * \c GL_FALSE is returned.
+ *
+ * \sa __driCreateNewScreen, driCheckDriDdxDrmVersions2
+ *
+ * \todo
+ * Now that the old \c driCheckDriDdxDrmVersions function is gone, this
+ * function and \c driCheckDriDdxDrmVersions2 should be renamed.
+ */
+GLboolean
+driCheckDriDdxDrmVersions3(const char * driver_name,
+ const __DRIversion * driActual,
+ const __DRIversion * driExpected,
+ const __DRIversion * ddxActual,
+ const __DRIutilversion2 * ddxExpected,
+ const __DRIversion * drmActual,
+ const __DRIversion * drmExpected)
+{
+ static const char format[] = "%s DRI driver expected %s version %d.%d.x "
+ "but got version %d.%d.%d\n";
+ static const char format2[] = "%s DRI driver expected %s version %d-%d.%d.x "
+ "but got version %d.%d.%d\n";
+
+
+ /* Check the DRI version */
+ if ( (driActual->major != driExpected->major)
+ || (driActual->minor < driExpected->minor) ) {
+ fprintf(stderr, format, driver_name, "DRI",
+ driExpected->major, driExpected->minor,
+ driActual->major, driActual->minor, driActual->patch);
+ return GL_FALSE;
+ }
+
+ /* Check that the DDX driver version is compatible */
+ if ( (ddxActual->major < ddxExpected->major_min)
+ || (ddxActual->major > ddxExpected->major_max)
+ || (ddxActual->minor < ddxExpected->minor) ) {
+ fprintf(stderr, format2, driver_name, "DDX",
+ ddxExpected->major_min, ddxExpected->major_max, ddxExpected->minor,
+ ddxActual->major, ddxActual->minor, ddxActual->patch);
+ return GL_FALSE;
+ }
+
+ /* Check that the DRM driver version is compatible */
+ if ( (drmActual->major != drmExpected->major)
+ || (drmActual->minor < drmExpected->minor) ) {
+ fprintf(stderr, format, driver_name, "DRM",
+ drmExpected->major, drmExpected->minor,
+ drmActual->major, drmActual->minor, drmActual->patch);
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+GLboolean
+driCheckDriDdxDrmVersions2(const char * driver_name,
+ const __DRIversion * driActual,
+ const __DRIversion * driExpected,
+ const __DRIversion * ddxActual,
+ const __DRIversion * ddxExpected,
+ const __DRIversion * drmActual,
+ const __DRIversion * drmExpected)
+{
+ __DRIutilversion2 ddx_expected;
+ ddx_expected.major_min = ddxExpected->major;
+ ddx_expected.major_max = ddxExpected->major;
+ ddx_expected.minor = ddxExpected->minor;
+ ddx_expected.patch = ddxExpected->patch;
+ return driCheckDriDdxDrmVersions3(driver_name, driActual,
+ driExpected, ddxActual, & ddx_expected,
+ drmActual, drmExpected);
+}
+
+GLboolean driClipRectToFramebuffer( const struct gl_framebuffer *buffer,
+ GLint *x, GLint *y,
+ GLsizei *width, GLsizei *height )
+{
+ /* left clipping */
+ if (*x < buffer->_Xmin) {
+ *width -= (buffer->_Xmin - *x);
+ *x = buffer->_Xmin;
+ }
+
+ /* right clipping */
+ if (*x + *width > buffer->_Xmax)
+ *width -= (*x + *width - buffer->_Xmax - 1);
+
+ if (*width <= 0)
+ return GL_FALSE;
+
+ /* bottom clipping */
+ if (*y < buffer->_Ymin) {
+ *height -= (buffer->_Ymin - *y);
+ *y = buffer->_Ymin;
+ }
+
+ /* top clipping */
+ if (*y + *height > buffer->_Ymax)
+ *height -= (*y + *height - buffer->_Ymax - 1);
+
+ if (*height <= 0)
+ return GL_FALSE;
+
+ return GL_TRUE;
+}
+
+/**
+ * Creates a set of \c struct gl_config that a driver will expose.
+ *
+ * A set of \c struct gl_config will be created based on the supplied
+ * parameters. The number of modes processed will be 2 *
+ * \c num_depth_stencil_bits * \c num_db_modes.
+ *
+ * For the most part, data is just copied from \c depth_bits, \c stencil_bits,
+ * \c db_modes, and \c visType into each \c struct gl_config element.
+ * However, the meanings of \c fb_format and \c fb_type require further
+ * explanation. The \c fb_format specifies which color components are in
+ * each pixel and what the default order is. For example, \c GL_RGB specifies
+ * that red, green, blue are available and red is in the "most significant"
+ * position and blue is in the "least significant". The \c fb_type specifies
+ * the bit sizes of each component and the actual ordering. For example, if
+ * \c GL_UNSIGNED_SHORT_5_6_5_REV is specified with \c GL_RGB, bits [15:11]
+ * are the blue value, bits [10:5] are the green value, and bits [4:0] are
+ * the red value.
+ *
+ * One sublte issue is the combination of \c GL_RGB or \c GL_BGR and either
+ * of the \c GL_UNSIGNED_INT_8_8_8_8 modes. The resulting mask values in the
+ * \c struct gl_config structure is \b identical to the \c GL_RGBA or
+ * \c GL_BGRA case, except the \c alphaMask is zero. This means that, as
+ * far as this routine is concerned, \c GL_RGB with \c GL_UNSIGNED_INT_8_8_8_8
+ * still uses 32-bits.
+ *
+ * If in doubt, look at the tables used in the function.
+ *
+ * \param ptr_to_modes Pointer to a pointer to a linked list of
+ * \c struct gl_config. Upon completion, a pointer to
+ * the next element to be process will be stored here.
+ * If the function fails and returns \c GL_FALSE, this
+ * value will be unmodified, but some elements in the
+ * linked list may be modified.
+ * \param fb_format Format of the framebuffer. Currently only \c GL_RGB,
+ * \c GL_RGBA, \c GL_BGR, and \c GL_BGRA are supported.
+ * \param fb_type Type of the pixels in the framebuffer. Currently only
+ * \c GL_UNSIGNED_SHORT_5_6_5,
+ * \c GL_UNSIGNED_SHORT_5_6_5_REV,
+ * \c GL_UNSIGNED_INT_8_8_8_8, and
+ * \c GL_UNSIGNED_INT_8_8_8_8_REV are supported.
+ * \param depth_bits Array of depth buffer sizes to be exposed.
+ * \param stencil_bits Array of stencil buffer sizes to be exposed.
+ * \param num_depth_stencil_bits Number of entries in both \c depth_bits and
+ * \c stencil_bits.
+ * \param db_modes Array of buffer swap modes. If an element has a
+ * value of \c GLX_NONE, then it represents a
+ * single-buffered mode. Other valid values are
+ * \c GLX_SWAP_EXCHANGE_OML, \c GLX_SWAP_COPY_OML, and
+ * \c GLX_SWAP_UNDEFINED_OML. See the
+ * GLX_OML_swap_method extension spec for more details.
+ * \param num_db_modes Number of entries in \c db_modes.
+ * \param msaa_samples Array of msaa sample count. 0 represents a visual
+ * without a multisample buffer.
+ * \param num_msaa_modes Number of entries in \c msaa_samples.
+ * \param visType GLX visual type. Usually either \c GLX_TRUE_COLOR or
+ * \c GLX_DIRECT_COLOR.
+ *
+ * \returns
+ * \c GL_TRUE on success or \c GL_FALSE on failure. Currently the only
+ * cause of failure is a bad parameter (i.e., unsupported \c fb_format or
+ * \c fb_type).
+ *
+ * \todo
+ * There is currently no way to support packed RGB modes (i.e., modes with
+ * exactly 3 bytes per pixel) or floating-point modes. This could probably
+ * be done by creating some new, private enums with clever names likes
+ * \c GL_UNSIGNED_3BYTE_8_8_8, \c GL_4FLOAT_32_32_32_32,
+ * \c GL_4HALF_16_16_16_16, etc. We can cross that bridge when we come to it.
+ */
+__DRIconfig **
+driCreateConfigs(GLenum fb_format, GLenum fb_type,
+ const uint8_t * depth_bits, const uint8_t * stencil_bits,
+ unsigned num_depth_stencil_bits,
+ const GLenum * db_modes, unsigned num_db_modes,
+ const uint8_t * msaa_samples, unsigned num_msaa_modes,
+ GLboolean enable_accum)
+{
+ static const uint8_t bits_table[4][4] = {
+ /* R G B A */
+ { 3, 3, 2, 0 }, /* Any GL_UNSIGNED_BYTE_3_3_2 */
+ { 5, 6, 5, 0 }, /* Any GL_UNSIGNED_SHORT_5_6_5 */
+ { 8, 8, 8, 0 }, /* Any RGB with any GL_UNSIGNED_INT_8_8_8_8 */
+ { 8, 8, 8, 8 } /* Any RGBA with any GL_UNSIGNED_INT_8_8_8_8 */
+ };
+
+ static const uint32_t masks_table_rgb[6][4] = {
+ { 0x000000E0, 0x0000001C, 0x00000003, 0x00000000 }, /* 3_3_2 */
+ { 0x00000007, 0x00000038, 0x000000C0, 0x00000000 }, /* 2_3_3_REV */
+ { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5 */
+ { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5_REV */
+ { 0xFF000000, 0x00FF0000, 0x0000FF00, 0x00000000 }, /* 8_8_8_8 */
+ { 0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000 } /* 8_8_8_8_REV */
+ };
+
+ static const uint32_t masks_table_rgba[6][4] = {
+ { 0x000000E0, 0x0000001C, 0x00000003, 0x00000000 }, /* 3_3_2 */
+ { 0x00000007, 0x00000038, 0x000000C0, 0x00000000 }, /* 2_3_3_REV */
+ { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5 */
+ { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5_REV */
+ { 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF }, /* 8_8_8_8 */
+ { 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 }, /* 8_8_8_8_REV */
+ };
+
+ static const uint32_t masks_table_bgr[6][4] = {
+ { 0x00000007, 0x00000038, 0x000000C0, 0x00000000 }, /* 3_3_2 */
+ { 0x000000E0, 0x0000001C, 0x00000003, 0x00000000 }, /* 2_3_3_REV */
+ { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5 */
+ { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5_REV */
+ { 0x0000FF00, 0x00FF0000, 0xFF000000, 0x00000000 }, /* 8_8_8_8 */
+ { 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000 }, /* 8_8_8_8_REV */
+ };
+
+ static const uint32_t masks_table_bgra[6][4] = {
+ { 0x00000007, 0x00000038, 0x000000C0, 0x00000000 }, /* 3_3_2 */
+ { 0x000000E0, 0x0000001C, 0x00000003, 0x00000000 }, /* 2_3_3_REV */
+ { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5 */
+ { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5_REV */
+ { 0x0000FF00, 0x00FF0000, 0xFF000000, 0x000000FF }, /* 8_8_8_8 */
+ { 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000 }, /* 8_8_8_8_REV */
+ };
+
+ static const uint8_t bytes_per_pixel[6] = {
+ 1, /* 3_3_2 */
+ 1, /* 2_3_3_REV */
+ 2, /* 5_6_5 */
+ 2, /* 5_6_5_REV */
+ 4, /* 8_8_8_8 */
+ 4 /* 8_8_8_8_REV */
+ };
+
+ const uint8_t * bits;
+ const uint32_t * masks;
+ int index;
+ __DRIconfig **configs, **c;
+ struct gl_config *modes;
+ unsigned i, j, k, h;
+ unsigned num_modes;
+ unsigned num_accum_bits = (enable_accum) ? 2 : 1;
+
+ switch ( fb_type ) {
+ case GL_UNSIGNED_BYTE_3_3_2:
+ index = 0;
+ break;
+ case GL_UNSIGNED_BYTE_2_3_3_REV:
+ index = 1;
+ break;
+ case GL_UNSIGNED_SHORT_5_6_5:
+ index = 2;
+ break;
+ case GL_UNSIGNED_SHORT_5_6_5_REV:
+ index = 3;
+ break;
+ case GL_UNSIGNED_INT_8_8_8_8:
+ index = 4;
+ break;
+ case GL_UNSIGNED_INT_8_8_8_8_REV:
+ index = 5;
+ break;
+ default:
+ fprintf( stderr, "[%s:%u] Unknown framebuffer type 0x%04x.\n",
+ __FUNCTION__, __LINE__, fb_type );
+ return NULL;
+ }
+
+
+ /* Valid types are GL_UNSIGNED_SHORT_5_6_5 and GL_UNSIGNED_INT_8_8_8_8 and
+ * the _REV versions.
+ *
+ * Valid formats are GL_RGBA, GL_RGB, and GL_BGRA.
+ */
+
+ switch ( fb_format ) {
+ case GL_RGB:
+ masks = masks_table_rgb[ index ];
+ break;
+
+ case GL_RGBA:
+ masks = masks_table_rgba[ index ];
+ break;
+
+ case GL_BGR:
+ masks = masks_table_bgr[ index ];
+ break;
+
+ case GL_BGRA:
+ masks = masks_table_bgra[ index ];
+ break;
+
+ default:
+ fprintf( stderr, "[%s:%u] Unknown framebuffer format 0x%04x.\n",
+ __FUNCTION__, __LINE__, fb_format );
+ return NULL;
+ }
+
+ switch ( bytes_per_pixel[ index ] ) {
+ case 1:
+ bits = bits_table[0];
+ break;
+ case 2:
+ bits = bits_table[1];
+ break;
+ default:
+ bits = ((fb_format == GL_RGB) || (fb_format == GL_BGR))
+ ? bits_table[2]
+ : bits_table[3];
+ break;
+ }
+
+ num_modes = num_depth_stencil_bits * num_db_modes * num_accum_bits * num_msaa_modes;
+ configs = calloc(1, (num_modes + 1) * sizeof *configs);
+ if (configs == NULL)
+ return NULL;
+
+ c = configs;
+ for ( k = 0 ; k < num_depth_stencil_bits ; k++ ) {
+ for ( i = 0 ; i < num_db_modes ; i++ ) {
+ for ( h = 0 ; h < num_msaa_modes; h++ ) {
+ for ( j = 0 ; j < num_accum_bits ; j++ ) {
+ *c = malloc (sizeof **c);
+ modes = &(*c)->modes;
+ c++;
+
+ memset(modes, 0, sizeof *modes);
+ modes->redBits = bits[0];
+ modes->greenBits = bits[1];
+ modes->blueBits = bits[2];
+ modes->alphaBits = bits[3];
+ modes->redMask = masks[0];
+ modes->greenMask = masks[1];
+ modes->blueMask = masks[2];
+ modes->alphaMask = masks[3];
+ modes->rgbBits = modes->redBits + modes->greenBits
+ + modes->blueBits + modes->alphaBits;
+
+ modes->accumRedBits = 16 * j;
+ modes->accumGreenBits = 16 * j;
+ modes->accumBlueBits = 16 * j;
+ modes->accumAlphaBits = (masks[3] != 0) ? 16 * j : 0;
+ modes->visualRating = (j == 0) ? GLX_NONE : GLX_SLOW_CONFIG;
+
+ modes->stencilBits = stencil_bits[k];
+ modes->depthBits = depth_bits[k];
+
+ modes->transparentPixel = GLX_NONE;
+ modes->transparentRed = GLX_DONT_CARE;
+ modes->transparentGreen = GLX_DONT_CARE;
+ modes->transparentBlue = GLX_DONT_CARE;
+ modes->transparentAlpha = GLX_DONT_CARE;
+ modes->transparentIndex = GLX_DONT_CARE;
+ modes->rgbMode = GL_TRUE;
+
+ if ( db_modes[i] == GLX_NONE ) {
+ modes->doubleBufferMode = GL_FALSE;
+ }
+ else {
+ modes->doubleBufferMode = GL_TRUE;
+ modes->swapMethod = db_modes[i];
+ }
+
+ modes->samples = msaa_samples[h];
+ modes->sampleBuffers = modes->samples ? 1 : 0;
+
+
+ modes->haveAccumBuffer = ((modes->accumRedBits +
+ modes->accumGreenBits +
+ modes->accumBlueBits +
+ modes->accumAlphaBits) > 0);
+ modes->haveDepthBuffer = (modes->depthBits > 0);
+ modes->haveStencilBuffer = (modes->stencilBits > 0);
+
+ modes->bindToTextureRgb = GL_TRUE;
+ modes->bindToTextureRgba = GL_TRUE;
+ modes->bindToMipmapTexture = GL_FALSE;
+ modes->bindToTextureTargets =
+ __DRI_ATTRIB_TEXTURE_1D_BIT |
+ __DRI_ATTRIB_TEXTURE_2D_BIT |
+ __DRI_ATTRIB_TEXTURE_RECTANGLE_BIT;
+ }
+ }
+ }
+ }
+ *c = NULL;
+
+ return configs;
+}
+
+__DRIconfig **driConcatConfigs(__DRIconfig **a,
+ __DRIconfig **b)
+{
+ __DRIconfig **all;
+ int i, j, index;
+
+ i = 0;
+ while (a[i] != NULL)
+ i++;
+ j = 0;
+ while (b[j] != NULL)
+ j++;
+
+ all = malloc((i + j + 1) * sizeof *all);
+ index = 0;
+ for (i = 0; a[i] != NULL; i++)
+ all[index++] = a[i];
+ for (j = 0; b[j] != NULL; j++)
+ all[index++] = b[j];
+ all[index++] = NULL;
+
+ free(a);
+ free(b);
+
+ return all;
+}
+
+#define __ATTRIB(attrib, field) \
+ { attrib, offsetof(struct gl_config, field) }
+
+static const struct { unsigned int attrib, offset; } attribMap[] = {
+ __ATTRIB(__DRI_ATTRIB_BUFFER_SIZE, rgbBits),
+ __ATTRIB(__DRI_ATTRIB_LEVEL, level),
+ __ATTRIB(__DRI_ATTRIB_RED_SIZE, redBits),
+ __ATTRIB(__DRI_ATTRIB_GREEN_SIZE, greenBits),
+ __ATTRIB(__DRI_ATTRIB_BLUE_SIZE, blueBits),
+ __ATTRIB(__DRI_ATTRIB_ALPHA_SIZE, alphaBits),
+ __ATTRIB(__DRI_ATTRIB_DEPTH_SIZE, depthBits),
+ __ATTRIB(__DRI_ATTRIB_STENCIL_SIZE, stencilBits),
+ __ATTRIB(__DRI_ATTRIB_ACCUM_RED_SIZE, accumRedBits),
+ __ATTRIB(__DRI_ATTRIB_ACCUM_GREEN_SIZE, accumGreenBits),
+ __ATTRIB(__DRI_ATTRIB_ACCUM_BLUE_SIZE, accumBlueBits),
+ __ATTRIB(__DRI_ATTRIB_ACCUM_ALPHA_SIZE, accumAlphaBits),
+ __ATTRIB(__DRI_ATTRIB_SAMPLE_BUFFERS, sampleBuffers),
+ __ATTRIB(__DRI_ATTRIB_SAMPLES, samples),
+ __ATTRIB(__DRI_ATTRIB_DOUBLE_BUFFER, doubleBufferMode),
+ __ATTRIB(__DRI_ATTRIB_STEREO, stereoMode),
+ __ATTRIB(__DRI_ATTRIB_AUX_BUFFERS, numAuxBuffers),
+ __ATTRIB(__DRI_ATTRIB_TRANSPARENT_TYPE, transparentPixel),
+ __ATTRIB(__DRI_ATTRIB_TRANSPARENT_INDEX_VALUE, transparentPixel),
+ __ATTRIB(__DRI_ATTRIB_TRANSPARENT_RED_VALUE, transparentRed),
+ __ATTRIB(__DRI_ATTRIB_TRANSPARENT_GREEN_VALUE, transparentGreen),
+ __ATTRIB(__DRI_ATTRIB_TRANSPARENT_BLUE_VALUE, transparentBlue),
+ __ATTRIB(__DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE, transparentAlpha),
+ __ATTRIB(__DRI_ATTRIB_FLOAT_MODE, floatMode),
+ __ATTRIB(__DRI_ATTRIB_RED_MASK, redMask),
+ __ATTRIB(__DRI_ATTRIB_GREEN_MASK, greenMask),
+ __ATTRIB(__DRI_ATTRIB_BLUE_MASK, blueMask),
+ __ATTRIB(__DRI_ATTRIB_ALPHA_MASK, alphaMask),
+ __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_WIDTH, maxPbufferWidth),
+ __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_HEIGHT, maxPbufferHeight),
+ __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_PIXELS, maxPbufferPixels),
+ __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH, optimalPbufferWidth),
+ __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT, optimalPbufferHeight),
+ __ATTRIB(__DRI_ATTRIB_SWAP_METHOD, swapMethod),
+ __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGB, bindToTextureRgb),
+ __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGBA, bindToTextureRgba),
+ __ATTRIB(__DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE, bindToMipmapTexture),
+ __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS, bindToTextureTargets),
+ __ATTRIB(__DRI_ATTRIB_YINVERTED, yInverted),
+
+ /* The struct field doesn't matter here, these are handled by the
+ * switch in driGetConfigAttribIndex. We need them in the array
+ * so the iterator includes them though.*/
+ __ATTRIB(__DRI_ATTRIB_RENDER_TYPE, level),
+ __ATTRIB(__DRI_ATTRIB_CONFIG_CAVEAT, level),
+ __ATTRIB(__DRI_ATTRIB_SWAP_METHOD, level)
+};
+
+#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
+
+
+/**
+ * Return the value of a configuration attribute. The attribute is
+ * indicated by the index.
+ */
+static int
+driGetConfigAttribIndex(const __DRIconfig *config,
+ unsigned int index, unsigned int *value)
+{
+ switch (attribMap[index].attrib) {
+ case __DRI_ATTRIB_RENDER_TYPE:
+ /* no support for color index mode */
+ *value = __DRI_ATTRIB_RGBA_BIT;
+ break;
+ case __DRI_ATTRIB_CONFIG_CAVEAT:
+ if (config->modes.visualRating == GLX_NON_CONFORMANT_CONFIG)
+ *value = __DRI_ATTRIB_NON_CONFORMANT_CONFIG;
+ else if (config->modes.visualRating == GLX_SLOW_CONFIG)
+ *value = __DRI_ATTRIB_SLOW_BIT;
+ else
+ *value = 0;
+ break;
+ case __DRI_ATTRIB_SWAP_METHOD:
+ /* XXX no return value??? */
+ break;
+
+ case __DRI_ATTRIB_FLOAT_MODE:
+ /* this field is not int-sized */
+ *value = config->modes.floatMode;
+ break;
+
+ default:
+ /* any other int-sized field */
+ *value = *(unsigned int *)
+ ((char *) &config->modes + attribMap[index].offset);
+
+ break;
+ }
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Get the value of a configuration attribute.
+ * \param attrib the attribute (one of the _DRI_ATTRIB_x tokens)
+ * \param value returns the attribute's value
+ * \return 1 for success, 0 for failure
+ */
+int
+driGetConfigAttrib(const __DRIconfig *config,
+ unsigned int attrib, unsigned int *value)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(attribMap); i++)
+ if (attribMap[i].attrib == attrib)
+ return driGetConfigAttribIndex(config, i, value);
+
+ return GL_FALSE;
+}
+
+
+/**
+ * Get a configuration attribute name and value, given an index.
+ * \param index which field of the __DRIconfig to query
+ * \param attrib returns the attribute name (one of the _DRI_ATTRIB_x tokens)
+ * \param value returns the attribute's value
+ * \return 1 for success, 0 for failure
+ */
+int
+driIndexConfigAttrib(const __DRIconfig *config, int index,
+ unsigned int *attrib, unsigned int *value)
+{
+ if (index >= 0 && index < ARRAY_SIZE(attribMap)) {
+ *attrib = attribMap[index].attrib;
+ return driGetConfigAttribIndex(config, index, value);
+ }
+
+ return GL_FALSE;
+}
diff --git a/mesalib/src/mesa/drivers/dri/common/utils.h b/mesalib/src/mesa/drivers/dri/common/utils.h
index de6070c39..2c952dc19 100644
--- a/mesalib/src/mesa/drivers/dri/common/utils.h
+++ b/mesalib/src/mesa/drivers/dri/common/utils.h
@@ -1,123 +1,123 @@
-/*
- * (C) Copyright IBM Corporation 2002, 2004
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * on the rights to use, copy, modify, merge, publish, distribute, sub
- * license, and/or sell copies of the Software, and to permit persons to whom
- * the Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Ian Romanick <idr@us.ibm.com>
- */
-
-#ifndef DRI_DEBUG_H
-#define DRI_DEBUG_H
-
-#include <GL/gl.h>
-#include <GL/internal/dri_interface.h>
-#include "main/context.h"
-#include "main/remap.h"
-
-typedef struct __DRIutilversionRec2 __DRIutilversion2;
-
-struct dri_debug_control {
- const char * string;
- unsigned flag;
-};
-
-/**
- * Description of the API for an extension to OpenGL.
- */
-struct dri_extension {
- /**
- * Name of the extension.
- */
- const char * name;
-
-
- /**
- * Pointer to a list of \c dri_extension_function structures. The list
- * is terminated by a structure with a \c NULL
- * \c dri_extension_function::strings pointer.
- */
- const struct gl_function_remap * functions;
-};
-
-/**
- * Used to store a version which includes a major range instead of a single
- * major version number.
- */
-struct __DRIutilversionRec2 {
- int major_min; /** min allowed Major version number. */
- int major_max; /** max allowed Major version number. */
- int minor; /**< Minor version number. */
- int patch; /**< Patch-level. */
-};
-
-extern void
-__driUtilMessage(const char *f, ...);
-
-extern unsigned driParseDebugString( const char * debug,
- const struct dri_debug_control * control );
-
-extern unsigned driGetRendererString( char * buffer,
- const char * hardware_name, const char * driver_date, GLuint agp_mode );
-
-extern void driInitExtensions( GLcontext * ctx,
- const struct dri_extension * card_extensions, GLboolean enable_imaging );
-
-extern void driInitSingleExtension( GLcontext * ctx,
- const struct dri_extension * ext );
-
-extern GLboolean driCheckDriDdxDrmVersions2(const char * driver_name,
- const __DRIversion * driActual, const __DRIversion * driExpected,
- const __DRIversion * ddxActual, const __DRIversion * ddxExpected,
- const __DRIversion * drmActual, const __DRIversion * drmExpected);
-
-extern GLboolean driCheckDriDdxDrmVersions3(const char * driver_name,
- const __DRIversion * driActual, const __DRIversion * driExpected,
- const __DRIversion * ddxActual, const __DRIutilversion2 * ddxExpected,
- const __DRIversion * drmActual, const __DRIversion * drmExpected);
-
-extern GLboolean driClipRectToFramebuffer( const GLframebuffer *buffer,
- GLint *x, GLint *y,
- GLsizei *width, GLsizei *height );
-
-struct __DRIconfigRec {
- __GLcontextModes modes;
-};
-
-extern __DRIconfig **
-driCreateConfigs(GLenum fb_format, GLenum fb_type,
- const uint8_t * depth_bits, const uint8_t * stencil_bits,
- unsigned num_depth_stencil_bits,
- const GLenum * db_modes, unsigned num_db_modes,
- const uint8_t * msaa_samples, unsigned num_msaa_modes,
- GLboolean enable_accum);
-
-__DRIconfig **driConcatConfigs(__DRIconfig **a,
- __DRIconfig **b);
-
-int
-driGetConfigAttrib(const __DRIconfig *config,
- unsigned int attrib, unsigned int *value);
-int
-driIndexConfigAttrib(const __DRIconfig *config, int index,
- unsigned int *attrib, unsigned int *value);
-
-#endif /* DRI_DEBUG_H */
+/*
+ * (C) Copyright IBM Corporation 2002, 2004
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Ian Romanick <idr@us.ibm.com>
+ */
+
+#ifndef DRI_DEBUG_H
+#define DRI_DEBUG_H
+
+#include <GL/gl.h>
+#include <GL/internal/dri_interface.h>
+#include "main/context.h"
+#include "main/remap.h"
+
+typedef struct __DRIutilversionRec2 __DRIutilversion2;
+
+struct dri_debug_control {
+ const char * string;
+ unsigned flag;
+};
+
+/**
+ * Description of the API for an extension to OpenGL.
+ */
+struct dri_extension {
+ /**
+ * Name of the extension.
+ */
+ const char * name;
+
+
+ /**
+ * Pointer to a list of \c dri_extension_function structures. The list
+ * is terminated by a structure with a \c NULL
+ * \c dri_extension_function::strings pointer.
+ */
+ const struct gl_function_remap * functions;
+};
+
+/**
+ * Used to store a version which includes a major range instead of a single
+ * major version number.
+ */
+struct __DRIutilversionRec2 {
+ int major_min; /** min allowed Major version number. */
+ int major_max; /** max allowed Major version number. */
+ int minor; /**< Minor version number. */
+ int patch; /**< Patch-level. */
+};
+
+extern void
+__driUtilMessage(const char *f, ...);
+
+extern unsigned driParseDebugString( const char * debug,
+ const struct dri_debug_control * control );
+
+extern unsigned driGetRendererString( char * buffer,
+ const char * hardware_name, const char * driver_date, GLuint agp_mode );
+
+extern void driInitExtensions( struct gl_context * ctx,
+ const struct dri_extension * card_extensions, GLboolean enable_imaging );
+
+extern void driInitSingleExtension( struct gl_context * ctx,
+ const struct dri_extension * ext );
+
+extern GLboolean driCheckDriDdxDrmVersions2(const char * driver_name,
+ const __DRIversion * driActual, const __DRIversion * driExpected,
+ const __DRIversion * ddxActual, const __DRIversion * ddxExpected,
+ const __DRIversion * drmActual, const __DRIversion * drmExpected);
+
+extern GLboolean driCheckDriDdxDrmVersions3(const char * driver_name,
+ const __DRIversion * driActual, const __DRIversion * driExpected,
+ const __DRIversion * ddxActual, const __DRIutilversion2 * ddxExpected,
+ const __DRIversion * drmActual, const __DRIversion * drmExpected);
+
+extern GLboolean driClipRectToFramebuffer( const struct gl_framebuffer *buffer,
+ GLint *x, GLint *y,
+ GLsizei *width, GLsizei *height );
+
+struct __DRIconfigRec {
+ struct gl_config modes;
+};
+
+extern __DRIconfig **
+driCreateConfigs(GLenum fb_format, GLenum fb_type,
+ const uint8_t * depth_bits, const uint8_t * stencil_bits,
+ unsigned num_depth_stencil_bits,
+ const GLenum * db_modes, unsigned num_db_modes,
+ const uint8_t * msaa_samples, unsigned num_msaa_modes,
+ GLboolean enable_accum);
+
+__DRIconfig **driConcatConfigs(__DRIconfig **a,
+ __DRIconfig **b);
+
+int
+driGetConfigAttrib(const __DRIconfig *config,
+ unsigned int attrib, unsigned int *value);
+int
+driIndexConfigAttrib(const __DRIconfig *config, int index,
+ unsigned int *attrib, unsigned int *value);
+
+#endif /* DRI_DEBUG_H */
diff --git a/mesalib/src/mesa/drivers/dri/common/vblank.c b/mesalib/src/mesa/drivers/dri/common/vblank.c
index 49b22a2dc..3b8136844 100644
--- a/mesalib/src/mesa/drivers/dri/common/vblank.c
+++ b/mesalib/src/mesa/drivers/dri/common/vblank.c
@@ -1,434 +1,434 @@
-/* -*- mode: c; c-basic-offset: 3 -*- */
-/*
- * (c) Copyright IBM Corporation 2002
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * on the rights to use, copy, modify, merge, publish, distribute, sub
- * license, and/or sell copies of the Software, and to permit persons to whom
- * the Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Ian Romanick <idr@us.ibm.com>
- */
-
-#include "main/glheader.h"
-#include "xf86drm.h"
-#include "main/mtypes.h"
-#include "main/macros.h"
-#include "main/dd.h"
-#include "vblank.h"
-#include "xmlpool.h"
-
-static unsigned int msc_to_vblank(__DRIdrawable * dPriv, int64_t msc)
-{
- return (unsigned int)(msc - dPriv->msc_base + dPriv->vblank_base);
-}
-
-static int64_t vblank_to_msc(__DRIdrawable * dPriv, unsigned int vblank)
-{
- return (int64_t)(vblank - dPriv->vblank_base + dPriv->msc_base);
-}
-
-
-/****************************************************************************/
-/**
- * Get the current MSC refresh counter.
- *
- * Stores the 64-bit count of vertical refreshes since some (arbitrary)
- * point in time in \c count. Unless the value wraps around, which it
- * may, it will never decrease for a given drawable.
- *
- * \warning This function is called from \c glXGetVideoSyncSGI, which expects
- * a \c count of type \c unsigned (32-bit), and \c glXGetSyncValuesOML, which
- * expects a \c count of type \c int64_t (signed 64-bit). The kernel ioctl
- * currently always returns a \c sequence of type \c unsigned.
- *
- * \param priv Pointer to the DRI screen private struct.
- * \param dPriv Pointer to the DRI drawable private struct
- * \param count Storage to hold MSC counter.
- * \return Zero is returned on success. A negative errno value
- * is returned on failure.
- */
-int driDrawableGetMSC32( __DRIscreen * priv,
- __DRIdrawable * dPriv,
- int64_t * count)
-{
- drmVBlank vbl;
- int ret;
-
- /* Don't wait for anything. Just get the current refresh count. */
-
- vbl.request.type = DRM_VBLANK_RELATIVE;
- vbl.request.sequence = 0;
- if ( dPriv && dPriv->vblFlags & VBLANK_FLAG_SECONDARY )
- vbl.request.type |= DRM_VBLANK_SECONDARY;
-
- ret = drmWaitVBlank( priv->fd, &vbl );
-
- if (dPriv) {
- *count = vblank_to_msc(dPriv, vbl.reply.sequence);
- } else {
- /* Old driver (no knowledge of drawable MSC callback) */
- *count = vbl.reply.sequence;
- }
-
- return ret;
-}
-
-/****************************************************************************/
-/**
- * Wait for a specified refresh count. This implements most of the
- * functionality of \c glXWaitForMscOML from the GLX_OML_sync_control spec.
- * Waits for the \c target_msc refresh. If that has already passed, it
- * waits until \f$(MSC \bmod divisor)\f$ is equal to \c remainder. If
- * \c target_msc is 0, use the behavior of glXWaitVideoSyncSGI(), which
- * omits the initial check against a target MSC value.
- *
- * This function is actually something of a hack. The problem is that, at
- * the time of this writing, none of the existing DRM modules support an
- * ioctl that returns a 64-bit count (at least not on 32-bit platforms).
- * However, this function exists to support a GLX function that requires
- * the use of 64-bit counts. As such, there is a little bit of ugly
- * hackery at the end of this function to make the 32-bit count act like
- * a 64-bit count. There are still some cases where this will break, but
- * I believe it catches the most common cases.
- *
- * The real solution is to provide an ioctl that uses a 64-bit count.
- *
- * \param dpy Pointer to the \c Display.
- * \param priv Pointer to the DRI drawable private.
- * \param target_msc Desired refresh count to wait for. A value of 0
- * means to use the glXWaitVideoSyncSGI() behavior.
- * \param divisor MSC divisor if \c target_msc is already reached.
- * \param remainder Desired MSC remainder if \c target_msc is already
- * reached.
- * \param msc Buffer to hold MSC when done waiting.
- *
- * \return Zero on success or \c GLX_BAD_CONTEXT on failure.
- */
-
-int driWaitForMSC32( __DRIdrawable *priv,
- int64_t target_msc, int64_t divisor, int64_t remainder,
- int64_t * msc )
-{
- drmVBlank vbl;
-
-
- if ( divisor != 0 ) {
- int64_t next = target_msc;
- int64_t r;
- int dont_wait = (target_msc == 0);
-
- do {
- /* dont_wait means we're using the glXWaitVideoSyncSGI() behavior.
- * The first time around, just get the current count and proceed
- * to the test for (MSC % divisor) == remainder.
- */
- vbl.request.type = dont_wait ? DRM_VBLANK_RELATIVE :
- DRM_VBLANK_ABSOLUTE;
- vbl.request.sequence = next ? msc_to_vblank(priv, next) : 0;
- if ( priv->vblFlags & VBLANK_FLAG_SECONDARY )
- vbl.request.type |= DRM_VBLANK_SECONDARY;
-
- if ( drmWaitVBlank( priv->driScreenPriv->fd, &vbl ) != 0 ) {
- /* FIXME: This doesn't seem like the right thing to return here.
- */
- return GLX_BAD_CONTEXT;
- }
-
- *msc = vblank_to_msc(priv, vbl.reply.sequence);
-
- if (!dont_wait && *msc == next)
- break;
- dont_wait = 0;
-
- /* Assuming the wait-done test fails, the next refresh to wait for
- * will be one that satisfies (MSC % divisor) == remainder. The
- * value (MSC - (MSC % divisor) + remainder) is the refresh value
- * closest to the current value that would satisfy the equation.
- * If this refresh has already happened, we add divisor to obtain
- * the next refresh after the current one that will satisfy it.
- */
- r = ((uint64_t)*msc % divisor);
- next = (*msc - r + remainder);
- if (next <= *msc)
- next += divisor;
-
- } while (r != remainder);
- }
- else {
- /* If the \c divisor is zero, just wait until the MSC is greater
- * than or equal to \c target_msc.
- */
-
- vbl.request.type = DRM_VBLANK_ABSOLUTE;
- vbl.request.sequence = target_msc ? msc_to_vblank(priv, target_msc) : 0;
-
- if ( priv->vblFlags & VBLANK_FLAG_SECONDARY )
- vbl.request.type |= DRM_VBLANK_SECONDARY;
-
- if ( drmWaitVBlank( priv->driScreenPriv->fd, &vbl ) != 0 ) {
- /* FIXME: This doesn't seem like the right thing to return here.
- */
- return GLX_BAD_CONTEXT;
- }
- }
-
- *msc = vblank_to_msc(priv, vbl.reply.sequence);
-
- if ( *msc < target_msc ) {
- *msc += 0x0000000100000000LL;
- }
-
- return 0;
-}
-
-
-/****************************************************************************/
-/**
- * Gets a set of default vertical-blank-wait flags based on the internal GLX
- * API version and several configuration options.
- */
-
-GLuint driGetDefaultVBlankFlags( const driOptionCache *optionCache )
-{
- GLuint flags = VBLANK_FLAG_INTERVAL;
- int vblank_mode;
-
-
- if ( driCheckOption( optionCache, "vblank_mode", DRI_ENUM ) )
- vblank_mode = driQueryOptioni( optionCache, "vblank_mode" );
- else
- vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1;
-
- switch (vblank_mode) {
- case DRI_CONF_VBLANK_NEVER:
- flags = 0;
- break;
- case DRI_CONF_VBLANK_DEF_INTERVAL_0:
- break;
- case DRI_CONF_VBLANK_DEF_INTERVAL_1:
- flags |= VBLANK_FLAG_THROTTLE;
- break;
- case DRI_CONF_VBLANK_ALWAYS_SYNC:
- flags |= VBLANK_FLAG_SYNC;
- break;
- }
-
- return flags;
-}
-
-
-/****************************************************************************/
-/**
- * Wrapper to call \c drmWaitVBlank. The main purpose of this function is to
- * wrap the error message logging. The error message should only be logged
- * the first time the \c drmWaitVBlank fails. If \c drmWaitVBlank is
- * successful, \c vbl_seq will be set the sequence value in the reply.
- *
- * \param vbl Pointer to drmVBlank packet desribing how to wait.
- * \param vbl_seq Location to store the current refresh counter.
- * \param fd File descriptor use to call into the DRM.
- * \return Zero on success or -1 on failure.
- */
-
-static int do_wait( drmVBlank * vbl, GLuint * vbl_seq, int fd )
-{
- int ret;
-
-
- ret = drmWaitVBlank( fd, vbl );
- if ( ret != 0 ) {
- static GLboolean first_time = GL_TRUE;
-
- if ( first_time ) {
- fprintf(stderr,
- "%s: drmWaitVBlank returned %d, IRQs don't seem to be"
- " working correctly.\nTry adjusting the vblank_mode"
- " configuration parameter.\n", __FUNCTION__, ret);
- first_time = GL_FALSE;
- }
-
- return -1;
- }
-
- *vbl_seq = vbl->reply.sequence;
- return 0;
-}
-
-
-/****************************************************************************/
-/**
- * Returns the default swap interval of the given drawable.
- */
-
-static unsigned
-driGetDefaultVBlankInterval( const __DRIdrawable *priv )
-{
- if ( (priv->vblFlags & (VBLANK_FLAG_THROTTLE | VBLANK_FLAG_SYNC)) != 0 ) {
- return 1;
- }
- else {
- return 0;
- }
-}
-
-
-/****************************************************************************/
-/**
- * Sets the default swap interval when the drawable is first bound to a
- * direct rendering context.
- */
-
-void driDrawableInitVBlank( __DRIdrawable *priv )
-{
- if ( priv->swap_interval == (unsigned)-1 &&
- !( priv->vblFlags & VBLANK_FLAG_NO_IRQ ) ) {
- /* Get current vertical blank sequence */
- drmVBlank vbl;
-
- vbl.request.type = DRM_VBLANK_RELATIVE;
- if ( priv->vblFlags & VBLANK_FLAG_SECONDARY )
- vbl.request.type |= DRM_VBLANK_SECONDARY;
- vbl.request.sequence = 0;
- do_wait( &vbl, &priv->vblSeq, priv->driScreenPriv->fd );
- priv->vblank_base = priv->vblSeq;
-
- priv->swap_interval = driGetDefaultVBlankInterval( priv );
- }
-}
-
-
-/****************************************************************************/
-/**
- * Returns the current swap interval of the given drawable.
- */
-
-unsigned
-driGetVBlankInterval( const __DRIdrawable *priv )
-{
- if ( (priv->vblFlags & VBLANK_FLAG_INTERVAL) != 0 ) {
- /* this must have been initialized when the drawable was first bound
- * to a direct rendering context. */
- assert ( priv->swap_interval != (unsigned)-1 );
-
- return priv->swap_interval;
- }
- else
- return driGetDefaultVBlankInterval( priv );
-}
-
-
-/****************************************************************************/
-/**
- * Returns the current vertical blank sequence number of the given drawable.
- */
-
-void
-driGetCurrentVBlank( __DRIdrawable *priv )
-{
- drmVBlank vbl;
-
- vbl.request.type = DRM_VBLANK_RELATIVE;
- if ( priv->vblFlags & VBLANK_FLAG_SECONDARY ) {
- vbl.request.type |= DRM_VBLANK_SECONDARY;
- }
- vbl.request.sequence = 0;
-
- (void) do_wait( &vbl, &priv->vblSeq, priv->driScreenPriv->fd );
-}
-
-
-/****************************************************************************/
-/**
- * Waits for the vertical blank for use with glXSwapBuffers.
- *
- * \param missed_deadline Set to \c GL_TRUE if the MSC after waiting is later
- * than the "target" based on \c priv->vblFlags. The idea is
- * that if \c missed_deadline is set, then the application is
- * not achieving its desired framerate.
- * \return Zero on success, -1 on error.
- */
-
-int
-driWaitForVBlank( __DRIdrawable *priv, GLboolean * missed_deadline )
-{
- drmVBlank vbl;
- unsigned original_seq;
- unsigned deadline;
- unsigned interval;
- unsigned diff;
-
- *missed_deadline = GL_FALSE;
- if ( (priv->vblFlags & (VBLANK_FLAG_INTERVAL |
- VBLANK_FLAG_THROTTLE |
- VBLANK_FLAG_SYNC)) == 0 ||
- (priv->vblFlags & VBLANK_FLAG_NO_IRQ) != 0 ) {
- return 0;
- }
-
-
- /* VBLANK_FLAG_SYNC means to wait for at least one vertical blank. If
- * that flag is not set, do a fake wait for zero vertical blanking
- * periods so that we can get the current MSC.
- *
- * VBLANK_FLAG_INTERVAL and VBLANK_FLAG_THROTTLE mean to wait for at
- * least one vertical blank since the last wait. Since do_wait modifies
- * priv->vblSeq, we have to save the original value of priv->vblSeq for the
- * VBLANK_FLAG_INTERVAL / VBLANK_FLAG_THROTTLE calculation later.
- */
-
- original_seq = priv->vblSeq;
- interval = driGetVBlankInterval(priv);
- deadline = original_seq + interval;
-
- vbl.request.type = DRM_VBLANK_RELATIVE;
- if ( priv->vblFlags & VBLANK_FLAG_SECONDARY ) {
- vbl.request.type |= DRM_VBLANK_SECONDARY;
- }
- vbl.request.sequence = ((priv->vblFlags & VBLANK_FLAG_SYNC) != 0) ? 1 : 0;
-
- if ( do_wait( & vbl, &priv->vblSeq, priv->driScreenPriv->fd ) != 0 ) {
- return -1;
- }
-
- diff = priv->vblSeq - deadline;
-
- /* No need to wait again if we've already reached the target */
- if (diff <= (1 << 23)) {
- *missed_deadline = (priv->vblFlags & VBLANK_FLAG_SYNC) ? (diff > 0) :
- GL_TRUE;
- return 0;
- }
-
- /* Wait until the target vertical blank. */
- vbl.request.type = DRM_VBLANK_ABSOLUTE;
- if ( priv->vblFlags & VBLANK_FLAG_SECONDARY ) {
- vbl.request.type |= DRM_VBLANK_SECONDARY;
- }
- vbl.request.sequence = deadline;
-
- if ( do_wait( & vbl, &priv->vblSeq, priv->driScreenPriv->fd ) != 0 ) {
- return -1;
- }
-
- diff = priv->vblSeq - deadline;
- *missed_deadline = diff > 0 && diff <= (1 << 23);
-
- return 0;
-}
+/* -*- mode: c; c-basic-offset: 3 -*- */
+/*
+ * (c) Copyright IBM Corporation 2002
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Ian Romanick <idr@us.ibm.com>
+ */
+
+#include "main/glheader.h"
+#include "xf86drm.h"
+#include "main/mtypes.h"
+#include "main/macros.h"
+#include "main/dd.h"
+#include "vblank.h"
+#include "xmlpool.h"
+
+static unsigned int msc_to_vblank(__DRIdrawable * dPriv, int64_t msc)
+{
+ return (unsigned int)(msc - dPriv->msc_base + dPriv->vblank_base);
+}
+
+static int64_t vblank_to_msc(__DRIdrawable * dPriv, unsigned int vblank)
+{
+ return (int64_t)(vblank - dPriv->vblank_base + dPriv->msc_base);
+}
+
+
+/****************************************************************************/
+/**
+ * Get the current MSC refresh counter.
+ *
+ * Stores the 64-bit count of vertical refreshes since some (arbitrary)
+ * point in time in \c count. Unless the value wraps around, which it
+ * may, it will never decrease for a given drawable.
+ *
+ * \warning This function is called from \c glXGetVideoSyncSGI, which expects
+ * a \c count of type \c unsigned (32-bit), and \c glXGetSyncValuesOML, which
+ * expects a \c count of type \c int64_t (signed 64-bit). The kernel ioctl
+ * currently always returns a \c sequence of type \c unsigned.
+ *
+ * \param priv Pointer to the DRI screen private struct.
+ * \param dPriv Pointer to the DRI drawable private struct
+ * \param count Storage to hold MSC counter.
+ * \return Zero is returned on success. A negative errno value
+ * is returned on failure.
+ */
+int driDrawableGetMSC32( __DRIscreen * priv,
+ __DRIdrawable * dPriv,
+ int64_t * count)
+{
+ drmVBlank vbl;
+ int ret;
+
+ /* Don't wait for anything. Just get the current refresh count. */
+
+ vbl.request.type = DRM_VBLANK_RELATIVE;
+ vbl.request.sequence = 0;
+ if ( dPriv && dPriv->vblFlags & VBLANK_FLAG_SECONDARY )
+ vbl.request.type |= DRM_VBLANK_SECONDARY;
+
+ ret = drmWaitVBlank( priv->fd, &vbl );
+
+ if (dPriv) {
+ *count = vblank_to_msc(dPriv, vbl.reply.sequence);
+ } else {
+ /* Old driver (no knowledge of drawable MSC callback) */
+ *count = vbl.reply.sequence;
+ }
+
+ return ret;
+}
+
+/****************************************************************************/
+/**
+ * Wait for a specified refresh count. This implements most of the
+ * functionality of \c glXWaitForMscOML from the GLX_OML_sync_control spec.
+ * Waits for the \c target_msc refresh. If that has already passed, it
+ * waits until \f$(MSC \bmod divisor)\f$ is equal to \c remainder. If
+ * \c target_msc is 0, use the behavior of glXWaitVideoSyncSGI(), which
+ * omits the initial check against a target MSC value.
+ *
+ * This function is actually something of a hack. The problem is that, at
+ * the time of this writing, none of the existing DRM modules support an
+ * ioctl that returns a 64-bit count (at least not on 32-bit platforms).
+ * However, this function exists to support a GLX function that requires
+ * the use of 64-bit counts. As such, there is a little bit of ugly
+ * hackery at the end of this function to make the 32-bit count act like
+ * a 64-bit count. There are still some cases where this will break, but
+ * I believe it catches the most common cases.
+ *
+ * The real solution is to provide an ioctl that uses a 64-bit count.
+ *
+ * \param dpy Pointer to the \c Display.
+ * \param priv Pointer to the DRI drawable private.
+ * \param target_msc Desired refresh count to wait for. A value of 0
+ * means to use the glXWaitVideoSyncSGI() behavior.
+ * \param divisor MSC divisor if \c target_msc is already reached.
+ * \param remainder Desired MSC remainder if \c target_msc is already
+ * reached.
+ * \param msc Buffer to hold MSC when done waiting.
+ *
+ * \return Zero on success or \c GLX_BAD_CONTEXT on failure.
+ */
+
+int driWaitForMSC32( __DRIdrawable *priv,
+ int64_t target_msc, int64_t divisor, int64_t remainder,
+ int64_t * msc )
+{
+ drmVBlank vbl;
+
+
+ if ( divisor != 0 ) {
+ int64_t next = target_msc;
+ int64_t r;
+ int dont_wait = (target_msc == 0);
+
+ do {
+ /* dont_wait means we're using the glXWaitVideoSyncSGI() behavior.
+ * The first time around, just get the current count and proceed
+ * to the test for (MSC % divisor) == remainder.
+ */
+ vbl.request.type = dont_wait ? DRM_VBLANK_RELATIVE :
+ DRM_VBLANK_ABSOLUTE;
+ vbl.request.sequence = next ? msc_to_vblank(priv, next) : 0;
+ if ( priv->vblFlags & VBLANK_FLAG_SECONDARY )
+ vbl.request.type |= DRM_VBLANK_SECONDARY;
+
+ if ( drmWaitVBlank( priv->driScreenPriv->fd, &vbl ) != 0 ) {
+ /* FIXME: This doesn't seem like the right thing to return here.
+ */
+ return GLX_BAD_CONTEXT;
+ }
+
+ *msc = vblank_to_msc(priv, vbl.reply.sequence);
+
+ if (!dont_wait && *msc == next)
+ break;
+ dont_wait = 0;
+
+ /* Assuming the wait-done test fails, the next refresh to wait for
+ * will be one that satisfies (MSC % divisor) == remainder. The
+ * value (MSC - (MSC % divisor) + remainder) is the refresh value
+ * closest to the current value that would satisfy the equation.
+ * If this refresh has already happened, we add divisor to obtain
+ * the next refresh after the current one that will satisfy it.
+ */
+ r = ((uint64_t)*msc % divisor);
+ next = (*msc - r + remainder);
+ if (next <= *msc)
+ next += divisor;
+
+ } while (r != remainder);
+ }
+ else {
+ /* If the \c divisor is zero, just wait until the MSC is greater
+ * than or equal to \c target_msc.
+ */
+
+ vbl.request.type = DRM_VBLANK_ABSOLUTE;
+ vbl.request.sequence = target_msc ? msc_to_vblank(priv, target_msc) : 0;
+
+ if ( priv->vblFlags & VBLANK_FLAG_SECONDARY )
+ vbl.request.type |= DRM_VBLANK_SECONDARY;
+
+ if ( drmWaitVBlank( priv->driScreenPriv->fd, &vbl ) != 0 ) {
+ /* FIXME: This doesn't seem like the right thing to return here.
+ */
+ return GLX_BAD_CONTEXT;
+ }
+ }
+
+ *msc = vblank_to_msc(priv, vbl.reply.sequence);
+
+ if ( *msc < target_msc ) {
+ *msc += 0x0000000100000000LL;
+ }
+
+ return 0;
+}
+
+
+/****************************************************************************/
+/**
+ * Gets a set of default vertical-blank-wait flags based on the internal GLX
+ * API version and several configuration options.
+ */
+
+GLuint driGetDefaultVBlankFlags( const driOptionCache *optionCache )
+{
+ GLuint flags = VBLANK_FLAG_INTERVAL;
+ int vblank_mode;
+
+
+ if ( driCheckOption( optionCache, "vblank_mode", DRI_ENUM ) )
+ vblank_mode = driQueryOptioni( optionCache, "vblank_mode" );
+ else
+ vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1;
+
+ switch (vblank_mode) {
+ case DRI_CONF_VBLANK_NEVER:
+ flags = 0;
+ break;
+ case DRI_CONF_VBLANK_DEF_INTERVAL_0:
+ break;
+ case DRI_CONF_VBLANK_DEF_INTERVAL_1:
+ flags |= VBLANK_FLAG_THROTTLE;
+ break;
+ case DRI_CONF_VBLANK_ALWAYS_SYNC:
+ flags |= VBLANK_FLAG_SYNC;
+ break;
+ }
+
+ return flags;
+}
+
+
+/****************************************************************************/
+/**
+ * Wrapper to call \c drmWaitVBlank. The main purpose of this function is to
+ * wrap the error message logging. The error message should only be logged
+ * the first time the \c drmWaitVBlank fails. If \c drmWaitVBlank is
+ * successful, \c vbl_seq will be set the sequence value in the reply.
+ *
+ * \param vbl Pointer to drmVBlank packet describing how to wait.
+ * \param vbl_seq Location to store the current refresh counter.
+ * \param fd File descriptor use to call into the DRM.
+ * \return Zero on success or -1 on failure.
+ */
+
+static int do_wait( drmVBlank * vbl, GLuint * vbl_seq, int fd )
+{
+ int ret;
+
+
+ ret = drmWaitVBlank( fd, vbl );
+ if ( ret != 0 ) {
+ static GLboolean first_time = GL_TRUE;
+
+ if ( first_time ) {
+ fprintf(stderr,
+ "%s: drmWaitVBlank returned %d, IRQs don't seem to be"
+ " working correctly.\nTry adjusting the vblank_mode"
+ " configuration parameter.\n", __FUNCTION__, ret);
+ first_time = GL_FALSE;
+ }
+
+ return -1;
+ }
+
+ *vbl_seq = vbl->reply.sequence;
+ return 0;
+}
+
+
+/****************************************************************************/
+/**
+ * Returns the default swap interval of the given drawable.
+ */
+
+static unsigned
+driGetDefaultVBlankInterval( const __DRIdrawable *priv )
+{
+ if ( (priv->vblFlags & (VBLANK_FLAG_THROTTLE | VBLANK_FLAG_SYNC)) != 0 ) {
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+
+
+/****************************************************************************/
+/**
+ * Sets the default swap interval when the drawable is first bound to a
+ * direct rendering context.
+ */
+
+void driDrawableInitVBlank( __DRIdrawable *priv )
+{
+ if ( priv->swap_interval == (unsigned)-1 &&
+ !( priv->vblFlags & VBLANK_FLAG_NO_IRQ ) ) {
+ /* Get current vertical blank sequence */
+ drmVBlank vbl;
+
+ vbl.request.type = DRM_VBLANK_RELATIVE;
+ if ( priv->vblFlags & VBLANK_FLAG_SECONDARY )
+ vbl.request.type |= DRM_VBLANK_SECONDARY;
+ vbl.request.sequence = 0;
+ do_wait( &vbl, &priv->vblSeq, priv->driScreenPriv->fd );
+ priv->vblank_base = priv->vblSeq;
+
+ priv->swap_interval = driGetDefaultVBlankInterval( priv );
+ }
+}
+
+
+/****************************************************************************/
+/**
+ * Returns the current swap interval of the given drawable.
+ */
+
+unsigned
+driGetVBlankInterval( const __DRIdrawable *priv )
+{
+ if ( (priv->vblFlags & VBLANK_FLAG_INTERVAL) != 0 ) {
+ /* this must have been initialized when the drawable was first bound
+ * to a direct rendering context. */
+ assert ( priv->swap_interval != (unsigned)-1 );
+
+ return priv->swap_interval;
+ }
+ else
+ return driGetDefaultVBlankInterval( priv );
+}
+
+
+/****************************************************************************/
+/**
+ * Returns the current vertical blank sequence number of the given drawable.
+ */
+
+void
+driGetCurrentVBlank( __DRIdrawable *priv )
+{
+ drmVBlank vbl;
+
+ vbl.request.type = DRM_VBLANK_RELATIVE;
+ if ( priv->vblFlags & VBLANK_FLAG_SECONDARY ) {
+ vbl.request.type |= DRM_VBLANK_SECONDARY;
+ }
+ vbl.request.sequence = 0;
+
+ (void) do_wait( &vbl, &priv->vblSeq, priv->driScreenPriv->fd );
+}
+
+
+/****************************************************************************/
+/**
+ * Waits for the vertical blank for use with glXSwapBuffers.
+ *
+ * \param missed_deadline Set to \c GL_TRUE if the MSC after waiting is later
+ * than the "target" based on \c priv->vblFlags. The idea is
+ * that if \c missed_deadline is set, then the application is
+ * not achieving its desired framerate.
+ * \return Zero on success, -1 on error.
+ */
+
+int
+driWaitForVBlank( __DRIdrawable *priv, GLboolean * missed_deadline )
+{
+ drmVBlank vbl;
+ unsigned original_seq;
+ unsigned deadline;
+ unsigned interval;
+ unsigned diff;
+
+ *missed_deadline = GL_FALSE;
+ if ( (priv->vblFlags & (VBLANK_FLAG_INTERVAL |
+ VBLANK_FLAG_THROTTLE |
+ VBLANK_FLAG_SYNC)) == 0 ||
+ (priv->vblFlags & VBLANK_FLAG_NO_IRQ) != 0 ) {
+ return 0;
+ }
+
+
+ /* VBLANK_FLAG_SYNC means to wait for at least one vertical blank. If
+ * that flag is not set, do a fake wait for zero vertical blanking
+ * periods so that we can get the current MSC.
+ *
+ * VBLANK_FLAG_INTERVAL and VBLANK_FLAG_THROTTLE mean to wait for at
+ * least one vertical blank since the last wait. Since do_wait modifies
+ * priv->vblSeq, we have to save the original value of priv->vblSeq for the
+ * VBLANK_FLAG_INTERVAL / VBLANK_FLAG_THROTTLE calculation later.
+ */
+
+ original_seq = priv->vblSeq;
+ interval = driGetVBlankInterval(priv);
+ deadline = original_seq + interval;
+
+ vbl.request.type = DRM_VBLANK_RELATIVE;
+ if ( priv->vblFlags & VBLANK_FLAG_SECONDARY ) {
+ vbl.request.type |= DRM_VBLANK_SECONDARY;
+ }
+ vbl.request.sequence = ((priv->vblFlags & VBLANK_FLAG_SYNC) != 0) ? 1 : 0;
+
+ if ( do_wait( & vbl, &priv->vblSeq, priv->driScreenPriv->fd ) != 0 ) {
+ return -1;
+ }
+
+ diff = priv->vblSeq - deadline;
+
+ /* No need to wait again if we've already reached the target */
+ if (diff <= (1 << 23)) {
+ *missed_deadline = (priv->vblFlags & VBLANK_FLAG_SYNC) ? (diff > 0) :
+ GL_TRUE;
+ return 0;
+ }
+
+ /* Wait until the target vertical blank. */
+ vbl.request.type = DRM_VBLANK_ABSOLUTE;
+ if ( priv->vblFlags & VBLANK_FLAG_SECONDARY ) {
+ vbl.request.type |= DRM_VBLANK_SECONDARY;
+ }
+ vbl.request.sequence = deadline;
+
+ if ( do_wait( & vbl, &priv->vblSeq, priv->driScreenPriv->fd ) != 0 ) {
+ return -1;
+ }
+
+ diff = priv->vblSeq - deadline;
+ *missed_deadline = diff > 0 && diff <= (1 << 23);
+
+ return 0;
+}
diff --git a/mesalib/src/mesa/drivers/dri/common/vblank.h b/mesalib/src/mesa/drivers/dri/common/vblank.h
index 29d1ad800..c46f4ccc3 100644
--- a/mesalib/src/mesa/drivers/dri/common/vblank.h
+++ b/mesalib/src/mesa/drivers/dri/common/vblank.h
@@ -1,75 +1,71 @@
-/* -*- mode: c; c-basic-offset: 3 -*- */
-/*
- * (c) Copyright IBM Corporation 2002
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * on the rights to use, copy, modify, merge, publish, distribute, sub
- * license, and/or sell copies of the Software, and to permit persons to whom
- * the Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Ian Romanick <idr@us.ibm.com>
- */
-
-#ifndef DRI_VBLANK_H
-#define DRI_VBLANK_H
-
-#include "main/context.h"
-#include "dri_util.h"
-#include "xmlconfig.h"
-
-#define VBLANK_FLAG_INTERVAL (1U << 0) /* Respect the swap_interval setting
- */
-#define VBLANK_FLAG_THROTTLE (1U << 1) /* Wait 1 refresh since last call.
- */
-#define VBLANK_FLAG_SYNC (1U << 2) /* Sync to the next refresh.
- */
-#define VBLANK_FLAG_NO_IRQ (1U << 7) /* DRM has no IRQ to wait on.
- */
-#define VBLANK_FLAG_SECONDARY (1U << 8) /* Wait for secondary vblank.
- */
-
-extern int driGetMSC32( __DRIscreen * priv, int64_t * count );
-extern int driDrawableGetMSC32( __DRIscreen * priv,
- __DRIdrawable * drawablePrivate,
- int64_t * count);
-extern int driWaitForMSC32( __DRIdrawable *priv,
- int64_t target_msc, int64_t divisor, int64_t remainder, int64_t * msc );
-extern GLuint driGetDefaultVBlankFlags( const driOptionCache *optionCache );
-extern void driDrawableInitVBlank ( __DRIdrawable *priv );
-extern unsigned driGetVBlankInterval( const __DRIdrawable *priv );
-extern void driGetCurrentVBlank( __DRIdrawable *priv );
-extern int driWaitForVBlank( __DRIdrawable *priv,
- GLboolean * missed_deadline );
-
-#undef usleep
-#include <unistd.h> /* for usleep() */
-#include <sched.h> /* for sched_yield() */
-
-#ifdef linux
-#include <sched.h> /* for sched_yield() */
-#endif
-
-#define DO_USLEEP(nr) \
- do { \
- if (0) fprintf(stderr, "%s: usleep for %u\n", __FUNCTION__, nr ); \
- if (1) usleep( nr ); \
- sched_yield(); \
- } while( 0 )
-
-#endif /* DRI_VBLANK_H */
+/* -*- mode: c; c-basic-offset: 3 -*- */
+/*
+ * (c) Copyright IBM Corporation 2002
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Ian Romanick <idr@us.ibm.com>
+ */
+
+#ifndef DRI_VBLANK_H
+#define DRI_VBLANK_H
+
+#include "main/context.h"
+#include "dri_util.h"
+#include "xmlconfig.h"
+
+#define VBLANK_FLAG_INTERVAL (1U << 0) /* Respect the swap_interval setting
+ */
+#define VBLANK_FLAG_THROTTLE (1U << 1) /* Wait 1 refresh since last call.
+ */
+#define VBLANK_FLAG_SYNC (1U << 2) /* Sync to the next refresh.
+ */
+#define VBLANK_FLAG_NO_IRQ (1U << 7) /* DRM has no IRQ to wait on.
+ */
+#define VBLANK_FLAG_SECONDARY (1U << 8) /* Wait for secondary vblank.
+ */
+
+extern int driGetMSC32( __DRIscreen * priv, int64_t * count );
+extern int driDrawableGetMSC32( __DRIscreen * priv,
+ __DRIdrawable * drawablePrivate,
+ int64_t * count);
+extern int driWaitForMSC32( __DRIdrawable *priv,
+ int64_t target_msc, int64_t divisor, int64_t remainder, int64_t * msc );
+extern GLuint driGetDefaultVBlankFlags( const driOptionCache *optionCache );
+extern void driDrawableInitVBlank ( __DRIdrawable *priv );
+extern unsigned driGetVBlankInterval( const __DRIdrawable *priv );
+extern void driGetCurrentVBlank( __DRIdrawable *priv );
+extern int driWaitForVBlank( __DRIdrawable *priv,
+ GLboolean * missed_deadline );
+
+#undef usleep
+#include <unistd.h> /* for usleep() */
+#include <sched.h> /* for sched_yield() */
+
+#define DO_USLEEP(nr) \
+ do { \
+ if (0) fprintf(stderr, "%s: usleep for %u\n", __FUNCTION__, nr ); \
+ if (1) usleep( nr ); \
+ sched_yield(); \
+ } while( 0 )
+
+#endif /* DRI_VBLANK_H */
diff --git a/mesalib/src/mesa/drivers/dri/common/xmlconfig.c b/mesalib/src/mesa/drivers/dri/common/xmlconfig.c
index 738b1ae97..eaba335a4 100644
--- a/mesalib/src/mesa/drivers/dri/common/xmlconfig.c
+++ b/mesalib/src/mesa/drivers/dri/common/xmlconfig.c
@@ -1,1001 +1,1004 @@
-/*
- * XML DRI client-side driver configuration
- * Copyright (C) 2003 Felix Kuehling
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * FELIX KUEHLING, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
- * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- */
-/**
- * \file xmlconfig.c
- * \brief Driver-independent client-side part of the XML configuration
- * \author Felix Kuehling
- */
-
-#include "main/glheader.h"
-
-#include <string.h>
-#include <assert.h>
-#include <expat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include "main/imports.h"
-#include "utils.h"
-#include "xmlconfig.h"
-
-#undef GET_PROGRAM_NAME
-
-#if (defined(__GNU_LIBRARY__) || defined(__GLIBC__)) && !defined(__UCLIBC__)
-# if !defined(__GLIBC__) || (__GLIBC__ < 2)
-/* These aren't declared in any libc5 header */
-extern char *program_invocation_name, *program_invocation_short_name;
-# endif
-# define GET_PROGRAM_NAME() program_invocation_short_name
-#elif defined(__FreeBSD__) && (__FreeBSD__ >= 2)
-# include <osreldate.h>
-# if (__FreeBSD_version >= 440000)
-# include <stdlib.h>
-# define GET_PROGRAM_NAME() getprogname()
-# endif
-#elif defined(__NetBSD__) && defined(__NetBSD_Version) && (__NetBSD_Version >= 106000100)
-# include <stdlib.h>
-# define GET_PROGRAM_NAME() getprogname()
-#elif defined(__sun)
-/* Solaris has getexecname() which returns the full path - return just
- the basename to match BSD getprogname() */
-# include <stdlib.h>
-# include <libgen.h>
-# define GET_PROGRAM_NAME() basename(getexecname())
-#endif
-
-#if !defined(GET_PROGRAM_NAME)
-# if defined(__OpenBSD__) || defined(NetBSD) || defined(__UCLIBC__)
-/* This is a hack. It's said to work on OpenBSD, NetBSD and GNU.
- * Rogelio M.Serrano Jr. reported it's also working with UCLIBC. It's
- * used as a last resort, if there is no documented facility available. */
-static const char *__getProgramName () {
- extern const char *__progname;
- char * arg = strrchr(__progname, '/');
- if (arg)
- return arg+1;
- else
- return __progname;
-}
-# define GET_PROGRAM_NAME() __getProgramName()
-# else
-# define GET_PROGRAM_NAME() ""
-# warning "Per application configuration won't work with your OS version."
-# endif
-#endif
-
-/** \brief Find an option in an option cache with the name as key */
-static GLuint findOption (const driOptionCache *cache, const char *name) {
- GLuint len = strlen (name);
- GLuint size = 1 << cache->tableSize, mask = size - 1;
- GLuint hash = 0;
- GLuint i, shift;
-
- /* compute a hash from the variable length name */
- for (i = 0, shift = 0; i < len; ++i, shift = (shift+8) & 31)
- hash += (GLuint)name[i] << shift;
- hash *= hash;
- hash = (hash >> (16-cache->tableSize/2)) & mask;
-
- /* this is just the starting point of the linear search for the option */
- for (i = 0; i < size; ++i, hash = (hash+1) & mask) {
- /* if we hit an empty entry then the option is not defined (yet) */
- if (cache->info[hash].name == 0)
- break;
- else if (!strcmp (name, cache->info[hash].name))
- break;
- }
- /* this assertion fails if the hash table is full */
- assert (i < size);
-
- return hash;
-}
-
-/** \brief Count the real number of options in an option cache */
-static GLuint countOptions (const driOptionCache *cache) {
- GLuint size = 1 << cache->tableSize;
- GLuint i, count = 0;
- for (i = 0; i < size; ++i)
- if (cache->info[i].name)
- count++;
- return count;
-}
-
-/** \brief Like strdup but using MALLOC and with error checking. */
-#define XSTRDUP(dest,source) do { \
- GLuint len = strlen (source); \
- if (!(dest = MALLOC (len+1))) { \
- fprintf (stderr, "%s: %d: out of memory.\n", __FILE__, __LINE__); \
- abort(); \
- } \
- memcpy (dest, source, len+1); \
-} while (0)
-
-static int compare (const void *a, const void *b) {
- return strcmp (*(char *const*)a, *(char *const*)b);
-}
-/** \brief Binary search in a string array. */
-static GLuint bsearchStr (const XML_Char *name,
- const XML_Char *elems[], GLuint count) {
- const XML_Char **found;
- found = bsearch (&name, elems, count, sizeof (XML_Char *), compare);
- if (found)
- return found - elems;
- else
- return count;
-}
-
-/** \brief Locale-independent integer parser.
- *
- * Works similar to strtol. Leading space is NOT skipped. The input
- * number may have an optional sign. Radix is specified by base. If
- * base is 0 then decimal is assumed unless the input number is
- * prefixed by 0x or 0X for hexadecimal or 0 for octal. After
- * returning tail points to the first character that is not part of
- * the integer number. If no number was found then tail points to the
- * start of the input string. */
-static GLint strToI (const XML_Char *string, const XML_Char **tail, int base) {
- GLint radix = base == 0 ? 10 : base;
- GLint result = 0;
- GLint sign = 1;
- GLboolean numberFound = GL_FALSE;
- const XML_Char *start = string;
-
- assert (radix >= 2 && radix <= 36);
-
- if (*string == '-') {
- sign = -1;
- string++;
- } else if (*string == '+')
- string++;
- if (base == 0 && *string == '0') {
- numberFound = GL_TRUE;
- if (*(string+1) == 'x' || *(string+1) == 'X') {
- radix = 16;
- string += 2;
- } else {
- radix = 8;
- string++;
- }
- }
- do {
- GLint digit = -1;
- if (radix <= 10) {
- if (*string >= '0' && *string < '0' + radix)
- digit = *string - '0';
- } else {
- if (*string >= '0' && *string <= '9')
- digit = *string - '0';
- else if (*string >= 'a' && *string < 'a' + radix - 10)
- digit = *string - 'a' + 10;
- else if (*string >= 'A' && *string < 'A' + radix - 10)
- digit = *string - 'A' + 10;
- }
- if (digit != -1) {
- numberFound = GL_TRUE;
- result = radix*result + digit;
- string++;
- } else
- break;
- } while (GL_TRUE);
- *tail = numberFound ? string : start;
- return sign * result;
-}
-
-/** \brief Locale-independent floating-point parser.
- *
- * Works similar to strtod. Leading space is NOT skipped. The input
- * number may have an optional sign. '.' is interpreted as decimal
- * point and may occor at most once. Optionally the number may end in
- * [eE]<exponent>, where <exponent> is an integer as recognized by
- * strToI. In that case the result is number * 10^exponent. After
- * returning tail points to the first character that is not part of
- * the floating point number. If no number was found then tail points
- * to the start of the input string.
- *
- * Uses two passes for maximum accuracy. */
-static GLfloat strToF (const XML_Char *string, const XML_Char **tail) {
- GLint nDigits = 0, pointPos, exponent;
- GLfloat sign = 1.0f, result = 0.0f, scale;
- const XML_Char *start = string, *numStart;
-
- /* sign */
- if (*string == '-') {
- sign = -1.0f;
- string++;
- } else if (*string == '+')
- string++;
-
- /* first pass: determine position of decimal point, number of
- * digits, exponent and the end of the number. */
- numStart = string;
- while (*string >= '0' && *string <= '9') {
- string++;
- nDigits++;
- }
- pointPos = nDigits;
- if (*string == '.') {
- string++;
- while (*string >= '0' && *string <= '9') {
- string++;
- nDigits++;
- }
- }
- if (nDigits == 0) {
- /* no digits, no number */
- *tail = start;
- return 0.0f;
- }
- *tail = string;
- if (*string == 'e' || *string == 'E') {
- const XML_Char *expTail;
- exponent = strToI (string+1, &expTail, 10);
- if (expTail == string+1)
- exponent = 0;
- else
- *tail = expTail;
- } else
- exponent = 0;
- string = numStart;
-
- /* scale of the first digit */
- scale = sign * (GLfloat)pow (10.0, (GLdouble)(pointPos-1 + exponent));
-
- /* second pass: parse digits */
- do {
- if (*string != '.') {
- assert (*string >= '0' && *string <= '9');
- result += scale * (GLfloat)(*string - '0');
- scale *= 0.1f;
- nDigits--;
- }
- string++;
- } while (nDigits > 0);
-
- return result;
-}
-
-/** \brief Parse a value of a given type. */
-static GLboolean parseValue (driOptionValue *v, driOptionType type,
- const XML_Char *string) {
- const XML_Char *tail = NULL;
- /* skip leading white-space */
- string += strspn (string, " \f\n\r\t\v");
- switch (type) {
- case DRI_BOOL:
- if (!strcmp (string, "false")) {
- v->_bool = GL_FALSE;
- tail = string + 5;
- } else if (!strcmp (string, "true")) {
- v->_bool = GL_TRUE;
- tail = string + 4;
- }
- else
- return GL_FALSE;
- break;
- case DRI_ENUM: /* enum is just a special integer */
- case DRI_INT:
- v->_int = strToI (string, &tail, 0);
- break;
- case DRI_FLOAT:
- v->_float = strToF (string, &tail);
- break;
- }
-
- if (tail == string)
- return GL_FALSE; /* empty string (or containing only white-space) */
- /* skip trailing white space */
- if (*tail)
- tail += strspn (tail, " \f\n\r\t\v");
- if (*tail)
- return GL_FALSE; /* something left over that is not part of value */
-
- return GL_TRUE;
-}
-
-/** \brief Parse a list of ranges of type info->type. */
-static GLboolean parseRanges (driOptionInfo *info, const XML_Char *string) {
- XML_Char *cp, *range;
- GLuint nRanges, i;
- driOptionRange *ranges;
-
- XSTRDUP (cp, string);
- /* pass 1: determine the number of ranges (number of commas + 1) */
- range = cp;
- for (nRanges = 1; *range; ++range)
- if (*range == ',')
- ++nRanges;
-
- if ((ranges = MALLOC (nRanges*sizeof(driOptionRange))) == NULL) {
- fprintf (stderr, "%s: %d: out of memory.\n", __FILE__, __LINE__);
- abort();
- }
-
- /* pass 2: parse all ranges into preallocated array */
- range = cp;
- for (i = 0; i < nRanges; ++i) {
- XML_Char *end, *sep;
- assert (range);
- end = strchr (range, ',');
- if (end)
- *end = '\0';
- sep = strchr (range, ':');
- if (sep) { /* non-empty interval */
- *sep = '\0';
- if (!parseValue (&ranges[i].start, info->type, range) ||
- !parseValue (&ranges[i].end, info->type, sep+1))
- break;
- if (info->type == DRI_INT &&
- ranges[i].start._int > ranges[i].end._int)
- break;
- if (info->type == DRI_FLOAT &&
- ranges[i].start._float > ranges[i].end._float)
- break;
- } else { /* empty interval */
- if (!parseValue (&ranges[i].start, info->type, range))
- break;
- ranges[i].end = ranges[i].start;
- }
- if (end)
- range = end+1;
- else
- range = NULL;
- }
- FREE (cp);
- if (i < nRanges) {
- FREE (ranges);
- return GL_FALSE;
- } else
- assert (range == NULL);
-
- info->nRanges = nRanges;
- info->ranges = ranges;
- return GL_TRUE;
-}
-
-/** \brief Check if a value is in one of info->ranges. */
-static GLboolean checkValue (const driOptionValue *v, const driOptionInfo *info) {
- GLuint i;
- assert (info->type != DRI_BOOL); /* should be caught by the parser */
- if (info->nRanges == 0)
- return GL_TRUE;
- switch (info->type) {
- case DRI_ENUM: /* enum is just a special integer */
- case DRI_INT:
- for (i = 0; i < info->nRanges; ++i)
- if (v->_int >= info->ranges[i].start._int &&
- v->_int <= info->ranges[i].end._int)
- return GL_TRUE;
- break;
- case DRI_FLOAT:
- for (i = 0; i < info->nRanges; ++i)
- if (v->_float >= info->ranges[i].start._float &&
- v->_float <= info->ranges[i].end._float)
- return GL_TRUE;
- break;
- default:
- assert (0); /* should never happen */
- }
- return GL_FALSE;
-}
-
-/** \brief Output a warning message. */
-#define XML_WARNING1(msg) do {\
- __driUtilMessage ("Warning in %s line %d, column %d: "msg, data->name, \
- (int) XML_GetCurrentLineNumber(data->parser), \
- (int) XML_GetCurrentColumnNumber(data->parser)); \
-} while (0)
-#define XML_WARNING(msg,args...) do { \
- __driUtilMessage ("Warning in %s line %d, column %d: "msg, data->name, \
- (int) XML_GetCurrentLineNumber(data->parser), \
- (int) XML_GetCurrentColumnNumber(data->parser), \
- args); \
-} while (0)
-/** \brief Output an error message. */
-#define XML_ERROR1(msg) do { \
- __driUtilMessage ("Error in %s line %d, column %d: "msg, data->name, \
- (int) XML_GetCurrentLineNumber(data->parser), \
- (int) XML_GetCurrentColumnNumber(data->parser)); \
-} while (0)
-#define XML_ERROR(msg,args...) do { \
- __driUtilMessage ("Error in %s line %d, column %d: "msg, data->name, \
- (int) XML_GetCurrentLineNumber(data->parser), \
- (int) XML_GetCurrentColumnNumber(data->parser), \
- args); \
-} while (0)
-/** \brief Output a fatal error message and abort. */
-#define XML_FATAL1(msg) do { \
- fprintf (stderr, "Fatal error in %s line %d, column %d: "msg"\n", \
- data->name, \
- (int) XML_GetCurrentLineNumber(data->parser), \
- (int) XML_GetCurrentColumnNumber(data->parser)); \
- abort();\
-} while (0)
-#define XML_FATAL(msg,args...) do { \
- fprintf (stderr, "Fatal error in %s line %d, column %d: "msg"\n", \
- data->name, \
- (int) XML_GetCurrentLineNumber(data->parser), \
- (int) XML_GetCurrentColumnNumber(data->parser), \
- args); \
- abort();\
-} while (0)
-
-/** \brief Parser context for __driConfigOptions. */
-struct OptInfoData {
- const char *name;
- XML_Parser parser;
- driOptionCache *cache;
- GLboolean inDriInfo;
- GLboolean inSection;
- GLboolean inDesc;
- GLboolean inOption;
- GLboolean inEnum;
- int curOption;
-};
-
-/** \brief Elements in __driConfigOptions. */
-enum OptInfoElem {
- OI_DESCRIPTION = 0, OI_DRIINFO, OI_ENUM, OI_OPTION, OI_SECTION, OI_COUNT
-};
-static const XML_Char *OptInfoElems[] = {
- "description", "driinfo", "enum", "option", "section"
-};
-
-/** \brief Parse attributes of an enum element.
- *
- * We're not actually interested in the data. Just make sure this is ok
- * for external configuration tools.
- */
-static void parseEnumAttr (struct OptInfoData *data, const XML_Char **attr) {
- GLuint i;
- const XML_Char *value = NULL, *text = NULL;
- driOptionValue v;
- GLuint opt = data->curOption;
- for (i = 0; attr[i]; i += 2) {
- if (!strcmp (attr[i], "value")) value = attr[i+1];
- else if (!strcmp (attr[i], "text")) text = attr[i+1];
- else XML_FATAL("illegal enum attribute: %s.", attr[i]);
- }
- if (!value) XML_FATAL1 ("value attribute missing in enum.");
- if (!text) XML_FATAL1 ("text attribute missing in enum.");
- if (!parseValue (&v, data->cache->info[opt].type, value))
- XML_FATAL ("illegal enum value: %s.", value);
- if (!checkValue (&v, &data->cache->info[opt]))
- XML_FATAL ("enum value out of valid range: %s.", value);
-}
-
-/** \brief Parse attributes of a description element.
- *
- * We're not actually interested in the data. Just make sure this is ok
- * for external configuration tools.
- */
-static void parseDescAttr (struct OptInfoData *data, const XML_Char **attr) {
- GLuint i;
- const XML_Char *lang = NULL, *text = NULL;
- for (i = 0; attr[i]; i += 2) {
- if (!strcmp (attr[i], "lang")) lang = attr[i+1];
- else if (!strcmp (attr[i], "text")) text = attr[i+1];
- else XML_FATAL("illegal description attribute: %s.", attr[i]);
- }
- if (!lang) XML_FATAL1 ("lang attribute missing in description.");
- if (!text) XML_FATAL1 ("text attribute missing in description.");
-}
-
-/** \brief Parse attributes of an option element. */
-static void parseOptInfoAttr (struct OptInfoData *data, const XML_Char **attr) {
- enum OptAttr {OA_DEFAULT = 0, OA_NAME, OA_TYPE, OA_VALID, OA_COUNT};
- static const XML_Char *optAttr[] = {"default", "name", "type", "valid"};
- const XML_Char *attrVal[OA_COUNT] = {NULL, NULL, NULL, NULL};
- const char *defaultVal;
- driOptionCache *cache = data->cache;
- GLuint opt, i;
- for (i = 0; attr[i]; i += 2) {
- GLuint attrName = bsearchStr (attr[i], optAttr, OA_COUNT);
- if (attrName >= OA_COUNT)
- XML_FATAL ("illegal option attribute: %s", attr[i]);
- attrVal[attrName] = attr[i+1];
- }
- if (!attrVal[OA_NAME]) XML_FATAL1 ("name attribute missing in option.");
- if (!attrVal[OA_TYPE]) XML_FATAL1 ("type attribute missing in option.");
- if (!attrVal[OA_DEFAULT]) XML_FATAL1 ("default attribute missing in option.");
-
- opt = findOption (cache, attrVal[OA_NAME]);
- if (cache->info[opt].name)
- XML_FATAL ("option %s redefined.", attrVal[OA_NAME]);
- data->curOption = opt;
-
- XSTRDUP (cache->info[opt].name, attrVal[OA_NAME]);
-
- if (!strcmp (attrVal[OA_TYPE], "bool"))
- cache->info[opt].type = DRI_BOOL;
- else if (!strcmp (attrVal[OA_TYPE], "enum"))
- cache->info[opt].type = DRI_ENUM;
- else if (!strcmp (attrVal[OA_TYPE], "int"))
- cache->info[opt].type = DRI_INT;
- else if (!strcmp (attrVal[OA_TYPE], "float"))
- cache->info[opt].type = DRI_FLOAT;
- else
- XML_FATAL ("illegal type in option: %s.", attrVal[OA_TYPE]);
-
- defaultVal = getenv (cache->info[opt].name);
- if (defaultVal != NULL) {
- /* don't use XML_WARNING, we want the user to see this! */
- fprintf (stderr,
- "ATTENTION: default value of option %s overridden by environment.\n",
- cache->info[opt].name);
- } else
- defaultVal = attrVal[OA_DEFAULT];
- if (!parseValue (&cache->values[opt], cache->info[opt].type, defaultVal))
- XML_FATAL ("illegal default value: %s.", defaultVal);
-
- if (attrVal[OA_VALID]) {
- if (cache->info[opt].type == DRI_BOOL)
- XML_FATAL1 ("boolean option with valid attribute.");
- if (!parseRanges (&cache->info[opt], attrVal[OA_VALID]))
- XML_FATAL ("illegal valid attribute: %s.", attrVal[OA_VALID]);
- if (!checkValue (&cache->values[opt], &cache->info[opt]))
- XML_FATAL ("default value out of valid range '%s': %s.",
- attrVal[OA_VALID], defaultVal);
- } else if (cache->info[opt].type == DRI_ENUM) {
- XML_FATAL1 ("valid attribute missing in option (mandatory for enums).");
- } else {
- cache->info[opt].nRanges = 0;
- cache->info[opt].ranges = NULL;
- }
-}
-
-/** \brief Handler for start element events. */
-static void optInfoStartElem (void *userData, const XML_Char *name,
- const XML_Char **attr) {
- struct OptInfoData *data = (struct OptInfoData *)userData;
- enum OptInfoElem elem = bsearchStr (name, OptInfoElems, OI_COUNT);
- switch (elem) {
- case OI_DRIINFO:
- if (data->inDriInfo)
- XML_FATAL1 ("nested <driinfo> elements.");
- if (attr[0])
- XML_FATAL1 ("attributes specified on <driinfo> element.");
- data->inDriInfo = GL_TRUE;
- break;
- case OI_SECTION:
- if (!data->inDriInfo)
- XML_FATAL1 ("<section> must be inside <driinfo>.");
- if (data->inSection)
- XML_FATAL1 ("nested <section> elements.");
- if (attr[0])
- XML_FATAL1 ("attributes specified on <section> element.");
- data->inSection = GL_TRUE;
- break;
- case OI_DESCRIPTION:
- if (!data->inSection && !data->inOption)
- XML_FATAL1 ("<description> must be inside <description> or <option.");
- if (data->inDesc)
- XML_FATAL1 ("nested <description> elements.");
- data->inDesc = GL_TRUE;
- parseDescAttr (data, attr);
- break;
- case OI_OPTION:
- if (!data->inSection)
- XML_FATAL1 ("<option> must be inside <section>.");
- if (data->inDesc)
- XML_FATAL1 ("<option> nested in <description> element.");
- if (data->inOption)
- XML_FATAL1 ("nested <option> elements.");
- data->inOption = GL_TRUE;
- parseOptInfoAttr (data, attr);
- break;
- case OI_ENUM:
- if (!(data->inOption && data->inDesc))
- XML_FATAL1 ("<enum> must be inside <option> and <description>.");
- if (data->inEnum)
- XML_FATAL1 ("nested <enum> elements.");
- data->inEnum = GL_TRUE;
- parseEnumAttr (data, attr);
- break;
- default:
- XML_FATAL ("unknown element: %s.", name);
- }
-}
-
-/** \brief Handler for end element events. */
-static void optInfoEndElem (void *userData, const XML_Char *name) {
- struct OptInfoData *data = (struct OptInfoData *)userData;
- enum OptInfoElem elem = bsearchStr (name, OptInfoElems, OI_COUNT);
- switch (elem) {
- case OI_DRIINFO:
- data->inDriInfo = GL_FALSE;
- break;
- case OI_SECTION:
- data->inSection = GL_FALSE;
- break;
- case OI_DESCRIPTION:
- data->inDesc = GL_FALSE;
- break;
- case OI_OPTION:
- data->inOption = GL_FALSE;
- break;
- case OI_ENUM:
- data->inEnum = GL_FALSE;
- break;
- default:
- assert (0); /* should have been caught by StartElem */
- }
-}
-
-void driParseOptionInfo (driOptionCache *info,
- const char *configOptions, GLuint nConfigOptions) {
- XML_Parser p;
- int status;
- struct OptInfoData userData;
- struct OptInfoData *data = &userData;
- GLuint realNoptions;
-
- /* determine hash table size and allocate memory:
- * 3/2 of the number of options, rounded up, so there remains always
- * at least one free entry. This is needed for detecting undefined
- * options in configuration files without getting a hash table overflow.
- * Round this up to a power of two. */
- GLuint minSize = (nConfigOptions*3 + 1) / 2;
- GLuint size, log2size;
- for (size = 1, log2size = 0; size < minSize; size <<= 1, ++log2size);
- info->tableSize = log2size;
- info->info = CALLOC (size * sizeof (driOptionInfo));
- info->values = CALLOC (size * sizeof (driOptionValue));
- if (info->info == NULL || info->values == NULL) {
- fprintf (stderr, "%s: %d: out of memory.\n", __FILE__, __LINE__);
- abort();
- }
-
- p = XML_ParserCreate ("UTF-8"); /* always UTF-8 */
- XML_SetElementHandler (p, optInfoStartElem, optInfoEndElem);
- XML_SetUserData (p, data);
-
- userData.name = "__driConfigOptions";
- userData.parser = p;
- userData.cache = info;
- userData.inDriInfo = GL_FALSE;
- userData.inSection = GL_FALSE;
- userData.inDesc = GL_FALSE;
- userData.inOption = GL_FALSE;
- userData.inEnum = GL_FALSE;
- userData.curOption = -1;
-
- status = XML_Parse (p, configOptions, strlen (configOptions), 1);
- if (!status)
- XML_FATAL ("%s.", XML_ErrorString(XML_GetErrorCode(p)));
-
- XML_ParserFree (p);
-
- /* Check if the actual number of options matches nConfigOptions.
- * A mismatch is not fatal (a hash table overflow would be) but we
- * want the driver developer's attention anyway. */
- realNoptions = countOptions (info);
- if (realNoptions != nConfigOptions) {
- fprintf (stderr,
- "Error: nConfigOptions (%u) does not match the actual number of options in\n"
- " __driConfigOptions (%u).\n",
- nConfigOptions, realNoptions);
- }
-}
-
-/** \brief Parser context for configuration files. */
-struct OptConfData {
- const char *name;
- XML_Parser parser;
- driOptionCache *cache;
- GLint screenNum;
- const char *driverName, *execName;
- GLuint ignoringDevice;
- GLuint ignoringApp;
- GLuint inDriConf;
- GLuint inDevice;
- GLuint inApp;
- GLuint inOption;
-};
-
-/** \brief Elements in configuration files. */
-enum OptConfElem {
- OC_APPLICATION = 0, OC_DEVICE, OC_DRICONF, OC_OPTION, OC_COUNT
-};
-static const XML_Char *OptConfElems[] = {
- "application", "device", "driconf", "option"
-};
-
-/** \brief Parse attributes of a device element. */
-static void parseDeviceAttr (struct OptConfData *data, const XML_Char **attr) {
- GLuint i;
- const XML_Char *driver = NULL, *screen = NULL;
- for (i = 0; attr[i]; i += 2) {
- if (!strcmp (attr[i], "driver")) driver = attr[i+1];
- else if (!strcmp (attr[i], "screen")) screen = attr[i+1];
- else XML_WARNING("unkown device attribute: %s.", attr[i]);
- }
- if (driver && strcmp (driver, data->driverName))
- data->ignoringDevice = data->inDevice;
- else if (screen) {
- driOptionValue screenNum;
- if (!parseValue (&screenNum, DRI_INT, screen))
- XML_WARNING("illegal screen number: %s.", screen);
- else if (screenNum._int != data->screenNum)
- data->ignoringDevice = data->inDevice;
- }
-}
-
-/** \brief Parse attributes of an application element. */
-static void parseAppAttr (struct OptConfData *data, const XML_Char **attr) {
- GLuint i;
- const XML_Char *name = NULL, *exec = NULL;
- for (i = 0; attr[i]; i += 2) {
- if (!strcmp (attr[i], "name")) name = attr[i+1];
- else if (!strcmp (attr[i], "executable")) exec = attr[i+1];
- else XML_WARNING("unkown application attribute: %s.", attr[i]);
- }
- if (exec && strcmp (exec, data->execName))
- data->ignoringApp = data->inApp;
-}
-
-/** \brief Parse attributes of an option element. */
-static void parseOptConfAttr (struct OptConfData *data, const XML_Char **attr) {
- GLuint i;
- const XML_Char *name = NULL, *value = NULL;
- for (i = 0; attr[i]; i += 2) {
- if (!strcmp (attr[i], "name")) name = attr[i+1];
- else if (!strcmp (attr[i], "value")) value = attr[i+1];
- else XML_WARNING("unkown option attribute: %s.", attr[i]);
- }
- if (!name) XML_WARNING1 ("name attribute missing in option.");
- if (!value) XML_WARNING1 ("value attribute missing in option.");
- if (name && value) {
- driOptionCache *cache = data->cache;
- GLuint opt = findOption (cache, name);
- if (cache->info[opt].name == NULL)
- XML_WARNING ("undefined option: %s.", name);
- else if (getenv (cache->info[opt].name))
- /* don't use XML_WARNING, we want the user to see this! */
- fprintf (stderr, "ATTENTION: option value of option %s ignored.\n",
- cache->info[opt].name);
- else if (!parseValue (&cache->values[opt], cache->info[opt].type, value))
- XML_WARNING ("illegal option value: %s.", value);
- }
-}
-
-/** \brief Handler for start element events. */
-static void optConfStartElem (void *userData, const XML_Char *name,
- const XML_Char **attr) {
- struct OptConfData *data = (struct OptConfData *)userData;
- enum OptConfElem elem = bsearchStr (name, OptConfElems, OC_COUNT);
- switch (elem) {
- case OC_DRICONF:
- if (data->inDriConf)
- XML_WARNING1 ("nested <driconf> elements.");
- if (attr[0])
- XML_WARNING1 ("attributes specified on <driconf> element.");
- data->inDriConf++;
- break;
- case OC_DEVICE:
- if (!data->inDriConf)
- XML_WARNING1 ("<device> should be inside <driconf>.");
- if (data->inDevice)
- XML_WARNING1 ("nested <device> elements.");
- data->inDevice++;
- if (!data->ignoringDevice && !data->ignoringApp)
- parseDeviceAttr (data, attr);
- break;
- case OC_APPLICATION:
- if (!data->inDevice)
- XML_WARNING1 ("<application> should be inside <device>.");
- if (data->inApp)
- XML_WARNING1 ("nested <application> elements.");
- data->inApp++;
- if (!data->ignoringDevice && !data->ignoringApp)
- parseAppAttr (data, attr);
- break;
- case OC_OPTION:
- if (!data->inApp)
- XML_WARNING1 ("<option> should be inside <application>.");
- if (data->inOption)
- XML_WARNING1 ("nested <option> elements.");
- data->inOption++;
- if (!data->ignoringDevice && !data->ignoringApp)
- parseOptConfAttr (data, attr);
- break;
- default:
- XML_WARNING ("unknown element: %s.", name);
- }
-}
-
-/** \brief Handler for end element events. */
-static void optConfEndElem (void *userData, const XML_Char *name) {
- struct OptConfData *data = (struct OptConfData *)userData;
- enum OptConfElem elem = bsearchStr (name, OptConfElems, OC_COUNT);
- switch (elem) {
- case OC_DRICONF:
- data->inDriConf--;
- break;
- case OC_DEVICE:
- if (data->inDevice-- == data->ignoringDevice)
- data->ignoringDevice = 0;
- break;
- case OC_APPLICATION:
- if (data->inApp-- == data->ignoringApp)
- data->ignoringApp = 0;
- break;
- case OC_OPTION:
- data->inOption--;
- break;
- default:
- /* unknown element, warning was produced on start tag */;
- }
-}
-
-/** \brief Initialize an option cache based on info */
-static void initOptionCache (driOptionCache *cache, const driOptionCache *info) {
- cache->info = info->info;
- cache->tableSize = info->tableSize;
- cache->values = MALLOC ((1<<info->tableSize) * sizeof (driOptionValue));
- if (cache->values == NULL) {
- fprintf (stderr, "%s: %d: out of memory.\n", __FILE__, __LINE__);
- abort();
- }
- memcpy (cache->values, info->values,
- (1<<info->tableSize) * sizeof (driOptionValue));
-}
-
-/** \brief Parse the named configuration file */
-static void parseOneConfigFile (XML_Parser p) {
-#define BUF_SIZE 0x1000
- struct OptConfData *data = (struct OptConfData *)XML_GetUserData (p);
- int status;
- int fd;
-
- if ((fd = open (data->name, O_RDONLY)) == -1) {
- __driUtilMessage ("Can't open configuration file %s: %s.",
- data->name, strerror (errno));
- return;
- }
-
- while (1) {
- int bytesRead;
- void *buffer = XML_GetBuffer (p, BUF_SIZE);
- if (!buffer) {
- __driUtilMessage ("Can't allocate parser buffer.");
- break;
- }
- bytesRead = read (fd, buffer, BUF_SIZE);
- if (bytesRead == -1) {
- __driUtilMessage ("Error reading from configuration file %s: %s.",
- data->name, strerror (errno));
- break;
- }
- status = XML_ParseBuffer (p, bytesRead, bytesRead == 0);
- if (!status) {
- XML_ERROR ("%s.", XML_ErrorString(XML_GetErrorCode(p)));
- break;
- }
- if (bytesRead == 0)
- break;
- }
-
- close (fd);
-#undef BUF_SIZE
-}
-
-void driParseConfigFiles (driOptionCache *cache, const driOptionCache *info,
- GLint screenNum, const char *driverName) {
- char *filenames[2] = {"/etc/drirc", NULL};
- char *home;
- GLuint i;
- struct OptConfData userData;
-
- initOptionCache (cache, info);
-
- userData.cache = cache;
- userData.screenNum = screenNum;
- userData.driverName = driverName;
- userData.execName = GET_PROGRAM_NAME();
-
- if ((home = getenv ("HOME"))) {
- GLuint len = strlen (home);
- filenames[1] = MALLOC (len + 7+1);
- if (filenames[1] == NULL)
- __driUtilMessage ("Can't allocate memory for %s/.drirc.", home);
- else {
- memcpy (filenames[1], home, len);
- memcpy (filenames[1] + len, "/.drirc", 7+1);
- }
- }
-
- for (i = 0; i < 2; ++i) {
- XML_Parser p;
- if (filenames[i] == NULL)
- continue;
-
- p = XML_ParserCreate (NULL); /* use encoding specified by file */
- XML_SetElementHandler (p, optConfStartElem, optConfEndElem);
- XML_SetUserData (p, &userData);
- userData.parser = p;
- userData.name = filenames[i];
- userData.ignoringDevice = 0;
- userData.ignoringApp = 0;
- userData.inDriConf = 0;
- userData.inDevice = 0;
- userData.inApp = 0;
- userData.inOption = 0;
-
- parseOneConfigFile (p);
- XML_ParserFree (p);
- }
-
- if (filenames[1])
- FREE (filenames[1]);
-}
-
-void driDestroyOptionInfo (driOptionCache *info) {
- driDestroyOptionCache (info);
- if (info->info) {
- GLuint i, size = 1 << info->tableSize;
- for (i = 0; i < size; ++i) {
- if (info->info[i].name) {
- FREE (info->info[i].name);
- if (info->info[i].ranges)
- FREE (info->info[i].ranges);
- }
- }
- FREE (info->info);
- }
-}
-
-void driDestroyOptionCache (driOptionCache *cache) {
- if (cache->values)
- FREE (cache->values);
-}
-
-GLboolean driCheckOption (const driOptionCache *cache, const char *name,
- driOptionType type) {
- GLuint i = findOption (cache, name);
- return cache->info[i].name != NULL && cache->info[i].type == type;
-}
-
-GLboolean driQueryOptionb (const driOptionCache *cache, const char *name) {
- GLuint i = findOption (cache, name);
- /* make sure the option is defined and has the correct type */
- assert (cache->info[i].name != NULL);
- assert (cache->info[i].type == DRI_BOOL);
- return cache->values[i]._bool;
-}
-
-GLint driQueryOptioni (const driOptionCache *cache, const char *name) {
- GLuint i = findOption (cache, name);
- /* make sure the option is defined and has the correct type */
- assert (cache->info[i].name != NULL);
- assert (cache->info[i].type == DRI_INT || cache->info[i].type == DRI_ENUM);
- return cache->values[i]._int;
-}
-
-GLfloat driQueryOptionf (const driOptionCache *cache, const char *name) {
- GLuint i = findOption (cache, name);
- /* make sure the option is defined and has the correct type */
- assert (cache->info[i].name != NULL);
- assert (cache->info[i].type == DRI_FLOAT);
- return cache->values[i]._float;
-}
+/*
+ * XML DRI client-side driver configuration
+ * Copyright (C) 2003 Felix Kuehling
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * FELIX KUEHLING, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+/**
+ * \file xmlconfig.c
+ * \brief Driver-independent client-side part of the XML configuration
+ * \author Felix Kuehling
+ */
+
+#include "main/glheader.h"
+
+#include <string.h>
+#include <assert.h>
+#include <expat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include "main/imports.h"
+#include "utils.h"
+#include "xmlconfig.h"
+
+#undef GET_PROGRAM_NAME
+
+#if (defined(__GNU_LIBRARY__) || defined(__GLIBC__)) && !defined(__UCLIBC__)
+# if !defined(__GLIBC__) || (__GLIBC__ < 2)
+/* These aren't declared in any libc5 header */
+extern char *program_invocation_name, *program_invocation_short_name;
+# endif
+# define GET_PROGRAM_NAME() program_invocation_short_name
+#elif defined(__FreeBSD__) && (__FreeBSD__ >= 2)
+# include <osreldate.h>
+# if (__FreeBSD_version >= 440000)
+# include <stdlib.h>
+# define GET_PROGRAM_NAME() getprogname()
+# endif
+#elif defined(__NetBSD__) && defined(__NetBSD_Version) && (__NetBSD_Version >= 106000100)
+# include <stdlib.h>
+# define GET_PROGRAM_NAME() getprogname()
+#elif defined(__APPLE__)
+# include <stdlib.h>
+# define GET_PROGRAM_NAME() getprogname()
+#elif defined(__sun)
+/* Solaris has getexecname() which returns the full path - return just
+ the basename to match BSD getprogname() */
+# include <stdlib.h>
+# include <libgen.h>
+# define GET_PROGRAM_NAME() basename(getexecname())
+#endif
+
+#if !defined(GET_PROGRAM_NAME)
+# if defined(__OpenBSD__) || defined(NetBSD) || defined(__UCLIBC__)
+/* This is a hack. It's said to work on OpenBSD, NetBSD and GNU.
+ * Rogelio M.Serrano Jr. reported it's also working with UCLIBC. It's
+ * used as a last resort, if there is no documented facility available. */
+static const char *__getProgramName () {
+ extern const char *__progname;
+ char * arg = strrchr(__progname, '/');
+ if (arg)
+ return arg+1;
+ else
+ return __progname;
+}
+# define GET_PROGRAM_NAME() __getProgramName()
+# else
+# define GET_PROGRAM_NAME() ""
+# warning "Per application configuration won't work with your OS version."
+# endif
+#endif
+
+/** \brief Find an option in an option cache with the name as key */
+static GLuint findOption (const driOptionCache *cache, const char *name) {
+ GLuint len = strlen (name);
+ GLuint size = 1 << cache->tableSize, mask = size - 1;
+ GLuint hash = 0;
+ GLuint i, shift;
+
+ /* compute a hash from the variable length name */
+ for (i = 0, shift = 0; i < len; ++i, shift = (shift+8) & 31)
+ hash += (GLuint)name[i] << shift;
+ hash *= hash;
+ hash = (hash >> (16-cache->tableSize/2)) & mask;
+
+ /* this is just the starting point of the linear search for the option */
+ for (i = 0; i < size; ++i, hash = (hash+1) & mask) {
+ /* if we hit an empty entry then the option is not defined (yet) */
+ if (cache->info[hash].name == 0)
+ break;
+ else if (!strcmp (name, cache->info[hash].name))
+ break;
+ }
+ /* this assertion fails if the hash table is full */
+ assert (i < size);
+
+ return hash;
+}
+
+/** \brief Count the real number of options in an option cache */
+static GLuint countOptions (const driOptionCache *cache) {
+ GLuint size = 1 << cache->tableSize;
+ GLuint i, count = 0;
+ for (i = 0; i < size; ++i)
+ if (cache->info[i].name)
+ count++;
+ return count;
+}
+
+/** \brief Like strdup but using MALLOC and with error checking. */
+#define XSTRDUP(dest,source) do { \
+ GLuint len = strlen (source); \
+ if (!(dest = MALLOC (len+1))) { \
+ fprintf (stderr, "%s: %d: out of memory.\n", __FILE__, __LINE__); \
+ abort(); \
+ } \
+ memcpy (dest, source, len+1); \
+} while (0)
+
+static int compare (const void *a, const void *b) {
+ return strcmp (*(char *const*)a, *(char *const*)b);
+}
+/** \brief Binary search in a string array. */
+static GLuint bsearchStr (const XML_Char *name,
+ const XML_Char *elems[], GLuint count) {
+ const XML_Char **found;
+ found = bsearch (&name, elems, count, sizeof (XML_Char *), compare);
+ if (found)
+ return found - elems;
+ else
+ return count;
+}
+
+/** \brief Locale-independent integer parser.
+ *
+ * Works similar to strtol. Leading space is NOT skipped. The input
+ * number may have an optional sign. Radix is specified by base. If
+ * base is 0 then decimal is assumed unless the input number is
+ * prefixed by 0x or 0X for hexadecimal or 0 for octal. After
+ * returning tail points to the first character that is not part of
+ * the integer number. If no number was found then tail points to the
+ * start of the input string. */
+static GLint strToI (const XML_Char *string, const XML_Char **tail, int base) {
+ GLint radix = base == 0 ? 10 : base;
+ GLint result = 0;
+ GLint sign = 1;
+ GLboolean numberFound = GL_FALSE;
+ const XML_Char *start = string;
+
+ assert (radix >= 2 && radix <= 36);
+
+ if (*string == '-') {
+ sign = -1;
+ string++;
+ } else if (*string == '+')
+ string++;
+ if (base == 0 && *string == '0') {
+ numberFound = GL_TRUE;
+ if (*(string+1) == 'x' || *(string+1) == 'X') {
+ radix = 16;
+ string += 2;
+ } else {
+ radix = 8;
+ string++;
+ }
+ }
+ do {
+ GLint digit = -1;
+ if (radix <= 10) {
+ if (*string >= '0' && *string < '0' + radix)
+ digit = *string - '0';
+ } else {
+ if (*string >= '0' && *string <= '9')
+ digit = *string - '0';
+ else if (*string >= 'a' && *string < 'a' + radix - 10)
+ digit = *string - 'a' + 10;
+ else if (*string >= 'A' && *string < 'A' + radix - 10)
+ digit = *string - 'A' + 10;
+ }
+ if (digit != -1) {
+ numberFound = GL_TRUE;
+ result = radix*result + digit;
+ string++;
+ } else
+ break;
+ } while (GL_TRUE);
+ *tail = numberFound ? string : start;
+ return sign * result;
+}
+
+/** \brief Locale-independent floating-point parser.
+ *
+ * Works similar to strtod. Leading space is NOT skipped. The input
+ * number may have an optional sign. '.' is interpreted as decimal
+ * point and may occur at most once. Optionally the number may end in
+ * [eE]<exponent>, where <exponent> is an integer as recognized by
+ * strToI. In that case the result is number * 10^exponent. After
+ * returning tail points to the first character that is not part of
+ * the floating point number. If no number was found then tail points
+ * to the start of the input string.
+ *
+ * Uses two passes for maximum accuracy. */
+static GLfloat strToF (const XML_Char *string, const XML_Char **tail) {
+ GLint nDigits = 0, pointPos, exponent;
+ GLfloat sign = 1.0f, result = 0.0f, scale;
+ const XML_Char *start = string, *numStart;
+
+ /* sign */
+ if (*string == '-') {
+ sign = -1.0f;
+ string++;
+ } else if (*string == '+')
+ string++;
+
+ /* first pass: determine position of decimal point, number of
+ * digits, exponent and the end of the number. */
+ numStart = string;
+ while (*string >= '0' && *string <= '9') {
+ string++;
+ nDigits++;
+ }
+ pointPos = nDigits;
+ if (*string == '.') {
+ string++;
+ while (*string >= '0' && *string <= '9') {
+ string++;
+ nDigits++;
+ }
+ }
+ if (nDigits == 0) {
+ /* no digits, no number */
+ *tail = start;
+ return 0.0f;
+ }
+ *tail = string;
+ if (*string == 'e' || *string == 'E') {
+ const XML_Char *expTail;
+ exponent = strToI (string+1, &expTail, 10);
+ if (expTail == string+1)
+ exponent = 0;
+ else
+ *tail = expTail;
+ } else
+ exponent = 0;
+ string = numStart;
+
+ /* scale of the first digit */
+ scale = sign * (GLfloat)pow (10.0, (GLdouble)(pointPos-1 + exponent));
+
+ /* second pass: parse digits */
+ do {
+ if (*string != '.') {
+ assert (*string >= '0' && *string <= '9');
+ result += scale * (GLfloat)(*string - '0');
+ scale *= 0.1f;
+ nDigits--;
+ }
+ string++;
+ } while (nDigits > 0);
+
+ return result;
+}
+
+/** \brief Parse a value of a given type. */
+static GLboolean parseValue (driOptionValue *v, driOptionType type,
+ const XML_Char *string) {
+ const XML_Char *tail = NULL;
+ /* skip leading white-space */
+ string += strspn (string, " \f\n\r\t\v");
+ switch (type) {
+ case DRI_BOOL:
+ if (!strcmp (string, "false")) {
+ v->_bool = GL_FALSE;
+ tail = string + 5;
+ } else if (!strcmp (string, "true")) {
+ v->_bool = GL_TRUE;
+ tail = string + 4;
+ }
+ else
+ return GL_FALSE;
+ break;
+ case DRI_ENUM: /* enum is just a special integer */
+ case DRI_INT:
+ v->_int = strToI (string, &tail, 0);
+ break;
+ case DRI_FLOAT:
+ v->_float = strToF (string, &tail);
+ break;
+ }
+
+ if (tail == string)
+ return GL_FALSE; /* empty string (or containing only white-space) */
+ /* skip trailing white space */
+ if (*tail)
+ tail += strspn (tail, " \f\n\r\t\v");
+ if (*tail)
+ return GL_FALSE; /* something left over that is not part of value */
+
+ return GL_TRUE;
+}
+
+/** \brief Parse a list of ranges of type info->type. */
+static GLboolean parseRanges (driOptionInfo *info, const XML_Char *string) {
+ XML_Char *cp, *range;
+ GLuint nRanges, i;
+ driOptionRange *ranges;
+
+ XSTRDUP (cp, string);
+ /* pass 1: determine the number of ranges (number of commas + 1) */
+ range = cp;
+ for (nRanges = 1; *range; ++range)
+ if (*range == ',')
+ ++nRanges;
+
+ if ((ranges = MALLOC (nRanges*sizeof(driOptionRange))) == NULL) {
+ fprintf (stderr, "%s: %d: out of memory.\n", __FILE__, __LINE__);
+ abort();
+ }
+
+ /* pass 2: parse all ranges into preallocated array */
+ range = cp;
+ for (i = 0; i < nRanges; ++i) {
+ XML_Char *end, *sep;
+ assert (range);
+ end = strchr (range, ',');
+ if (end)
+ *end = '\0';
+ sep = strchr (range, ':');
+ if (sep) { /* non-empty interval */
+ *sep = '\0';
+ if (!parseValue (&ranges[i].start, info->type, range) ||
+ !parseValue (&ranges[i].end, info->type, sep+1))
+ break;
+ if (info->type == DRI_INT &&
+ ranges[i].start._int > ranges[i].end._int)
+ break;
+ if (info->type == DRI_FLOAT &&
+ ranges[i].start._float > ranges[i].end._float)
+ break;
+ } else { /* empty interval */
+ if (!parseValue (&ranges[i].start, info->type, range))
+ break;
+ ranges[i].end = ranges[i].start;
+ }
+ if (end)
+ range = end+1;
+ else
+ range = NULL;
+ }
+ FREE (cp);
+ if (i < nRanges) {
+ FREE (ranges);
+ return GL_FALSE;
+ } else
+ assert (range == NULL);
+
+ info->nRanges = nRanges;
+ info->ranges = ranges;
+ return GL_TRUE;
+}
+
+/** \brief Check if a value is in one of info->ranges. */
+static GLboolean checkValue (const driOptionValue *v, const driOptionInfo *info) {
+ GLuint i;
+ assert (info->type != DRI_BOOL); /* should be caught by the parser */
+ if (info->nRanges == 0)
+ return GL_TRUE;
+ switch (info->type) {
+ case DRI_ENUM: /* enum is just a special integer */
+ case DRI_INT:
+ for (i = 0; i < info->nRanges; ++i)
+ if (v->_int >= info->ranges[i].start._int &&
+ v->_int <= info->ranges[i].end._int)
+ return GL_TRUE;
+ break;
+ case DRI_FLOAT:
+ for (i = 0; i < info->nRanges; ++i)
+ if (v->_float >= info->ranges[i].start._float &&
+ v->_float <= info->ranges[i].end._float)
+ return GL_TRUE;
+ break;
+ default:
+ assert (0); /* should never happen */
+ }
+ return GL_FALSE;
+}
+
+/** \brief Output a warning message. */
+#define XML_WARNING1(msg) do {\
+ __driUtilMessage ("Warning in %s line %d, column %d: "msg, data->name, \
+ (int) XML_GetCurrentLineNumber(data->parser), \
+ (int) XML_GetCurrentColumnNumber(data->parser)); \
+} while (0)
+#define XML_WARNING(msg,args...) do { \
+ __driUtilMessage ("Warning in %s line %d, column %d: "msg, data->name, \
+ (int) XML_GetCurrentLineNumber(data->parser), \
+ (int) XML_GetCurrentColumnNumber(data->parser), \
+ args); \
+} while (0)
+/** \brief Output an error message. */
+#define XML_ERROR1(msg) do { \
+ __driUtilMessage ("Error in %s line %d, column %d: "msg, data->name, \
+ (int) XML_GetCurrentLineNumber(data->parser), \
+ (int) XML_GetCurrentColumnNumber(data->parser)); \
+} while (0)
+#define XML_ERROR(msg,args...) do { \
+ __driUtilMessage ("Error in %s line %d, column %d: "msg, data->name, \
+ (int) XML_GetCurrentLineNumber(data->parser), \
+ (int) XML_GetCurrentColumnNumber(data->parser), \
+ args); \
+} while (0)
+/** \brief Output a fatal error message and abort. */
+#define XML_FATAL1(msg) do { \
+ fprintf (stderr, "Fatal error in %s line %d, column %d: "msg"\n", \
+ data->name, \
+ (int) XML_GetCurrentLineNumber(data->parser), \
+ (int) XML_GetCurrentColumnNumber(data->parser)); \
+ abort();\
+} while (0)
+#define XML_FATAL(msg,args...) do { \
+ fprintf (stderr, "Fatal error in %s line %d, column %d: "msg"\n", \
+ data->name, \
+ (int) XML_GetCurrentLineNumber(data->parser), \
+ (int) XML_GetCurrentColumnNumber(data->parser), \
+ args); \
+ abort();\
+} while (0)
+
+/** \brief Parser context for __driConfigOptions. */
+struct OptInfoData {
+ const char *name;
+ XML_Parser parser;
+ driOptionCache *cache;
+ GLboolean inDriInfo;
+ GLboolean inSection;
+ GLboolean inDesc;
+ GLboolean inOption;
+ GLboolean inEnum;
+ int curOption;
+};
+
+/** \brief Elements in __driConfigOptions. */
+enum OptInfoElem {
+ OI_DESCRIPTION = 0, OI_DRIINFO, OI_ENUM, OI_OPTION, OI_SECTION, OI_COUNT
+};
+static const XML_Char *OptInfoElems[] = {
+ "description", "driinfo", "enum", "option", "section"
+};
+
+/** \brief Parse attributes of an enum element.
+ *
+ * We're not actually interested in the data. Just make sure this is ok
+ * for external configuration tools.
+ */
+static void parseEnumAttr (struct OptInfoData *data, const XML_Char **attr) {
+ GLuint i;
+ const XML_Char *value = NULL, *text = NULL;
+ driOptionValue v;
+ GLuint opt = data->curOption;
+ for (i = 0; attr[i]; i += 2) {
+ if (!strcmp (attr[i], "value")) value = attr[i+1];
+ else if (!strcmp (attr[i], "text")) text = attr[i+1];
+ else XML_FATAL("illegal enum attribute: %s.", attr[i]);
+ }
+ if (!value) XML_FATAL1 ("value attribute missing in enum.");
+ if (!text) XML_FATAL1 ("text attribute missing in enum.");
+ if (!parseValue (&v, data->cache->info[opt].type, value))
+ XML_FATAL ("illegal enum value: %s.", value);
+ if (!checkValue (&v, &data->cache->info[opt]))
+ XML_FATAL ("enum value out of valid range: %s.", value);
+}
+
+/** \brief Parse attributes of a description element.
+ *
+ * We're not actually interested in the data. Just make sure this is ok
+ * for external configuration tools.
+ */
+static void parseDescAttr (struct OptInfoData *data, const XML_Char **attr) {
+ GLuint i;
+ const XML_Char *lang = NULL, *text = NULL;
+ for (i = 0; attr[i]; i += 2) {
+ if (!strcmp (attr[i], "lang")) lang = attr[i+1];
+ else if (!strcmp (attr[i], "text")) text = attr[i+1];
+ else XML_FATAL("illegal description attribute: %s.", attr[i]);
+ }
+ if (!lang) XML_FATAL1 ("lang attribute missing in description.");
+ if (!text) XML_FATAL1 ("text attribute missing in description.");
+}
+
+/** \brief Parse attributes of an option element. */
+static void parseOptInfoAttr (struct OptInfoData *data, const XML_Char **attr) {
+ enum OptAttr {OA_DEFAULT = 0, OA_NAME, OA_TYPE, OA_VALID, OA_COUNT};
+ static const XML_Char *optAttr[] = {"default", "name", "type", "valid"};
+ const XML_Char *attrVal[OA_COUNT] = {NULL, NULL, NULL, NULL};
+ const char *defaultVal;
+ driOptionCache *cache = data->cache;
+ GLuint opt, i;
+ for (i = 0; attr[i]; i += 2) {
+ GLuint attrName = bsearchStr (attr[i], optAttr, OA_COUNT);
+ if (attrName >= OA_COUNT)
+ XML_FATAL ("illegal option attribute: %s", attr[i]);
+ attrVal[attrName] = attr[i+1];
+ }
+ if (!attrVal[OA_NAME]) XML_FATAL1 ("name attribute missing in option.");
+ if (!attrVal[OA_TYPE]) XML_FATAL1 ("type attribute missing in option.");
+ if (!attrVal[OA_DEFAULT]) XML_FATAL1 ("default attribute missing in option.");
+
+ opt = findOption (cache, attrVal[OA_NAME]);
+ if (cache->info[opt].name)
+ XML_FATAL ("option %s redefined.", attrVal[OA_NAME]);
+ data->curOption = opt;
+
+ XSTRDUP (cache->info[opt].name, attrVal[OA_NAME]);
+
+ if (!strcmp (attrVal[OA_TYPE], "bool"))
+ cache->info[opt].type = DRI_BOOL;
+ else if (!strcmp (attrVal[OA_TYPE], "enum"))
+ cache->info[opt].type = DRI_ENUM;
+ else if (!strcmp (attrVal[OA_TYPE], "int"))
+ cache->info[opt].type = DRI_INT;
+ else if (!strcmp (attrVal[OA_TYPE], "float"))
+ cache->info[opt].type = DRI_FLOAT;
+ else
+ XML_FATAL ("illegal type in option: %s.", attrVal[OA_TYPE]);
+
+ defaultVal = getenv (cache->info[opt].name);
+ if (defaultVal != NULL) {
+ /* don't use XML_WARNING, we want the user to see this! */
+ fprintf (stderr,
+ "ATTENTION: default value of option %s overridden by environment.\n",
+ cache->info[opt].name);
+ } else
+ defaultVal = attrVal[OA_DEFAULT];
+ if (!parseValue (&cache->values[opt], cache->info[opt].type, defaultVal))
+ XML_FATAL ("illegal default value: %s.", defaultVal);
+
+ if (attrVal[OA_VALID]) {
+ if (cache->info[opt].type == DRI_BOOL)
+ XML_FATAL1 ("boolean option with valid attribute.");
+ if (!parseRanges (&cache->info[opt], attrVal[OA_VALID]))
+ XML_FATAL ("illegal valid attribute: %s.", attrVal[OA_VALID]);
+ if (!checkValue (&cache->values[opt], &cache->info[opt]))
+ XML_FATAL ("default value out of valid range '%s': %s.",
+ attrVal[OA_VALID], defaultVal);
+ } else if (cache->info[opt].type == DRI_ENUM) {
+ XML_FATAL1 ("valid attribute missing in option (mandatory for enums).");
+ } else {
+ cache->info[opt].nRanges = 0;
+ cache->info[opt].ranges = NULL;
+ }
+}
+
+/** \brief Handler for start element events. */
+static void optInfoStartElem (void *userData, const XML_Char *name,
+ const XML_Char **attr) {
+ struct OptInfoData *data = (struct OptInfoData *)userData;
+ enum OptInfoElem elem = bsearchStr (name, OptInfoElems, OI_COUNT);
+ switch (elem) {
+ case OI_DRIINFO:
+ if (data->inDriInfo)
+ XML_FATAL1 ("nested <driinfo> elements.");
+ if (attr[0])
+ XML_FATAL1 ("attributes specified on <driinfo> element.");
+ data->inDriInfo = GL_TRUE;
+ break;
+ case OI_SECTION:
+ if (!data->inDriInfo)
+ XML_FATAL1 ("<section> must be inside <driinfo>.");
+ if (data->inSection)
+ XML_FATAL1 ("nested <section> elements.");
+ if (attr[0])
+ XML_FATAL1 ("attributes specified on <section> element.");
+ data->inSection = GL_TRUE;
+ break;
+ case OI_DESCRIPTION:
+ if (!data->inSection && !data->inOption)
+ XML_FATAL1 ("<description> must be inside <description> or <option.");
+ if (data->inDesc)
+ XML_FATAL1 ("nested <description> elements.");
+ data->inDesc = GL_TRUE;
+ parseDescAttr (data, attr);
+ break;
+ case OI_OPTION:
+ if (!data->inSection)
+ XML_FATAL1 ("<option> must be inside <section>.");
+ if (data->inDesc)
+ XML_FATAL1 ("<option> nested in <description> element.");
+ if (data->inOption)
+ XML_FATAL1 ("nested <option> elements.");
+ data->inOption = GL_TRUE;
+ parseOptInfoAttr (data, attr);
+ break;
+ case OI_ENUM:
+ if (!(data->inOption && data->inDesc))
+ XML_FATAL1 ("<enum> must be inside <option> and <description>.");
+ if (data->inEnum)
+ XML_FATAL1 ("nested <enum> elements.");
+ data->inEnum = GL_TRUE;
+ parseEnumAttr (data, attr);
+ break;
+ default:
+ XML_FATAL ("unknown element: %s.", name);
+ }
+}
+
+/** \brief Handler for end element events. */
+static void optInfoEndElem (void *userData, const XML_Char *name) {
+ struct OptInfoData *data = (struct OptInfoData *)userData;
+ enum OptInfoElem elem = bsearchStr (name, OptInfoElems, OI_COUNT);
+ switch (elem) {
+ case OI_DRIINFO:
+ data->inDriInfo = GL_FALSE;
+ break;
+ case OI_SECTION:
+ data->inSection = GL_FALSE;
+ break;
+ case OI_DESCRIPTION:
+ data->inDesc = GL_FALSE;
+ break;
+ case OI_OPTION:
+ data->inOption = GL_FALSE;
+ break;
+ case OI_ENUM:
+ data->inEnum = GL_FALSE;
+ break;
+ default:
+ assert (0); /* should have been caught by StartElem */
+ }
+}
+
+void driParseOptionInfo (driOptionCache *info,
+ const char *configOptions, GLuint nConfigOptions) {
+ XML_Parser p;
+ int status;
+ struct OptInfoData userData;
+ struct OptInfoData *data = &userData;
+ GLuint realNoptions;
+
+ /* determine hash table size and allocate memory:
+ * 3/2 of the number of options, rounded up, so there remains always
+ * at least one free entry. This is needed for detecting undefined
+ * options in configuration files without getting a hash table overflow.
+ * Round this up to a power of two. */
+ GLuint minSize = (nConfigOptions*3 + 1) / 2;
+ GLuint size, log2size;
+ for (size = 1, log2size = 0; size < minSize; size <<= 1, ++log2size);
+ info->tableSize = log2size;
+ info->info = CALLOC (size * sizeof (driOptionInfo));
+ info->values = CALLOC (size * sizeof (driOptionValue));
+ if (info->info == NULL || info->values == NULL) {
+ fprintf (stderr, "%s: %d: out of memory.\n", __FILE__, __LINE__);
+ abort();
+ }
+
+ p = XML_ParserCreate ("UTF-8"); /* always UTF-8 */
+ XML_SetElementHandler (p, optInfoStartElem, optInfoEndElem);
+ XML_SetUserData (p, data);
+
+ userData.name = "__driConfigOptions";
+ userData.parser = p;
+ userData.cache = info;
+ userData.inDriInfo = GL_FALSE;
+ userData.inSection = GL_FALSE;
+ userData.inDesc = GL_FALSE;
+ userData.inOption = GL_FALSE;
+ userData.inEnum = GL_FALSE;
+ userData.curOption = -1;
+
+ status = XML_Parse (p, configOptions, strlen (configOptions), 1);
+ if (!status)
+ XML_FATAL ("%s.", XML_ErrorString(XML_GetErrorCode(p)));
+
+ XML_ParserFree (p);
+
+ /* Check if the actual number of options matches nConfigOptions.
+ * A mismatch is not fatal (a hash table overflow would be) but we
+ * want the driver developer's attention anyway. */
+ realNoptions = countOptions (info);
+ if (realNoptions != nConfigOptions) {
+ fprintf (stderr,
+ "Error: nConfigOptions (%u) does not match the actual number of options in\n"
+ " __driConfigOptions (%u).\n",
+ nConfigOptions, realNoptions);
+ }
+}
+
+/** \brief Parser context for configuration files. */
+struct OptConfData {
+ const char *name;
+ XML_Parser parser;
+ driOptionCache *cache;
+ GLint screenNum;
+ const char *driverName, *execName;
+ GLuint ignoringDevice;
+ GLuint ignoringApp;
+ GLuint inDriConf;
+ GLuint inDevice;
+ GLuint inApp;
+ GLuint inOption;
+};
+
+/** \brief Elements in configuration files. */
+enum OptConfElem {
+ OC_APPLICATION = 0, OC_DEVICE, OC_DRICONF, OC_OPTION, OC_COUNT
+};
+static const XML_Char *OptConfElems[] = {
+ "application", "device", "driconf", "option"
+};
+
+/** \brief Parse attributes of a device element. */
+static void parseDeviceAttr (struct OptConfData *data, const XML_Char **attr) {
+ GLuint i;
+ const XML_Char *driver = NULL, *screen = NULL;
+ for (i = 0; attr[i]; i += 2) {
+ if (!strcmp (attr[i], "driver")) driver = attr[i+1];
+ else if (!strcmp (attr[i], "screen")) screen = attr[i+1];
+ else XML_WARNING("unknown device attribute: %s.", attr[i]);
+ }
+ if (driver && strcmp (driver, data->driverName))
+ data->ignoringDevice = data->inDevice;
+ else if (screen) {
+ driOptionValue screenNum;
+ if (!parseValue (&screenNum, DRI_INT, screen))
+ XML_WARNING("illegal screen number: %s.", screen);
+ else if (screenNum._int != data->screenNum)
+ data->ignoringDevice = data->inDevice;
+ }
+}
+
+/** \brief Parse attributes of an application element. */
+static void parseAppAttr (struct OptConfData *data, const XML_Char **attr) {
+ GLuint i;
+ const XML_Char *name = NULL, *exec = NULL;
+ for (i = 0; attr[i]; i += 2) {
+ if (!strcmp (attr[i], "name")) name = attr[i+1];
+ else if (!strcmp (attr[i], "executable")) exec = attr[i+1];
+ else XML_WARNING("unknown application attribute: %s.", attr[i]);
+ }
+ if (exec && strcmp (exec, data->execName))
+ data->ignoringApp = data->inApp;
+}
+
+/** \brief Parse attributes of an option element. */
+static void parseOptConfAttr (struct OptConfData *data, const XML_Char **attr) {
+ GLuint i;
+ const XML_Char *name = NULL, *value = NULL;
+ for (i = 0; attr[i]; i += 2) {
+ if (!strcmp (attr[i], "name")) name = attr[i+1];
+ else if (!strcmp (attr[i], "value")) value = attr[i+1];
+ else XML_WARNING("unknown option attribute: %s.", attr[i]);
+ }
+ if (!name) XML_WARNING1 ("name attribute missing in option.");
+ if (!value) XML_WARNING1 ("value attribute missing in option.");
+ if (name && value) {
+ driOptionCache *cache = data->cache;
+ GLuint opt = findOption (cache, name);
+ if (cache->info[opt].name == NULL)
+ XML_WARNING ("undefined option: %s.", name);
+ else if (getenv (cache->info[opt].name))
+ /* don't use XML_WARNING, we want the user to see this! */
+ fprintf (stderr, "ATTENTION: option value of option %s ignored.\n",
+ cache->info[opt].name);
+ else if (!parseValue (&cache->values[opt], cache->info[opt].type, value))
+ XML_WARNING ("illegal option value: %s.", value);
+ }
+}
+
+/** \brief Handler for start element events. */
+static void optConfStartElem (void *userData, const XML_Char *name,
+ const XML_Char **attr) {
+ struct OptConfData *data = (struct OptConfData *)userData;
+ enum OptConfElem elem = bsearchStr (name, OptConfElems, OC_COUNT);
+ switch (elem) {
+ case OC_DRICONF:
+ if (data->inDriConf)
+ XML_WARNING1 ("nested <driconf> elements.");
+ if (attr[0])
+ XML_WARNING1 ("attributes specified on <driconf> element.");
+ data->inDriConf++;
+ break;
+ case OC_DEVICE:
+ if (!data->inDriConf)
+ XML_WARNING1 ("<device> should be inside <driconf>.");
+ if (data->inDevice)
+ XML_WARNING1 ("nested <device> elements.");
+ data->inDevice++;
+ if (!data->ignoringDevice && !data->ignoringApp)
+ parseDeviceAttr (data, attr);
+ break;
+ case OC_APPLICATION:
+ if (!data->inDevice)
+ XML_WARNING1 ("<application> should be inside <device>.");
+ if (data->inApp)
+ XML_WARNING1 ("nested <application> elements.");
+ data->inApp++;
+ if (!data->ignoringDevice && !data->ignoringApp)
+ parseAppAttr (data, attr);
+ break;
+ case OC_OPTION:
+ if (!data->inApp)
+ XML_WARNING1 ("<option> should be inside <application>.");
+ if (data->inOption)
+ XML_WARNING1 ("nested <option> elements.");
+ data->inOption++;
+ if (!data->ignoringDevice && !data->ignoringApp)
+ parseOptConfAttr (data, attr);
+ break;
+ default:
+ XML_WARNING ("unknown element: %s.", name);
+ }
+}
+
+/** \brief Handler for end element events. */
+static void optConfEndElem (void *userData, const XML_Char *name) {
+ struct OptConfData *data = (struct OptConfData *)userData;
+ enum OptConfElem elem = bsearchStr (name, OptConfElems, OC_COUNT);
+ switch (elem) {
+ case OC_DRICONF:
+ data->inDriConf--;
+ break;
+ case OC_DEVICE:
+ if (data->inDevice-- == data->ignoringDevice)
+ data->ignoringDevice = 0;
+ break;
+ case OC_APPLICATION:
+ if (data->inApp-- == data->ignoringApp)
+ data->ignoringApp = 0;
+ break;
+ case OC_OPTION:
+ data->inOption--;
+ break;
+ default:
+ /* unknown element, warning was produced on start tag */;
+ }
+}
+
+/** \brief Initialize an option cache based on info */
+static void initOptionCache (driOptionCache *cache, const driOptionCache *info) {
+ cache->info = info->info;
+ cache->tableSize = info->tableSize;
+ cache->values = MALLOC ((1<<info->tableSize) * sizeof (driOptionValue));
+ if (cache->values == NULL) {
+ fprintf (stderr, "%s: %d: out of memory.\n", __FILE__, __LINE__);
+ abort();
+ }
+ memcpy (cache->values, info->values,
+ (1<<info->tableSize) * sizeof (driOptionValue));
+}
+
+/** \brief Parse the named configuration file */
+static void parseOneConfigFile (XML_Parser p) {
+#define BUF_SIZE 0x1000
+ struct OptConfData *data = (struct OptConfData *)XML_GetUserData (p);
+ int status;
+ int fd;
+
+ if ((fd = open (data->name, O_RDONLY)) == -1) {
+ __driUtilMessage ("Can't open configuration file %s: %s.",
+ data->name, strerror (errno));
+ return;
+ }
+
+ while (1) {
+ int bytesRead;
+ void *buffer = XML_GetBuffer (p, BUF_SIZE);
+ if (!buffer) {
+ __driUtilMessage ("Can't allocate parser buffer.");
+ break;
+ }
+ bytesRead = read (fd, buffer, BUF_SIZE);
+ if (bytesRead == -1) {
+ __driUtilMessage ("Error reading from configuration file %s: %s.",
+ data->name, strerror (errno));
+ break;
+ }
+ status = XML_ParseBuffer (p, bytesRead, bytesRead == 0);
+ if (!status) {
+ XML_ERROR ("%s.", XML_ErrorString(XML_GetErrorCode(p)));
+ break;
+ }
+ if (bytesRead == 0)
+ break;
+ }
+
+ close (fd);
+#undef BUF_SIZE
+}
+
+void driParseConfigFiles (driOptionCache *cache, const driOptionCache *info,
+ GLint screenNum, const char *driverName) {
+ char *filenames[2] = {"/etc/drirc", NULL};
+ char *home;
+ GLuint i;
+ struct OptConfData userData;
+
+ initOptionCache (cache, info);
+
+ userData.cache = cache;
+ userData.screenNum = screenNum;
+ userData.driverName = driverName;
+ userData.execName = GET_PROGRAM_NAME();
+
+ if ((home = getenv ("HOME"))) {
+ GLuint len = strlen (home);
+ filenames[1] = MALLOC (len + 7+1);
+ if (filenames[1] == NULL)
+ __driUtilMessage ("Can't allocate memory for %s/.drirc.", home);
+ else {
+ memcpy (filenames[1], home, len);
+ memcpy (filenames[1] + len, "/.drirc", 7+1);
+ }
+ }
+
+ for (i = 0; i < 2; ++i) {
+ XML_Parser p;
+ if (filenames[i] == NULL)
+ continue;
+
+ p = XML_ParserCreate (NULL); /* use encoding specified by file */
+ XML_SetElementHandler (p, optConfStartElem, optConfEndElem);
+ XML_SetUserData (p, &userData);
+ userData.parser = p;
+ userData.name = filenames[i];
+ userData.ignoringDevice = 0;
+ userData.ignoringApp = 0;
+ userData.inDriConf = 0;
+ userData.inDevice = 0;
+ userData.inApp = 0;
+ userData.inOption = 0;
+
+ parseOneConfigFile (p);
+ XML_ParserFree (p);
+ }
+
+ if (filenames[1])
+ FREE (filenames[1]);
+}
+
+void driDestroyOptionInfo (driOptionCache *info) {
+ driDestroyOptionCache (info);
+ if (info->info) {
+ GLuint i, size = 1 << info->tableSize;
+ for (i = 0; i < size; ++i) {
+ if (info->info[i].name) {
+ FREE (info->info[i].name);
+ if (info->info[i].ranges)
+ FREE (info->info[i].ranges);
+ }
+ }
+ FREE (info->info);
+ }
+}
+
+void driDestroyOptionCache (driOptionCache *cache) {
+ if (cache->values)
+ FREE (cache->values);
+}
+
+GLboolean driCheckOption (const driOptionCache *cache, const char *name,
+ driOptionType type) {
+ GLuint i = findOption (cache, name);
+ return cache->info[i].name != NULL && cache->info[i].type == type;
+}
+
+GLboolean driQueryOptionb (const driOptionCache *cache, const char *name) {
+ GLuint i = findOption (cache, name);
+ /* make sure the option is defined and has the correct type */
+ assert (cache->info[i].name != NULL);
+ assert (cache->info[i].type == DRI_BOOL);
+ return cache->values[i]._bool;
+}
+
+GLint driQueryOptioni (const driOptionCache *cache, const char *name) {
+ GLuint i = findOption (cache, name);
+ /* make sure the option is defined and has the correct type */
+ assert (cache->info[i].name != NULL);
+ assert (cache->info[i].type == DRI_INT || cache->info[i].type == DRI_ENUM);
+ return cache->values[i]._int;
+}
+
+GLfloat driQueryOptionf (const driOptionCache *cache, const char *name) {
+ GLuint i = findOption (cache, name);
+ /* make sure the option is defined and has the correct type */
+ assert (cache->info[i].name != NULL);
+ assert (cache->info[i].type == DRI_FLOAT);
+ return cache->values[i]._float;
+}
diff --git a/mesalib/src/mesa/drivers/dri/common/xmlpool/Makefile b/mesalib/src/mesa/drivers/dri/common/xmlpool/Makefile
index 62ec919ea..ae3d89938 100644
--- a/mesalib/src/mesa/drivers/dri/common/xmlpool/Makefile
+++ b/mesalib/src/mesa/drivers/dri/common/xmlpool/Makefile
@@ -1,96 +1,96 @@
-# Convenient makefile for managing translations.
-
-# Prerequisites:
-# - GNU gettext
-# - Python
-
-# Adding new translations
-# -----------------------
-
-# To start working on a new translation edit the POS=... line
-# below. If you want to add for example a french translation, add
-# fr.po.
-
-# Then run "make po" to generate a fresh .po file from translatable
-# strings in t_options.h. Now you can edit the new .po file (fr.po in
-# the example above) to translate the strings. Please make sure that
-# your editor encodes the file in UTF-8.
-
-# Updating existing translations
-# ------------------------------
-
-# Run "make po" to update .po files with new translatable strings from
-# t_options.h. Now you can edit the .po files you're interested
-# in. Please make sure that your editor encodes the file in UTF-8.
-
-# Updating options.h
-# ------------------
-
-# Finally run "make" to generate options.h from t_options.h with all
-# translations. Now you can rebuild the drivers. Any common options
-# used by the drivers will have option descriptions with the latest
-# translations.
-
-# Publishing translations
-# -----------------------
-
-# To get your translation(s) into Mesa CVS, please send me your
-# <lang>.po file.
-
-# More information:
-# - info gettext
-
-# The set of supported languages. Add languages as needed.
-POS=de.po es.po nl.po fr.po sv.po
-
-#
-# Don't change anything below, unless you know what you're doing.
-#
-LANGS=$(POS:%.po=%)
-MOS=$(POS:%.po=%/LC_MESSAGES/options.mo)
-POT=xmlpool.pot
-
-.PHONY: all clean pot po mo
-
-all: options.h
-
-# Only intermediate files are cleaned up. options.h is not deleted because
-# it's in CVS.
-clean:
- -rm -f $(POT) *~
- -rm -rf $(LANGS)
-
-# Default target options.h
-options.h: t_options.h mo
- python gen_xmlpool.py $(LANGS) > options.h
-
-# Update .mo files from the corresponding .po files.
-mo:
- @for mo in $(MOS); do \
- lang=$${mo%%/*}; \
- echo "Updating $$mo from $$lang.po."; \
- mkdir -p $${mo%/*}; \
- msgfmt -o $$mo $$lang.po; \
- done
-
-# Use this target to create or update .po files with new messages in
-# driconf.py.
-po: $(POS)
-
-pot: $(POT)
-
-# Extract message catalog from driconf.py.
-$(POT): t_options.h
- xgettext -L C --from-code utf-8 -o $(POT) t_options.h
-
-# Create or update a .po file for a specific language.
-%.po: $(POT)
- @if [ -f $@ ]; then \
- echo "Merging new strings from $(POT) into $@."; \
- mv $@ $@~; \
- msgmerge -o $@ $@~ $(POT); \
- else \
- echo "Initializing $@ from $(POT)."; \
- msginit -i $(POT) -o $@~ --locale=$*; \
- sed -e 's/charset=.*\\n/charset=UTF-8\\n/' $@~ > $@; \
- fi
+# Convenient makefile for managing translations.
+
+# Prerequisites:
+# - GNU gettext
+# - Python
+
+# Adding new translations
+# -----------------------
+
+# To start working on a new translation edit the POS=... line
+# below. If you want to add for example a french translation, add
+# fr.po.
+
+# Then run "make po" to generate a fresh .po file from translatable
+# strings in t_options.h. Now you can edit the new .po file (fr.po in
+# the example above) to translate the strings. Please make sure that
+# your editor encodes the file in UTF-8.
+
+# Updating existing translations
+# ------------------------------
+
+# Run "make po" to update .po files with new translatable strings from
+# t_options.h. Now you can edit the .po files you're interested
+# in. Please make sure that your editor encodes the file in UTF-8.
+
+# Updating options.h
+# ------------------
+
+# Finally run "make" to generate options.h from t_options.h with all
+# translations. Now you can rebuild the drivers. Any common options
+# used by the drivers will have option descriptions with the latest
+# translations.
+
+# Publishing translations
+# -----------------------
+
+# To get your translation(s) into Mesa CVS, please send me your
+# <lang>.po file.
+
+# More information:
+# - info gettext
+
+# The set of supported languages. Add languages as needed.
+POS=de.po es.po nl.po fr.po sv.po
+
+#
+# Don't change anything below, unless you know what you're doing.
+#
+LANGS=$(POS:%.po=%)
+MOS=$(POS:%.po=%/LC_MESSAGES/options.mo)
+POT=xmlpool.pot
+
+.PHONY: all clean pot po mo
+
+all: options.h
+
+# Only intermediate files are cleaned up. options.h is not deleted because
+# it's in CVS.
+clean:
+ -rm -f $(POT) *~
+ -rm -rf $(LANGS)
+
+# Default target options.h
+options.h: t_options.h mo
+ $(PYTHON2) $(PYTHON_FLAGS) gen_xmlpool.py $(LANGS) > options.h
+
+# Update .mo files from the corresponding .po files.
+mo:
+ @for mo in $(MOS); do \
+ lang=$${mo%%/*}; \
+ echo "Updating $$mo from $$lang.po."; \
+ mkdir -p $${mo%/*}; \
+ msgfmt -o $$mo $$lang.po; \
+ done
+
+# Use this target to create or update .po files with new messages in
+# driconf.py.
+po: $(POS)
+
+pot: $(POT)
+
+# Extract message catalog from driconf.py.
+$(POT): t_options.h
+ xgettext -L C --from-code utf-8 -o $(POT) t_options.h
+
+# Create or update a .po file for a specific language.
+%.po: $(POT)
+ @if [ -f $@ ]; then \
+ echo "Merging new strings from $(POT) into $@."; \
+ mv $@ $@~; \
+ msgmerge -o $@ $@~ $(POT); \
+ else \
+ echo "Initializing $@ from $(POT)."; \
+ msginit -i $(POT) -o $@~ --locale=$*; \
+ sed -e 's/charset=.*\\n/charset=UTF-8\\n/' $@~ > $@; \
+ fi
diff --git a/mesalib/src/mesa/drivers/dri/common/xmlpool/gen_xmlpool.py b/mesalib/src/mesa/drivers/dri/common/xmlpool/gen_xmlpool.py
new file mode 100644
index 000000000..f5ac5e25b
--- /dev/null
+++ b/mesalib/src/mesa/drivers/dri/common/xmlpool/gen_xmlpool.py
@@ -0,0 +1,191 @@
+#!/usr/bin/python
+
+import sys
+import gettext
+import re
+
+# List of supported languages
+languages = sys.argv[1:]
+
+# Escape special characters in C strings
+def escapeCString (s):
+ escapeSeqs = {'\a' : '\\a', '\b' : '\\b', '\f' : '\\f', '\n' : '\\n',
+ '\r' : '\\r', '\t' : '\\t', '\v' : '\\v', '\\' : '\\\\'}
+ # " -> '' is a hack. Quotes (") aren't possible in XML attributes.
+ # Better use Unicode characters for typographic quotes in option
+ # descriptions and translations.
+ i = 0
+ r = ''
+ while i < len(s):
+ # Special case: escape double quote with \u201c or \u201d, depending
+ # on whether it's an open or close quote. This is needed because plain
+ # double quotes are not possible in XML attributes.
+ if s[i] == '"':
+ if i == len(s)-1 or s[i+1].isspace():
+ # close quote
+ q = u'\u201c'
+ else:
+ # open quote
+ q = u'\u201d'
+ r = r + q
+ elif escapeSeqs.has_key(s[i]):
+ r = r + escapeSeqs[s[i]]
+ else:
+ r = r + s[i]
+ i = i + 1
+ return r
+
+# Expand escape sequences in C strings (needed for gettext lookup)
+def expandCString (s):
+ escapeSeqs = {'a' : '\a', 'b' : '\b', 'f' : '\f', 'n' : '\n',
+ 'r' : '\r', 't' : '\t', 'v' : '\v',
+ '"' : '"', '\\' : '\\'}
+ i = 0
+ escape = False
+ hexa = False
+ octa = False
+ num = 0
+ digits = 0
+ r = ''
+ while i < len(s):
+ if not escape:
+ if s[i] == '\\':
+ escape = True
+ else:
+ r = r + s[i]
+ elif hexa:
+ if (s[i] >= '0' and s[i] <= '9') or \
+ (s[i] >= 'a' and s[i] <= 'f') or \
+ (s[i] >= 'A' and s[i] <= 'F'):
+ num = num * 16 + int(s[i],16)
+ digits = digits + 1
+ else:
+ digits = 2
+ if digits >= 2:
+ hexa = False
+ escape = False
+ r = r + chr(num)
+ elif octa:
+ if s[i] >= '0' and s[i] <= '7':
+ num = num * 8 + int(s[i],8)
+ digits = digits + 1
+ else:
+ digits = 3
+ if digits >= 3:
+ octa = False
+ escape = False
+ r = r + chr(num)
+ else:
+ if escapeSeqs.has_key(s[i]):
+ r = r + escapeSeqs[s[i]]
+ escape = False
+ elif s[i] >= '0' and s[i] <= '7':
+ octa = True
+ num = int(s[i],8)
+ if num <= 3:
+ digits = 1
+ else:
+ digits = 2
+ elif s[i] == 'x' or s[i] == 'X':
+ hexa = True
+ num = 0
+ digits = 0
+ else:
+ r = r + s[i]
+ escape = False
+ i = i + 1
+ return r
+
+# Expand matches. The first match is always a DESC or DESC_BEGIN match.
+# Subsequent matches are ENUM matches.
+#
+# DESC, DESC_BEGIN format: \1 \2=<lang> \3 \4=gettext(" \5=<text> \6=") \7
+# ENUM format: \1 \2=gettext(" \3=<text> \4=") \5
+def expandMatches (matches, translations, end=None):
+ assert len(matches) > 0
+ nTranslations = len(translations)
+ i = 0
+ # Expand the description+enums for all translations
+ for lang,trans in translations:
+ i = i + 1
+ # Make sure that all but the last line of a simple description
+ # are extended with a backslash.
+ suffix = ''
+ if len(matches) == 1 and i < len(translations) and \
+ not matches[0].expand (r'\7').endswith('\\'):
+ suffix = ' \\'
+ # Expand the description line. Need to use ugettext in order to allow
+ # non-ascii unicode chars in the original English descriptions.
+ text = escapeCString (trans.ugettext (unicode (expandCString (
+ matches[0].expand (r'\5')), "utf-8"))).encode("utf-8")
+ print matches[0].expand (r'\1' + lang + r'\3"' + text + r'"\7') + suffix
+ # Expand any subsequent enum lines
+ for match in matches[1:]:
+ text = escapeCString (trans.ugettext (unicode (expandCString (
+ match.expand (r'\3')), "utf-8"))).encode("utf-8")
+ print match.expand (r'\1"' + text + r'"\5')
+
+ # Expand description end
+ if end:
+ print end,
+
+# Compile a list of translation classes to all supported languages.
+# The first translation is always a NullTranslations.
+translations = [("en", gettext.NullTranslations())]
+for lang in languages:
+ try:
+ trans = gettext.translation ("options", ".", [lang])
+ except IOError:
+ sys.stderr.write ("Warning: language '%s' not found.\n" % lang)
+ continue
+ translations.append ((lang, trans))
+
+# Regular expressions:
+reLibintl_h = re.compile (r'#\s*include\s*<libintl.h>')
+reDESC = re.compile (r'(\s*DRI_CONF_DESC\s*\(\s*)([a-z]+)(\s*,\s*)(gettext\s*\(\s*")(.*)("\s*\))(\s*\)[ \t]*\\?)$')
+reDESC_BEGIN = re.compile (r'(\s*DRI_CONF_DESC_BEGIN\s*\(\s*)([a-z]+)(\s*,\s*)(gettext\s*\(\s*")(.*)("\s*\))(\s*\)[ \t]*\\?)$')
+reENUM = re.compile (r'(\s*DRI_CONF_ENUM\s*\([^,]+,\s*)(gettext\s*\(\s*")(.*)("\s*\))(\s*\)[ \t]*\\?)$')
+reDESC_END = re.compile (r'\s*DRI_CONF_DESC_END')
+
+# Print a header
+print \
+"/***********************************************************************\n" \
+" *** THIS FILE IS GENERATED AUTOMATICALLY. DON'T EDIT! ***\n" \
+" ***********************************************************************/"
+
+# Process the options template and generate options.h with all
+# translations.
+template = file ("t_options.h", "r")
+descMatches = []
+for line in template:
+ if len(descMatches) > 0:
+ matchENUM = reENUM .match (line)
+ matchDESC_END = reDESC_END.match (line)
+ if matchENUM:
+ descMatches.append (matchENUM)
+ elif matchDESC_END:
+ expandMatches (descMatches, translations, line)
+ descMatches = []
+ else:
+ sys.stderr.write (
+ "Warning: unexpected line inside description dropped:\n%s\n" \
+ % line)
+ continue
+ if reLibintl_h.search (line):
+ # Ignore (comment out) #include <libintl.h>
+ print "/* %s * commented out by gen_xmlpool.py */" % line
+ continue
+ matchDESC = reDESC .match (line)
+ matchDESC_BEGIN = reDESC_BEGIN.match (line)
+ if matchDESC:
+ assert len(descMatches) == 0
+ expandMatches ([matchDESC], translations)
+ elif matchDESC_BEGIN:
+ assert len(descMatches) == 0
+ descMatches = [matchDESC_BEGIN]
+ else:
+ print line,
+
+if len(descMatches) > 0:
+ sys.stderr.write ("Warning: unterminated description at end of file.\n")
+ expandMatches (descMatches, translations)
diff --git a/mesalib/src/mesa/drivers/dri/swrast/swrast.c b/mesalib/src/mesa/drivers/dri/swrast/swrast.c
index ff53ffd0d..3ac32b1b4 100644
--- a/mesalib/src/mesa/drivers/dri/swrast/swrast.c
+++ b/mesalib/src/mesa/drivers/dri/swrast/swrast.c
@@ -1,741 +1,739 @@
-/*
- * Copyright 2008, 2010 George Sapountzis <gsapountzis@gmail.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/*
- * DRI software rasterizer
- *
- * This is the mesa swrast module packaged into a DRI driver structure.
- *
- * The front-buffer is allocated by the loader. The loader provides read/write
- * callbacks for access to the front-buffer. The driver uses a scratch row for
- * front-buffer rendering to avoid repeated calls to the loader.
- *
- * The back-buffer is allocated by the driver and is private.
- */
-
-#include "main/context.h"
-#include "main/extensions.h"
-#include "main/formats.h"
-#include "main/framebuffer.h"
-#include "main/imports.h"
-#include "main/renderbuffer.h"
-#include "swrast/swrast.h"
-#include "swrast_setup/swrast_setup.h"
-#include "tnl/tnl.h"
-#include "tnl/t_context.h"
-#include "tnl/t_pipeline.h"
-#include "vbo/vbo.h"
-#include "drivers/common/driverfuncs.h"
-#include "drivers/common/meta.h"
-#include "utils.h"
-
-#include "main/teximage.h"
-#include "main/texfetch.h"
-#include "main/texformat.h"
-#include "main/texstate.h"
-
-#include "swrast_priv.h"
-
-
-/**
- * Screen and config-related functions
- */
-
-static void swrastSetTexBuffer2(__DRIcontext *pDRICtx, GLint target,
- GLint texture_format, __DRIdrawable *dPriv)
-{
- struct dri_context *dri_ctx;
- int x, y, w, h;
- __DRIscreen *sPriv = dPriv->driScreenPriv;
- struct gl_texture_unit *texUnit;
- struct gl_texture_object *texObj;
- struct gl_texture_image *texImage;
- uint32_t internalFormat;
-
- dri_ctx = pDRICtx->driverPrivate;
-
- internalFormat = (texture_format == __DRI_TEXTURE_FORMAT_RGB ? 3 : 4);
-
- texUnit = _mesa_get_current_tex_unit(&dri_ctx->Base);
- texObj = _mesa_select_tex_object(&dri_ctx->Base, texUnit, target);
- texImage = _mesa_get_tex_image(&dri_ctx->Base, texObj, target, 0);
-
- _mesa_lock_texture(&dri_ctx->Base, texObj);
-
- sPriv->swrast_loader->getDrawableInfo(dPriv, &x, &y, &w, &h, dPriv->loaderPrivate);
-
- _mesa_init_teximage_fields(&dri_ctx->Base, target, texImage,
- w, h, 1, 0, internalFormat);
-
- if (texture_format == __DRI_TEXTURE_FORMAT_RGB)
- texImage->TexFormat = MESA_FORMAT_XRGB8888;
- else
- texImage->TexFormat = MESA_FORMAT_ARGB8888;
-
- _mesa_set_fetch_functions(texImage, 2);
-
- sPriv->swrast_loader->getImage(dPriv, x, y, w, h, (char *)texImage->Data,
- dPriv->loaderPrivate);
-
- _mesa_unlock_texture(&dri_ctx->Base, texObj);
-}
-
-static void swrastSetTexBuffer(__DRIcontext *pDRICtx, GLint target,
- __DRIdrawable *dPriv)
-{
- swrastSetTexBuffer2(pDRICtx, target, __DRI_TEXTURE_FORMAT_RGBA, dPriv);
-}
-
-static const __DRItexBufferExtension swrastTexBufferExtension = {
- { __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION },
- swrastSetTexBuffer,
- swrastSetTexBuffer2,
-};
-
-static const __DRIextension *dri_screen_extensions[] = {
- &swrastTexBufferExtension.base,
- NULL
-};
-
-static __DRIconfig **
-swrastFillInModes(__DRIscreen *psp,
- unsigned pixel_bits, unsigned depth_bits,
- unsigned stencil_bits, GLboolean have_back_buffer)
-{
- __DRIconfig **configs;
- unsigned depth_buffer_factor;
- unsigned back_buffer_factor;
- GLenum fb_format;
- GLenum fb_type;
-
- /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't
- * support pageflipping at all.
- */
- static const GLenum back_buffer_modes[] = {
- GLX_NONE, GLX_SWAP_UNDEFINED_OML
- };
-
- uint8_t depth_bits_array[4];
- uint8_t stencil_bits_array[4];
- uint8_t msaa_samples_array[1];
-
- depth_bits_array[0] = 0;
- depth_bits_array[1] = 0;
- depth_bits_array[2] = depth_bits;
- depth_bits_array[3] = depth_bits;
-
- /* Just like with the accumulation buffer, always provide some modes
- * with a stencil buffer.
- */
- stencil_bits_array[0] = 0;
- stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits;
- stencil_bits_array[2] = 0;
- stencil_bits_array[3] = (stencil_bits == 0) ? 8 : stencil_bits;
-
- msaa_samples_array[0] = 0;
-
- depth_buffer_factor = 4;
- back_buffer_factor = 2;
-
- switch (pixel_bits) {
- case 8:
- fb_format = GL_RGB;
- fb_type = GL_UNSIGNED_BYTE_2_3_3_REV;
- break;
- case 16:
- fb_format = GL_RGB;
- fb_type = GL_UNSIGNED_SHORT_5_6_5;
- break;
- case 24:
- fb_format = GL_BGR;
- fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
- break;
- case 32:
- fb_format = GL_BGRA;
- fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
- break;
- default:
- fprintf(stderr, "[%s:%u] bad depth %d\n", __func__, __LINE__,
- pixel_bits);
- return NULL;
- }
-
- configs = driCreateConfigs(fb_format, fb_type,
- depth_bits_array, stencil_bits_array,
- depth_buffer_factor, back_buffer_modes,
- back_buffer_factor, msaa_samples_array, 1,
- GL_TRUE);
- if (configs == NULL) {
- fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
- __LINE__);
- return NULL;
- }
-
- return configs;
-}
-
-static const __DRIconfig **
-dri_init_screen(__DRIscreen * psp)
-{
- __DRIconfig **configs8, **configs16, **configs24, **configs32;
-
- TRACE;
-
- psp->extensions = dri_screen_extensions;
-
- configs8 = swrastFillInModes(psp, 8, 8, 0, 1);
- configs16 = swrastFillInModes(psp, 16, 16, 0, 1);
- configs24 = swrastFillInModes(psp, 24, 24, 8, 1);
- configs32 = swrastFillInModes(psp, 32, 24, 8, 1);
-
- configs16 = driConcatConfigs(configs8, configs16);
- configs24 = driConcatConfigs(configs16, configs24);
- configs32 = driConcatConfigs(configs24, configs32);
-
- return (const __DRIconfig **)configs32;
-}
-
-static void
-dri_destroy_screen(__DRIscreen * sPriv)
-{
- TRACE;
-}
-
-
-/**
- * Framebuffer and renderbuffer-related functions.
- */
-
-static GLuint
-choose_pixel_format(const GLvisual *v)
-{
- int depth = v->rgbBits;
-
- if (depth == 32
- && v->redMask == 0xff0000
- && v->greenMask == 0x00ff00
- && v->blueMask == 0x0000ff)
- return PF_A8R8G8B8;
- else if (depth == 24
- && v->redMask == 0xff0000
- && v->greenMask == 0x00ff00
- && v->blueMask == 0x0000ff)
- return PF_X8R8G8B8;
- else if (depth == 16
- && v->redMask == 0xf800
- && v->greenMask == 0x07e0
- && v->blueMask == 0x001f)
- return PF_R5G6B5;
- else if (depth == 8
- && v->redMask == 0x07
- && v->greenMask == 0x38
- && v->blueMask == 0xc0)
- return PF_R3G3B2;
-
- _mesa_problem( NULL, "unexpected format in %s", __FUNCTION__ );
- return 0;
-}
-
-static void
-swrast_delete_renderbuffer(struct gl_renderbuffer *rb)
-{
- TRACE;
-
- free(rb->Data);
- free(rb);
-}
-
-/* see bytes_per_line in libGL */
-static INLINE int
-bytes_per_line(unsigned pitch_bits, unsigned mul)
-{
- unsigned mask = mul - 1;
-
- return ((pitch_bits + mask) & ~mask) / 8;
-}
-
-static GLboolean
-swrast_alloc_front_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
- GLenum internalFormat, GLuint width, GLuint height)
-{
- struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb);
-
- TRACE;
-
- rb->Data = NULL;
- rb->Width = width;
- rb->Height = height;
-
- xrb->pitch = bytes_per_line(width * xrb->bpp, 32);
-
- return GL_TRUE;
-}
-
-static GLboolean
-swrast_alloc_back_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
- GLenum internalFormat, GLuint width, GLuint height)
-{
- struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb);
-
- TRACE;
-
- free(rb->Data);
-
- swrast_alloc_front_storage(ctx, rb, internalFormat, width, height);
-
- rb->Data = malloc(height * xrb->pitch);
-
- return GL_TRUE;
-}
-
-static struct swrast_renderbuffer *
-swrast_new_renderbuffer(const GLvisual *visual, GLboolean front)
-{
- struct swrast_renderbuffer *xrb = calloc(1, sizeof *xrb);
- GLuint pixel_format;
-
- TRACE;
-
- if (!xrb)
- return NULL;
-
- _mesa_init_renderbuffer(&xrb->Base, 0);
-
- pixel_format = choose_pixel_format(visual);
-
- xrb->Base.Delete = swrast_delete_renderbuffer;
- if (front) {
- xrb->Base.AllocStorage = swrast_alloc_front_storage;
- swrast_set_span_funcs_front(xrb, pixel_format);
- }
- else {
- xrb->Base.AllocStorage = swrast_alloc_back_storage;
- swrast_set_span_funcs_back(xrb, pixel_format);
- }
-
- switch (pixel_format) {
- case PF_A8R8G8B8:
- xrb->Base.Format = MESA_FORMAT_ARGB8888;
- xrb->Base.InternalFormat = GL_RGBA;
- xrb->Base._BaseFormat = GL_RGBA;
- xrb->Base.DataType = GL_UNSIGNED_BYTE;
- xrb->bpp = 32;
- break;
- case PF_X8R8G8B8:
- xrb->Base.Format = MESA_FORMAT_ARGB8888; /* XXX */
- xrb->Base.InternalFormat = GL_RGB;
- xrb->Base._BaseFormat = GL_RGB;
- xrb->Base.DataType = GL_UNSIGNED_BYTE;
- xrb->bpp = 32;
- break;
- case PF_R5G6B5:
- xrb->Base.Format = MESA_FORMAT_RGB565;
- xrb->Base.InternalFormat = GL_RGB;
- xrb->Base._BaseFormat = GL_RGB;
- xrb->Base.DataType = GL_UNSIGNED_BYTE;
- xrb->bpp = 16;
- break;
- case PF_R3G3B2:
- xrb->Base.Format = MESA_FORMAT_RGB332;
- xrb->Base.InternalFormat = GL_RGB;
- xrb->Base._BaseFormat = GL_RGB;
- xrb->Base.DataType = GL_UNSIGNED_BYTE;
- xrb->bpp = 8;
- break;
- default:
- return NULL;
- }
-
- return xrb;
-}
-
-static GLboolean
-dri_create_buffer(__DRIscreen * sPriv,
- __DRIdrawable * dPriv,
- const __GLcontextModes * visual, GLboolean isPixmap)
-{
- struct dri_drawable *drawable = NULL;
- GLframebuffer *fb;
- struct swrast_renderbuffer *frontrb, *backrb;
-
- TRACE;
-
- drawable = CALLOC_STRUCT(dri_drawable);
- if (drawable == NULL)
- goto drawable_fail;
-
- dPriv->driverPrivate = drawable;
- drawable->dPriv = dPriv;
-
- drawable->row = malloc(MAX_WIDTH * 4);
- if (drawable->row == NULL)
- goto drawable_fail;
-
- fb = &drawable->Base;
-
- /* basic framebuffer setup */
- _mesa_initialize_window_framebuffer(fb, visual);
-
- /* add front renderbuffer */
- frontrb = swrast_new_renderbuffer(visual, GL_TRUE);
- _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontrb->Base);
-
- /* add back renderbuffer */
- if (visual->doubleBufferMode) {
- backrb = swrast_new_renderbuffer(visual, GL_FALSE);
- _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backrb->Base);
- }
-
- /* add software renderbuffers */
- _mesa_add_soft_renderbuffers(fb,
- GL_FALSE, /* color */
- visual->haveDepthBuffer,
- visual->haveStencilBuffer,
- visual->haveAccumBuffer,
- GL_FALSE, /* alpha */
- GL_FALSE /* aux bufs */);
-
- return GL_TRUE;
-
-drawable_fail:
-
- if (drawable)
- free(drawable->row);
-
- FREE(drawable);
-
- return GL_FALSE;
-}
-
-static void
-dri_destroy_buffer(__DRIdrawable * dPriv)
-{
- TRACE;
-
- if (dPriv) {
- struct dri_drawable *drawable = dri_drawable(dPriv);
- GLframebuffer *fb;
-
- free(drawable->row);
-
- fb = &drawable->Base;
-
- fb->DeletePending = GL_TRUE;
- _mesa_reference_framebuffer(&fb, NULL);
- }
-}
-
-static void
-dri_swap_buffers(__DRIdrawable * dPriv)
-{
- __DRIscreen *sPriv = dPriv->driScreenPriv;
-
- GET_CURRENT_CONTEXT(ctx);
-
- struct dri_drawable *drawable = dri_drawable(dPriv);
- GLframebuffer *fb;
- struct swrast_renderbuffer *frontrb, *backrb;
-
- TRACE;
-
- fb = &drawable->Base;
-
- frontrb =
- swrast_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
- backrb =
- swrast_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer);
-
- /* check for signle-buffered */
- if (backrb == NULL)
- return;
-
- /* check if swapping currently bound buffer */
- if (ctx && ctx->DrawBuffer == fb) {
- /* flush pending rendering */
- _mesa_notifySwapBuffers(ctx);
- }
-
- sPriv->swrast_loader->putImage(dPriv, __DRI_SWRAST_IMAGE_OP_SWAP,
- 0, 0,
- frontrb->Base.Width,
- frontrb->Base.Height,
- backrb->Base.Data,
- dPriv->loaderPrivate);
-}
-
-
-/**
- * General device driver functions.
- */
-
-static void
-get_window_size( GLframebuffer *fb, GLsizei *w, GLsizei *h )
-{
- __DRIdrawable *dPriv = swrast_drawable(fb)->dPriv;
- __DRIscreen *sPriv = dPriv->driScreenPriv;
- int x, y;
-
- sPriv->swrast_loader->getDrawableInfo(dPriv,
- &x, &y, w, h,
- dPriv->loaderPrivate);
-}
-
-static void
-swrast_check_and_update_window_size( GLcontext *ctx, GLframebuffer *fb )
-{
- GLsizei width, height;
-
- get_window_size(fb, &width, &height);
- if (fb->Width != width || fb->Height != height) {
- _mesa_resize_framebuffer(ctx, fb, width, height);
- }
-}
-
-static const GLubyte *
-get_string(GLcontext *ctx, GLenum pname)
-{
- (void) ctx;
- switch (pname) {
- case GL_VENDOR:
- return (const GLubyte *) "Mesa Project";
- case GL_RENDERER:
- return (const GLubyte *) "Software Rasterizer";
- default:
- return NULL;
- }
-}
-
-static void
-update_state( GLcontext *ctx, GLuint new_state )
-{
- /* not much to do here - pass it on */
- _swrast_InvalidateState( ctx, new_state );
- _swsetup_InvalidateState( ctx, new_state );
- _vbo_InvalidateState( ctx, new_state );
- _tnl_InvalidateState( ctx, new_state );
-}
-
-static void
-viewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
-{
- GLframebuffer *draw = ctx->WinSysDrawBuffer;
- GLframebuffer *read = ctx->WinSysReadBuffer;
-
- swrast_check_and_update_window_size(ctx, draw);
- swrast_check_and_update_window_size(ctx, read);
-}
-
-static gl_format swrastChooseTextureFormat(GLcontext * ctx,
- GLint internalFormat,
- GLenum format,
- GLenum type)
-{
- if (internalFormat == GL_RGB)
- return MESA_FORMAT_XRGB8888;
- return _mesa_choose_tex_format(ctx, internalFormat, format, type);
-}
-
-static void
-swrast_init_driver_functions(struct dd_function_table *driver)
-{
- driver->GetString = get_string;
- driver->UpdateState = update_state;
- driver->GetBufferSize = NULL;
- driver->Viewport = viewport;
- driver->ChooseTextureFormat = swrastChooseTextureFormat;
-}
-
-
-/**
- * Context-related functions.
- */
-
-static GLboolean
-dri_create_context(gl_api api,
- const __GLcontextModes * visual,
- __DRIcontext * cPriv, void *sharedContextPrivate)
-{
- struct dri_context *ctx = NULL;
- struct dri_context *share = (struct dri_context *)sharedContextPrivate;
- GLcontext *mesaCtx = NULL;
- GLcontext *sharedCtx = NULL;
- struct dd_function_table functions;
-
- TRACE;
-
- ctx = CALLOC_STRUCT(dri_context);
- if (ctx == NULL)
- goto context_fail;
-
- cPriv->driverPrivate = ctx;
- ctx->cPriv = cPriv;
-
- /* build table of device driver functions */
- _mesa_init_driver_functions(&functions);
- swrast_init_driver_functions(&functions);
-
- if (share) {
- sharedCtx = &share->Base;
- }
-
- mesaCtx = &ctx->Base;
-
- /* basic context setup */
- if (!_mesa_initialize_context(mesaCtx, visual, sharedCtx, &functions, (void *) cPriv)) {
- goto context_fail;
- }
-
- /* do bounds checking to prevent segfaults and server crashes! */
- mesaCtx->Const.CheckArrayBounds = GL_TRUE;
-
- /* create module contexts */
- _swrast_CreateContext( mesaCtx );
- _vbo_CreateContext( mesaCtx );
- _tnl_CreateContext( mesaCtx );
- _swsetup_CreateContext( mesaCtx );
- _swsetup_Wakeup( mesaCtx );
-
- /* use default TCL pipeline */
- {
- TNLcontext *tnl = TNL_CONTEXT(mesaCtx);
- tnl->Driver.RunPipeline = _tnl_run_pipeline;
- }
-
- _mesa_enable_sw_extensions(mesaCtx);
- _mesa_enable_1_3_extensions(mesaCtx);
- _mesa_enable_1_4_extensions(mesaCtx);
- _mesa_enable_1_5_extensions(mesaCtx);
- _mesa_enable_2_0_extensions(mesaCtx);
- _mesa_enable_2_1_extensions(mesaCtx);
-
- _mesa_meta_init(mesaCtx);
-
- driInitExtensions( mesaCtx, NULL, GL_FALSE );
-
- return GL_TRUE;
-
-context_fail:
-
- FREE(ctx);
-
- return GL_FALSE;
-}
-
-static void
-dri_destroy_context(__DRIcontext * cPriv)
-{
- TRACE;
-
- if (cPriv) {
- struct dri_context *ctx = dri_context(cPriv);
- GLcontext *mesaCtx;
-
- mesaCtx = &ctx->Base;
-
- _mesa_meta_free(mesaCtx);
- _swsetup_DestroyContext( mesaCtx );
- _swrast_DestroyContext( mesaCtx );
- _tnl_DestroyContext( mesaCtx );
- _vbo_DestroyContext( mesaCtx );
- _mesa_destroy_context( mesaCtx );
- }
-}
-
-static GLboolean
-dri_make_current(__DRIcontext * cPriv,
- __DRIdrawable * driDrawPriv,
- __DRIdrawable * driReadPriv)
-{
- GLcontext *mesaCtx;
- GLframebuffer *mesaDraw;
- GLframebuffer *mesaRead;
- TRACE;
-
- if (cPriv) {
- struct dri_context *ctx = dri_context(cPriv);
- struct dri_drawable *draw;
- struct dri_drawable *read;
-
- if (!driDrawPriv || !driReadPriv)
- return GL_FALSE;
-
- draw = dri_drawable(driDrawPriv);
- read = dri_drawable(driReadPriv);
- mesaCtx = &ctx->Base;
- mesaDraw = &draw->Base;
- mesaRead = &read->Base;
-
- /* check for same context and buffer */
- if (mesaCtx == _mesa_get_current_context()
- && mesaCtx->DrawBuffer == mesaDraw
- && mesaCtx->ReadBuffer == mesaRead) {
- return GL_TRUE;
- }
-
- _glapi_check_multithread();
-
- swrast_check_and_update_window_size(mesaCtx, mesaDraw);
- if (mesaRead != mesaDraw)
- swrast_check_and_update_window_size(mesaCtx, mesaRead);
-
- _mesa_make_current( mesaCtx,
- mesaDraw,
- mesaRead );
- }
- else {
- /* unbind */
- _mesa_make_current( NULL, NULL, NULL );
- }
-
- return GL_TRUE;
-}
-
-static GLboolean
-dri_unbind_context(__DRIcontext * cPriv)
-{
- TRACE;
- (void) cPriv;
-
- /* Unset current context and dispath table */
- _mesa_make_current(NULL, NULL, NULL);
-
- return GL_TRUE;
-}
-
-
-const struct __DriverAPIRec driDriverAPI = {
- .InitScreen = dri_init_screen,
- .DestroyScreen = dri_destroy_screen,
- .CreateContext = dri_create_context,
- .DestroyContext = dri_destroy_context,
- .CreateBuffer = dri_create_buffer,
- .DestroyBuffer = dri_destroy_buffer,
- .SwapBuffers = dri_swap_buffers,
- .MakeCurrent = dri_make_current,
- .UnbindContext = dri_unbind_context,
-};
-
-/* This is the table of extensions that the loader will dlsym() for. */
-PUBLIC const __DRIextension *__driDriverExtensions[] = {
- &driCoreExtension.base,
- &driSWRastExtension.base,
- NULL
-};
+/*
+ * Copyright 2008, 2010 George Sapountzis <gsapountzis@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * DRI software rasterizer
+ *
+ * This is the mesa swrast module packaged into a DRI driver structure.
+ *
+ * The front-buffer is allocated by the loader. The loader provides read/write
+ * callbacks for access to the front-buffer. The driver uses a scratch row for
+ * front-buffer rendering to avoid repeated calls to the loader.
+ *
+ * The back-buffer is allocated by the driver and is private.
+ */
+
+#include "main/context.h"
+#include "main/extensions.h"
+#include "main/formats.h"
+#include "main/framebuffer.h"
+#include "main/imports.h"
+#include "main/renderbuffer.h"
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+#include "vbo/vbo.h"
+#include "drivers/common/driverfuncs.h"
+#include "drivers/common/meta.h"
+#include "utils.h"
+
+#include "main/teximage.h"
+#include "main/texformat.h"
+#include "main/texstate.h"
+
+#include "swrast_priv.h"
+
+
+/**
+ * Screen and config-related functions
+ */
+
+static void swrastSetTexBuffer2(__DRIcontext *pDRICtx, GLint target,
+ GLint texture_format, __DRIdrawable *dPriv)
+{
+ struct dri_context *dri_ctx;
+ int x, y, w, h;
+ __DRIscreen *sPriv = dPriv->driScreenPriv;
+ struct gl_texture_unit *texUnit;
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ uint32_t internalFormat;
+ gl_format texFormat;
+
+ dri_ctx = pDRICtx->driverPrivate;
+
+ internalFormat = (texture_format == __DRI_TEXTURE_FORMAT_RGB ? 3 : 4);
+
+ texUnit = _mesa_get_current_tex_unit(&dri_ctx->Base);
+ texObj = _mesa_select_tex_object(&dri_ctx->Base, texUnit, target);
+ texImage = _mesa_get_tex_image(&dri_ctx->Base, texObj, target, 0);
+
+ _mesa_lock_texture(&dri_ctx->Base, texObj);
+
+ sPriv->swrast_loader->getDrawableInfo(dPriv, &x, &y, &w, &h, dPriv->loaderPrivate);
+
+ if (texture_format == __DRI_TEXTURE_FORMAT_RGB)
+ texFormat = MESA_FORMAT_XRGB8888;
+ else
+ texFormat = MESA_FORMAT_ARGB8888;
+
+ _mesa_init_teximage_fields(&dri_ctx->Base, target, texImage,
+ w, h, 1, 0, internalFormat, texFormat);
+
+ sPriv->swrast_loader->getImage(dPriv, x, y, w, h, (char *)texImage->Data,
+ dPriv->loaderPrivate);
+
+ _mesa_unlock_texture(&dri_ctx->Base, texObj);
+}
+
+static void swrastSetTexBuffer(__DRIcontext *pDRICtx, GLint target,
+ __DRIdrawable *dPriv)
+{
+ swrastSetTexBuffer2(pDRICtx, target, __DRI_TEXTURE_FORMAT_RGBA, dPriv);
+}
+
+static const __DRItexBufferExtension swrastTexBufferExtension = {
+ { __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION },
+ swrastSetTexBuffer,
+ swrastSetTexBuffer2,
+};
+
+static const __DRIextension *dri_screen_extensions[] = {
+ &swrastTexBufferExtension.base,
+ NULL
+};
+
+static __DRIconfig **
+swrastFillInModes(__DRIscreen *psp,
+ unsigned pixel_bits, unsigned depth_bits,
+ unsigned stencil_bits, GLboolean have_back_buffer)
+{
+ __DRIconfig **configs;
+ unsigned depth_buffer_factor;
+ unsigned back_buffer_factor;
+ GLenum fb_format;
+ GLenum fb_type;
+
+ /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't
+ * support pageflipping at all.
+ */
+ static const GLenum back_buffer_modes[] = {
+ GLX_NONE, GLX_SWAP_UNDEFINED_OML
+ };
+
+ uint8_t depth_bits_array[4];
+ uint8_t stencil_bits_array[4];
+ uint8_t msaa_samples_array[1];
+
+ depth_bits_array[0] = 0;
+ depth_bits_array[1] = 0;
+ depth_bits_array[2] = depth_bits;
+ depth_bits_array[3] = depth_bits;
+
+ /* Just like with the accumulation buffer, always provide some modes
+ * with a stencil buffer.
+ */
+ stencil_bits_array[0] = 0;
+ stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits;
+ stencil_bits_array[2] = 0;
+ stencil_bits_array[3] = (stencil_bits == 0) ? 8 : stencil_bits;
+
+ msaa_samples_array[0] = 0;
+
+ depth_buffer_factor = 4;
+ back_buffer_factor = 2;
+
+ switch (pixel_bits) {
+ case 8:
+ fb_format = GL_RGB;
+ fb_type = GL_UNSIGNED_BYTE_2_3_3_REV;
+ break;
+ case 16:
+ fb_format = GL_RGB;
+ fb_type = GL_UNSIGNED_SHORT_5_6_5;
+ break;
+ case 24:
+ fb_format = GL_BGR;
+ fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
+ break;
+ case 32:
+ fb_format = GL_BGRA;
+ fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
+ break;
+ default:
+ fprintf(stderr, "[%s:%u] bad depth %d\n", __func__, __LINE__,
+ pixel_bits);
+ return NULL;
+ }
+
+ configs = driCreateConfigs(fb_format, fb_type,
+ depth_bits_array, stencil_bits_array,
+ depth_buffer_factor, back_buffer_modes,
+ back_buffer_factor, msaa_samples_array, 1,
+ GL_TRUE);
+ if (configs == NULL) {
+ fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
+ __LINE__);
+ return NULL;
+ }
+
+ return configs;
+}
+
+static const __DRIconfig **
+dri_init_screen(__DRIscreen * psp)
+{
+ __DRIconfig **configs8, **configs16, **configs24, **configs32;
+
+ TRACE;
+
+ psp->extensions = dri_screen_extensions;
+
+ configs8 = swrastFillInModes(psp, 8, 8, 0, 1);
+ configs16 = swrastFillInModes(psp, 16, 16, 0, 1);
+ configs24 = swrastFillInModes(psp, 24, 24, 8, 1);
+ configs32 = swrastFillInModes(psp, 32, 24, 8, 1);
+
+ configs16 = driConcatConfigs(configs8, configs16);
+ configs24 = driConcatConfigs(configs16, configs24);
+ configs32 = driConcatConfigs(configs24, configs32);
+
+ return (const __DRIconfig **)configs32;
+}
+
+static void
+dri_destroy_screen(__DRIscreen * sPriv)
+{
+ TRACE;
+}
+
+
+/**
+ * Framebuffer and renderbuffer-related functions.
+ */
+
+static GLuint
+choose_pixel_format(const struct gl_config *v)
+{
+ int depth = v->rgbBits;
+
+ if (depth == 32
+ && v->redMask == 0xff0000
+ && v->greenMask == 0x00ff00
+ && v->blueMask == 0x0000ff)
+ return PF_A8R8G8B8;
+ else if (depth == 24
+ && v->redMask == 0xff0000
+ && v->greenMask == 0x00ff00
+ && v->blueMask == 0x0000ff)
+ return PF_X8R8G8B8;
+ else if (depth == 16
+ && v->redMask == 0xf800
+ && v->greenMask == 0x07e0
+ && v->blueMask == 0x001f)
+ return PF_R5G6B5;
+ else if (depth == 8
+ && v->redMask == 0x07
+ && v->greenMask == 0x38
+ && v->blueMask == 0xc0)
+ return PF_R3G3B2;
+
+ _mesa_problem( NULL, "unexpected format in %s", __FUNCTION__ );
+ return 0;
+}
+
+static void
+swrast_delete_renderbuffer(struct gl_renderbuffer *rb)
+{
+ TRACE;
+
+ free(rb->Data);
+ free(rb);
+}
+
+/* see bytes_per_line in libGL */
+static INLINE int
+bytes_per_line(unsigned pitch_bits, unsigned mul)
+{
+ unsigned mask = mul - 1;
+
+ return ((pitch_bits + mask) & ~mask) / 8;
+}
+
+static GLboolean
+swrast_alloc_front_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
+ GLenum internalFormat, GLuint width, GLuint height)
+{
+ struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb);
+
+ TRACE;
+
+ rb->Data = NULL;
+ rb->Width = width;
+ rb->Height = height;
+
+ xrb->pitch = bytes_per_line(width * xrb->bpp, 32);
+
+ return GL_TRUE;
+}
+
+static GLboolean
+swrast_alloc_back_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
+ GLenum internalFormat, GLuint width, GLuint height)
+{
+ struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb);
+
+ TRACE;
+
+ free(rb->Data);
+
+ swrast_alloc_front_storage(ctx, rb, internalFormat, width, height);
+
+ rb->Data = malloc(height * xrb->pitch);
+
+ return GL_TRUE;
+}
+
+static struct swrast_renderbuffer *
+swrast_new_renderbuffer(const struct gl_config *visual, GLboolean front)
+{
+ struct swrast_renderbuffer *xrb = calloc(1, sizeof *xrb);
+ GLuint pixel_format;
+
+ TRACE;
+
+ if (!xrb)
+ return NULL;
+
+ _mesa_init_renderbuffer(&xrb->Base, 0);
+
+ pixel_format = choose_pixel_format(visual);
+
+ xrb->Base.Delete = swrast_delete_renderbuffer;
+ if (front) {
+ xrb->Base.AllocStorage = swrast_alloc_front_storage;
+ swrast_set_span_funcs_front(xrb, pixel_format);
+ }
+ else {
+ xrb->Base.AllocStorage = swrast_alloc_back_storage;
+ swrast_set_span_funcs_back(xrb, pixel_format);
+ }
+
+ switch (pixel_format) {
+ case PF_A8R8G8B8:
+ xrb->Base.Format = MESA_FORMAT_ARGB8888;
+ xrb->Base.InternalFormat = GL_RGBA;
+ xrb->Base._BaseFormat = GL_RGBA;
+ xrb->Base.DataType = GL_UNSIGNED_BYTE;
+ xrb->bpp = 32;
+ break;
+ case PF_X8R8G8B8:
+ xrb->Base.Format = MESA_FORMAT_ARGB8888; /* XXX */
+ xrb->Base.InternalFormat = GL_RGB;
+ xrb->Base._BaseFormat = GL_RGB;
+ xrb->Base.DataType = GL_UNSIGNED_BYTE;
+ xrb->bpp = 32;
+ break;
+ case PF_R5G6B5:
+ xrb->Base.Format = MESA_FORMAT_RGB565;
+ xrb->Base.InternalFormat = GL_RGB;
+ xrb->Base._BaseFormat = GL_RGB;
+ xrb->Base.DataType = GL_UNSIGNED_BYTE;
+ xrb->bpp = 16;
+ break;
+ case PF_R3G3B2:
+ xrb->Base.Format = MESA_FORMAT_RGB332;
+ xrb->Base.InternalFormat = GL_RGB;
+ xrb->Base._BaseFormat = GL_RGB;
+ xrb->Base.DataType = GL_UNSIGNED_BYTE;
+ xrb->bpp = 8;
+ break;
+ default:
+ return NULL;
+ }
+
+ return xrb;
+}
+
+static GLboolean
+dri_create_buffer(__DRIscreen * sPriv,
+ __DRIdrawable * dPriv,
+ const struct gl_config * visual, GLboolean isPixmap)
+{
+ struct dri_drawable *drawable = NULL;
+ struct gl_framebuffer *fb;
+ struct swrast_renderbuffer *frontrb, *backrb;
+
+ TRACE;
+
+ drawable = CALLOC_STRUCT(dri_drawable);
+ if (drawable == NULL)
+ goto drawable_fail;
+
+ dPriv->driverPrivate = drawable;
+ drawable->dPriv = dPriv;
+
+ drawable->row = malloc(MAX_WIDTH * 4);
+ if (drawable->row == NULL)
+ goto drawable_fail;
+
+ fb = &drawable->Base;
+
+ /* basic framebuffer setup */
+ _mesa_initialize_window_framebuffer(fb, visual);
+
+ /* add front renderbuffer */
+ frontrb = swrast_new_renderbuffer(visual, GL_TRUE);
+ _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontrb->Base);
+
+ /* add back renderbuffer */
+ if (visual->doubleBufferMode) {
+ backrb = swrast_new_renderbuffer(visual, GL_FALSE);
+ _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backrb->Base);
+ }
+
+ /* add software renderbuffers */
+ _mesa_add_soft_renderbuffers(fb,
+ GL_FALSE, /* color */
+ visual->haveDepthBuffer,
+ visual->haveStencilBuffer,
+ visual->haveAccumBuffer,
+ GL_FALSE, /* alpha */
+ GL_FALSE /* aux bufs */);
+
+ return GL_TRUE;
+
+drawable_fail:
+
+ if (drawable)
+ free(drawable->row);
+
+ FREE(drawable);
+
+ return GL_FALSE;
+}
+
+static void
+dri_destroy_buffer(__DRIdrawable * dPriv)
+{
+ TRACE;
+
+ if (dPriv) {
+ struct dri_drawable *drawable = dri_drawable(dPriv);
+ struct gl_framebuffer *fb;
+
+ free(drawable->row);
+
+ fb = &drawable->Base;
+
+ fb->DeletePending = GL_TRUE;
+ _mesa_reference_framebuffer(&fb, NULL);
+ }
+}
+
+static void
+dri_swap_buffers(__DRIdrawable * dPriv)
+{
+ __DRIscreen *sPriv = dPriv->driScreenPriv;
+
+ GET_CURRENT_CONTEXT(ctx);
+
+ struct dri_drawable *drawable = dri_drawable(dPriv);
+ struct gl_framebuffer *fb;
+ struct swrast_renderbuffer *frontrb, *backrb;
+
+ TRACE;
+
+ fb = &drawable->Base;
+
+ frontrb =
+ swrast_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
+ backrb =
+ swrast_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer);
+
+ /* check for signle-buffered */
+ if (backrb == NULL)
+ return;
+
+ /* check if swapping currently bound buffer */
+ if (ctx && ctx->DrawBuffer == fb) {
+ /* flush pending rendering */
+ _mesa_notifySwapBuffers(ctx);
+ }
+
+ sPriv->swrast_loader->putImage(dPriv, __DRI_SWRAST_IMAGE_OP_SWAP,
+ 0, 0,
+ frontrb->Base.Width,
+ frontrb->Base.Height,
+ backrb->Base.Data,
+ dPriv->loaderPrivate);
+}
+
+
+/**
+ * General device driver functions.
+ */
+
+static void
+get_window_size( struct gl_framebuffer *fb, GLsizei *w, GLsizei *h )
+{
+ __DRIdrawable *dPriv = swrast_drawable(fb)->dPriv;
+ __DRIscreen *sPriv = dPriv->driScreenPriv;
+ int x, y;
+
+ sPriv->swrast_loader->getDrawableInfo(dPriv,
+ &x, &y, w, h,
+ dPriv->loaderPrivate);
+}
+
+static void
+swrast_check_and_update_window_size( struct gl_context *ctx, struct gl_framebuffer *fb )
+{
+ GLsizei width, height;
+
+ get_window_size(fb, &width, &height);
+ if (fb->Width != width || fb->Height != height) {
+ _mesa_resize_framebuffer(ctx, fb, width, height);
+ }
+}
+
+static const GLubyte *
+get_string(struct gl_context *ctx, GLenum pname)
+{
+ (void) ctx;
+ switch (pname) {
+ case GL_VENDOR:
+ return (const GLubyte *) "Mesa Project";
+ case GL_RENDERER:
+ return (const GLubyte *) "Software Rasterizer";
+ default:
+ return NULL;
+ }
+}
+
+static void
+update_state( struct gl_context *ctx, GLuint new_state )
+{
+ /* not much to do here - pass it on */
+ _swrast_InvalidateState( ctx, new_state );
+ _swsetup_InvalidateState( ctx, new_state );
+ _vbo_InvalidateState( ctx, new_state );
+ _tnl_InvalidateState( ctx, new_state );
+}
+
+static void
+viewport(struct gl_context *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
+{
+ struct gl_framebuffer *draw = ctx->WinSysDrawBuffer;
+ struct gl_framebuffer *read = ctx->WinSysReadBuffer;
+
+ swrast_check_and_update_window_size(ctx, draw);
+ swrast_check_and_update_window_size(ctx, read);
+}
+
+static gl_format swrastChooseTextureFormat(struct gl_context * ctx,
+ GLint internalFormat,
+ GLenum format,
+ GLenum type)
+{
+ if (internalFormat == GL_RGB)
+ return MESA_FORMAT_XRGB8888;
+ return _mesa_choose_tex_format(ctx, internalFormat, format, type);
+}
+
+static void
+swrast_init_driver_functions(struct dd_function_table *driver)
+{
+ driver->GetString = get_string;
+ driver->UpdateState = update_state;
+ driver->GetBufferSize = NULL;
+ driver->Viewport = viewport;
+ driver->ChooseTextureFormat = swrastChooseTextureFormat;
+}
+
+
+/**
+ * Context-related functions.
+ */
+
+static GLboolean
+dri_create_context(gl_api api,
+ const struct gl_config * visual,
+ __DRIcontext * cPriv, void *sharedContextPrivate)
+{
+ struct dri_context *ctx = NULL;
+ struct dri_context *share = (struct dri_context *)sharedContextPrivate;
+ struct gl_context *mesaCtx = NULL;
+ struct gl_context *sharedCtx = NULL;
+ struct dd_function_table functions;
+
+ TRACE;
+
+ ctx = CALLOC_STRUCT(dri_context);
+ if (ctx == NULL)
+ goto context_fail;
+
+ cPriv->driverPrivate = ctx;
+ ctx->cPriv = cPriv;
+
+ /* build table of device driver functions */
+ _mesa_init_driver_functions(&functions);
+ swrast_init_driver_functions(&functions);
+
+ if (share) {
+ sharedCtx = &share->Base;
+ }
+
+ mesaCtx = &ctx->Base;
+
+ /* basic context setup */
+ if (!_mesa_initialize_context(mesaCtx, visual, sharedCtx, &functions, (void *) cPriv)) {
+ goto context_fail;
+ }
+
+ /* do bounds checking to prevent segfaults and server crashes! */
+ mesaCtx->Const.CheckArrayBounds = GL_TRUE;
+
+ /* create module contexts */
+ _swrast_CreateContext( mesaCtx );
+ _vbo_CreateContext( mesaCtx );
+ _tnl_CreateContext( mesaCtx );
+ _swsetup_CreateContext( mesaCtx );
+ _swsetup_Wakeup( mesaCtx );
+
+ /* use default TCL pipeline */
+ {
+ TNLcontext *tnl = TNL_CONTEXT(mesaCtx);
+ tnl->Driver.RunPipeline = _tnl_run_pipeline;
+ }
+
+ _mesa_enable_sw_extensions(mesaCtx);
+ _mesa_enable_1_3_extensions(mesaCtx);
+ _mesa_enable_1_4_extensions(mesaCtx);
+ _mesa_enable_1_5_extensions(mesaCtx);
+ _mesa_enable_2_0_extensions(mesaCtx);
+ _mesa_enable_2_1_extensions(mesaCtx);
+
+ _mesa_meta_init(mesaCtx);
+
+ driInitExtensions( mesaCtx, NULL, GL_FALSE );
+
+ return GL_TRUE;
+
+context_fail:
+
+ FREE(ctx);
+
+ return GL_FALSE;
+}
+
+static void
+dri_destroy_context(__DRIcontext * cPriv)
+{
+ TRACE;
+
+ if (cPriv) {
+ struct dri_context *ctx = dri_context(cPriv);
+ struct gl_context *mesaCtx;
+
+ mesaCtx = &ctx->Base;
+
+ _mesa_meta_free(mesaCtx);
+ _swsetup_DestroyContext( mesaCtx );
+ _swrast_DestroyContext( mesaCtx );
+ _tnl_DestroyContext( mesaCtx );
+ _vbo_DestroyContext( mesaCtx );
+ _mesa_destroy_context( mesaCtx );
+ }
+}
+
+static GLboolean
+dri_make_current(__DRIcontext * cPriv,
+ __DRIdrawable * driDrawPriv,
+ __DRIdrawable * driReadPriv)
+{
+ struct gl_context *mesaCtx;
+ struct gl_framebuffer *mesaDraw;
+ struct gl_framebuffer *mesaRead;
+ TRACE;
+
+ if (cPriv) {
+ struct dri_context *ctx = dri_context(cPriv);
+ struct dri_drawable *draw;
+ struct dri_drawable *read;
+
+ if (!driDrawPriv || !driReadPriv)
+ return GL_FALSE;
+
+ draw = dri_drawable(driDrawPriv);
+ read = dri_drawable(driReadPriv);
+ mesaCtx = &ctx->Base;
+ mesaDraw = &draw->Base;
+ mesaRead = &read->Base;
+
+ /* check for same context and buffer */
+ if (mesaCtx == _mesa_get_current_context()
+ && mesaCtx->DrawBuffer == mesaDraw
+ && mesaCtx->ReadBuffer == mesaRead) {
+ return GL_TRUE;
+ }
+
+ _glapi_check_multithread();
+
+ swrast_check_and_update_window_size(mesaCtx, mesaDraw);
+ if (mesaRead != mesaDraw)
+ swrast_check_and_update_window_size(mesaCtx, mesaRead);
+
+ _mesa_make_current( mesaCtx,
+ mesaDraw,
+ mesaRead );
+ }
+ else {
+ /* unbind */
+ _mesa_make_current( NULL, NULL, NULL );
+ }
+
+ return GL_TRUE;
+}
+
+static GLboolean
+dri_unbind_context(__DRIcontext * cPriv)
+{
+ TRACE;
+ (void) cPriv;
+
+ /* Unset current context and dispath table */
+ _mesa_make_current(NULL, NULL, NULL);
+
+ return GL_TRUE;
+}
+
+
+const struct __DriverAPIRec driDriverAPI = {
+ .InitScreen = dri_init_screen,
+ .DestroyScreen = dri_destroy_screen,
+ .CreateContext = dri_create_context,
+ .DestroyContext = dri_destroy_context,
+ .CreateBuffer = dri_create_buffer,
+ .DestroyBuffer = dri_destroy_buffer,
+ .SwapBuffers = dri_swap_buffers,
+ .MakeCurrent = dri_make_current,
+ .UnbindContext = dri_unbind_context,
+};
+
+/* This is the table of extensions that the loader will dlsym() for. */
+PUBLIC const __DRIextension *__driDriverExtensions[] = {
+ &driCoreExtension.base,
+ &driSWRastExtension.base,
+ NULL
+};
diff --git a/mesalib/src/mesa/drivers/dri/swrast/swrast_priv.h b/mesalib/src/mesa/drivers/dri/swrast/swrast_priv.h
index 6679061a9..4c3c9830f 100644
--- a/mesalib/src/mesa/drivers/dri/swrast/swrast_priv.h
+++ b/mesalib/src/mesa/drivers/dri/swrast/swrast_priv.h
@@ -1,138 +1,138 @@
-/*
- * Mesa 3-D graphics library
- * Version: 7.1
- *
- * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
- * Copyright 2008, 2010 George Sapountzis <gsapountzis@gmail.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#ifndef _SWRAST_PRIV_H
-#define _SWRAST_PRIV_H
-
-#include <GL/gl.h>
-#include <GL/internal/dri_interface.h>
-#include "main/mtypes.h"
-#include "drisw_util.h"
-
-
-/**
- * Debugging
- */
-#define DEBUG_CORE 0
-#define DEBUG_SPAN 0
-
-#if DEBUG_CORE
-#define TRACE printf("--> %s\n", __FUNCTION__)
-#else
-#define TRACE
-#endif
-
-#if DEBUG_SPAN
-#define TRACE_SPAN printf("--> %s\n", __FUNCTION__)
-#else
-#define TRACE_SPAN
-#endif
-
-
-/**
- * Data types
- */
-struct dri_context
-{
- /* mesa, base class, must be first */
- GLcontext Base;
-
- /* dri */
- __DRIcontext *cPriv;
-};
-
-static INLINE struct dri_context *
-dri_context(__DRIcontext * driContextPriv)
-{
- return (struct dri_context *)driContextPriv->driverPrivate;
-}
-
-static INLINE struct dri_context *
-swrast_context(GLcontext *ctx)
-{
- return (struct dri_context *) ctx;
-}
-
-struct dri_drawable
-{
- /* mesa, base class, must be first */
- GLframebuffer Base;
-
- /* dri */
- __DRIdrawable *dPriv;
-
- /* scratch row for optimized front-buffer rendering */
- char *row;
-};
-
-static INLINE struct dri_drawable *
-dri_drawable(__DRIdrawable * driDrawPriv)
-{
- return (struct dri_drawable *)driDrawPriv->driverPrivate;
-}
-
-static INLINE struct dri_drawable *
-swrast_drawable(GLframebuffer *fb)
-{
- return (struct dri_drawable *) fb;
-}
-
-struct swrast_renderbuffer {
- struct gl_renderbuffer Base;
-
- /* renderbuffer pitch (in bytes) */
- GLuint pitch;
- /* bits per pixel of storage */
- GLuint bpp;
-};
-
-static INLINE struct swrast_renderbuffer *
-swrast_renderbuffer(struct gl_renderbuffer *rb)
-{
- return (struct swrast_renderbuffer *) rb;
-}
-
-
-/**
- * Pixel formats we support
- */
-#define PF_A8R8G8B8 1 /**< 32bpp TrueColor: 8-A, 8-R, 8-G, 8-B bits */
-#define PF_R5G6B5 2 /**< 16bpp TrueColor: 5-R, 6-G, 5-B bits */
-#define PF_R3G3B2 3 /**< 8bpp TrueColor: 3-R, 3-G, 2-B bits */
-#define PF_X8R8G8B8 4 /**< 32bpp TrueColor: 8-R, 8-G, 8-B bits */
-
-
-/* swrast_span.c */
-
-extern void
-swrast_set_span_funcs_back(struct swrast_renderbuffer *xrb,
- GLuint pixel_format);
-
-extern void
-swrast_set_span_funcs_front(struct swrast_renderbuffer *xrb,
- GLuint pixel_format);
-
-#endif /* _SWRAST_PRIV_H_ */
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright 2008, 2010 George Sapountzis <gsapountzis@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef _SWRAST_PRIV_H
+#define _SWRAST_PRIV_H
+
+#include <GL/gl.h>
+#include <GL/internal/dri_interface.h>
+#include "main/mtypes.h"
+#include "drisw_util.h"
+
+
+/**
+ * Debugging
+ */
+#define DEBUG_CORE 0
+#define DEBUG_SPAN 0
+
+#if DEBUG_CORE
+#define TRACE printf("--> %s\n", __FUNCTION__)
+#else
+#define TRACE
+#endif
+
+#if DEBUG_SPAN
+#define TRACE_SPAN printf("--> %s\n", __FUNCTION__)
+#else
+#define TRACE_SPAN
+#endif
+
+
+/**
+ * Data types
+ */
+struct dri_context
+{
+ /* mesa, base class, must be first */
+ struct gl_context Base;
+
+ /* dri */
+ __DRIcontext *cPriv;
+};
+
+static INLINE struct dri_context *
+dri_context(__DRIcontext * driContextPriv)
+{
+ return (struct dri_context *)driContextPriv->driverPrivate;
+}
+
+static INLINE struct dri_context *
+swrast_context(struct gl_context *ctx)
+{
+ return (struct dri_context *) ctx;
+}
+
+struct dri_drawable
+{
+ /* mesa, base class, must be first */
+ struct gl_framebuffer Base;
+
+ /* dri */
+ __DRIdrawable *dPriv;
+
+ /* scratch row for optimized front-buffer rendering */
+ char *row;
+};
+
+static INLINE struct dri_drawable *
+dri_drawable(__DRIdrawable * driDrawPriv)
+{
+ return (struct dri_drawable *)driDrawPriv->driverPrivate;
+}
+
+static INLINE struct dri_drawable *
+swrast_drawable(struct gl_framebuffer *fb)
+{
+ return (struct dri_drawable *) fb;
+}
+
+struct swrast_renderbuffer {
+ struct gl_renderbuffer Base;
+
+ /* renderbuffer pitch (in bytes) */
+ GLuint pitch;
+ /* bits per pixel of storage */
+ GLuint bpp;
+};
+
+static INLINE struct swrast_renderbuffer *
+swrast_renderbuffer(struct gl_renderbuffer *rb)
+{
+ return (struct swrast_renderbuffer *) rb;
+}
+
+
+/**
+ * Pixel formats we support
+ */
+#define PF_A8R8G8B8 1 /**< 32bpp TrueColor: 8-A, 8-R, 8-G, 8-B bits */
+#define PF_R5G6B5 2 /**< 16bpp TrueColor: 5-R, 6-G, 5-B bits */
+#define PF_R3G3B2 3 /**< 8bpp TrueColor: 3-R, 3-G, 2-B bits */
+#define PF_X8R8G8B8 4 /**< 32bpp TrueColor: 8-R, 8-G, 8-B bits */
+
+
+/* swrast_span.c */
+
+extern void
+swrast_set_span_funcs_back(struct swrast_renderbuffer *xrb,
+ GLuint pixel_format);
+
+extern void
+swrast_set_span_funcs_front(struct swrast_renderbuffer *xrb,
+ GLuint pixel_format);
+
+#endif /* _SWRAST_PRIV_H_ */
diff --git a/mesalib/src/mesa/drivers/dri/swrast/swrast_spantemp.h b/mesalib/src/mesa/drivers/dri/swrast/swrast_spantemp.h
index 1e9405eeb..0d2703ca5 100644
--- a/mesalib/src/mesa/drivers/dri/swrast/swrast_spantemp.h
+++ b/mesalib/src/mesa/drivers/dri/swrast/swrast_spantemp.h
@@ -1,319 +1,319 @@
-/*
- * Mesa 3-D graphics library
- * Version: 6.5.1
- *
- * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-/*
- * Modified version of swrast/s_spantemp.h for front-buffer rendering. The
- * no-mask paths use a scratch row to avoid repeated calls to the loader.
- *
- * For the mask paths we always use an array of 4 elements of RB_TYPE. This is
- * to satisfy the xorg loader requirement of an image pitch of 32 bits and
- * should be ok for other loaders also.
- */
-
-
-#ifndef _SWRAST_SPANTEMP_ONCE
-#define _SWRAST_SPANTEMP_ONCE
-
-static INLINE void
-PUT_PIXEL( GLcontext *glCtx, GLint x, GLint y, GLvoid *p )
-{
- __DRIcontext *ctx = swrast_context(glCtx)->cPriv;
- __DRIdrawable *draw = swrast_drawable(glCtx->DrawBuffer)->dPriv;
-
- __DRIscreen *screen = ctx->driScreenPriv;
-
- screen->swrast_loader->putImage(draw, __DRI_SWRAST_IMAGE_OP_DRAW,
- x, y, 1, 1, (char *)p,
- draw->loaderPrivate);
-}
-
-
-static INLINE void
-GET_PIXEL( GLcontext *glCtx, GLint x, GLint y, GLubyte *p )
-{
- __DRIcontext *ctx = swrast_context(glCtx)->cPriv;
- __DRIdrawable *read = swrast_drawable(glCtx->ReadBuffer)->dPriv;
-
- __DRIscreen *screen = ctx->driScreenPriv;
-
- screen->swrast_loader->getImage(read, x, y, 1, 1, (char *)p,
- read->loaderPrivate);
-}
-
-static INLINE void
-PUT_ROW( GLcontext *glCtx, GLint x, GLint y, GLuint n, char *row )
-{
- __DRIcontext *ctx = swrast_context(glCtx)->cPriv;
- __DRIdrawable *draw = swrast_drawable(glCtx->DrawBuffer)->dPriv;
-
- __DRIscreen *screen = ctx->driScreenPriv;
-
- screen->swrast_loader->putImage(draw, __DRI_SWRAST_IMAGE_OP_DRAW,
- x, y, n, 1, row,
- draw->loaderPrivate);
-}
-
-static INLINE void
-GET_ROW( GLcontext *glCtx, GLint x, GLint y, GLuint n, char *row )
-{
- __DRIcontext *ctx = swrast_context(glCtx)->cPriv;
- __DRIdrawable *read = swrast_drawable(glCtx->ReadBuffer)->dPriv;
-
- __DRIscreen *screen = ctx->driScreenPriv;
-
- screen->swrast_loader->getImage(read, x, y, n, 1, row,
- read->loaderPrivate);
-}
-
-#endif /* _SWRAST_SPANTEMP_ONCE */
-
-
-/*
- * Templates for the span/pixel-array write/read functions called via
- * the gl_renderbuffer's GetRow, GetValues, PutRow, PutMonoRow, PutValues
- * and PutMonoValues functions.
- *
- * Define the following macros before including this file:
- * NAME(BASE) to generate the function name (i.e. add prefix or suffix)
- * RB_TYPE the renderbuffer DataType
- * SPAN_VARS to declare any local variables
- * INIT_PIXEL_PTR(P, X, Y) to initialize a pointer to a pixel
- * INC_PIXEL_PTR(P) to increment a pixel pointer by one pixel
- * STORE_PIXEL(DST, X, Y, VALUE) to store pixel values in buffer
- * FETCH_PIXEL(DST, SRC) to fetch pixel values from buffer
- *
- * Note that in the STORE_PIXEL macros, we also pass in the (X,Y) coordinates
- * for the pixels to be stored. This is useful when dithering and probably
- * ignored otherwise.
- */
-
-#include "main/macros.h"
-
-
-#if !defined(RB_COMPONENTS)
-#define RB_COMPONENTS 4
-#endif
-
-
-static void
-NAME(get_row)( GLcontext *ctx, struct gl_renderbuffer *rb,
- GLuint count, GLint x, GLint y, void *values )
-{
-#ifdef SPAN_VARS
- SPAN_VARS
-#endif
- RB_TYPE (*dest)[RB_COMPONENTS] = (RB_TYPE (*)[RB_COMPONENTS]) values;
- GLuint i;
- char *row = swrast_drawable(ctx->ReadBuffer)->row;
- INIT_PIXEL_PTR(pixel, x, y);
- GET_ROW( ctx, x, YFLIP(xrb, y), count, row );
- for (i = 0; i < count; i++) {
- FETCH_PIXEL(dest[i], pixel);
- INC_PIXEL_PTR(pixel);
- }
- (void) rb;
-}
-
-
-static void
-NAME(get_values)( GLcontext *ctx, struct gl_renderbuffer *rb,
- GLuint count, const GLint x[], const GLint y[], void *values )
-{
-#ifdef SPAN_VARS
- SPAN_VARS
-#endif
- RB_TYPE (*dest)[RB_COMPONENTS] = (RB_TYPE (*)[RB_COMPONENTS]) values;
- GLuint i;
- for (i = 0; i < count; i++) {
- RB_TYPE pixel[4];
- GET_PIXEL(ctx, x[i], YFLIP(xrb, y[i]), pixel);
- FETCH_PIXEL(dest[i], pixel);
- }
- (void) rb;
-}
-
-
-static void
-NAME(put_row)( GLcontext *ctx, struct gl_renderbuffer *rb,
- GLuint count, GLint x, GLint y,
- const void *values, const GLubyte mask[] )
-{
-#ifdef SPAN_VARS
- SPAN_VARS
-#endif
- const RB_TYPE (*src)[RB_COMPONENTS] = (const RB_TYPE (*)[RB_COMPONENTS]) values;
- GLuint i;
- if (mask) {
- for (i = 0; i < count; i++) {
- if (mask[i]) {
- RB_TYPE row[4];
- INIT_PIXEL_PTR(pixel, x, y);
- STORE_PIXEL(pixel, x + i, y, src[i]);
- PUT_PIXEL(ctx, x + i, YFLIP(xrb, y), pixel);
- }
- }
- }
- else {
- char *row = swrast_drawable(ctx->DrawBuffer)->row;
- INIT_PIXEL_PTR(pixel, x, y);
- for (i = 0; i < count; i++) {
- STORE_PIXEL(pixel, x + i, y, src[i]);
- INC_PIXEL_PTR(pixel);
- }
- PUT_ROW( ctx, x, YFLIP(xrb, y), count, row );
- }
- (void) rb;
-}
-
-
-static void
-NAME(put_row_rgb)( GLcontext *ctx, struct gl_renderbuffer *rb,
- GLuint count, GLint x, GLint y,
- const void *values, const GLubyte mask[] )
-{
-#ifdef SPAN_VARS
- SPAN_VARS
-#endif
- const RB_TYPE (*src)[3] = (const RB_TYPE (*)[3]) values;
- GLuint i;
- if (mask) {
- for (i = 0; i < count; i++) {
- if (mask[i]) {
- RB_TYPE row[4];
- INIT_PIXEL_PTR(pixel, x, y);
-#ifdef STORE_PIXEL_RGB
- STORE_PIXEL_RGB(pixel, x + i, y, src[i]);
-#else
- STORE_PIXEL(pixel, x + i, y, src[i]);
-#endif
- PUT_PIXEL(ctx, x + i, YFLIP(xrb, y), pixel);
- }
- }
- }
- else {
- char *row = swrast_drawable(ctx->DrawBuffer)->row;
- INIT_PIXEL_PTR(pixel, x, y);
- for (i = 0; i < count; i++) {
-#ifdef STORE_PIXEL_RGB
- STORE_PIXEL_RGB(pixel, x + i, y, src[i]);
-#else
- STORE_PIXEL(pixel, x + i, y, src[i]);
-#endif
- INC_PIXEL_PTR(pixel);
- }
- PUT_ROW( ctx, x, YFLIP(xrb, y), count, row );
- }
- (void) rb;
-}
-
-
-static void
-NAME(put_mono_row)( GLcontext *ctx, struct gl_renderbuffer *rb,
- GLuint count, GLint x, GLint y,
- const void *value, const GLubyte mask[] )
-{
-#ifdef SPAN_VARS
- SPAN_VARS
-#endif
- const RB_TYPE *src = (const RB_TYPE *) value;
- GLuint i;
- if (mask) {
- for (i = 0; i < count; i++) {
- if (mask[i]) {
- RB_TYPE row[4];
- INIT_PIXEL_PTR(pixel, x, y);
- STORE_PIXEL(pixel, x + i, y, src);
- PUT_PIXEL(ctx, x + i, YFLIP(xrb, y), pixel);
- }
- }
- }
- else {
- char *row = swrast_drawable(ctx->DrawBuffer)->row;
- INIT_PIXEL_PTR(pixel, x, y);
- for (i = 0; i < count; i++) {
- STORE_PIXEL(pixel, x + i, y, src);
- INC_PIXEL_PTR(pixel);
- }
- PUT_ROW( ctx, x, YFLIP(xrb, y), count, row );
- }
- (void) rb;
-}
-
-
-static void
-NAME(put_values)( GLcontext *ctx, struct gl_renderbuffer *rb,
- GLuint count, const GLint x[], const GLint y[],
- const void *values, const GLubyte mask[] )
-{
-#ifdef SPAN_VARS
- SPAN_VARS
-#endif
- const RB_TYPE (*src)[RB_COMPONENTS] = (const RB_TYPE (*)[RB_COMPONENTS]) values;
- GLuint i;
- ASSERT(mask);
- for (i = 0; i < count; i++) {
- if (mask[i]) {
- RB_TYPE row[4];
- INIT_PIXEL_PTR(pixel, x, y);
- STORE_PIXEL(pixel, x[i], y[i], src[i]);
- PUT_PIXEL(ctx, x[i], YFLIP(xrb, y[i]), pixel);
- }
- }
- (void) rb;
-}
-
-
-static void
-NAME(put_mono_values)( GLcontext *ctx, struct gl_renderbuffer *rb,
- GLuint count, const GLint x[], const GLint y[],
- const void *value, const GLubyte mask[] )
-{
-#ifdef SPAN_VARS
- SPAN_VARS
-#endif
- const RB_TYPE *src = (const RB_TYPE *) value;
- GLuint i;
- ASSERT(mask);
- for (i = 0; i < count; i++) {
- if (mask[i]) {
- RB_TYPE row[4];
- INIT_PIXEL_PTR(pixel, x, y);
- STORE_PIXEL(pixel, x[i], y[i], src);
- PUT_PIXEL(ctx, x[i], YFLIP(xrb, y[i]), pixel);
- }
- }
- (void) rb;
-}
-
-
-#undef NAME
-#undef RB_TYPE
-#undef RB_COMPONENTS
-#undef SPAN_VARS
-#undef INIT_PIXEL_PTR
-#undef INC_PIXEL_PTR
-#undef STORE_PIXEL
-#undef STORE_PIXEL_RGB
-#undef FETCH_PIXEL
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.1
+ *
+ * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+/*
+ * Modified version of swrast/s_spantemp.h for front-buffer rendering. The
+ * no-mask paths use a scratch row to avoid repeated calls to the loader.
+ *
+ * For the mask paths we always use an array of 4 elements of RB_TYPE. This is
+ * to satisfy the xorg loader requirement of an image pitch of 32 bits and
+ * should be ok for other loaders also.
+ */
+
+
+#ifndef _SWRAST_SPANTEMP_ONCE
+#define _SWRAST_SPANTEMP_ONCE
+
+static INLINE void
+PUT_PIXEL( struct gl_context *glCtx, GLint x, GLint y, GLvoid *p )
+{
+ __DRIcontext *ctx = swrast_context(glCtx)->cPriv;
+ __DRIdrawable *draw = swrast_drawable(glCtx->DrawBuffer)->dPriv;
+
+ __DRIscreen *screen = ctx->driScreenPriv;
+
+ screen->swrast_loader->putImage(draw, __DRI_SWRAST_IMAGE_OP_DRAW,
+ x, y, 1, 1, (char *)p,
+ draw->loaderPrivate);
+}
+
+
+static INLINE void
+GET_PIXEL( struct gl_context *glCtx, GLint x, GLint y, GLubyte *p )
+{
+ __DRIcontext *ctx = swrast_context(glCtx)->cPriv;
+ __DRIdrawable *read = swrast_drawable(glCtx->ReadBuffer)->dPriv;
+
+ __DRIscreen *screen = ctx->driScreenPriv;
+
+ screen->swrast_loader->getImage(read, x, y, 1, 1, (char *)p,
+ read->loaderPrivate);
+}
+
+static INLINE void
+PUT_ROW( struct gl_context *glCtx, GLint x, GLint y, GLuint n, char *row )
+{
+ __DRIcontext *ctx = swrast_context(glCtx)->cPriv;
+ __DRIdrawable *draw = swrast_drawable(glCtx->DrawBuffer)->dPriv;
+
+ __DRIscreen *screen = ctx->driScreenPriv;
+
+ screen->swrast_loader->putImage(draw, __DRI_SWRAST_IMAGE_OP_DRAW,
+ x, y, n, 1, row,
+ draw->loaderPrivate);
+}
+
+static INLINE void
+GET_ROW( struct gl_context *glCtx, GLint x, GLint y, GLuint n, char *row )
+{
+ __DRIcontext *ctx = swrast_context(glCtx)->cPriv;
+ __DRIdrawable *read = swrast_drawable(glCtx->ReadBuffer)->dPriv;
+
+ __DRIscreen *screen = ctx->driScreenPriv;
+
+ screen->swrast_loader->getImage(read, x, y, n, 1, row,
+ read->loaderPrivate);
+}
+
+#endif /* _SWRAST_SPANTEMP_ONCE */
+
+
+/*
+ * Templates for the span/pixel-array write/read functions called via
+ * the gl_renderbuffer's GetRow, GetValues, PutRow, PutMonoRow, PutValues
+ * and PutMonoValues functions.
+ *
+ * Define the following macros before including this file:
+ * NAME(BASE) to generate the function name (i.e. add prefix or suffix)
+ * RB_TYPE the renderbuffer DataType
+ * SPAN_VARS to declare any local variables
+ * INIT_PIXEL_PTR(P, X, Y) to initialize a pointer to a pixel
+ * INC_PIXEL_PTR(P) to increment a pixel pointer by one pixel
+ * STORE_PIXEL(DST, X, Y, VALUE) to store pixel values in buffer
+ * FETCH_PIXEL(DST, SRC) to fetch pixel values from buffer
+ *
+ * Note that in the STORE_PIXEL macros, we also pass in the (X,Y) coordinates
+ * for the pixels to be stored. This is useful when dithering and probably
+ * ignored otherwise.
+ */
+
+#include "main/macros.h"
+
+
+#if !defined(RB_COMPONENTS)
+#define RB_COMPONENTS 4
+#endif
+
+
+static void
+NAME(get_row)( struct gl_context *ctx, struct gl_renderbuffer *rb,
+ GLuint count, GLint x, GLint y, void *values )
+{
+#ifdef SPAN_VARS
+ SPAN_VARS
+#endif
+ RB_TYPE (*dest)[RB_COMPONENTS] = (RB_TYPE (*)[RB_COMPONENTS]) values;
+ GLuint i;
+ char *row = swrast_drawable(ctx->ReadBuffer)->row;
+ INIT_PIXEL_PTR(pixel, x, y);
+ GET_ROW( ctx, x, YFLIP(xrb, y), count, row );
+ for (i = 0; i < count; i++) {
+ FETCH_PIXEL(dest[i], pixel);
+ INC_PIXEL_PTR(pixel);
+ }
+ (void) rb;
+}
+
+
+static void
+NAME(get_values)( struct gl_context *ctx, struct gl_renderbuffer *rb,
+ GLuint count, const GLint x[], const GLint y[], void *values )
+{
+#ifdef SPAN_VARS
+ SPAN_VARS
+#endif
+ RB_TYPE (*dest)[RB_COMPONENTS] = (RB_TYPE (*)[RB_COMPONENTS]) values;
+ GLuint i;
+ for (i = 0; i < count; i++) {
+ RB_TYPE pixel[4];
+ GET_PIXEL(ctx, x[i], YFLIP(xrb, y[i]), pixel);
+ FETCH_PIXEL(dest[i], pixel);
+ }
+ (void) rb;
+}
+
+
+static void
+NAME(put_row)( struct gl_context *ctx, struct gl_renderbuffer *rb,
+ GLuint count, GLint x, GLint y,
+ const void *values, const GLubyte mask[] )
+{
+#ifdef SPAN_VARS
+ SPAN_VARS
+#endif
+ const RB_TYPE (*src)[RB_COMPONENTS] = (const RB_TYPE (*)[RB_COMPONENTS]) values;
+ GLuint i;
+ if (mask) {
+ for (i = 0; i < count; i++) {
+ if (mask[i]) {
+ RB_TYPE row[4];
+ INIT_PIXEL_PTR(pixel, x, y);
+ STORE_PIXEL(pixel, x + i, y, src[i]);
+ PUT_PIXEL(ctx, x + i, YFLIP(xrb, y), pixel);
+ }
+ }
+ }
+ else {
+ char *row = swrast_drawable(ctx->DrawBuffer)->row;
+ INIT_PIXEL_PTR(pixel, x, y);
+ for (i = 0; i < count; i++) {
+ STORE_PIXEL(pixel, x + i, y, src[i]);
+ INC_PIXEL_PTR(pixel);
+ }
+ PUT_ROW( ctx, x, YFLIP(xrb, y), count, row );
+ }
+ (void) rb;
+}
+
+
+static void
+NAME(put_row_rgb)( struct gl_context *ctx, struct gl_renderbuffer *rb,
+ GLuint count, GLint x, GLint y,
+ const void *values, const GLubyte mask[] )
+{
+#ifdef SPAN_VARS
+ SPAN_VARS
+#endif
+ const RB_TYPE (*src)[3] = (const RB_TYPE (*)[3]) values;
+ GLuint i;
+ if (mask) {
+ for (i = 0; i < count; i++) {
+ if (mask[i]) {
+ RB_TYPE row[4];
+ INIT_PIXEL_PTR(pixel, x, y);
+#ifdef STORE_PIXEL_RGB
+ STORE_PIXEL_RGB(pixel, x + i, y, src[i]);
+#else
+ STORE_PIXEL(pixel, x + i, y, src[i]);
+#endif
+ PUT_PIXEL(ctx, x + i, YFLIP(xrb, y), pixel);
+ }
+ }
+ }
+ else {
+ char *row = swrast_drawable(ctx->DrawBuffer)->row;
+ INIT_PIXEL_PTR(pixel, x, y);
+ for (i = 0; i < count; i++) {
+#ifdef STORE_PIXEL_RGB
+ STORE_PIXEL_RGB(pixel, x + i, y, src[i]);
+#else
+ STORE_PIXEL(pixel, x + i, y, src[i]);
+#endif
+ INC_PIXEL_PTR(pixel);
+ }
+ PUT_ROW( ctx, x, YFLIP(xrb, y), count, row );
+ }
+ (void) rb;
+}
+
+
+static void
+NAME(put_mono_row)( struct gl_context *ctx, struct gl_renderbuffer *rb,
+ GLuint count, GLint x, GLint y,
+ const void *value, const GLubyte mask[] )
+{
+#ifdef SPAN_VARS
+ SPAN_VARS
+#endif
+ const RB_TYPE *src = (const RB_TYPE *) value;
+ GLuint i;
+ if (mask) {
+ for (i = 0; i < count; i++) {
+ if (mask[i]) {
+ RB_TYPE row[4];
+ INIT_PIXEL_PTR(pixel, x, y);
+ STORE_PIXEL(pixel, x + i, y, src);
+ PUT_PIXEL(ctx, x + i, YFLIP(xrb, y), pixel);
+ }
+ }
+ }
+ else {
+ char *row = swrast_drawable(ctx->DrawBuffer)->row;
+ INIT_PIXEL_PTR(pixel, x, y);
+ for (i = 0; i < count; i++) {
+ STORE_PIXEL(pixel, x + i, y, src);
+ INC_PIXEL_PTR(pixel);
+ }
+ PUT_ROW( ctx, x, YFLIP(xrb, y), count, row );
+ }
+ (void) rb;
+}
+
+
+static void
+NAME(put_values)( struct gl_context *ctx, struct gl_renderbuffer *rb,
+ GLuint count, const GLint x[], const GLint y[],
+ const void *values, const GLubyte mask[] )
+{
+#ifdef SPAN_VARS
+ SPAN_VARS
+#endif
+ const RB_TYPE (*src)[RB_COMPONENTS] = (const RB_TYPE (*)[RB_COMPONENTS]) values;
+ GLuint i;
+ ASSERT(mask);
+ for (i = 0; i < count; i++) {
+ if (mask[i]) {
+ RB_TYPE row[4];
+ INIT_PIXEL_PTR(pixel, x, y);
+ STORE_PIXEL(pixel, x[i], y[i], src[i]);
+ PUT_PIXEL(ctx, x[i], YFLIP(xrb, y[i]), pixel);
+ }
+ }
+ (void) rb;
+}
+
+
+static void
+NAME(put_mono_values)( struct gl_context *ctx, struct gl_renderbuffer *rb,
+ GLuint count, const GLint x[], const GLint y[],
+ const void *value, const GLubyte mask[] )
+{
+#ifdef SPAN_VARS
+ SPAN_VARS
+#endif
+ const RB_TYPE *src = (const RB_TYPE *) value;
+ GLuint i;
+ ASSERT(mask);
+ for (i = 0; i < count; i++) {
+ if (mask[i]) {
+ RB_TYPE row[4];
+ INIT_PIXEL_PTR(pixel, x, y);
+ STORE_PIXEL(pixel, x[i], y[i], src);
+ PUT_PIXEL(ctx, x[i], YFLIP(xrb, y[i]), pixel);
+ }
+ }
+ (void) rb;
+}
+
+
+#undef NAME
+#undef RB_TYPE
+#undef RB_COMPONENTS
+#undef SPAN_VARS
+#undef INIT_PIXEL_PTR
+#undef INC_PIXEL_PTR
+#undef STORE_PIXEL
+#undef STORE_PIXEL_RGB
+#undef FETCH_PIXEL
diff --git a/mesalib/src/mesa/drivers/windows/fx/fx.rc b/mesalib/src/mesa/drivers/windows/fx/fx.rc
new file mode 100644
index 000000000..a9aedfc97
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/fx/fx.rc
@@ -0,0 +1,39 @@
+#include <windows.h>
+
+#define PRODNAME "Mesa 6.x"
+#define CONTACTSTR "http://www.mesa3d.org"
+#define HWSTR "3dfx Voodoo Graphics, Voodoo Rush, Voodoo^2, Voodoo Banshee, Velocity 100/200, Voodoo3, Voodoo4, Voodoo5"
+#define COPYRIGHTSTR "Copyright \251 Brian E. Paul"
+
+#define VERSIONSTR "6.3.0.1"
+#define MANVERSION 6
+#define MANREVISION 3
+#define BUILD_NUMBER 1
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION MANVERSION, MANREVISION, 0, BUILD_NUMBER
+ PRODUCTVERSION MANVERSION, MANREVISION, 0, BUILD_NUMBER
+ FILEFLAGSMASK 0x0030003FL
+
+ FILEOS VOS_DOS_WINDOWS32
+ FILETYPE VFT_DRV
+ FILESUBTYPE VFT2_DRV_INSTALLABLE
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904E4"
+ BEGIN
+ VALUE "FileDescription", PRODNAME
+ VALUE "FileVersion", VERSIONSTR
+ VALUE "LegalCopyright", COPYRIGHTSTR
+ VALUE "ProductName", PRODNAME
+ VALUE "Graphics Subsystem", HWSTR
+ VALUE "Contact", CONTACTSTR
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ /* the following line should be extended for localized versions */
+ VALUE "Translation", 0x409, 1252
+ END
+END
diff --git a/mesalib/src/mesa/drivers/windows/fx/fxopengl.def b/mesalib/src/mesa/drivers/windows/fx/fxopengl.def
index d65b763d2..8714ae983 100644
--- a/mesalib/src/mesa/drivers/windows/fx/fxopengl.def
+++ b/mesalib/src/mesa/drivers/windows/fx/fxopengl.def
@@ -1,955 +1,953 @@
-LIBRARY OpenGL32
-DESCRIPTION "Mesa 5.1"
-EXPORTS
- glAccum
- glActiveStencilFaceEXT
- glActiveTexture
- glActiveTextureARB
- glAlphaFunc
- glAreProgramsResidentNV
- glAreTexturesResident
- glAreTexturesResidentEXT
- glArrayElement
- glArrayElementEXT
- glBegin
- glBeginQueryARB
- glBindBufferARB
- glBindProgramARB
- glBindProgramNV
- glBindTexture
- glBindTextureEXT
- glBitmap
-;glBlendColor
-;glBlendColorEXT
- glBlendEquation
- glBlendEquationEXT
- glBlendFunc
- glBlendFuncSeparate
- glBlendFuncSeparateEXT
- glBlendFuncSeparateINGR
- glBufferDataARB
- glBufferSubDataARB
- glCallList
- glCallLists
- glClear
- glClearAccum
- glClearColor
- glClearDepth
- glClearIndex
- glClearStencil
- glClientActiveTexture
- glClientActiveTextureARB
- glClipPlane
- glColorMask
- glColorMaterial
- glColorPointer
- glColorPointerEXT
- glColorSubTable
- glColorSubTableEXT
- glColorTable
- glColorTableEXT
- glColorTableParameterfv
- glColorTableParameterfvSGI
- glColorTableParameteriv
- glColorTableParameterivSGI
- glColorTableSGI
- glColor3b
- glColor3bv
- glColor3d
- glColor3dv
- glColor3f
- glColor3fv
- glColor3i
- glColor3iv
- glColor3s
- glColor3sv
- glColor3ub
- glColor3ubv
- glColor3ui
- glColor3uiv
- glColor3us
- glColor3usv
- glColor4b
- glColor4bv
- glColor4d
- glColor4dv
- glColor4f
- glColor4fv
- glColor4i
- glColor4iv
- glColor4s
- glColor4sv
- glColor4ub
- glColor4ubv
- glColor4ui
- glColor4uiv
- glColor4us
- glColor4usv
- glCombinerInputNV
- glCombinerOutputNV
- glCombinerParameterfNV
- glCombinerParameterfvNV
- glCombinerParameteriNV
- glCombinerParameterivNV
- glCompressedTexImage1D
- glCompressedTexImage1DARB
- glCompressedTexImage2D
- glCompressedTexImage2DARB
- glCompressedTexImage3D
- glCompressedTexImage3DARB
- glCompressedTexSubImage1D
- glCompressedTexSubImage1DARB
- glCompressedTexSubImage2D
- glCompressedTexSubImage2DARB
- glCompressedTexSubImage3D
- glCompressedTexSubImage3DARB
- glConvolutionFilter1D
- glConvolutionFilter1DEXT
- glConvolutionFilter2D
- glConvolutionFilter2DEXT
- glConvolutionParameterf
- glConvolutionParameterfEXT
- glConvolutionParameterfv
- glConvolutionParameterfvEXT
- glConvolutionParameteri
- glConvolutionParameteriEXT
- glConvolutionParameteriv
- glConvolutionParameterivEXT
- glCopyColorSubTable
- glCopyColorSubTableEXT
- glCopyColorTable
- glCopyColorTableSGI
- glCopyConvolutionFilter1D
- glCopyConvolutionFilter1DEXT
- glCopyConvolutionFilter2D
- glCopyConvolutionFilter2DEXT
- glCopyPixels
- glCopyTexImage1D
- glCopyTexImage1DEXT
- glCopyTexImage2D
- glCopyTexImage2DEXT
- glCopyTexSubImage1D
- glCopyTexSubImage1DEXT
- glCopyTexSubImage2D
- glCopyTexSubImage2DEXT
- glCopyTexSubImage3D
- glCopyTexSubImage3DEXT
- glCullFace
- glCullParameterdvEXT
- glCullParameterfvEXT
- glDeleteBuffersARB
- glDeleteFencesNV
- glDeleteLists
- glDeleteProgramsARB
- glDeleteProgramsNV
- glDeleteQueriesARB
- glDeleteTextures
- glDeleteTexturesEXT
- glDepthBoundsEXT
- glDepthFunc
- glDepthMask
- glDepthRange
- glDetailTexFuncSGIS
- glDisable
- glDisableClientState
- glDisableVertexAttribArrayARB
- glDrawArrays
- glDrawArraysEXT
- glDrawBuffer
- glDrawElements
- glDrawPixels
- glDrawRangeElements
- glDrawRangeElementsEXT
- glEdgeFlag
- glEdgeFlagPointer
- glEdgeFlagPointerEXT
- glEdgeFlagv
- glEnable
- glEnableClientState
- glEnableVertexAttribArrayARB
- glEnd
- glEndList
- glEndQueryARB
- glEvalCoord1d
- glEvalCoord1dv
- glEvalCoord1f
- glEvalCoord1fv
- glEvalCoord2d
- glEvalCoord2dv
- glEvalCoord2f
- glEvalCoord2fv
- glEvalMesh1
- glEvalMesh2
- glEvalPoint1
- glEvalPoint2
- glExecuteProgramNV
- glFeedbackBuffer
- glFinalCombinerInputNV
- glFinish
- glFinishFenceNV
- glFlush
- glFlushRasterSGIX
- glFlushVertexArrayRangeNV
- glFogCoordd
- glFogCoorddEXT
- glFogCoorddv
- glFogCoorddvEXT
- glFogCoordf
- glFogCoordfEXT
- glFogCoordfv
- glFogCoordfvEXT
- glFogCoordPointer
- glFogCoordPointerEXT
- glFogf
- glFogfv
- glFogi
- glFogiv
- glFragmentColorMaterialSGIX
- glFragmentLightfSGIX
- glFragmentLightfvSGIX
- glFragmentLightiSGIX
- glFragmentLightivSGIX
- glFragmentLightModelfSGIX
- glFragmentLightModelfvSGIX
- glFragmentLightModeliSGIX
- glFragmentLightModelivSGIX
- glFragmentMaterialfSGIX
- glFragmentMaterialfvSGIX
- glFragmentMaterialiSGIX
- glFragmentMaterialivSGIX
- glFrameZoomSGIX
- glFrontFace
- glFrustum
- glGenBuffersARB
- glGenFencesNV
- glGenLists
- glGenProgramsARB
- glGenProgramsNV
- glGenQueriesARB
- glGenTextures
- glGenTexturesEXT
- glGetBooleanv
- glGetBufferParameterivARB
- glGetBufferPointervARB
- glGetBufferSubDataARB
- glGetClipPlane
- glGetColorTable
- glGetColorTableEXT
- glGetColorTableParameterfv
- glGetColorTableParameterfvEXT
- glGetColorTableParameterfvSGI
- glGetColorTableParameteriv
- glGetColorTableParameterivEXT
- glGetColorTableParameterivSGI
- glGetColorTableSGI
- glGetCombinerInputParameterfvNV
- glGetCombinerInputParameterivNV
- glGetCombinerOutputParameterfvNV
- glGetCombinerOutputParameterivNV
- glGetCompressedTexImage
- glGetCompressedTexImageARB
- glGetConvolutionFilter
- glGetConvolutionFilterEXT
- glGetConvolutionParameterfv
- glGetConvolutionParameterfvEXT
- glGetConvolutionParameteriv
- glGetConvolutionParameterivEXT
- glGetDetailTexFuncSGIS
- glGetDoublev
- glGetError
- glGetFenceivNV
- glGetFinalCombinerInputParameterfvNV
- glGetFinalCombinerInputParameterivNV
- glGetFloatv
- glGetFragmentLightfvSGIX
- glGetFragmentLightivSGIX
- glGetFragmentMaterialfvSGIX
- glGetFragmentMaterialivSGIX
- glGetHistogram
- glGetHistogramEXT
- glGetHistogramParameterfv
- glGetHistogramParameterfvEXT
- glGetHistogramParameteriv
- glGetHistogramParameterivEXT
- glGetInstrumentsSGIX
- glGetIntegerv
- glGetLightfv
- glGetLightiv
- glGetListParameterfvSGIX
- glGetListParameterivSGIX
- glGetMapdv
- glGetMapfv
- glGetMapiv
- glGetMaterialfv
- glGetMaterialiv
- glGetMinmax
- glGetMinmaxEXT
- glGetMinmaxParameterfv
- glGetMinmaxParameterfvEXT
- glGetMinmaxParameteriv
- glGetMinmaxParameterivEXT
- glGetPixelMapfv
- glGetPixelMapuiv
- glGetPixelMapusv
- glGetPixelTexGenParameterfvSGIS
- glGetPixelTexGenParameterivSGIS
- glGetPointerv
- glGetPointervEXT
- glGetPolygonStipple
- glGetProgramEnvParameterdvARB
- glGetProgramEnvParameterfvARB
- glGetProgramivARB
- glGetProgramivNV
- glGetProgramLocalParameterdvARB
- glGetProgramLocalParameterfvARB
- glGetProgramNamedParameterdvNV
- glGetProgramNamedParameterfvNV
- glGetProgramParameterdvNV
- glGetProgramParameterfvNV
- glGetProgramStringARB
- glGetProgramStringNV
- glGetQueryivARB
- glGetQueryObjectivARB
- glGetQueryObjectuivARB
- glGetSeparableFilter
- glGetSeparableFilterEXT
- glGetSharpenTexFuncSGIS
- glGetString
- glGetTexEnvfv
- glGetTexEnviv
- glGetTexFilterFuncSGIS
- glGetTexGendv
- glGetTexGenfv
- glGetTexGeniv
- glGetTexImage
- glGetTexLevelParameterfv
- glGetTexLevelParameteriv
- glGetTexParameterfv
- glGetTexParameteriv
- glGetTrackMatrixivNV
- glGetVertexAttribdvARB
- glGetVertexAttribdvNV
- glGetVertexAttribfvARB
- glGetVertexAttribfvNV
- glGetVertexAttribivARB
- glGetVertexAttribivNV
- glGetVertexAttribPointervARB
- glGetVertexAttribPointervNV
- glHint
- glHintPGI
- glHistogram
- glHistogramEXT
- glIndexd
- glIndexdv
- glIndexf
- glIndexFuncEXT
- glIndexfv
- glIndexi
- glIndexiv
- glIndexMask
- glIndexMaterialEXT
- glIndexPointer
- glIndexPointerEXT
- glIndexs
- glIndexsv
- glIndexub
- glIndexubv
- glInitNames
- glInstrumentsBufferSGIX
- glInterleavedArrays
- glIsBufferARB
- glIsEnabled
- glIsFenceNV
- glIsList
- glIsProgramARB
- glIsProgramNV
- glIsQueryARB
- glIsTexture
- glIsTextureEXT
- glLightEnviSGIX
- glLightf
- glLightfv
- glLighti
- glLightiv
- glLightModelf
- glLightModelfv
- glLightModeli
- glLightModeliv
- glLineStipple
- glLineWidth
- glListBase
- glListParameterfSGIX
- glListParameterfvSGIX
- glListParameteriSGIX
- glListParameterivSGIX
- glLoadIdentity
- glLoadMatrixd
- glLoadMatrixf
- glLoadName
- glLoadProgramNV
- glLoadTransposeMatrixd
- glLoadTransposeMatrixdARB
- glLoadTransposeMatrixf
- glLoadTransposeMatrixfARB
- glLockArraysEXT
- glLogicOp
- glMapBufferARB
- glMapGrid1d
- glMapGrid1f
- glMapGrid2d
- glMapGrid2f
- glMap1d
- glMap1f
- glMap2d
- glMap2f
- glMaterialf
- glMaterialfv
- glMateriali
- glMaterialiv
- glMatrixMode
- glMinmax
- glMinmaxEXT
- glMultiDrawArrays
- glMultiDrawArraysEXT
- glMultiDrawElements
- glMultiDrawElementsEXT
- glMultiModeDrawArraysIBM
- glMultiModeDrawElementsIBM
- glMultiTexCoord1d
- glMultiTexCoord1dARB
- glMultiTexCoord1dv
- glMultiTexCoord1dvARB
- glMultiTexCoord1f
- glMultiTexCoord1fARB
- glMultiTexCoord1fv
- glMultiTexCoord1fvARB
- glMultiTexCoord1i
- glMultiTexCoord1iARB
- glMultiTexCoord1iv
- glMultiTexCoord1ivARB
- glMultiTexCoord1s
- glMultiTexCoord1sARB
- glMultiTexCoord1sv
- glMultiTexCoord1svARB
- glMultiTexCoord2d
- glMultiTexCoord2dARB
- glMultiTexCoord2dv
- glMultiTexCoord2dvARB
- glMultiTexCoord2f
- glMultiTexCoord2fARB
- glMultiTexCoord2fv
- glMultiTexCoord2fvARB
- glMultiTexCoord2i
- glMultiTexCoord2iARB
- glMultiTexCoord2iv
- glMultiTexCoord2ivARB
- glMultiTexCoord2s
- glMultiTexCoord2sARB
- glMultiTexCoord2sv
- glMultiTexCoord2svARB
- glMultiTexCoord3d
- glMultiTexCoord3dARB
- glMultiTexCoord3dv
- glMultiTexCoord3dvARB
- glMultiTexCoord3f
- glMultiTexCoord3fARB
- glMultiTexCoord3fv
- glMultiTexCoord3fvARB
- glMultiTexCoord3i
- glMultiTexCoord3iARB
- glMultiTexCoord3iv
- glMultiTexCoord3ivARB
- glMultiTexCoord3s
- glMultiTexCoord3sARB
- glMultiTexCoord3sv
- glMultiTexCoord3svARB
- glMultiTexCoord4d
- glMultiTexCoord4dARB
- glMultiTexCoord4dv
- glMultiTexCoord4dvARB
- glMultiTexCoord4f
- glMultiTexCoord4fARB
- glMultiTexCoord4fv
- glMultiTexCoord4fvARB
- glMultiTexCoord4i
- glMultiTexCoord4iARB
- glMultiTexCoord4iv
- glMultiTexCoord4ivARB
- glMultiTexCoord4s
- glMultiTexCoord4sARB
- glMultiTexCoord4sv
- glMultiTexCoord4svARB
- glMultMatrixd
- glMultMatrixf
- glMultTransposeMatrixd
- glMultTransposeMatrixdARB
- glMultTransposeMatrixf
- glMultTransposeMatrixfARB
- glNewList
- glNormalPointer
- glNormalPointerEXT
- glNormal3b
- glNormal3bv
- glNormal3d
- glNormal3dv
- glNormal3f
- glNormal3fv
- glNormal3i
- glNormal3iv
- glNormal3s
- glNormal3sv
- glOrtho
- glPassThrough
- glPixelMapfv
- glPixelMapuiv
- glPixelMapusv
- glPixelStoref
- glPixelStorei
- glPixelTexGenParameterfSGIS
- glPixelTexGenParameterfvSGIS
- glPixelTexGenParameteriSGIS
- glPixelTexGenParameterivSGIS
- glPixelTexGenSGIX
- glPixelTransferf
- glPixelTransferi
- glPixelZoom
- glPointParameterf
- glPointParameterfARB
- glPointParameterfEXT
- glPointParameterfSGIS
- glPointParameterfv
- glPointParameterfvARB
- glPointParameterfvEXT
- glPointParameterfvSGIS
- glPointParameteri
- glPointParameteriNV
- glPointParameteriv
- glPointParameterivNV
- glPointSize
- glPollInstrumentsSGIX
- glPolygonMode
- glPolygonOffset
- glPolygonOffsetEXT
- glPolygonStipple
- glPopAttrib
- glPopClientAttrib
- glPopMatrix
- glPopName
- glPrioritizeTextures
- glPrioritizeTexturesEXT
- glProgramEnvParameter4dARB
- glProgramEnvParameter4dvARB
- glProgramEnvParameter4fARB
- glProgramEnvParameter4fvARB
- glProgramLocalParameter4dARB
- glProgramLocalParameter4dvARB
- glProgramLocalParameter4fARB
- glProgramLocalParameter4fvARB
- glProgramNamedParameter4dNV
- glProgramNamedParameter4dvNV
- glProgramNamedParameter4fNV
- glProgramNamedParameter4fvNV
- glProgramParameters4dvNV
- glProgramParameters4fvNV
- glProgramParameter4dNV
- glProgramParameter4dvNV
- glProgramParameter4fNV
- glProgramParameter4fvNV
- glProgramStringARB
- glPushAttrib
- glPushClientAttrib
- glPushMatrix
- glPushName
- glRasterPos2d
- glRasterPos2dv
- glRasterPos2f
- glRasterPos2fv
- glRasterPos2i
- glRasterPos2iv
- glRasterPos2s
- glRasterPos2sv
- glRasterPos3d
- glRasterPos3dv
- glRasterPos3f
- glRasterPos3fv
- glRasterPos3i
- glRasterPos3iv
- glRasterPos3s
- glRasterPos3sv
- glRasterPos4d
- glRasterPos4dv
- glRasterPos4f
- glRasterPos4fv
- glRasterPos4i
- glRasterPos4iv
- glRasterPos4s
- glRasterPos4sv
- glReadBuffer
- glReadInstrumentsSGIX
- glReadPixels
- glRectd
- glRectdv
- glRectf
- glRectfv
- glRecti
- glRectiv
- glRects
- glRectsv
- glReferencePlaneSGIX
- glRenderMode
- glRequestResidentProgramsNV
- glResetHistogram
- glResetHistogramEXT
- glResetMinmax
- glResetMinmaxEXT
- glResizeBuffersMESA
- glRotated
- glRotatef
- glSampleCoverage
- glSampleCoverageARB
- glSampleMaskEXT
- glSampleMaskSGIS
- glSamplePatternEXT
- glSamplePatternSGIS
- glScaled
- glScalef
- glScissor
- glSecondaryColorPointer
- glSecondaryColorPointerEXT
- glSecondaryColor3b
- glSecondaryColor3bEXT
- glSecondaryColor3bv
- glSecondaryColor3bvEXT
- glSecondaryColor3d
- glSecondaryColor3dEXT
- glSecondaryColor3dv
- glSecondaryColor3dvEXT
- glSecondaryColor3f
- glSecondaryColor3fEXT
- glSecondaryColor3fv
- glSecondaryColor3fvEXT
- glSecondaryColor3i
- glSecondaryColor3iEXT
- glSecondaryColor3iv
- glSecondaryColor3ivEXT
- glSecondaryColor3s
- glSecondaryColor3sEXT
- glSecondaryColor3sv
- glSecondaryColor3svEXT
- glSecondaryColor3ub
- glSecondaryColor3ubEXT
- glSecondaryColor3ubv
- glSecondaryColor3ubvEXT
- glSecondaryColor3ui
- glSecondaryColor3uiEXT
- glSecondaryColor3uiv
- glSecondaryColor3uivEXT
- glSecondaryColor3us
- glSecondaryColor3usEXT
- glSecondaryColor3usv
- glSecondaryColor3usvEXT
- glSelectBuffer
- glSeparableFilter2D
- glSeparableFilter2DEXT
- glSetFenceNV
- glShadeModel
- glSharpenTexFuncSGIS
- glSpriteParameterfSGIX
- glSpriteParameterfvSGIX
- glSpriteParameteriSGIX
- glSpriteParameterivSGIX
- glStartInstrumentsSGIX
- glStencilFunc
- glStencilMask
- glStencilOp
- glStopInstrumentsSGIX
- glTagSampleBufferSGIX
- glTbufferMask3DFX
- glTestFenceNV
- glTexCoordPointer
- glTexCoordPointerEXT
- glTexCoord1d
- glTexCoord1dv
- glTexCoord1f
- glTexCoord1fv
- glTexCoord1i
- glTexCoord1iv
- glTexCoord1s
- glTexCoord1sv
- glTexCoord2d
- glTexCoord2dv
- glTexCoord2f
- glTexCoord2fv
- glTexCoord2i
- glTexCoord2iv
- glTexCoord2s
- glTexCoord2sv
- glTexCoord3d
- glTexCoord3dv
- glTexCoord3f
- glTexCoord3fv
- glTexCoord3i
- glTexCoord3iv
- glTexCoord3s
- glTexCoord3sv
- glTexCoord4d
- glTexCoord4dv
- glTexCoord4f
- glTexCoord4fv
- glTexCoord4i
- glTexCoord4iv
- glTexCoord4s
- glTexCoord4sv
- glTexEnvf
- glTexEnvfv
- glTexEnvi
- glTexEnviv
- glTexFilterFuncSGIS
- glTexGend
- glTexGendv
- glTexGenf
- glTexGenfv
- glTexGeni
- glTexGeniv
- glTexImage1D
- glTexImage2D
- glTexImage3D
- glTexImage3DEXT
- glTexImage4DSGIS
- glTexParameterf
- glTexParameterfv
- glTexParameteri
- glTexParameteriv
- glTexSubImage1D
- glTexSubImage1DEXT
- glTexSubImage2D
- glTexSubImage2DEXT
- glTexSubImage3D
- glTexSubImage3DEXT
- glTexSubImage4DSGIS
- glTrackMatrixNV
- glTranslated
- glTranslatef
- glUnlockArraysEXT
- glUnmapBufferARB
- glVertexArrayRangeNV
- glVertexAttribPointerARB
- glVertexAttribPointerNV
- glVertexAttribs1dvNV
- glVertexAttribs1fvNV
- glVertexAttribs1svNV
- glVertexAttribs2dvNV
- glVertexAttribs2fvNV
- glVertexAttribs2svNV
- glVertexAttribs3dvNV
- glVertexAttribs3fvNV
- glVertexAttribs3svNV
- glVertexAttribs4dvNV
- glVertexAttribs4fvNV
- glVertexAttribs4svNV
- glVertexAttribs4ubvNV
- glVertexAttrib1dARB
- glVertexAttrib1dNV
- glVertexAttrib1dvARB
- glVertexAttrib1dvNV
- glVertexAttrib1fARB
- glVertexAttrib1fNV
- glVertexAttrib1fvARB
- glVertexAttrib1fvNV
- glVertexAttrib1sARB
- glVertexAttrib1sNV
- glVertexAttrib1svARB
- glVertexAttrib1svNV
- glVertexAttrib2dARB
- glVertexAttrib2dNV
- glVertexAttrib2dvARB
- glVertexAttrib2dvNV
- glVertexAttrib2fARB
- glVertexAttrib2fNV
- glVertexAttrib2fvARB
- glVertexAttrib2fvNV
- glVertexAttrib2sARB
- glVertexAttrib2sNV
- glVertexAttrib2svARB
- glVertexAttrib2svNV
- glVertexAttrib3dARB
- glVertexAttrib3dNV
- glVertexAttrib3dvARB
- glVertexAttrib3dvNV
- glVertexAttrib3fARB
- glVertexAttrib3fNV
- glVertexAttrib3fvARB
- glVertexAttrib3fvNV
- glVertexAttrib3sARB
- glVertexAttrib3sNV
- glVertexAttrib3svARB
- glVertexAttrib3svNV
- glVertexAttrib4bvARB
- glVertexAttrib4dARB
- glVertexAttrib4dNV
- glVertexAttrib4dvARB
- glVertexAttrib4dvNV
- glVertexAttrib4fARB
- glVertexAttrib4fNV
- glVertexAttrib4fvARB
- glVertexAttrib4fvNV
- glVertexAttrib4ivARB
- glVertexAttrib4NbvARB
- glVertexAttrib4NivARB
- glVertexAttrib4NsvARB
- glVertexAttrib4NubARB
- glVertexAttrib4NubvARB
- glVertexAttrib4NuivARB
- glVertexAttrib4NusvARB
- glVertexAttrib4sARB
- glVertexAttrib4sNV
- glVertexAttrib4svARB
- glVertexAttrib4svNV
- glVertexAttrib4ubNV
- glVertexAttrib4ubvARB
- glVertexAttrib4ubvNV
- glVertexAttrib4uivARB
- glVertexAttrib4usvARB
- glVertexPointer
- glVertexPointerEXT
- glVertexWeightfEXT
- glVertexWeightfvEXT
- glVertexWeightPointerEXT
- glVertex2d
- glVertex2dv
- glVertex2f
- glVertex2fv
- glVertex2i
- glVertex2iv
- glVertex2s
- glVertex2sv
- glVertex3d
- glVertex3dv
- glVertex3f
- glVertex3fv
- glVertex3i
- glVertex3iv
- glVertex3s
- glVertex3sv
- glVertex4d
- glVertex4dv
- glVertex4f
- glVertex4fv
- glVertex4i
- glVertex4iv
- glVertex4s
- glVertex4sv
- glViewport
- glWindowPos2d
- glWindowPos2dARB
- glWindowPos2dMESA
- glWindowPos2dv
- glWindowPos2dvARB
- glWindowPos2dvMESA
- glWindowPos2f
- glWindowPos2fARB
- glWindowPos2fMESA
- glWindowPos2fv
- glWindowPos2fvARB
- glWindowPos2fvMESA
- glWindowPos2i
- glWindowPos2iARB
- glWindowPos2iMESA
- glWindowPos2iv
- glWindowPos2ivARB
- glWindowPos2ivMESA
- glWindowPos2s
- glWindowPos2sARB
- glWindowPos2sMESA
- glWindowPos2sv
- glWindowPos2svARB
- glWindowPos2svMESA
- glWindowPos3d
- glWindowPos3dARB
- glWindowPos3dMESA
- glWindowPos3dv
- glWindowPos3dvARB
- glWindowPos3dvMESA
- glWindowPos3f
- glWindowPos3fARB
- glWindowPos3fMESA
- glWindowPos3fv
- glWindowPos3fvARB
- glWindowPos3fvMESA
- glWindowPos3i
- glWindowPos3iARB
- glWindowPos3iMESA
- glWindowPos3iv
- glWindowPos3ivARB
- glWindowPos3ivMESA
- glWindowPos3s
- glWindowPos3sARB
- glWindowPos3sMESA
- glWindowPos3sv
- glWindowPos3svARB
- glWindowPos3svMESA
- glWindowPos4dMESA
- glWindowPos4dvMESA
- glWindowPos4fMESA
- glWindowPos4fvMESA
- glWindowPos4iMESA
- glWindowPos4ivMESA
- glWindowPos4sMESA
- glWindowPos4svMESA
- fxCloseHardware
-;fxGetScreenGeometry
- fxMesaCreateBestContext
- fxMesaCreateContext
- fxMesaDestroyContext
- fxMesaGetCurrentContext
- fxMesaMakeCurrent
- fxMesaSelectCurrentBoard
-;fxMesaSetNearFar
- fxMesaSwapBuffers
- fxMesaUpdateScreenSize
- wglChoosePixelFormat
- wglCopyContext
- wglCreateContext
- wglCreateLayerContext
- wglDeleteContext
- wglDescribeLayerPlane
- wglDescribePixelFormat
- wglGetCurrentContext
- wglGetCurrentDC
- wglGetDefaultProcAddress
- wglGetLayerPaletteEntries
- wglGetPixelFormat
- wglGetProcAddress
- wglMakeCurrent
- wglRealizeLayerPalette
- wglSetLayerPaletteEntries
- wglSetPixelFormat
- wglShareLists
- wglSwapBuffers
- wglSwapLayerBuffers
- wglUseFontBitmapsA
- wglUseFontBitmapsW
- wglUseFontOutlinesA
- wglUseFontOutlinesW
- ChoosePixelFormat
- DescribePixelFormat
- GetPixelFormat
- SetPixelFormat
- SwapBuffers
- DrvCopyContext
- DrvCreateContext
- DrvCreateLayerContext
- DrvDeleteContext
- DrvDescribeLayerPlane
- DrvDescribePixelFormat
- DrvGetLayerPaletteEntries
- DrvGetProcAddress
- DrvReleaseContext
- DrvRealizeLayerPalette
- DrvSetContext
- DrvSetLayerPaletteEntries
- DrvSetPixelFormat
- DrvShareLists
- DrvSwapBuffers
- DrvSwapLayerBuffers
- DrvValidateVersion
+LIBRARY OpenGL32
+DESCRIPTION "Mesa 5.1"
+EXPORTS
+ glAccum
+ glActiveStencilFaceEXT
+ glActiveTexture
+ glActiveTextureARB
+ glAlphaFunc
+ glAreProgramsResidentNV
+ glAreTexturesResident
+ glAreTexturesResidentEXT
+ glArrayElement
+ glArrayElementEXT
+ glBegin
+ glBeginQueryARB
+ glBindBufferARB
+ glBindProgramARB
+ glBindProgramNV
+ glBindTexture
+ glBindTextureEXT
+ glBitmap
+;glBlendColor
+;glBlendColorEXT
+ glBlendEquation
+ glBlendEquationEXT
+ glBlendFunc
+ glBlendFuncSeparate
+ glBlendFuncSeparateEXT
+ glBlendFuncSeparateINGR
+ glBufferDataARB
+ glBufferSubDataARB
+ glCallList
+ glCallLists
+ glClear
+ glClearAccum
+ glClearColor
+ glClearDepth
+ glClearIndex
+ glClearStencil
+ glClientActiveTexture
+ glClientActiveTextureARB
+ glClipPlane
+ glColorMask
+ glColorMaterial
+ glColorPointer
+ glColorPointerEXT
+ glColorSubTable
+ glColorSubTableEXT
+ glColorTable
+ glColorTableEXT
+ glColorTableParameterfv
+ glColorTableParameterfvSGI
+ glColorTableParameteriv
+ glColorTableParameterivSGI
+ glColorTableSGI
+ glColor3b
+ glColor3bv
+ glColor3d
+ glColor3dv
+ glColor3f
+ glColor3fv
+ glColor3i
+ glColor3iv
+ glColor3s
+ glColor3sv
+ glColor3ub
+ glColor3ubv
+ glColor3ui
+ glColor3uiv
+ glColor3us
+ glColor3usv
+ glColor4b
+ glColor4bv
+ glColor4d
+ glColor4dv
+ glColor4f
+ glColor4fv
+ glColor4i
+ glColor4iv
+ glColor4s
+ glColor4sv
+ glColor4ub
+ glColor4ubv
+ glColor4ui
+ glColor4uiv
+ glColor4us
+ glColor4usv
+ glCombinerInputNV
+ glCombinerOutputNV
+ glCombinerParameterfNV
+ glCombinerParameterfvNV
+ glCombinerParameteriNV
+ glCombinerParameterivNV
+ glCompressedTexImage1D
+ glCompressedTexImage1DARB
+ glCompressedTexImage2D
+ glCompressedTexImage2DARB
+ glCompressedTexImage3D
+ glCompressedTexImage3DARB
+ glCompressedTexSubImage1D
+ glCompressedTexSubImage1DARB
+ glCompressedTexSubImage2D
+ glCompressedTexSubImage2DARB
+ glCompressedTexSubImage3D
+ glCompressedTexSubImage3DARB
+ glConvolutionFilter1D
+ glConvolutionFilter1DEXT
+ glConvolutionFilter2D
+ glConvolutionFilter2DEXT
+ glConvolutionParameterf
+ glConvolutionParameterfEXT
+ glConvolutionParameterfv
+ glConvolutionParameterfvEXT
+ glConvolutionParameteri
+ glConvolutionParameteriEXT
+ glConvolutionParameteriv
+ glConvolutionParameterivEXT
+ glCopyColorSubTable
+ glCopyColorSubTableEXT
+ glCopyColorTable
+ glCopyColorTableSGI
+ glCopyConvolutionFilter1D
+ glCopyConvolutionFilter1DEXT
+ glCopyConvolutionFilter2D
+ glCopyConvolutionFilter2DEXT
+ glCopyPixels
+ glCopyTexImage1D
+ glCopyTexImage1DEXT
+ glCopyTexImage2D
+ glCopyTexImage2DEXT
+ glCopyTexSubImage1D
+ glCopyTexSubImage1DEXT
+ glCopyTexSubImage2D
+ glCopyTexSubImage2DEXT
+ glCopyTexSubImage3D
+ glCopyTexSubImage3DEXT
+ glCullFace
+ glDeleteBuffersARB
+ glDeleteFencesNV
+ glDeleteLists
+ glDeleteProgramsARB
+ glDeleteProgramsNV
+ glDeleteQueriesARB
+ glDeleteTextures
+ glDeleteTexturesEXT
+ glDepthBoundsEXT
+ glDepthFunc
+ glDepthMask
+ glDepthRange
+ glDetailTexFuncSGIS
+ glDisable
+ glDisableClientState
+ glDisableVertexAttribArrayARB
+ glDrawArrays
+ glDrawArraysEXT
+ glDrawBuffer
+ glDrawElements
+ glDrawPixels
+ glDrawRangeElements
+ glDrawRangeElementsEXT
+ glEdgeFlag
+ glEdgeFlagPointer
+ glEdgeFlagPointerEXT
+ glEdgeFlagv
+ glEnable
+ glEnableClientState
+ glEnableVertexAttribArrayARB
+ glEnd
+ glEndList
+ glEndQueryARB
+ glEvalCoord1d
+ glEvalCoord1dv
+ glEvalCoord1f
+ glEvalCoord1fv
+ glEvalCoord2d
+ glEvalCoord2dv
+ glEvalCoord2f
+ glEvalCoord2fv
+ glEvalMesh1
+ glEvalMesh2
+ glEvalPoint1
+ glEvalPoint2
+ glExecuteProgramNV
+ glFeedbackBuffer
+ glFinalCombinerInputNV
+ glFinish
+ glFinishFenceNV
+ glFlush
+ glFlushRasterSGIX
+ glFlushVertexArrayRangeNV
+ glFogCoordd
+ glFogCoorddEXT
+ glFogCoorddv
+ glFogCoorddvEXT
+ glFogCoordf
+ glFogCoordfEXT
+ glFogCoordfv
+ glFogCoordfvEXT
+ glFogCoordPointer
+ glFogCoordPointerEXT
+ glFogf
+ glFogfv
+ glFogi
+ glFogiv
+ glFragmentColorMaterialSGIX
+ glFragmentLightfSGIX
+ glFragmentLightfvSGIX
+ glFragmentLightiSGIX
+ glFragmentLightivSGIX
+ glFragmentLightModelfSGIX
+ glFragmentLightModelfvSGIX
+ glFragmentLightModeliSGIX
+ glFragmentLightModelivSGIX
+ glFragmentMaterialfSGIX
+ glFragmentMaterialfvSGIX
+ glFragmentMaterialiSGIX
+ glFragmentMaterialivSGIX
+ glFrameZoomSGIX
+ glFrontFace
+ glFrustum
+ glGenBuffersARB
+ glGenFencesNV
+ glGenLists
+ glGenProgramsARB
+ glGenProgramsNV
+ glGenQueriesARB
+ glGenTextures
+ glGenTexturesEXT
+ glGetBooleanv
+ glGetBufferParameterivARB
+ glGetBufferPointervARB
+ glGetBufferSubDataARB
+ glGetClipPlane
+ glGetColorTable
+ glGetColorTableEXT
+ glGetColorTableParameterfv
+ glGetColorTableParameterfvEXT
+ glGetColorTableParameterfvSGI
+ glGetColorTableParameteriv
+ glGetColorTableParameterivEXT
+ glGetColorTableParameterivSGI
+ glGetColorTableSGI
+ glGetCombinerInputParameterfvNV
+ glGetCombinerInputParameterivNV
+ glGetCombinerOutputParameterfvNV
+ glGetCombinerOutputParameterivNV
+ glGetCompressedTexImage
+ glGetCompressedTexImageARB
+ glGetConvolutionFilter
+ glGetConvolutionFilterEXT
+ glGetConvolutionParameterfv
+ glGetConvolutionParameterfvEXT
+ glGetConvolutionParameteriv
+ glGetConvolutionParameterivEXT
+ glGetDetailTexFuncSGIS
+ glGetDoublev
+ glGetError
+ glGetFenceivNV
+ glGetFinalCombinerInputParameterfvNV
+ glGetFinalCombinerInputParameterivNV
+ glGetFloatv
+ glGetFragmentLightfvSGIX
+ glGetFragmentLightivSGIX
+ glGetFragmentMaterialfvSGIX
+ glGetFragmentMaterialivSGIX
+ glGetHistogram
+ glGetHistogramEXT
+ glGetHistogramParameterfv
+ glGetHistogramParameterfvEXT
+ glGetHistogramParameteriv
+ glGetHistogramParameterivEXT
+ glGetInstrumentsSGIX
+ glGetIntegerv
+ glGetLightfv
+ glGetLightiv
+ glGetListParameterfvSGIX
+ glGetListParameterivSGIX
+ glGetMapdv
+ glGetMapfv
+ glGetMapiv
+ glGetMaterialfv
+ glGetMaterialiv
+ glGetMinmax
+ glGetMinmaxEXT
+ glGetMinmaxParameterfv
+ glGetMinmaxParameterfvEXT
+ glGetMinmaxParameteriv
+ glGetMinmaxParameterivEXT
+ glGetPixelMapfv
+ glGetPixelMapuiv
+ glGetPixelMapusv
+ glGetPixelTexGenParameterfvSGIS
+ glGetPixelTexGenParameterivSGIS
+ glGetPointerv
+ glGetPointervEXT
+ glGetPolygonStipple
+ glGetProgramEnvParameterdvARB
+ glGetProgramEnvParameterfvARB
+ glGetProgramivARB
+ glGetProgramivNV
+ glGetProgramLocalParameterdvARB
+ glGetProgramLocalParameterfvARB
+ glGetProgramNamedParameterdvNV
+ glGetProgramNamedParameterfvNV
+ glGetProgramParameterdvNV
+ glGetProgramParameterfvNV
+ glGetProgramStringARB
+ glGetProgramStringNV
+ glGetQueryivARB
+ glGetQueryObjectivARB
+ glGetQueryObjectuivARB
+ glGetSeparableFilter
+ glGetSeparableFilterEXT
+ glGetSharpenTexFuncSGIS
+ glGetString
+ glGetTexEnvfv
+ glGetTexEnviv
+ glGetTexFilterFuncSGIS
+ glGetTexGendv
+ glGetTexGenfv
+ glGetTexGeniv
+ glGetTexImage
+ glGetTexLevelParameterfv
+ glGetTexLevelParameteriv
+ glGetTexParameterfv
+ glGetTexParameteriv
+ glGetTrackMatrixivNV
+ glGetVertexAttribdvARB
+ glGetVertexAttribdvNV
+ glGetVertexAttribfvARB
+ glGetVertexAttribfvNV
+ glGetVertexAttribivARB
+ glGetVertexAttribivNV
+ glGetVertexAttribPointervARB
+ glGetVertexAttribPointervNV
+ glHint
+ glHintPGI
+ glHistogram
+ glHistogramEXT
+ glIndexd
+ glIndexdv
+ glIndexf
+ glIndexFuncEXT
+ glIndexfv
+ glIndexi
+ glIndexiv
+ glIndexMask
+ glIndexMaterialEXT
+ glIndexPointer
+ glIndexPointerEXT
+ glIndexs
+ glIndexsv
+ glIndexub
+ glIndexubv
+ glInitNames
+ glInstrumentsBufferSGIX
+ glInterleavedArrays
+ glIsBufferARB
+ glIsEnabled
+ glIsFenceNV
+ glIsList
+ glIsProgramARB
+ glIsProgramNV
+ glIsQueryARB
+ glIsTexture
+ glIsTextureEXT
+ glLightEnviSGIX
+ glLightf
+ glLightfv
+ glLighti
+ glLightiv
+ glLightModelf
+ glLightModelfv
+ glLightModeli
+ glLightModeliv
+ glLineStipple
+ glLineWidth
+ glListBase
+ glListParameterfSGIX
+ glListParameterfvSGIX
+ glListParameteriSGIX
+ glListParameterivSGIX
+ glLoadIdentity
+ glLoadMatrixd
+ glLoadMatrixf
+ glLoadName
+ glLoadProgramNV
+ glLoadTransposeMatrixd
+ glLoadTransposeMatrixdARB
+ glLoadTransposeMatrixf
+ glLoadTransposeMatrixfARB
+ glLockArraysEXT
+ glLogicOp
+ glMapBufferARB
+ glMapGrid1d
+ glMapGrid1f
+ glMapGrid2d
+ glMapGrid2f
+ glMap1d
+ glMap1f
+ glMap2d
+ glMap2f
+ glMaterialf
+ glMaterialfv
+ glMateriali
+ glMaterialiv
+ glMatrixMode
+ glMinmax
+ glMinmaxEXT
+ glMultiDrawArrays
+ glMultiDrawArraysEXT
+ glMultiDrawElements
+ glMultiDrawElementsEXT
+ glMultiModeDrawArraysIBM
+ glMultiModeDrawElementsIBM
+ glMultiTexCoord1d
+ glMultiTexCoord1dARB
+ glMultiTexCoord1dv
+ glMultiTexCoord1dvARB
+ glMultiTexCoord1f
+ glMultiTexCoord1fARB
+ glMultiTexCoord1fv
+ glMultiTexCoord1fvARB
+ glMultiTexCoord1i
+ glMultiTexCoord1iARB
+ glMultiTexCoord1iv
+ glMultiTexCoord1ivARB
+ glMultiTexCoord1s
+ glMultiTexCoord1sARB
+ glMultiTexCoord1sv
+ glMultiTexCoord1svARB
+ glMultiTexCoord2d
+ glMultiTexCoord2dARB
+ glMultiTexCoord2dv
+ glMultiTexCoord2dvARB
+ glMultiTexCoord2f
+ glMultiTexCoord2fARB
+ glMultiTexCoord2fv
+ glMultiTexCoord2fvARB
+ glMultiTexCoord2i
+ glMultiTexCoord2iARB
+ glMultiTexCoord2iv
+ glMultiTexCoord2ivARB
+ glMultiTexCoord2s
+ glMultiTexCoord2sARB
+ glMultiTexCoord2sv
+ glMultiTexCoord2svARB
+ glMultiTexCoord3d
+ glMultiTexCoord3dARB
+ glMultiTexCoord3dv
+ glMultiTexCoord3dvARB
+ glMultiTexCoord3f
+ glMultiTexCoord3fARB
+ glMultiTexCoord3fv
+ glMultiTexCoord3fvARB
+ glMultiTexCoord3i
+ glMultiTexCoord3iARB
+ glMultiTexCoord3iv
+ glMultiTexCoord3ivARB
+ glMultiTexCoord3s
+ glMultiTexCoord3sARB
+ glMultiTexCoord3sv
+ glMultiTexCoord3svARB
+ glMultiTexCoord4d
+ glMultiTexCoord4dARB
+ glMultiTexCoord4dv
+ glMultiTexCoord4dvARB
+ glMultiTexCoord4f
+ glMultiTexCoord4fARB
+ glMultiTexCoord4fv
+ glMultiTexCoord4fvARB
+ glMultiTexCoord4i
+ glMultiTexCoord4iARB
+ glMultiTexCoord4iv
+ glMultiTexCoord4ivARB
+ glMultiTexCoord4s
+ glMultiTexCoord4sARB
+ glMultiTexCoord4sv
+ glMultiTexCoord4svARB
+ glMultMatrixd
+ glMultMatrixf
+ glMultTransposeMatrixd
+ glMultTransposeMatrixdARB
+ glMultTransposeMatrixf
+ glMultTransposeMatrixfARB
+ glNewList
+ glNormalPointer
+ glNormalPointerEXT
+ glNormal3b
+ glNormal3bv
+ glNormal3d
+ glNormal3dv
+ glNormal3f
+ glNormal3fv
+ glNormal3i
+ glNormal3iv
+ glNormal3s
+ glNormal3sv
+ glOrtho
+ glPassThrough
+ glPixelMapfv
+ glPixelMapuiv
+ glPixelMapusv
+ glPixelStoref
+ glPixelStorei
+ glPixelTexGenParameterfSGIS
+ glPixelTexGenParameterfvSGIS
+ glPixelTexGenParameteriSGIS
+ glPixelTexGenParameterivSGIS
+ glPixelTexGenSGIX
+ glPixelTransferf
+ glPixelTransferi
+ glPixelZoom
+ glPointParameterf
+ glPointParameterfARB
+ glPointParameterfEXT
+ glPointParameterfSGIS
+ glPointParameterfv
+ glPointParameterfvARB
+ glPointParameterfvEXT
+ glPointParameterfvSGIS
+ glPointParameteri
+ glPointParameteriNV
+ glPointParameteriv
+ glPointParameterivNV
+ glPointSize
+ glPollInstrumentsSGIX
+ glPolygonMode
+ glPolygonOffset
+ glPolygonOffsetEXT
+ glPolygonStipple
+ glPopAttrib
+ glPopClientAttrib
+ glPopMatrix
+ glPopName
+ glPrioritizeTextures
+ glPrioritizeTexturesEXT
+ glProgramEnvParameter4dARB
+ glProgramEnvParameter4dvARB
+ glProgramEnvParameter4fARB
+ glProgramEnvParameter4fvARB
+ glProgramLocalParameter4dARB
+ glProgramLocalParameter4dvARB
+ glProgramLocalParameter4fARB
+ glProgramLocalParameter4fvARB
+ glProgramNamedParameter4dNV
+ glProgramNamedParameter4dvNV
+ glProgramNamedParameter4fNV
+ glProgramNamedParameter4fvNV
+ glProgramParameters4dvNV
+ glProgramParameters4fvNV
+ glProgramParameter4dNV
+ glProgramParameter4dvNV
+ glProgramParameter4fNV
+ glProgramParameter4fvNV
+ glProgramStringARB
+ glPushAttrib
+ glPushClientAttrib
+ glPushMatrix
+ glPushName
+ glRasterPos2d
+ glRasterPos2dv
+ glRasterPos2f
+ glRasterPos2fv
+ glRasterPos2i
+ glRasterPos2iv
+ glRasterPos2s
+ glRasterPos2sv
+ glRasterPos3d
+ glRasterPos3dv
+ glRasterPos3f
+ glRasterPos3fv
+ glRasterPos3i
+ glRasterPos3iv
+ glRasterPos3s
+ glRasterPos3sv
+ glRasterPos4d
+ glRasterPos4dv
+ glRasterPos4f
+ glRasterPos4fv
+ glRasterPos4i
+ glRasterPos4iv
+ glRasterPos4s
+ glRasterPos4sv
+ glReadBuffer
+ glReadInstrumentsSGIX
+ glReadPixels
+ glRectd
+ glRectdv
+ glRectf
+ glRectfv
+ glRecti
+ glRectiv
+ glRects
+ glRectsv
+ glReferencePlaneSGIX
+ glRenderMode
+ glRequestResidentProgramsNV
+ glResetHistogram
+ glResetHistogramEXT
+ glResetMinmax
+ glResetMinmaxEXT
+ glResizeBuffersMESA
+ glRotated
+ glRotatef
+ glSampleCoverage
+ glSampleCoverageARB
+ glSampleMaskEXT
+ glSampleMaskSGIS
+ glSamplePatternEXT
+ glSamplePatternSGIS
+ glScaled
+ glScalef
+ glScissor
+ glSecondaryColorPointer
+ glSecondaryColorPointerEXT
+ glSecondaryColor3b
+ glSecondaryColor3bEXT
+ glSecondaryColor3bv
+ glSecondaryColor3bvEXT
+ glSecondaryColor3d
+ glSecondaryColor3dEXT
+ glSecondaryColor3dv
+ glSecondaryColor3dvEXT
+ glSecondaryColor3f
+ glSecondaryColor3fEXT
+ glSecondaryColor3fv
+ glSecondaryColor3fvEXT
+ glSecondaryColor3i
+ glSecondaryColor3iEXT
+ glSecondaryColor3iv
+ glSecondaryColor3ivEXT
+ glSecondaryColor3s
+ glSecondaryColor3sEXT
+ glSecondaryColor3sv
+ glSecondaryColor3svEXT
+ glSecondaryColor3ub
+ glSecondaryColor3ubEXT
+ glSecondaryColor3ubv
+ glSecondaryColor3ubvEXT
+ glSecondaryColor3ui
+ glSecondaryColor3uiEXT
+ glSecondaryColor3uiv
+ glSecondaryColor3uivEXT
+ glSecondaryColor3us
+ glSecondaryColor3usEXT
+ glSecondaryColor3usv
+ glSecondaryColor3usvEXT
+ glSelectBuffer
+ glSeparableFilter2D
+ glSeparableFilter2DEXT
+ glSetFenceNV
+ glShadeModel
+ glSharpenTexFuncSGIS
+ glSpriteParameterfSGIX
+ glSpriteParameterfvSGIX
+ glSpriteParameteriSGIX
+ glSpriteParameterivSGIX
+ glStartInstrumentsSGIX
+ glStencilFunc
+ glStencilMask
+ glStencilOp
+ glStopInstrumentsSGIX
+ glTagSampleBufferSGIX
+ glTbufferMask3DFX
+ glTestFenceNV
+ glTexCoordPointer
+ glTexCoordPointerEXT
+ glTexCoord1d
+ glTexCoord1dv
+ glTexCoord1f
+ glTexCoord1fv
+ glTexCoord1i
+ glTexCoord1iv
+ glTexCoord1s
+ glTexCoord1sv
+ glTexCoord2d
+ glTexCoord2dv
+ glTexCoord2f
+ glTexCoord2fv
+ glTexCoord2i
+ glTexCoord2iv
+ glTexCoord2s
+ glTexCoord2sv
+ glTexCoord3d
+ glTexCoord3dv
+ glTexCoord3f
+ glTexCoord3fv
+ glTexCoord3i
+ glTexCoord3iv
+ glTexCoord3s
+ glTexCoord3sv
+ glTexCoord4d
+ glTexCoord4dv
+ glTexCoord4f
+ glTexCoord4fv
+ glTexCoord4i
+ glTexCoord4iv
+ glTexCoord4s
+ glTexCoord4sv
+ glTexEnvf
+ glTexEnvfv
+ glTexEnvi
+ glTexEnviv
+ glTexFilterFuncSGIS
+ glTexGend
+ glTexGendv
+ glTexGenf
+ glTexGenfv
+ glTexGeni
+ glTexGeniv
+ glTexImage1D
+ glTexImage2D
+ glTexImage3D
+ glTexImage3DEXT
+ glTexImage4DSGIS
+ glTexParameterf
+ glTexParameterfv
+ glTexParameteri
+ glTexParameteriv
+ glTexSubImage1D
+ glTexSubImage1DEXT
+ glTexSubImage2D
+ glTexSubImage2DEXT
+ glTexSubImage3D
+ glTexSubImage3DEXT
+ glTexSubImage4DSGIS
+ glTrackMatrixNV
+ glTranslated
+ glTranslatef
+ glUnlockArraysEXT
+ glUnmapBufferARB
+ glVertexArrayRangeNV
+ glVertexAttribPointerARB
+ glVertexAttribPointerNV
+ glVertexAttribs1dvNV
+ glVertexAttribs1fvNV
+ glVertexAttribs1svNV
+ glVertexAttribs2dvNV
+ glVertexAttribs2fvNV
+ glVertexAttribs2svNV
+ glVertexAttribs3dvNV
+ glVertexAttribs3fvNV
+ glVertexAttribs3svNV
+ glVertexAttribs4dvNV
+ glVertexAttribs4fvNV
+ glVertexAttribs4svNV
+ glVertexAttribs4ubvNV
+ glVertexAttrib1dARB
+ glVertexAttrib1dNV
+ glVertexAttrib1dvARB
+ glVertexAttrib1dvNV
+ glVertexAttrib1fARB
+ glVertexAttrib1fNV
+ glVertexAttrib1fvARB
+ glVertexAttrib1fvNV
+ glVertexAttrib1sARB
+ glVertexAttrib1sNV
+ glVertexAttrib1svARB
+ glVertexAttrib1svNV
+ glVertexAttrib2dARB
+ glVertexAttrib2dNV
+ glVertexAttrib2dvARB
+ glVertexAttrib2dvNV
+ glVertexAttrib2fARB
+ glVertexAttrib2fNV
+ glVertexAttrib2fvARB
+ glVertexAttrib2fvNV
+ glVertexAttrib2sARB
+ glVertexAttrib2sNV
+ glVertexAttrib2svARB
+ glVertexAttrib2svNV
+ glVertexAttrib3dARB
+ glVertexAttrib3dNV
+ glVertexAttrib3dvARB
+ glVertexAttrib3dvNV
+ glVertexAttrib3fARB
+ glVertexAttrib3fNV
+ glVertexAttrib3fvARB
+ glVertexAttrib3fvNV
+ glVertexAttrib3sARB
+ glVertexAttrib3sNV
+ glVertexAttrib3svARB
+ glVertexAttrib3svNV
+ glVertexAttrib4bvARB
+ glVertexAttrib4dARB
+ glVertexAttrib4dNV
+ glVertexAttrib4dvARB
+ glVertexAttrib4dvNV
+ glVertexAttrib4fARB
+ glVertexAttrib4fNV
+ glVertexAttrib4fvARB
+ glVertexAttrib4fvNV
+ glVertexAttrib4ivARB
+ glVertexAttrib4NbvARB
+ glVertexAttrib4NivARB
+ glVertexAttrib4NsvARB
+ glVertexAttrib4NubARB
+ glVertexAttrib4NubvARB
+ glVertexAttrib4NuivARB
+ glVertexAttrib4NusvARB
+ glVertexAttrib4sARB
+ glVertexAttrib4sNV
+ glVertexAttrib4svARB
+ glVertexAttrib4svNV
+ glVertexAttrib4ubNV
+ glVertexAttrib4ubvARB
+ glVertexAttrib4ubvNV
+ glVertexAttrib4uivARB
+ glVertexAttrib4usvARB
+ glVertexPointer
+ glVertexPointerEXT
+ glVertexWeightfEXT
+ glVertexWeightfvEXT
+ glVertexWeightPointerEXT
+ glVertex2d
+ glVertex2dv
+ glVertex2f
+ glVertex2fv
+ glVertex2i
+ glVertex2iv
+ glVertex2s
+ glVertex2sv
+ glVertex3d
+ glVertex3dv
+ glVertex3f
+ glVertex3fv
+ glVertex3i
+ glVertex3iv
+ glVertex3s
+ glVertex3sv
+ glVertex4d
+ glVertex4dv
+ glVertex4f
+ glVertex4fv
+ glVertex4i
+ glVertex4iv
+ glVertex4s
+ glVertex4sv
+ glViewport
+ glWindowPos2d
+ glWindowPos2dARB
+ glWindowPos2dMESA
+ glWindowPos2dv
+ glWindowPos2dvARB
+ glWindowPos2dvMESA
+ glWindowPos2f
+ glWindowPos2fARB
+ glWindowPos2fMESA
+ glWindowPos2fv
+ glWindowPos2fvARB
+ glWindowPos2fvMESA
+ glWindowPos2i
+ glWindowPos2iARB
+ glWindowPos2iMESA
+ glWindowPos2iv
+ glWindowPos2ivARB
+ glWindowPos2ivMESA
+ glWindowPos2s
+ glWindowPos2sARB
+ glWindowPos2sMESA
+ glWindowPos2sv
+ glWindowPos2svARB
+ glWindowPos2svMESA
+ glWindowPos3d
+ glWindowPos3dARB
+ glWindowPos3dMESA
+ glWindowPos3dv
+ glWindowPos3dvARB
+ glWindowPos3dvMESA
+ glWindowPos3f
+ glWindowPos3fARB
+ glWindowPos3fMESA
+ glWindowPos3fv
+ glWindowPos3fvARB
+ glWindowPos3fvMESA
+ glWindowPos3i
+ glWindowPos3iARB
+ glWindowPos3iMESA
+ glWindowPos3iv
+ glWindowPos3ivARB
+ glWindowPos3ivMESA
+ glWindowPos3s
+ glWindowPos3sARB
+ glWindowPos3sMESA
+ glWindowPos3sv
+ glWindowPos3svARB
+ glWindowPos3svMESA
+ glWindowPos4dMESA
+ glWindowPos4dvMESA
+ glWindowPos4fMESA
+ glWindowPos4fvMESA
+ glWindowPos4iMESA
+ glWindowPos4ivMESA
+ glWindowPos4sMESA
+ glWindowPos4svMESA
+ fxCloseHardware
+;fxGetScreenGeometry
+ fxMesaCreateBestContext
+ fxMesaCreateContext
+ fxMesaDestroyContext
+ fxMesaGetCurrentContext
+ fxMesaMakeCurrent
+ fxMesaSelectCurrentBoard
+;fxMesaSetNearFar
+ fxMesaSwapBuffers
+ fxMesaUpdateScreenSize
+ wglChoosePixelFormat
+ wglCopyContext
+ wglCreateContext
+ wglCreateLayerContext
+ wglDeleteContext
+ wglDescribeLayerPlane
+ wglDescribePixelFormat
+ wglGetCurrentContext
+ wglGetCurrentDC
+ wglGetDefaultProcAddress
+ wglGetLayerPaletteEntries
+ wglGetPixelFormat
+ wglGetProcAddress
+ wglMakeCurrent
+ wglRealizeLayerPalette
+ wglSetLayerPaletteEntries
+ wglSetPixelFormat
+ wglShareLists
+ wglSwapBuffers
+ wglSwapLayerBuffers
+ wglUseFontBitmapsA
+ wglUseFontBitmapsW
+ wglUseFontOutlinesA
+ wglUseFontOutlinesW
+ ChoosePixelFormat
+ DescribePixelFormat
+ GetPixelFormat
+ SetPixelFormat
+ SwapBuffers
+ DrvCopyContext
+ DrvCreateContext
+ DrvCreateLayerContext
+ DrvDeleteContext
+ DrvDescribeLayerPlane
+ DrvDescribePixelFormat
+ DrvGetLayerPaletteEntries
+ DrvGetProcAddress
+ DrvReleaseContext
+ DrvRealizeLayerPalette
+ DrvSetContext
+ DrvSetLayerPaletteEntries
+ DrvSetPixelFormat
+ DrvShareLists
+ DrvSwapBuffers
+ DrvSwapLayerBuffers
+ DrvValidateVersion
diff --git a/mesalib/src/mesa/drivers/windows/gdi/InitCritSections.cpp b/mesalib/src/mesa/drivers/windows/gdi/InitCritSections.cpp
new file mode 100644
index 000000000..78e5f3851
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/gdi/InitCritSections.cpp
@@ -0,0 +1,33 @@
+#include "glapi.h"
+#include "glThread.h"
+
+#ifdef WIN32
+
+extern "C" _glthread_Mutex OneTimeLock;
+extern "C" _glthread_Mutex GenTexturesLock;
+
+extern "C" void FreeAllTSD(void);
+
+class _CriticalSectionInit
+{
+public:
+ static _CriticalSectionInit m_inst;
+
+ _CriticalSectionInit()
+ {
+ _glthread_INIT_MUTEX(OneTimeLock);
+ _glthread_INIT_MUTEX(GenTexturesLock);
+ }
+
+ ~_CriticalSectionInit()
+ {
+ _glthread_DESTROY_MUTEX(OneTimeLock);
+ _glthread_DESTROY_MUTEX(GenTexturesLock);
+ FreeAllTSD();
+ }
+};
+
+_CriticalSectionInit _CriticalSectionInit::m_inst;
+
+
+#endif /* WIN32 */
diff --git a/mesalib/src/mesa/drivers/windows/gdi/wmesa.c b/mesalib/src/mesa/drivers/windows/gdi/wmesa.c
index 22b0c46b4..a30326c0c 100644
--- a/mesalib/src/mesa/drivers/windows/gdi/wmesa.c
+++ b/mesalib/src/mesa/drivers/windows/gdi/wmesa.c
@@ -1,1661 +1,1661 @@
-/*
- * Windows (Win32/Win64) device driver for Mesa
- *
- */
-
-#include "wmesadef.h"
-#include "colors.h"
-#include <GL/wmesa.h>
-#include <winuser.h>
-#include "context.h"
-#include "extensions.h"
-#include "framebuffer.h"
-#include "renderbuffer.h"
-#include "drivers/common/driverfuncs.h"
-#include "drivers/common/meta.h"
-#include "vbo/vbo.h"
-#include "swrast/swrast.h"
-#include "swrast_setup/swrast_setup.h"
-#include "tnl/tnl.h"
-#include "tnl/t_context.h"
-#include "tnl/t_pipeline.h"
-
-
-/* linked list of our Framebuffers (windows) */
-static WMesaFramebuffer FirstFramebuffer = NULL;
-
-
-/**
- * Create a new WMesaFramebuffer object which will correspond to the
- * given HDC (Window handle).
- */
-WMesaFramebuffer
-wmesa_new_framebuffer(HDC hdc, GLvisual *visual)
-{
- WMesaFramebuffer pwfb
- = (WMesaFramebuffer) malloc(sizeof(struct wmesa_framebuffer));
- if (pwfb) {
- _mesa_initialize_window_framebuffer(&pwfb->Base, visual);
- pwfb->hDC = hdc;
- /* insert at head of list */
- pwfb->next = FirstFramebuffer;
- FirstFramebuffer = pwfb;
- }
- return pwfb;
-}
-
-/**
- * Given an hdc, free the corresponding WMesaFramebuffer
- */
-void
-wmesa_free_framebuffer(HDC hdc)
-{
- WMesaFramebuffer pwfb, prev;
- for (pwfb = FirstFramebuffer; pwfb; pwfb = pwfb->next) {
- if (pwfb->hDC == hdc)
- break;
- prev = pwfb;
- }
- if (pwfb) {
- struct gl_framebuffer *fb;
- if (pwfb == FirstFramebuffer)
- FirstFramebuffer = pwfb->next;
- else
- prev->next = pwfb->next;
- fb = &pwfb->Base;
- _mesa_reference_framebuffer(&fb, NULL);
- }
-}
-
-/**
- * Given an hdc, return the corresponding WMesaFramebuffer
- */
-WMesaFramebuffer
-wmesa_lookup_framebuffer(HDC hdc)
-{
- WMesaFramebuffer pwfb;
- for (pwfb = FirstFramebuffer; pwfb; pwfb = pwfb->next) {
- if (pwfb->hDC == hdc)
- return pwfb;
- }
- return NULL;
-}
-
-
-/**
- * Given a GLframebuffer, return the corresponding WMesaFramebuffer.
- */
-static WMesaFramebuffer wmesa_framebuffer(GLframebuffer *fb)
-{
- return (WMesaFramebuffer) fb;
-}
-
-
-/**
- * Given a GLcontext, return the corresponding WMesaContext.
- */
-static WMesaContext wmesa_context(const GLcontext *ctx)
-{
- return (WMesaContext) ctx;
-}
-
-
-/*
- * Every driver should implement a GetString function in order to
- * return a meaningful GL_RENDERER string.
- */
-static const GLubyte *wmesa_get_string(GLcontext *ctx, GLenum name)
-{
- return (name == GL_RENDERER) ?
- (GLubyte *) "Mesa Windows GDI Driver" : NULL;
-}
-
-
-/*
- * Determine the pixel format based on the pixel size.
- */
-static void wmSetPixelFormat(WMesaFramebuffer pwfb, HDC hDC)
-{
- pwfb->cColorBits = GetDeviceCaps(hDC, BITSPIXEL);
-
- /* Only 16 and 32 bit targets are supported now */
- assert(pwfb->cColorBits == 0 ||
- pwfb->cColorBits == 16 ||
- pwfb->cColorBits == 24 ||
- pwfb->cColorBits == 32);
-
- switch(pwfb->cColorBits){
- case 8:
- pwfb->pixelformat = PF_INDEX8;
- break;
- case 16:
- pwfb->pixelformat = PF_5R6G5B;
- break;
- case 24:
- case 32:
- pwfb->pixelformat = PF_8R8G8B;
- break;
- default:
- pwfb->pixelformat = PF_BADFORMAT;
- }
-}
-
-
-/**
- * Create DIB for back buffer.
- * We write into this memory with the span routines and then blit it
- * to the window on a buffer swap.
- */
-BOOL wmCreateBackingStore(WMesaFramebuffer pwfb, long lxSize, long lySize)
-{
- HDC hdc = pwfb->hDC;
- LPBITMAPINFO pbmi = &(pwfb->bmi);
- HDC hic;
-
- pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- pbmi->bmiHeader.biWidth = lxSize;
- pbmi->bmiHeader.biHeight= -lySize;
- pbmi->bmiHeader.biPlanes = 1;
- pbmi->bmiHeader.biBitCount = GetDeviceCaps(pwfb->hDC, BITSPIXEL);
- pbmi->bmiHeader.biCompression = BI_RGB;
- pbmi->bmiHeader.biSizeImage = 0;
- pbmi->bmiHeader.biXPelsPerMeter = 0;
- pbmi->bmiHeader.biYPelsPerMeter = 0;
- pbmi->bmiHeader.biClrUsed = 0;
- pbmi->bmiHeader.biClrImportant = 0;
-
- pwfb->cColorBits = pbmi->bmiHeader.biBitCount;
- pwfb->ScanWidth = (lxSize * (pwfb->cColorBits / 8) + 3) & ~3;
-
- hic = CreateIC("display", NULL, NULL, NULL);
- pwfb->dib_hDC = CreateCompatibleDC(hic);
-
- pwfb->hbmDIB = CreateDIBSection(hic,
- &pwfb->bmi,
- DIB_RGB_COLORS,
- (void **)&(pwfb->pbPixels),
- 0,
- 0);
- pwfb->hOldBitmap = SelectObject(pwfb->dib_hDC, pwfb->hbmDIB);
-
- DeleteDC(hic);
-
- wmSetPixelFormat(pwfb, pwfb->hDC);
- return TRUE;
-}
-
-
-static wmDeleteBackingStore(WMesaFramebuffer pwfb)
-{
- if (pwfb->hbmDIB) {
- SelectObject(pwfb->dib_hDC, pwfb->hOldBitmap);
- DeleteDC(pwfb->dib_hDC);
- DeleteObject(pwfb->hbmDIB);
- }
-}
-
-
-/**
- * Find the width and height of the window named by hdc.
- */
-static void
-get_window_size(HDC hdc, GLuint *width, GLuint *height)
-{
- if (WindowFromDC(hdc)) {
- RECT rect;
- GetClientRect(WindowFromDC(hdc), &rect);
- *width = rect.right - rect.left;
- *height = rect.bottom - rect.top;
- }
- else { /* Memory context */
- /* From contributed code - use the size of the desktop
- * for the size of a memory context (?) */
- *width = GetDeviceCaps(hdc, HORZRES);
- *height = GetDeviceCaps(hdc, VERTRES);
- }
-}
-
-
-static void
-wmesa_get_buffer_size(GLframebuffer *buffer, GLuint *width, GLuint *height)
-{
- WMesaFramebuffer pwfb = wmesa_framebuffer(buffer);
- get_window_size(pwfb->hDC, width, height);
-}
-
-
-static void wmesa_flush(GLcontext *ctx)
-{
- WMesaContext pwc = wmesa_context(ctx);
- WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->WinSysDrawBuffer);
-
- if (ctx->Visual.doubleBufferMode == 1) {
- BitBlt(pwfb->hDC, 0, 0, pwfb->Base.Width, pwfb->Base.Height,
- pwfb->dib_hDC, 0, 0, SRCCOPY);
- }
- else {
- /* Do nothing for single buffer */
- }
-}
-
-
-/**********************************************************************/
-/***** CLEAR Functions *****/
-/**********************************************************************/
-
-/* If we do not implement these, Mesa clears the buffers via the pixel
- * span writing interface, which is very slow for a clear operation.
- */
-
-/*
- * Set the color used to clear the color buffer.
- */
-static void clear_color(GLcontext *ctx, const GLfloat color[4])
-{
- WMesaContext pwc = wmesa_context(ctx);
- WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
- GLubyte col[3];
- UINT bytesPerPixel = pwfb->cColorBits / 8;
-
- CLAMPED_FLOAT_TO_UBYTE(col[0], color[0]);
- CLAMPED_FLOAT_TO_UBYTE(col[1], color[1]);
- CLAMPED_FLOAT_TO_UBYTE(col[2], color[2]);
- pwc->clearColorRef = RGB(col[0], col[1], col[2]);
- DeleteObject(pwc->clearPen);
- DeleteObject(pwc->clearBrush);
- pwc->clearPen = CreatePen(PS_SOLID, 1, pwc->clearColorRef);
- pwc->clearBrush = CreateSolidBrush(pwc->clearColorRef);
-}
-
-
-/*
- * Clear the specified region of the color buffer using the clear color
- * or index as specified by one of the two functions above.
- *
- * This procedure clears either the front and/or the back COLOR buffers.
- * Only the "left" buffer is cleared since we are not stereo.
- * Clearing of the other non-color buffers is left to the swrast.
- */
-
-static void clear(GLcontext *ctx, GLbitfield mask)
-{
-#define FLIP(Y) (ctx->DrawBuffer->Height - (Y) - 1)
- const GLint x = ctx->DrawBuffer->_Xmin;
- const GLint y = ctx->DrawBuffer->_Ymin;
- const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
- const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
-
- WMesaContext pwc = wmesa_context(ctx);
- WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
- int done = 0;
-
- /* Let swrast do all the work if the masks are not set to
- * clear all channels. */
- if (!ctx->Color.ColorMask[0][0] ||
- !ctx->Color.ColorMask[0][1] ||
- !ctx->Color.ColorMask[0][2] ||
- !ctx->Color.ColorMask[0][3]) {
- _swrast_Clear(ctx, mask);
- return;
- }
-
- /* Back buffer */
- if (mask & BUFFER_BIT_BACK_LEFT) {
-
- int i, rowSize;
- UINT bytesPerPixel = pwfb->cColorBits / 8;
- LPBYTE lpb, clearRow;
- LPWORD lpw;
- BYTE bColor;
- WORD wColor;
- BYTE r, g, b;
- DWORD dwColor;
- LPDWORD lpdw;
-
- /* Try for a fast clear - clearing entire buffer with a single
- * byte value. */
- if (width == ctx->DrawBuffer->Width &&
- height == ctx->DrawBuffer->Height) { /* entire buffer */
- /* Now check for an easy clear value */
- switch (bytesPerPixel) {
- case 1:
- bColor = BGR8(GetRValue(pwc->clearColorRef),
- GetGValue(pwc->clearColorRef),
- GetBValue(pwc->clearColorRef));
- memset(pwfb->pbPixels, bColor,
- pwfb->ScanWidth * height);
- done = 1;
- break;
- case 2:
- wColor = BGR16(GetRValue(pwc->clearColorRef),
- GetGValue(pwc->clearColorRef),
- GetBValue(pwc->clearColorRef));
- if (((wColor >> 8) & 0xff) == (wColor & 0xff)) {
- memset(pwfb->pbPixels, wColor & 0xff,
- pwfb->ScanWidth * height);
- done = 1;
- }
- break;
- case 3:
- /* fall through */
- case 4:
- if (GetRValue(pwc->clearColorRef) ==
- GetGValue(pwc->clearColorRef) &&
- GetRValue(pwc->clearColorRef) ==
- GetBValue(pwc->clearColorRef)) {
- memset(pwfb->pbPixels,
- GetRValue(pwc->clearColorRef),
- pwfb->ScanWidth * height);
- done = 1;
- }
- break;
- default:
- break;
- }
- } /* all */
-
- if (!done) {
- /* Need to clear a row at a time. Begin by setting the first
- * row in the area to be cleared to the clear color. */
-
- clearRow = pwfb->pbPixels +
- pwfb->ScanWidth * FLIP(y) +
- bytesPerPixel * x;
- switch (bytesPerPixel) {
- case 1:
- lpb = clearRow;
- bColor = BGR8(GetRValue(pwc->clearColorRef),
- GetGValue(pwc->clearColorRef),
- GetBValue(pwc->clearColorRef));
- memset(lpb, bColor, width);
- break;
- case 2:
- lpw = (LPWORD)clearRow;
- wColor = BGR16(GetRValue(pwc->clearColorRef),
- GetGValue(pwc->clearColorRef),
- GetBValue(pwc->clearColorRef));
- for (i=0; i<width; i++)
- *lpw++ = wColor;
- break;
- case 3:
- lpb = clearRow;
- r = GetRValue(pwc->clearColorRef);
- g = GetGValue(pwc->clearColorRef);
- b = GetBValue(pwc->clearColorRef);
- for (i=0; i<width; i++) {
- *lpb++ = b;
- *lpb++ = g;
- *lpb++ = r;
- }
- break;
- case 4:
- lpdw = (LPDWORD)clearRow;
- dwColor = BGR32(GetRValue(pwc->clearColorRef),
- GetGValue(pwc->clearColorRef),
- GetBValue(pwc->clearColorRef));
- for (i=0; i<width; i++)
- *lpdw++ = dwColor;
- break;
- default:
- break;
- } /* switch */
-
- /* copy cleared row to other rows in buffer */
- lpb = clearRow - pwfb->ScanWidth;
- rowSize = width * bytesPerPixel;
- for (i=1; i<height; i++) {
- memcpy(lpb, clearRow, rowSize);
- lpb -= pwfb->ScanWidth;
- }
- } /* not done */
- mask &= ~BUFFER_BIT_BACK_LEFT;
- } /* back buffer */
-
- /* front buffer */
- if (mask & BUFFER_BIT_FRONT_LEFT) {
- HDC DC = pwc->hDC;
- HPEN Old_Pen = SelectObject(DC, pwc->clearPen);
- HBRUSH Old_Brush = SelectObject(DC, pwc->clearBrush);
- Rectangle(DC,
- x,
- FLIP(y) + 1,
- x + width + 1,
- FLIP(y) - height + 1);
- SelectObject(DC, Old_Pen);
- SelectObject(DC, Old_Brush);
- mask &= ~BUFFER_BIT_FRONT_LEFT;
- } /* front buffer */
-
- /* Call swrast if there is anything left to clear (like DEPTH) */
- if (mask)
- _swrast_Clear(ctx, mask);
-
-#undef FLIP
-}
-
-
-/**********************************************************************/
-/***** PIXEL Functions *****/
-/**********************************************************************/
-
-#define FLIP(Y) (rb->Height - (Y) - 1)
-
-
-/**
- ** Front Buffer reading/writing
- ** These are slow, but work with all non-indexed visual types.
- **/
-
-/* Write a horizontal span of RGBA color pixels with a boolean mask. */
-static void write_rgba_span_front(const GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, GLint x, GLint y,
- const GLubyte rgba[][4],
- const GLubyte mask[] )
-{
- WMesaContext pwc = wmesa_context(ctx);
- WMesaFramebuffer pwfb = wmesa_lookup_framebuffer(pwc->hDC);
- CONST BITMAPINFO bmi=
- {
- {
- sizeof(BITMAPINFOHEADER),
- n, 1, 1, 32, BI_RGB, 0, 1, 1, 0, 0
- }
- };
- HBITMAP bmp=0;
- HDC mdc=0;
- typedef union
- {
- unsigned i;
- struct {
- unsigned b:8, g:8, r:8, a:8;
- };
- } BGRA;
- BGRA *bgra, c;
- GLuint i;
-
- if (n < 16) { // the value 16 is just guessed
- y=FLIP(y);
- if (mask) {
- for (i=0; i<n; i++)
- if (mask[i])
- SetPixel(pwc->hDC, x+i, y,
- RGB(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]));
- }
- else {
- for (i=0; i<n; i++)
- SetPixel(pwc->hDC, x+i, y,
- RGB(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]));
- }
- }
- else {
- if (!pwfb) {
- _mesa_problem(NULL, "wmesa: write_rgba_span_front on unknown hdc");
- return;
- }
- bgra=malloc(n*sizeof(BGRA));
- if (!bgra) {
- _mesa_problem(NULL, "wmesa: write_rgba_span_front: out of memory");
- return;
- }
- c.a=0;
- if (mask) {
- for (i=0; i<n; i++) {
- if (mask[i]) {
- c.r=rgba[i][RCOMP];
- c.g=rgba[i][GCOMP];
- c.b=rgba[i][BCOMP];
- c.a=rgba[i][ACOMP];
- bgra[i]=c;
- }
- else
- bgra[i].i=0;
- }
- }
- else {
- for (i=0; i<n; i++) {
- c.r=rgba[i][RCOMP];
- c.g=rgba[i][GCOMP];
- c.b=rgba[i][BCOMP];
- c.a=rgba[i][ACOMP];
- bgra[i]=c;
- }
- }
- bmp=CreateBitmap(n, 1, 1, 32, bgra);
- mdc=CreateCompatibleDC(pwfb->hDC);
- SelectObject(mdc, bmp);
- y=FLIP(y);
- BitBlt(pwfb->hDC, x, y, n, 1, mdc, 0, 0, SRCCOPY);
- SelectObject(mdc, 0);
- DeleteObject(bmp);
- DeleteDC(mdc);
- free(bgra);
- }
-}
-
-/* Write a horizontal span of RGB color pixels with a boolean mask. */
-static void write_rgb_span_front(const GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, GLint x, GLint y,
- const GLubyte rgb[][3],
- const GLubyte mask[] )
-{
- WMesaContext pwc = wmesa_context(ctx);
- GLuint i;
-
- (void) ctx;
- y=FLIP(y);
- if (mask) {
- for (i=0; i<n; i++)
- if (mask[i])
- SetPixel(pwc->hDC, x+i, y, RGB(rgb[i][RCOMP], rgb[i][GCOMP],
- rgb[i][BCOMP]));
- }
- else {
- for (i=0; i<n; i++)
- SetPixel(pwc->hDC, x+i, y, RGB(rgb[i][RCOMP], rgb[i][GCOMP],
- rgb[i][BCOMP]));
- }
-
-}
-
-/*
- * Write a horizontal span of pixels with a boolean mask. The current color
- * is used for all pixels.
- */
-static void write_mono_rgba_span_front(const GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, GLint x, GLint y,
- const GLchan color[4],
- const GLubyte mask[])
-{
- GLuint i;
- WMesaContext pwc = wmesa_context(ctx);
- COLORREF colorref;
-
- (void) ctx;
- colorref = RGB(color[RCOMP], color[GCOMP], color[BCOMP]);
- y=FLIP(y);
- if (mask) {
- for (i=0; i<n; i++)
- if (mask[i])
- SetPixel(pwc->hDC, x+i, y, colorref);
- }
- else
- for (i=0; i<n; i++)
- SetPixel(pwc->hDC, x+i, y, colorref);
-
-}
-
-/* Write an array of RGBA pixels with a boolean mask. */
-static void write_rgba_pixels_front(const GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n,
- const GLint x[], const GLint y[],
- const GLubyte rgba[][4],
- const GLubyte mask[] )
-{
- GLuint i;
- WMesaContext pwc = wmesa_context(ctx);
- (void) ctx;
- for (i=0; i<n; i++)
- if (mask[i])
- SetPixel(pwc->hDC, x[i], FLIP(y[i]),
- RGB(rgba[i][RCOMP], rgba[i][GCOMP],
- rgba[i][BCOMP]));
-}
-
-
-
-/*
- * Write an array of pixels with a boolean mask. The current color
- * is used for all pixels.
- */
-static void write_mono_rgba_pixels_front(const GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n,
- const GLint x[], const GLint y[],
- const GLchan color[4],
- const GLubyte mask[] )
-{
- GLuint i;
- WMesaContext pwc = wmesa_context(ctx);
- COLORREF colorref;
- (void) ctx;
- colorref = RGB(color[RCOMP], color[GCOMP], color[BCOMP]);
- for (i=0; i<n; i++)
- if (mask[i])
- SetPixel(pwc->hDC, x[i], FLIP(y[i]), colorref);
-}
-
-/* Read a horizontal span of color pixels. */
-static void read_rgba_span_front(const GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, GLint x, GLint y,
- GLubyte rgba[][4] )
-{
- WMesaContext pwc = wmesa_context(ctx);
- GLuint i;
- COLORREF Color;
- y = FLIP(y);
- for (i=0; i<n; i++) {
- Color = GetPixel(pwc->hDC, x+i, y);
- rgba[i][RCOMP] = GetRValue(Color);
- rgba[i][GCOMP] = GetGValue(Color);
- rgba[i][BCOMP] = GetBValue(Color);
- rgba[i][ACOMP] = 255;
- }
-}
-
-
-/* Read an array of color pixels. */
-static void read_rgba_pixels_front(const GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, const GLint x[], const GLint y[],
- GLubyte rgba[][4])
-{
- WMesaContext pwc = wmesa_context(ctx);
- GLuint i;
- COLORREF Color;
- for (i=0; i<n; i++) {
- GLint y2 = FLIP(y[i]);
- Color = GetPixel(pwc->hDC, x[i], y2);
- rgba[i][RCOMP] = GetRValue(Color);
- rgba[i][GCOMP] = GetGValue(Color);
- rgba[i][BCOMP] = GetBValue(Color);
- rgba[i][ACOMP] = 255;
- }
-}
-
-/*********************************************************************/
-
-/* DOUBLE BUFFER 32-bit */
-
-#define WMSETPIXEL32(pwc, y, x, r, g, b) { \
-LPDWORD lpdw = ((LPDWORD)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (x)); \
-*lpdw = BGR32((r),(g),(b)); }
-
-
-
-/* Write a horizontal span of RGBA color pixels with a boolean mask. */
-static void write_rgba_span_32(const GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, GLint x, GLint y,
- const GLubyte rgba[][4],
- const GLubyte mask[] )
-{
- WMesaContext pwc = wmesa_context(ctx);
- WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
- GLuint i;
- LPDWORD lpdw;
-
- (void) ctx;
-
- y=FLIP(y);
- lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
- if (mask) {
- for (i=0; i<n; i++)
- if (mask[i])
- lpdw[i] = BGR32(rgba[i][RCOMP], rgba[i][GCOMP],
- rgba[i][BCOMP]);
- }
- else {
- for (i=0; i<n; i++)
- *lpdw++ = BGR32(rgba[i][RCOMP], rgba[i][GCOMP],
- rgba[i][BCOMP]);
- }
-}
-
-
-/* Write a horizontal span of RGB color pixels with a boolean mask. */
-static void write_rgb_span_32(const GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, GLint x, GLint y,
- const GLubyte rgb[][3],
- const GLubyte mask[] )
-{
- WMesaContext pwc = wmesa_context(ctx);
- WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
- GLuint i;
- LPDWORD lpdw;
-
- (void) ctx;
-
- y=FLIP(y);
- lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
- if (mask) {
- for (i=0; i<n; i++)
- if (mask[i])
- lpdw[i] = BGR32(rgb[i][RCOMP], rgb[i][GCOMP],
- rgb[i][BCOMP]);
- }
- else {
- for (i=0; i<n; i++)
- *lpdw++ = BGR32(rgb[i][RCOMP], rgb[i][GCOMP],
- rgb[i][BCOMP]);
- }
-}
-
-/*
- * Write a horizontal span of pixels with a boolean mask. The current color
- * is used for all pixels.
- */
-static void write_mono_rgba_span_32(const GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, GLint x, GLint y,
- const GLchan color[4],
- const GLubyte mask[])
-{
- LPDWORD lpdw;
- DWORD pixel;
- GLuint i;
- WMesaContext pwc = wmesa_context(ctx);
- WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
- lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
- y=FLIP(y);
- pixel = BGR32(color[RCOMP], color[GCOMP], color[BCOMP]);
- if (mask) {
- for (i=0; i<n; i++)
- if (mask[i])
- lpdw[i] = pixel;
- }
- else
- for (i=0; i<n; i++)
- *lpdw++ = pixel;
-
-}
-
-/* Write an array of RGBA pixels with a boolean mask. */
-static void write_rgba_pixels_32(const GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, const GLint x[], const GLint y[],
- const GLubyte rgba[][4],
- const GLubyte mask[])
-{
- GLuint i;
- WMesaContext pwc = wmesa_context(ctx);
- WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
- for (i=0; i<n; i++)
- if (mask[i])
- WMSETPIXEL32(pwfb, FLIP(y[i]), x[i],
- rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
-}
-
-/*
- * Write an array of pixels with a boolean mask. The current color
- * is used for all pixels.
- */
-static void write_mono_rgba_pixels_32(const GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n,
- const GLint x[], const GLint y[],
- const GLchan color[4],
- const GLubyte mask[])
-{
- GLuint i;
- WMesaContext pwc = wmesa_context(ctx);
- WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
- for (i=0; i<n; i++)
- if (mask[i])
- WMSETPIXEL32(pwfb, FLIP(y[i]),x[i],color[RCOMP],
- color[GCOMP], color[BCOMP]);
-}
-
-/* Read a horizontal span of color pixels. */
-static void read_rgba_span_32(const GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, GLint x, GLint y,
- GLubyte rgba[][4] )
-{
- GLuint i;
- DWORD pixel;
- LPDWORD lpdw;
- WMesaContext pwc = wmesa_context(ctx);
- WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
-
- y = FLIP(y);
- lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
- for (i=0; i<n; i++) {
- pixel = lpdw[i];
- rgba[i][RCOMP] = (GLubyte)((pixel & 0x00ff0000) >> 16);
- rgba[i][GCOMP] = (GLubyte)((pixel & 0x0000ff00) >> 8);
- rgba[i][BCOMP] = (GLubyte)(pixel & 0x000000ff);
- rgba[i][ACOMP] = 255;
- }
-}
-
-
-/* Read an array of color pixels. */
-static void read_rgba_pixels_32(const GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, const GLint x[], const GLint y[],
- GLubyte rgba[][4])
-{
- GLuint i;
- DWORD pixel;
- LPDWORD lpdw;
- WMesaContext pwc = wmesa_context(ctx);
- WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
-
- for (i=0; i<n; i++) {
- GLint y2 = FLIP(y[i]);
- lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y2)) + x[i];
- pixel = *lpdw;
- rgba[i][RCOMP] = (GLubyte)((pixel & 0x00ff0000) >> 16);
- rgba[i][GCOMP] = (GLubyte)((pixel & 0x0000ff00) >> 8);
- rgba[i][BCOMP] = (GLubyte)(pixel & 0x000000ff);
- rgba[i][ACOMP] = 255;
- }
-}
-
-
-/*********************************************************************/
-
-/* DOUBLE BUFFER 24-bit */
-
-#define WMSETPIXEL24(pwc, y, x, r, g, b) { \
-LPBYTE lpb = ((LPBYTE)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (3 * x)); \
-lpb[0] = (b); \
-lpb[1] = (g); \
-lpb[2] = (r); }
-
-/* Write a horizontal span of RGBA color pixels with a boolean mask. */
-static void write_rgba_span_24(const GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, GLint x, GLint y,
- const GLubyte rgba[][4],
- const GLubyte mask[] )
-{
- WMesaContext pwc = wmesa_context(ctx);
- WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
- GLuint i;
- LPBYTE lpb;
-
- (void) ctx;
-
- y=FLIP(y);
- lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y)) + (3 * x);
- if (mask) {
- for (i=0; i<n; i++)
- if (mask[i]) {
- lpb[3*i] = rgba[i][BCOMP];
- lpb[3*i+1] = rgba[i][GCOMP];
- lpb[3*i+2] = rgba[i][RCOMP];
- }
- }
- else {
- for (i=0; i<n; i++) {
- *lpb++ = rgba[i][BCOMP];
- *lpb++ = rgba[i][GCOMP];
- *lpb++ = rgba[i][RCOMP];
- }
- }
-}
-
-
-/* Write a horizontal span of RGB color pixels with a boolean mask. */
-static void write_rgb_span_24(const GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, GLint x, GLint y,
- const GLubyte rgb[][3],
- const GLubyte mask[] )
-{
- WMesaContext pwc = wmesa_context(ctx);
- WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
- GLuint i;
- LPBYTE lpb;
-
- (void) ctx;
-
- y=FLIP(y);
- lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y)) + (3 * x);
- if (mask) {
- for (i=0; i<n; i++)
- if (mask[i]) {
- lpb[3*i] = rgb[i][BCOMP];
- lpb[3*i+1] = rgb[i][GCOMP];
- lpb[3*i+2] = rgb[i][RCOMP];
- }
- }
- else {
- for (i=0; i<n; i++) {
- *lpb++ = rgb[i][BCOMP];
- *lpb++ = rgb[i][GCOMP];
- *lpb++ = rgb[i][RCOMP];
- }
- }
-}
-
-/*
- * Write a horizontal span of pixels with a boolean mask. The current color
- * is used for all pixels.
- */
-static void write_mono_rgba_span_24(const GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, GLint x, GLint y,
- const GLchan color[4],
- const GLubyte mask[])
-{
- LPBYTE lpb;
- GLuint i;
- WMesaContext pwc = wmesa_context(ctx);
- WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
- lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y)) + (3 * x);
- y=FLIP(y);
- if (mask) {
- for (i=0; i<n; i++)
- if (mask[i]) {
- lpb[3*i] = color[BCOMP];
- lpb[3*i+1] = color[GCOMP];
- lpb[3*i+2] = color[RCOMP];
- }
- }
- else
- for (i=0; i<n; i++) {
- *lpb++ = color[BCOMP];
- *lpb++ = color[GCOMP];
- *lpb++ = color[RCOMP];
- }
-}
-
-/* Write an array of RGBA pixels with a boolean mask. */
-static void write_rgba_pixels_24(const GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, const GLint x[], const GLint y[],
- const GLubyte rgba[][4],
- const GLubyte mask[])
-{
- GLuint i;
- WMesaContext pwc = wmesa_context(ctx);
- WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
- for (i=0; i<n; i++)
- if (mask[i])
- WMSETPIXEL24(pwfb, FLIP(y[i]), x[i],
- rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
-}
-
-/*
- * Write an array of pixels with a boolean mask. The current color
- * is used for all pixels.
- */
-static void write_mono_rgba_pixels_24(const GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n,
- const GLint x[], const GLint y[],
- const GLchan color[4],
- const GLubyte mask[])
-{
- GLuint i;
- WMesaContext pwc = wmesa_context(ctx);
- WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
- for (i=0; i<n; i++)
- if (mask[i])
- WMSETPIXEL24(pwfb, FLIP(y[i]),x[i],color[RCOMP],
- color[GCOMP], color[BCOMP]);
-}
-
-/* Read a horizontal span of color pixels. */
-static void read_rgba_span_24(const GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, GLint x, GLint y,
- GLubyte rgba[][4] )
-{
- GLuint i;
- LPBYTE lpb;
- WMesaContext pwc = wmesa_context(ctx);
- WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
-
- y = FLIP(y);
- lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y)) + (3 * x);
- for (i=0; i<n; i++) {
- rgba[i][RCOMP] = lpb[3*i+2];
- rgba[i][GCOMP] = lpb[3*i+1];
- rgba[i][BCOMP] = lpb[3*i];
- rgba[i][ACOMP] = 255;
- }
-}
-
-
-/* Read an array of color pixels. */
-static void read_rgba_pixels_24(const GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, const GLint x[], const GLint y[],
- GLubyte rgba[][4])
-{
- GLuint i;
- LPBYTE lpb;
- WMesaContext pwc = wmesa_context(ctx);
- WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
-
- for (i=0; i<n; i++) {
- GLint y2 = FLIP(y[i]);
- lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y2)) + (3 * x[i]);
- rgba[i][RCOMP] = lpb[3*i+2];
- rgba[i][GCOMP] = lpb[3*i+1];
- rgba[i][BCOMP] = lpb[3*i];
- rgba[i][ACOMP] = 255;
- }
-}
-
-
-/*********************************************************************/
-
-/* DOUBLE BUFFER 16-bit */
-
-#define WMSETPIXEL16(pwc, y, x, r, g, b) { \
-LPWORD lpw = ((LPWORD)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (x)); \
-*lpw = BGR16((r),(g),(b)); }
-
-
-
-/* Write a horizontal span of RGBA color pixels with a boolean mask. */
-static void write_rgba_span_16(const GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, GLint x, GLint y,
- const GLubyte rgba[][4],
- const GLubyte mask[] )
-{
- WMesaContext pwc = wmesa_context(ctx);
- WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
- GLuint i;
- LPWORD lpw;
-
- (void) ctx;
-
- y=FLIP(y);
- lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
- if (mask) {
- for (i=0; i<n; i++)
- if (mask[i])
- lpw[i] = BGR16(rgba[i][RCOMP], rgba[i][GCOMP],
- rgba[i][BCOMP]);
- }
- else {
- for (i=0; i<n; i++)
- *lpw++ = BGR16(rgba[i][RCOMP], rgba[i][GCOMP],
- rgba[i][BCOMP]);
- }
-}
-
-
-/* Write a horizontal span of RGB color pixels with a boolean mask. */
-static void write_rgb_span_16(const GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, GLint x, GLint y,
- const GLubyte rgb[][3],
- const GLubyte mask[] )
-{
- WMesaContext pwc = wmesa_context(ctx);
- WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
- GLuint i;
- LPWORD lpw;
-
- (void) ctx;
-
- y=FLIP(y);
- lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
- if (mask) {
- for (i=0; i<n; i++)
- if (mask[i])
- lpw[i] = BGR16(rgb[i][RCOMP], rgb[i][GCOMP],
- rgb[i][BCOMP]);
- }
- else {
- for (i=0; i<n; i++)
- *lpw++ = BGR16(rgb[i][RCOMP], rgb[i][GCOMP],
- rgb[i][BCOMP]);
- }
-}
-
-/*
- * Write a horizontal span of pixels with a boolean mask. The current color
- * is used for all pixels.
- */
-static void write_mono_rgba_span_16(const GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, GLint x, GLint y,
- const GLchan color[4],
- const GLubyte mask[])
-{
- LPWORD lpw;
- WORD pixel;
- GLuint i;
- WMesaContext pwc = wmesa_context(ctx);
- WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
- (void) ctx;
- lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
- y=FLIP(y);
- pixel = BGR16(color[RCOMP], color[GCOMP], color[BCOMP]);
- if (mask) {
- for (i=0; i<n; i++)
- if (mask[i])
- lpw[i] = pixel;
- }
- else
- for (i=0; i<n; i++)
- *lpw++ = pixel;
-
-}
-
-/* Write an array of RGBA pixels with a boolean mask. */
-static void write_rgba_pixels_16(const GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, const GLint x[], const GLint y[],
- const GLubyte rgba[][4],
- const GLubyte mask[])
-{
- GLuint i;
- WMesaContext pwc = wmesa_context(ctx);
- WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
- (void) ctx;
- for (i=0; i<n; i++)
- if (mask[i])
- WMSETPIXEL16(pwfb, FLIP(y[i]), x[i],
- rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
-}
-
-/*
- * Write an array of pixels with a boolean mask. The current color
- * is used for all pixels.
- */
-static void write_mono_rgba_pixels_16(const GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n,
- const GLint x[], const GLint y[],
- const GLchan color[4],
- const GLubyte mask[])
-{
- GLuint i;
- WMesaContext pwc = wmesa_context(ctx);
- WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
- (void) ctx;
- for (i=0; i<n; i++)
- if (mask[i])
- WMSETPIXEL16(pwfb, FLIP(y[i]),x[i],color[RCOMP],
- color[GCOMP], color[BCOMP]);
-}
-
-/* Read a horizontal span of color pixels. */
-static void read_rgba_span_16(const GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, GLint x, GLint y,
- GLubyte rgba[][4] )
-{
- GLuint i, pixel;
- LPWORD lpw;
- WMesaContext pwc = wmesa_context(ctx);
- WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
-
- y = FLIP(y);
- lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
- for (i=0; i<n; i++) {
- pixel = lpw[i];
- /* Windows uses 5,5,5 for 16-bit */
- rgba[i][RCOMP] = (pixel & 0x7c00) >> 7;
- rgba[i][GCOMP] = (pixel & 0x03e0) >> 2;
- rgba[i][BCOMP] = (pixel & 0x001f) << 3;
- rgba[i][ACOMP] = 255;
- }
-}
-
-
-/* Read an array of color pixels. */
-static void read_rgba_pixels_16(const GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLuint n, const GLint x[], const GLint y[],
- GLubyte rgba[][4])
-{
- GLuint i, pixel;
- LPWORD lpw;
- WMesaContext pwc = wmesa_context(ctx);
- WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
-
- for (i=0; i<n; i++) {
- GLint y2 = FLIP(y[i]);
- lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y2)) + x[i];
- pixel = *lpw;
- /* Windows uses 5,5,5 for 16-bit */
- rgba[i][RCOMP] = (pixel & 0x7c00) >> 7;
- rgba[i][GCOMP] = (pixel & 0x03e0) >> 2;
- rgba[i][BCOMP] = (pixel & 0x001f) << 3;
- rgba[i][ACOMP] = 255;
- }
-}
-
-
-
-
-/**********************************************************************/
-/***** BUFFER Functions *****/
-/**********************************************************************/
-
-
-
-
-static void
-wmesa_delete_renderbuffer(struct gl_renderbuffer *rb)
-{
- free(rb);
-}
-
-
-/**
- * This is called by Mesa whenever it determines that the window size
- * has changed. Do whatever's needed to cope with that.
- */
-static GLboolean
-wmesa_renderbuffer_storage(GLcontext *ctx,
- struct gl_renderbuffer *rb,
- GLenum internalFormat,
- GLuint width,
- GLuint height)
-{
- rb->Width = width;
- rb->Height = height;
- return GL_TRUE;
-}
-
-
-/**
- * Plug in the Get/PutRow/Values functions for a renderbuffer depending
- * on if we're drawing to the front or back color buffer.
- */
-void wmesa_set_renderbuffer_funcs(struct gl_renderbuffer *rb, int pixelformat,
- int cColorBits, int double_buffer)
-{
- if (double_buffer) {
- /* back buffer */
- /* Picking the correct span functions is important because
- * the DIB was allocated with the indicated depth. */
- switch(pixelformat) {
- case PF_5R6G5B:
- rb->PutRow = write_rgba_span_16;
- rb->PutRowRGB = write_rgb_span_16;
- rb->PutMonoRow = write_mono_rgba_span_16;
- rb->PutValues = write_rgba_pixels_16;
- rb->PutMonoValues = write_mono_rgba_pixels_16;
- rb->GetRow = read_rgba_span_16;
- rb->GetValues = read_rgba_pixels_16;
- break;
- case PF_8R8G8B:
- if (cColorBits == 24)
- {
- rb->PutRow = write_rgba_span_24;
- rb->PutRowRGB = write_rgb_span_24;
- rb->PutMonoRow = write_mono_rgba_span_24;
- rb->PutValues = write_rgba_pixels_24;
- rb->PutMonoValues = write_mono_rgba_pixels_24;
- rb->GetRow = read_rgba_span_24;
- rb->GetValues = read_rgba_pixels_24;
- }
- else
- {
- rb->PutRow = write_rgba_span_32;
- rb->PutRowRGB = write_rgb_span_32;
- rb->PutMonoRow = write_mono_rgba_span_32;
- rb->PutValues = write_rgba_pixels_32;
- rb->PutMonoValues = write_mono_rgba_pixels_32;
- rb->GetRow = read_rgba_span_32;
- rb->GetValues = read_rgba_pixels_32;
- }
- break;
- default:
- break;
- }
- }
- else {
- /* front buffer (actual Windows window) */
- rb->PutRow = write_rgba_span_front;
- rb->PutRowRGB = write_rgb_span_front;
- rb->PutMonoRow = write_mono_rgba_span_front;
- rb->PutValues = write_rgba_pixels_front;
- rb->PutMonoValues = write_mono_rgba_pixels_front;
- rb->GetRow = read_rgba_span_front;
- rb->GetValues = read_rgba_pixels_front;
- }
-}
-
-/**
- * Called by ctx->Driver.ResizeBuffers()
- * Resize the front/back colorbuffers to match the latest window size.
- */
-static void
-wmesa_resize_buffers(GLcontext *ctx, GLframebuffer *buffer,
- GLuint width, GLuint height)
-{
- WMesaContext pwc = wmesa_context(ctx);
- WMesaFramebuffer pwfb = wmesa_framebuffer(buffer);
-
- if (pwfb->Base.Width != width || pwfb->Base.Height != height) {
- /* Realloc back buffer */
- if (ctx->Visual.doubleBufferMode == 1) {
- wmDeleteBackingStore(pwfb);
- wmCreateBackingStore(pwfb, width, height);
- }
- }
- _mesa_resize_framebuffer(ctx, buffer, width, height);
-}
-
-
-/**
- * Called by glViewport.
- * This is a good time for us to poll the current window size and adjust
- * our renderbuffers to match the current window size.
- * Remember, we have no opportunity to respond to conventional
- * resize events since the driver has no event loop.
- * Thus, we poll.
- * MakeCurrent also ends up making a call here, so that ensures
- * we get the viewport set correctly, even if the app does not call
- * glViewport and relies on the defaults.
- */
-static void wmesa_viewport(GLcontext *ctx,
- GLint x, GLint y,
- GLsizei width, GLsizei height)
-{
- WMesaContext pwc = wmesa_context(ctx);
- GLuint new_width, new_height;
-
- wmesa_get_buffer_size(ctx->WinSysDrawBuffer, &new_width, &new_height);
-
- /**
- * Resize buffers if the window size changed.
- */
- wmesa_resize_buffers(ctx, ctx->WinSysDrawBuffer, new_width, new_height);
- ctx->NewState |= _NEW_BUFFERS; /* to update scissor / window bounds */
-}
-
-
-
-
-/**
- * Called when the driver should update it's state, based on the new_state
- * flags.
- */
-static void wmesa_update_state(GLcontext *ctx, GLuint new_state)
-{
- _swrast_InvalidateState(ctx, new_state);
- _swsetup_InvalidateState(ctx, new_state);
- _vbo_InvalidateState(ctx, new_state);
- _tnl_InvalidateState(ctx, new_state);
-
- /* TODO - This code is not complete yet because I
- * don't know what to do for all state updates.
- */
-
- if (new_state & _NEW_BUFFERS) {
- }
-}
-
-
-
-
-
-/**********************************************************************/
-/***** WMESA Functions *****/
-/**********************************************************************/
-
-WMesaContext WMesaCreateContext(HDC hDC,
- HPALETTE* Pal,
- GLboolean rgb_flag,
- GLboolean db_flag,
- GLboolean alpha_flag)
-{
- WMesaContext c;
- struct dd_function_table functions;
- GLint red_bits, green_bits, blue_bits, alpha_bits;
- GLcontext *ctx;
- GLvisual *visual;
-
- (void) Pal;
-
- /* Indexed mode not supported */
- if (!rgb_flag)
- return NULL;
-
- /* Allocate wmesa context */
- c = CALLOC_STRUCT(wmesa_context);
- if (!c)
- return NULL;
-
-#if 0
- /* I do not understand this contributed code */
- /* Support memory and device contexts */
- if(WindowFromDC(hDC) != NULL) {
- c->hDC = GetDC(WindowFromDC(hDC)); /* huh ???? */
- }
- else {
- c->hDC = hDC;
- }
-#else
- c->hDC = hDC;
-#endif
-
- /* Get data for visual */
- /* Dealing with this is actually a bit of overkill because Mesa will end
- * up treating all color component size requests less than 8 by using
- * a single byte per channel. In addition, the interface to the span
- * routines passes colors as an entire byte per channel anyway, so there
- * is nothing to be saved by telling the visual to be 16 bits if the device
- * is 16 bits. That is, Mesa is going to compute colors down to 8 bits per
- * channel anyway.
- * But we go through the motions here anyway.
- */
- switch (GetDeviceCaps(c->hDC, BITSPIXEL)) {
- case 16:
- red_bits = green_bits = blue_bits = 5;
- alpha_bits = 0;
- break;
- default:
- red_bits = green_bits = blue_bits = 8;
- alpha_bits = 8;
- break;
- }
- /* Create visual based on flags */
- visual = _mesa_create_visual(db_flag, /* db_flag */
- GL_FALSE, /* stereo */
- red_bits, green_bits, blue_bits, /* color RGB */
- alpha_flag ? alpha_bits : 0, /* color A */
- DEFAULT_SOFTWARE_DEPTH_BITS, /* depth_bits */
- 8, /* stencil_bits */
- 16,16,16, /* accum RGB */
- alpha_flag ? 16 : 0, /* accum A */
- 1); /* num samples */
-
- if (!visual) {
- free(c);
- return NULL;
- }
-
- /* Set up driver functions */
- _mesa_init_driver_functions(&functions);
- functions.GetString = wmesa_get_string;
- functions.UpdateState = wmesa_update_state;
- functions.GetBufferSize = wmesa_get_buffer_size;
- functions.Flush = wmesa_flush;
- functions.Clear = clear;
- functions.ClearColor = clear_color;
- functions.ResizeBuffers = wmesa_resize_buffers;
- functions.Viewport = wmesa_viewport;
-
- /* initialize the Mesa context data */
- ctx = &c->gl_ctx;
- _mesa_initialize_context(ctx, visual, NULL, &functions, (void *)c);
-
- /* visual no longer needed - it was copied by _mesa_initialize_context() */
- _mesa_destroy_visual(visual);
-
- _mesa_enable_sw_extensions(ctx);
- _mesa_enable_1_3_extensions(ctx);
- _mesa_enable_1_4_extensions(ctx);
- _mesa_enable_1_5_extensions(ctx);
- _mesa_enable_2_0_extensions(ctx);
- _mesa_enable_2_1_extensions(ctx);
-
- _mesa_meta_init(ctx);
-
- /* Initialize the software rasterizer and helper modules. */
- if (!_swrast_CreateContext(ctx) ||
- !_vbo_CreateContext(ctx) ||
- !_tnl_CreateContext(ctx) ||
- !_swsetup_CreateContext(ctx)) {
- _mesa_free_context_data(ctx);
- free(c);
- return NULL;
- }
- _swsetup_Wakeup(ctx);
- TNL_CONTEXT(ctx)->Driver.RunPipeline = _tnl_run_pipeline;
-
- return c;
-}
-
-
-void WMesaDestroyContext( WMesaContext pwc )
-{
- GLcontext *ctx = &pwc->gl_ctx;
- WMesaFramebuffer pwfb;
- GET_CURRENT_CONTEXT(cur_ctx);
-
- if (cur_ctx == ctx) {
- /* unbind current if deleting current context */
- WMesaMakeCurrent(NULL, NULL);
- }
-
- /* clean up frame buffer resources */
- pwfb = wmesa_lookup_framebuffer(pwc->hDC);
- if (pwfb) {
- if (ctx->Visual.doubleBufferMode == 1)
- wmDeleteBackingStore(pwfb);
- wmesa_free_framebuffer(pwc->hDC);
- }
-
- /* Release for device, not memory contexts */
- if (WindowFromDC(pwc->hDC) != NULL)
- {
- ReleaseDC(WindowFromDC(pwc->hDC), pwc->hDC);
- }
- DeleteObject(pwc->clearPen);
- DeleteObject(pwc->clearBrush);
-
- _mesa_meta_free(ctx);
-
- _swsetup_DestroyContext(ctx);
- _tnl_DestroyContext(ctx);
- _vbo_DestroyContext(ctx);
- _swrast_DestroyContext(ctx);
-
- _mesa_free_context_data(ctx);
- free(pwc);
-}
-
-
-/**
- * Create a new color renderbuffer.
- */
-struct gl_renderbuffer *
-wmesa_new_renderbuffer(void)
-{
- struct gl_renderbuffer *rb = CALLOC_STRUCT(gl_renderbuffer);
- if (!rb)
- return NULL;
-
- _mesa_init_renderbuffer(rb, (GLuint)0);
-
- rb->_BaseFormat = GL_RGBA;
- rb->InternalFormat = GL_RGBA;
- rb->DataType = CHAN_TYPE;
- rb->Delete = wmesa_delete_renderbuffer;
- rb->AllocStorage = wmesa_renderbuffer_storage;
- return rb;
-}
-
-
-void WMesaMakeCurrent(WMesaContext c, HDC hdc)
-{
- WMesaFramebuffer pwfb;
-
- {
- /* return if already current */
- GET_CURRENT_CONTEXT(ctx);
- WMesaContext pwc = wmesa_context(ctx);
- if (pwc && c == pwc && pwc->hDC == hdc)
- return;
- }
-
- pwfb = wmesa_lookup_framebuffer(hdc);
-
- /* Lazy creation of framebuffers */
- if (c && !pwfb && hdc) {
- struct gl_renderbuffer *rb;
- GLvisual *visual = &c->gl_ctx.Visual;
- GLuint width, height;
-
- get_window_size(hdc, &width, &height);
-
- c->clearPen = CreatePen(PS_SOLID, 1, 0);
- c->clearBrush = CreateSolidBrush(0);
-
- pwfb = wmesa_new_framebuffer(hdc, visual);
-
- /* Create back buffer if double buffered */
- if (visual->doubleBufferMode == 1) {
- wmCreateBackingStore(pwfb, width, height);
- }
-
- /* make render buffers */
- if (visual->doubleBufferMode == 1) {
- rb = wmesa_new_renderbuffer();
- _mesa_add_renderbuffer(&pwfb->Base, BUFFER_BACK_LEFT, rb);
- wmesa_set_renderbuffer_funcs(rb, pwfb->pixelformat, pwfb->cColorBits, 1);
- }
- rb = wmesa_new_renderbuffer();
- _mesa_add_renderbuffer(&pwfb->Base, BUFFER_FRONT_LEFT, rb);
- wmesa_set_renderbuffer_funcs(rb, pwfb->pixelformat, pwfb->cColorBits, 0);
-
- /* Let Mesa own the Depth, Stencil, and Accum buffers */
- _mesa_add_soft_renderbuffers(&pwfb->Base,
- GL_FALSE, /* color */
- visual->depthBits > 0,
- visual->stencilBits > 0,
- visual->accumRedBits > 0,
- visual->alphaBits >0,
- GL_FALSE);
- }
-
- if (c && pwfb)
- _mesa_make_current(&c->gl_ctx, &pwfb->Base, &pwfb->Base);
- else
- _mesa_make_current(NULL, NULL, NULL);
-}
-
-
-void WMesaSwapBuffers( HDC hdc )
-{
- GET_CURRENT_CONTEXT(ctx);
- WMesaContext pwc = wmesa_context(ctx);
- WMesaFramebuffer pwfb = wmesa_lookup_framebuffer(hdc);
-
- if (!pwfb) {
- _mesa_problem(NULL, "wmesa: swapbuffers on unknown hdc");
- return;
- }
-
- /* If we're swapping the buffer associated with the current context
- * we have to flush any pending rendering commands first.
- */
- if (pwc->hDC == hdc) {
- _mesa_notifySwapBuffers(ctx);
-
- BitBlt(pwfb->hDC, 0, 0, pwfb->Base.Width, pwfb->Base.Height,
- pwfb->dib_hDC, 0, 0, SRCCOPY);
- }
- else {
- /* XXX for now only allow swapping current window */
- _mesa_problem(NULL, "wmesa: can't swap non-current window");
- }
-}
-
-void WMesaShareLists(WMesaContext ctx_to_share, WMesaContext ctx)
-{
- _mesa_share_state(&ctx->gl_ctx, &ctx_to_share->gl_ctx);
-}
-
+/*
+ * Windows (Win32/Win64) device driver for Mesa
+ *
+ */
+
+#include "wmesadef.h"
+#include "colors.h"
+#include <GL/wmesa.h>
+#include <winuser.h>
+#include "context.h"
+#include "extensions.h"
+#include "framebuffer.h"
+#include "renderbuffer.h"
+#include "drivers/common/driverfuncs.h"
+#include "drivers/common/meta.h"
+#include "vbo/vbo.h"
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+
+/* linked list of our Framebuffers (windows) */
+static WMesaFramebuffer FirstFramebuffer = NULL;
+
+
+/**
+ * Create a new WMesaFramebuffer object which will correspond to the
+ * given HDC (Window handle).
+ */
+WMesaFramebuffer
+wmesa_new_framebuffer(HDC hdc, struct gl_config *visual)
+{
+ WMesaFramebuffer pwfb
+ = (WMesaFramebuffer) malloc(sizeof(struct wmesa_framebuffer));
+ if (pwfb) {
+ _mesa_initialize_window_framebuffer(&pwfb->Base, visual);
+ pwfb->hDC = hdc;
+ /* insert at head of list */
+ pwfb->next = FirstFramebuffer;
+ FirstFramebuffer = pwfb;
+ }
+ return pwfb;
+}
+
+/**
+ * Given an hdc, free the corresponding WMesaFramebuffer
+ */
+void
+wmesa_free_framebuffer(HDC hdc)
+{
+ WMesaFramebuffer pwfb, prev;
+ for (pwfb = FirstFramebuffer; pwfb; pwfb = pwfb->next) {
+ if (pwfb->hDC == hdc)
+ break;
+ prev = pwfb;
+ }
+ if (pwfb) {
+ struct gl_framebuffer *fb;
+ if (pwfb == FirstFramebuffer)
+ FirstFramebuffer = pwfb->next;
+ else
+ prev->next = pwfb->next;
+ fb = &pwfb->Base;
+ _mesa_reference_framebuffer(&fb, NULL);
+ }
+}
+
+/**
+ * Given an hdc, return the corresponding WMesaFramebuffer
+ */
+WMesaFramebuffer
+wmesa_lookup_framebuffer(HDC hdc)
+{
+ WMesaFramebuffer pwfb;
+ for (pwfb = FirstFramebuffer; pwfb; pwfb = pwfb->next) {
+ if (pwfb->hDC == hdc)
+ return pwfb;
+ }
+ return NULL;
+}
+
+
+/**
+ * Given a struct gl_framebuffer, return the corresponding WMesaFramebuffer.
+ */
+static WMesaFramebuffer wmesa_framebuffer(struct gl_framebuffer *fb)
+{
+ return (WMesaFramebuffer) fb;
+}
+
+
+/**
+ * Given a struct gl_context, return the corresponding WMesaContext.
+ */
+static WMesaContext wmesa_context(const struct gl_context *ctx)
+{
+ return (WMesaContext) ctx;
+}
+
+
+/*
+ * Every driver should implement a GetString function in order to
+ * return a meaningful GL_RENDERER string.
+ */
+static const GLubyte *wmesa_get_string(struct gl_context *ctx, GLenum name)
+{
+ return (name == GL_RENDERER) ?
+ (GLubyte *) "Mesa Windows GDI Driver" : NULL;
+}
+
+
+/*
+ * Determine the pixel format based on the pixel size.
+ */
+static void wmSetPixelFormat(WMesaFramebuffer pwfb, HDC hDC)
+{
+ pwfb->cColorBits = GetDeviceCaps(hDC, BITSPIXEL);
+
+ /* Only 16 and 32 bit targets are supported now */
+ assert(pwfb->cColorBits == 0 ||
+ pwfb->cColorBits == 16 ||
+ pwfb->cColorBits == 24 ||
+ pwfb->cColorBits == 32);
+
+ switch(pwfb->cColorBits){
+ case 8:
+ pwfb->pixelformat = PF_INDEX8;
+ break;
+ case 16:
+ pwfb->pixelformat = PF_5R6G5B;
+ break;
+ case 24:
+ case 32:
+ pwfb->pixelformat = PF_8R8G8B;
+ break;
+ default:
+ pwfb->pixelformat = PF_BADFORMAT;
+ }
+}
+
+
+/**
+ * Create DIB for back buffer.
+ * We write into this memory with the span routines and then blit it
+ * to the window on a buffer swap.
+ */
+BOOL wmCreateBackingStore(WMesaFramebuffer pwfb, long lxSize, long lySize)
+{
+ HDC hdc = pwfb->hDC;
+ LPBITMAPINFO pbmi = &(pwfb->bmi);
+ HDC hic;
+
+ pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ pbmi->bmiHeader.biWidth = lxSize;
+ pbmi->bmiHeader.biHeight= -lySize;
+ pbmi->bmiHeader.biPlanes = 1;
+ pbmi->bmiHeader.biBitCount = GetDeviceCaps(pwfb->hDC, BITSPIXEL);
+ pbmi->bmiHeader.biCompression = BI_RGB;
+ pbmi->bmiHeader.biSizeImage = 0;
+ pbmi->bmiHeader.biXPelsPerMeter = 0;
+ pbmi->bmiHeader.biYPelsPerMeter = 0;
+ pbmi->bmiHeader.biClrUsed = 0;
+ pbmi->bmiHeader.biClrImportant = 0;
+
+ pwfb->cColorBits = pbmi->bmiHeader.biBitCount;
+ pwfb->ScanWidth = (lxSize * (pwfb->cColorBits / 8) + 3) & ~3;
+
+ hic = CreateIC("display", NULL, NULL, NULL);
+ pwfb->dib_hDC = CreateCompatibleDC(hic);
+
+ pwfb->hbmDIB = CreateDIBSection(hic,
+ &pwfb->bmi,
+ DIB_RGB_COLORS,
+ (void **)&(pwfb->pbPixels),
+ 0,
+ 0);
+ pwfb->hOldBitmap = SelectObject(pwfb->dib_hDC, pwfb->hbmDIB);
+
+ DeleteDC(hic);
+
+ wmSetPixelFormat(pwfb, pwfb->hDC);
+ return TRUE;
+}
+
+
+static wmDeleteBackingStore(WMesaFramebuffer pwfb)
+{
+ if (pwfb->hbmDIB) {
+ SelectObject(pwfb->dib_hDC, pwfb->hOldBitmap);
+ DeleteDC(pwfb->dib_hDC);
+ DeleteObject(pwfb->hbmDIB);
+ }
+}
+
+
+/**
+ * Find the width and height of the window named by hdc.
+ */
+static void
+get_window_size(HDC hdc, GLuint *width, GLuint *height)
+{
+ if (WindowFromDC(hdc)) {
+ RECT rect;
+ GetClientRect(WindowFromDC(hdc), &rect);
+ *width = rect.right - rect.left;
+ *height = rect.bottom - rect.top;
+ }
+ else { /* Memory context */
+ /* From contributed code - use the size of the desktop
+ * for the size of a memory context (?) */
+ *width = GetDeviceCaps(hdc, HORZRES);
+ *height = GetDeviceCaps(hdc, VERTRES);
+ }
+}
+
+
+static void
+wmesa_get_buffer_size(struct gl_framebuffer *buffer, GLuint *width, GLuint *height)
+{
+ WMesaFramebuffer pwfb = wmesa_framebuffer(buffer);
+ get_window_size(pwfb->hDC, width, height);
+}
+
+
+static void wmesa_flush(struct gl_context *ctx)
+{
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->WinSysDrawBuffer);
+
+ if (ctx->Visual.doubleBufferMode == 1) {
+ BitBlt(pwfb->hDC, 0, 0, pwfb->Base.Width, pwfb->Base.Height,
+ pwfb->dib_hDC, 0, 0, SRCCOPY);
+ }
+ else {
+ /* Do nothing for single buffer */
+ }
+}
+
+
+/**********************************************************************/
+/***** CLEAR Functions *****/
+/**********************************************************************/
+
+/* If we do not implement these, Mesa clears the buffers via the pixel
+ * span writing interface, which is very slow for a clear operation.
+ */
+
+/*
+ * Set the color used to clear the color buffer.
+ */
+static void clear_color(struct gl_context *ctx, const GLfloat color[4])
+{
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+ GLubyte col[3];
+ UINT bytesPerPixel = pwfb->cColorBits / 8;
+
+ CLAMPED_FLOAT_TO_UBYTE(col[0], color[0]);
+ CLAMPED_FLOAT_TO_UBYTE(col[1], color[1]);
+ CLAMPED_FLOAT_TO_UBYTE(col[2], color[2]);
+ pwc->clearColorRef = RGB(col[0], col[1], col[2]);
+ DeleteObject(pwc->clearPen);
+ DeleteObject(pwc->clearBrush);
+ pwc->clearPen = CreatePen(PS_SOLID, 1, pwc->clearColorRef);
+ pwc->clearBrush = CreateSolidBrush(pwc->clearColorRef);
+}
+
+
+/*
+ * Clear the specified region of the color buffer using the clear color
+ * or index as specified by one of the two functions above.
+ *
+ * This procedure clears either the front and/or the back COLOR buffers.
+ * Only the "left" buffer is cleared since we are not stereo.
+ * Clearing of the other non-color buffers is left to the swrast.
+ */
+
+static void clear(struct gl_context *ctx, GLbitfield mask)
+{
+#define FLIP(Y) (ctx->DrawBuffer->Height - (Y) - 1)
+ const GLint x = ctx->DrawBuffer->_Xmin;
+ const GLint y = ctx->DrawBuffer->_Ymin;
+ const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
+ const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
+
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+ int done = 0;
+
+ /* Let swrast do all the work if the masks are not set to
+ * clear all channels. */
+ if (!ctx->Color.ColorMask[0][0] ||
+ !ctx->Color.ColorMask[0][1] ||
+ !ctx->Color.ColorMask[0][2] ||
+ !ctx->Color.ColorMask[0][3]) {
+ _swrast_Clear(ctx, mask);
+ return;
+ }
+
+ /* Back buffer */
+ if (mask & BUFFER_BIT_BACK_LEFT) {
+
+ int i, rowSize;
+ UINT bytesPerPixel = pwfb->cColorBits / 8;
+ LPBYTE lpb, clearRow;
+ LPWORD lpw;
+ BYTE bColor;
+ WORD wColor;
+ BYTE r, g, b;
+ DWORD dwColor;
+ LPDWORD lpdw;
+
+ /* Try for a fast clear - clearing entire buffer with a single
+ * byte value. */
+ if (width == ctx->DrawBuffer->Width &&
+ height == ctx->DrawBuffer->Height) { /* entire buffer */
+ /* Now check for an easy clear value */
+ switch (bytesPerPixel) {
+ case 1:
+ bColor = BGR8(GetRValue(pwc->clearColorRef),
+ GetGValue(pwc->clearColorRef),
+ GetBValue(pwc->clearColorRef));
+ memset(pwfb->pbPixels, bColor,
+ pwfb->ScanWidth * height);
+ done = 1;
+ break;
+ case 2:
+ wColor = BGR16(GetRValue(pwc->clearColorRef),
+ GetGValue(pwc->clearColorRef),
+ GetBValue(pwc->clearColorRef));
+ if (((wColor >> 8) & 0xff) == (wColor & 0xff)) {
+ memset(pwfb->pbPixels, wColor & 0xff,
+ pwfb->ScanWidth * height);
+ done = 1;
+ }
+ break;
+ case 3:
+ /* fall through */
+ case 4:
+ if (GetRValue(pwc->clearColorRef) ==
+ GetGValue(pwc->clearColorRef) &&
+ GetRValue(pwc->clearColorRef) ==
+ GetBValue(pwc->clearColorRef)) {
+ memset(pwfb->pbPixels,
+ GetRValue(pwc->clearColorRef),
+ pwfb->ScanWidth * height);
+ done = 1;
+ }
+ break;
+ default:
+ break;
+ }
+ } /* all */
+
+ if (!done) {
+ /* Need to clear a row at a time. Begin by setting the first
+ * row in the area to be cleared to the clear color. */
+
+ clearRow = pwfb->pbPixels +
+ pwfb->ScanWidth * FLIP(y) +
+ bytesPerPixel * x;
+ switch (bytesPerPixel) {
+ case 1:
+ lpb = clearRow;
+ bColor = BGR8(GetRValue(pwc->clearColorRef),
+ GetGValue(pwc->clearColorRef),
+ GetBValue(pwc->clearColorRef));
+ memset(lpb, bColor, width);
+ break;
+ case 2:
+ lpw = (LPWORD)clearRow;
+ wColor = BGR16(GetRValue(pwc->clearColorRef),
+ GetGValue(pwc->clearColorRef),
+ GetBValue(pwc->clearColorRef));
+ for (i=0; i<width; i++)
+ *lpw++ = wColor;
+ break;
+ case 3:
+ lpb = clearRow;
+ r = GetRValue(pwc->clearColorRef);
+ g = GetGValue(pwc->clearColorRef);
+ b = GetBValue(pwc->clearColorRef);
+ for (i=0; i<width; i++) {
+ *lpb++ = b;
+ *lpb++ = g;
+ *lpb++ = r;
+ }
+ break;
+ case 4:
+ lpdw = (LPDWORD)clearRow;
+ dwColor = BGR32(GetRValue(pwc->clearColorRef),
+ GetGValue(pwc->clearColorRef),
+ GetBValue(pwc->clearColorRef));
+ for (i=0; i<width; i++)
+ *lpdw++ = dwColor;
+ break;
+ default:
+ break;
+ } /* switch */
+
+ /* copy cleared row to other rows in buffer */
+ lpb = clearRow - pwfb->ScanWidth;
+ rowSize = width * bytesPerPixel;
+ for (i=1; i<height; i++) {
+ memcpy(lpb, clearRow, rowSize);
+ lpb -= pwfb->ScanWidth;
+ }
+ } /* not done */
+ mask &= ~BUFFER_BIT_BACK_LEFT;
+ } /* back buffer */
+
+ /* front buffer */
+ if (mask & BUFFER_BIT_FRONT_LEFT) {
+ HDC DC = pwc->hDC;
+ HPEN Old_Pen = SelectObject(DC, pwc->clearPen);
+ HBRUSH Old_Brush = SelectObject(DC, pwc->clearBrush);
+ Rectangle(DC,
+ x,
+ FLIP(y) + 1,
+ x + width + 1,
+ FLIP(y) - height + 1);
+ SelectObject(DC, Old_Pen);
+ SelectObject(DC, Old_Brush);
+ mask &= ~BUFFER_BIT_FRONT_LEFT;
+ } /* front buffer */
+
+ /* Call swrast if there is anything left to clear (like DEPTH) */
+ if (mask)
+ _swrast_Clear(ctx, mask);
+
+#undef FLIP
+}
+
+
+/**********************************************************************/
+/***** PIXEL Functions *****/
+/**********************************************************************/
+
+#define FLIP(Y) (rb->Height - (Y) - 1)
+
+
+/**
+ ** Front Buffer reading/writing
+ ** These are slow, but work with all non-indexed visual types.
+ **/
+
+/* Write a horizontal span of RGBA color pixels with a boolean mask. */
+static void write_rgba_span_front(const struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const GLubyte rgba[][4],
+ const GLubyte mask[] )
+{
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_lookup_framebuffer(pwc->hDC);
+ CONST BITMAPINFO bmi=
+ {
+ {
+ sizeof(BITMAPINFOHEADER),
+ n, 1, 1, 32, BI_RGB, 0, 1, 1, 0, 0
+ }
+ };
+ HBITMAP bmp=0;
+ HDC mdc=0;
+ typedef union
+ {
+ unsigned i;
+ struct {
+ unsigned b:8, g:8, r:8, a:8;
+ };
+ } BGRA;
+ BGRA *bgra, c;
+ GLuint i;
+
+ if (n < 16) { // the value 16 is just guessed
+ y=FLIP(y);
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ SetPixel(pwc->hDC, x+i, y,
+ RGB(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]));
+ }
+ else {
+ for (i=0; i<n; i++)
+ SetPixel(pwc->hDC, x+i, y,
+ RGB(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]));
+ }
+ }
+ else {
+ if (!pwfb) {
+ _mesa_problem(NULL, "wmesa: write_rgba_span_front on unknown hdc");
+ return;
+ }
+ bgra=malloc(n*sizeof(BGRA));
+ if (!bgra) {
+ _mesa_problem(NULL, "wmesa: write_rgba_span_front: out of memory");
+ return;
+ }
+ c.a=0;
+ if (mask) {
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ c.r=rgba[i][RCOMP];
+ c.g=rgba[i][GCOMP];
+ c.b=rgba[i][BCOMP];
+ c.a=rgba[i][ACOMP];
+ bgra[i]=c;
+ }
+ else
+ bgra[i].i=0;
+ }
+ }
+ else {
+ for (i=0; i<n; i++) {
+ c.r=rgba[i][RCOMP];
+ c.g=rgba[i][GCOMP];
+ c.b=rgba[i][BCOMP];
+ c.a=rgba[i][ACOMP];
+ bgra[i]=c;
+ }
+ }
+ bmp=CreateBitmap(n, 1, 1, 32, bgra);
+ mdc=CreateCompatibleDC(pwfb->hDC);
+ SelectObject(mdc, bmp);
+ y=FLIP(y);
+ BitBlt(pwfb->hDC, x, y, n, 1, mdc, 0, 0, SRCCOPY);
+ SelectObject(mdc, 0);
+ DeleteObject(bmp);
+ DeleteDC(mdc);
+ free(bgra);
+ }
+}
+
+/* Write a horizontal span of RGB color pixels with a boolean mask. */
+static void write_rgb_span_front(const struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const GLubyte rgb[][3],
+ const GLubyte mask[] )
+{
+ WMesaContext pwc = wmesa_context(ctx);
+ GLuint i;
+
+ (void) ctx;
+ y=FLIP(y);
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ SetPixel(pwc->hDC, x+i, y, RGB(rgb[i][RCOMP], rgb[i][GCOMP],
+ rgb[i][BCOMP]));
+ }
+ else {
+ for (i=0; i<n; i++)
+ SetPixel(pwc->hDC, x+i, y, RGB(rgb[i][RCOMP], rgb[i][GCOMP],
+ rgb[i][BCOMP]));
+ }
+
+}
+
+/*
+ * Write a horizontal span of pixels with a boolean mask. The current color
+ * is used for all pixels.
+ */
+static void write_mono_rgba_span_front(const struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const GLchan color[4],
+ const GLubyte mask[])
+{
+ GLuint i;
+ WMesaContext pwc = wmesa_context(ctx);
+ COLORREF colorref;
+
+ (void) ctx;
+ colorref = RGB(color[RCOMP], color[GCOMP], color[BCOMP]);
+ y=FLIP(y);
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ SetPixel(pwc->hDC, x+i, y, colorref);
+ }
+ else
+ for (i=0; i<n; i++)
+ SetPixel(pwc->hDC, x+i, y, colorref);
+
+}
+
+/* Write an array of RGBA pixels with a boolean mask. */
+static void write_rgba_pixels_front(const struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ const GLubyte rgba[][4],
+ const GLubyte mask[] )
+{
+ GLuint i;
+ WMesaContext pwc = wmesa_context(ctx);
+ (void) ctx;
+ for (i=0; i<n; i++)
+ if (mask[i])
+ SetPixel(pwc->hDC, x[i], FLIP(y[i]),
+ RGB(rgba[i][RCOMP], rgba[i][GCOMP],
+ rgba[i][BCOMP]));
+}
+
+
+
+/*
+ * Write an array of pixels with a boolean mask. The current color
+ * is used for all pixels.
+ */
+static void write_mono_rgba_pixels_front(const struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ const GLchan color[4],
+ const GLubyte mask[] )
+{
+ GLuint i;
+ WMesaContext pwc = wmesa_context(ctx);
+ COLORREF colorref;
+ (void) ctx;
+ colorref = RGB(color[RCOMP], color[GCOMP], color[BCOMP]);
+ for (i=0; i<n; i++)
+ if (mask[i])
+ SetPixel(pwc->hDC, x[i], FLIP(y[i]), colorref);
+}
+
+/* Read a horizontal span of color pixels. */
+static void read_rgba_span_front(const struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ GLubyte rgba[][4] )
+{
+ WMesaContext pwc = wmesa_context(ctx);
+ GLuint i;
+ COLORREF Color;
+ y = FLIP(y);
+ for (i=0; i<n; i++) {
+ Color = GetPixel(pwc->hDC, x+i, y);
+ rgba[i][RCOMP] = GetRValue(Color);
+ rgba[i][GCOMP] = GetGValue(Color);
+ rgba[i][BCOMP] = GetBValue(Color);
+ rgba[i][ACOMP] = 255;
+ }
+}
+
+
+/* Read an array of color pixels. */
+static void read_rgba_pixels_front(const struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte rgba[][4])
+{
+ WMesaContext pwc = wmesa_context(ctx);
+ GLuint i;
+ COLORREF Color;
+ for (i=0; i<n; i++) {
+ GLint y2 = FLIP(y[i]);
+ Color = GetPixel(pwc->hDC, x[i], y2);
+ rgba[i][RCOMP] = GetRValue(Color);
+ rgba[i][GCOMP] = GetGValue(Color);
+ rgba[i][BCOMP] = GetBValue(Color);
+ rgba[i][ACOMP] = 255;
+ }
+}
+
+/*********************************************************************/
+
+/* DOUBLE BUFFER 32-bit */
+
+#define WMSETPIXEL32(pwc, y, x, r, g, b) { \
+LPDWORD lpdw = ((LPDWORD)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (x)); \
+*lpdw = BGR32((r),(g),(b)); }
+
+
+
+/* Write a horizontal span of RGBA color pixels with a boolean mask. */
+static void write_rgba_span_32(const struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const GLubyte rgba[][4],
+ const GLubyte mask[] )
+{
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+ GLuint i;
+ LPDWORD lpdw;
+
+ (void) ctx;
+
+ y=FLIP(y);
+ lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ lpdw[i] = BGR32(rgba[i][RCOMP], rgba[i][GCOMP],
+ rgba[i][BCOMP]);
+ }
+ else {
+ for (i=0; i<n; i++)
+ *lpdw++ = BGR32(rgba[i][RCOMP], rgba[i][GCOMP],
+ rgba[i][BCOMP]);
+ }
+}
+
+
+/* Write a horizontal span of RGB color pixels with a boolean mask. */
+static void write_rgb_span_32(const struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const GLubyte rgb[][3],
+ const GLubyte mask[] )
+{
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+ GLuint i;
+ LPDWORD lpdw;
+
+ (void) ctx;
+
+ y=FLIP(y);
+ lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ lpdw[i] = BGR32(rgb[i][RCOMP], rgb[i][GCOMP],
+ rgb[i][BCOMP]);
+ }
+ else {
+ for (i=0; i<n; i++)
+ *lpdw++ = BGR32(rgb[i][RCOMP], rgb[i][GCOMP],
+ rgb[i][BCOMP]);
+ }
+}
+
+/*
+ * Write a horizontal span of pixels with a boolean mask. The current color
+ * is used for all pixels.
+ */
+static void write_mono_rgba_span_32(const struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const GLchan color[4],
+ const GLubyte mask[])
+{
+ LPDWORD lpdw;
+ DWORD pixel;
+ GLuint i;
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+ lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
+ y=FLIP(y);
+ pixel = BGR32(color[RCOMP], color[GCOMP], color[BCOMP]);
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ lpdw[i] = pixel;
+ }
+ else
+ for (i=0; i<n; i++)
+ *lpdw++ = pixel;
+
+}
+
+/* Write an array of RGBA pixels with a boolean mask. */
+static void write_rgba_pixels_32(const struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLubyte rgba[][4],
+ const GLubyte mask[])
+{
+ GLuint i;
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+ for (i=0; i<n; i++)
+ if (mask[i])
+ WMSETPIXEL32(pwfb, FLIP(y[i]), x[i],
+ rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
+}
+
+/*
+ * Write an array of pixels with a boolean mask. The current color
+ * is used for all pixels.
+ */
+static void write_mono_rgba_pixels_32(const struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ const GLchan color[4],
+ const GLubyte mask[])
+{
+ GLuint i;
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+ for (i=0; i<n; i++)
+ if (mask[i])
+ WMSETPIXEL32(pwfb, FLIP(y[i]),x[i],color[RCOMP],
+ color[GCOMP], color[BCOMP]);
+}
+
+/* Read a horizontal span of color pixels. */
+static void read_rgba_span_32(const struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ GLubyte rgba[][4] )
+{
+ GLuint i;
+ DWORD pixel;
+ LPDWORD lpdw;
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+
+ y = FLIP(y);
+ lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
+ for (i=0; i<n; i++) {
+ pixel = lpdw[i];
+ rgba[i][RCOMP] = (GLubyte)((pixel & 0x00ff0000) >> 16);
+ rgba[i][GCOMP] = (GLubyte)((pixel & 0x0000ff00) >> 8);
+ rgba[i][BCOMP] = (GLubyte)(pixel & 0x000000ff);
+ rgba[i][ACOMP] = 255;
+ }
+}
+
+
+/* Read an array of color pixels. */
+static void read_rgba_pixels_32(const struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte rgba[][4])
+{
+ GLuint i;
+ DWORD pixel;
+ LPDWORD lpdw;
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+
+ for (i=0; i<n; i++) {
+ GLint y2 = FLIP(y[i]);
+ lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y2)) + x[i];
+ pixel = *lpdw;
+ rgba[i][RCOMP] = (GLubyte)((pixel & 0x00ff0000) >> 16);
+ rgba[i][GCOMP] = (GLubyte)((pixel & 0x0000ff00) >> 8);
+ rgba[i][BCOMP] = (GLubyte)(pixel & 0x000000ff);
+ rgba[i][ACOMP] = 255;
+ }
+}
+
+
+/*********************************************************************/
+
+/* DOUBLE BUFFER 24-bit */
+
+#define WMSETPIXEL24(pwc, y, x, r, g, b) { \
+LPBYTE lpb = ((LPBYTE)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (3 * x)); \
+lpb[0] = (b); \
+lpb[1] = (g); \
+lpb[2] = (r); }
+
+/* Write a horizontal span of RGBA color pixels with a boolean mask. */
+static void write_rgba_span_24(const struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const GLubyte rgba[][4],
+ const GLubyte mask[] )
+{
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+ GLuint i;
+ LPBYTE lpb;
+
+ (void) ctx;
+
+ y=FLIP(y);
+ lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y)) + (3 * x);
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i]) {
+ lpb[3*i] = rgba[i][BCOMP];
+ lpb[3*i+1] = rgba[i][GCOMP];
+ lpb[3*i+2] = rgba[i][RCOMP];
+ }
+ }
+ else {
+ for (i=0; i<n; i++) {
+ *lpb++ = rgba[i][BCOMP];
+ *lpb++ = rgba[i][GCOMP];
+ *lpb++ = rgba[i][RCOMP];
+ }
+ }
+}
+
+
+/* Write a horizontal span of RGB color pixels with a boolean mask. */
+static void write_rgb_span_24(const struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const GLubyte rgb[][3],
+ const GLubyte mask[] )
+{
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+ GLuint i;
+ LPBYTE lpb;
+
+ (void) ctx;
+
+ y=FLIP(y);
+ lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y)) + (3 * x);
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i]) {
+ lpb[3*i] = rgb[i][BCOMP];
+ lpb[3*i+1] = rgb[i][GCOMP];
+ lpb[3*i+2] = rgb[i][RCOMP];
+ }
+ }
+ else {
+ for (i=0; i<n; i++) {
+ *lpb++ = rgb[i][BCOMP];
+ *lpb++ = rgb[i][GCOMP];
+ *lpb++ = rgb[i][RCOMP];
+ }
+ }
+}
+
+/*
+ * Write a horizontal span of pixels with a boolean mask. The current color
+ * is used for all pixels.
+ */
+static void write_mono_rgba_span_24(const struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const GLchan color[4],
+ const GLubyte mask[])
+{
+ LPBYTE lpb;
+ GLuint i;
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+ lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y)) + (3 * x);
+ y=FLIP(y);
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i]) {
+ lpb[3*i] = color[BCOMP];
+ lpb[3*i+1] = color[GCOMP];
+ lpb[3*i+2] = color[RCOMP];
+ }
+ }
+ else
+ for (i=0; i<n; i++) {
+ *lpb++ = color[BCOMP];
+ *lpb++ = color[GCOMP];
+ *lpb++ = color[RCOMP];
+ }
+}
+
+/* Write an array of RGBA pixels with a boolean mask. */
+static void write_rgba_pixels_24(const struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLubyte rgba[][4],
+ const GLubyte mask[])
+{
+ GLuint i;
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+ for (i=0; i<n; i++)
+ if (mask[i])
+ WMSETPIXEL24(pwfb, FLIP(y[i]), x[i],
+ rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
+}
+
+/*
+ * Write an array of pixels with a boolean mask. The current color
+ * is used for all pixels.
+ */
+static void write_mono_rgba_pixels_24(const struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ const GLchan color[4],
+ const GLubyte mask[])
+{
+ GLuint i;
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+ for (i=0; i<n; i++)
+ if (mask[i])
+ WMSETPIXEL24(pwfb, FLIP(y[i]),x[i],color[RCOMP],
+ color[GCOMP], color[BCOMP]);
+}
+
+/* Read a horizontal span of color pixels. */
+static void read_rgba_span_24(const struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ GLubyte rgba[][4] )
+{
+ GLuint i;
+ LPBYTE lpb;
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+
+ y = FLIP(y);
+ lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y)) + (3 * x);
+ for (i=0; i<n; i++) {
+ rgba[i][RCOMP] = lpb[3*i+2];
+ rgba[i][GCOMP] = lpb[3*i+1];
+ rgba[i][BCOMP] = lpb[3*i];
+ rgba[i][ACOMP] = 255;
+ }
+}
+
+
+/* Read an array of color pixels. */
+static void read_rgba_pixels_24(const struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte rgba[][4])
+{
+ GLuint i;
+ LPBYTE lpb;
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+
+ for (i=0; i<n; i++) {
+ GLint y2 = FLIP(y[i]);
+ lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y2)) + (3 * x[i]);
+ rgba[i][RCOMP] = lpb[3*i+2];
+ rgba[i][GCOMP] = lpb[3*i+1];
+ rgba[i][BCOMP] = lpb[3*i];
+ rgba[i][ACOMP] = 255;
+ }
+}
+
+
+/*********************************************************************/
+
+/* DOUBLE BUFFER 16-bit */
+
+#define WMSETPIXEL16(pwc, y, x, r, g, b) { \
+LPWORD lpw = ((LPWORD)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (x)); \
+*lpw = BGR16((r),(g),(b)); }
+
+
+
+/* Write a horizontal span of RGBA color pixels with a boolean mask. */
+static void write_rgba_span_16(const struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const GLubyte rgba[][4],
+ const GLubyte mask[] )
+{
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+ GLuint i;
+ LPWORD lpw;
+
+ (void) ctx;
+
+ y=FLIP(y);
+ lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ lpw[i] = BGR16(rgba[i][RCOMP], rgba[i][GCOMP],
+ rgba[i][BCOMP]);
+ }
+ else {
+ for (i=0; i<n; i++)
+ *lpw++ = BGR16(rgba[i][RCOMP], rgba[i][GCOMP],
+ rgba[i][BCOMP]);
+ }
+}
+
+
+/* Write a horizontal span of RGB color pixels with a boolean mask. */
+static void write_rgb_span_16(const struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const GLubyte rgb[][3],
+ const GLubyte mask[] )
+{
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+ GLuint i;
+ LPWORD lpw;
+
+ (void) ctx;
+
+ y=FLIP(y);
+ lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ lpw[i] = BGR16(rgb[i][RCOMP], rgb[i][GCOMP],
+ rgb[i][BCOMP]);
+ }
+ else {
+ for (i=0; i<n; i++)
+ *lpw++ = BGR16(rgb[i][RCOMP], rgb[i][GCOMP],
+ rgb[i][BCOMP]);
+ }
+}
+
+/*
+ * Write a horizontal span of pixels with a boolean mask. The current color
+ * is used for all pixels.
+ */
+static void write_mono_rgba_span_16(const struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const GLchan color[4],
+ const GLubyte mask[])
+{
+ LPWORD lpw;
+ WORD pixel;
+ GLuint i;
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+ (void) ctx;
+ lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
+ y=FLIP(y);
+ pixel = BGR16(color[RCOMP], color[GCOMP], color[BCOMP]);
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ lpw[i] = pixel;
+ }
+ else
+ for (i=0; i<n; i++)
+ *lpw++ = pixel;
+
+}
+
+/* Write an array of RGBA pixels with a boolean mask. */
+static void write_rgba_pixels_16(const struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLubyte rgba[][4],
+ const GLubyte mask[])
+{
+ GLuint i;
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+ (void) ctx;
+ for (i=0; i<n; i++)
+ if (mask[i])
+ WMSETPIXEL16(pwfb, FLIP(y[i]), x[i],
+ rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
+}
+
+/*
+ * Write an array of pixels with a boolean mask. The current color
+ * is used for all pixels.
+ */
+static void write_mono_rgba_pixels_16(const struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ const GLchan color[4],
+ const GLubyte mask[])
+{
+ GLuint i;
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+ (void) ctx;
+ for (i=0; i<n; i++)
+ if (mask[i])
+ WMSETPIXEL16(pwfb, FLIP(y[i]),x[i],color[RCOMP],
+ color[GCOMP], color[BCOMP]);
+}
+
+/* Read a horizontal span of color pixels. */
+static void read_rgba_span_16(const struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ GLubyte rgba[][4] )
+{
+ GLuint i, pixel;
+ LPWORD lpw;
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+
+ y = FLIP(y);
+ lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
+ for (i=0; i<n; i++) {
+ pixel = lpw[i];
+ /* Windows uses 5,5,5 for 16-bit */
+ rgba[i][RCOMP] = (pixel & 0x7c00) >> 7;
+ rgba[i][GCOMP] = (pixel & 0x03e0) >> 2;
+ rgba[i][BCOMP] = (pixel & 0x001f) << 3;
+ rgba[i][ACOMP] = 255;
+ }
+}
+
+
+/* Read an array of color pixels. */
+static void read_rgba_pixels_16(const struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte rgba[][4])
+{
+ GLuint i, pixel;
+ LPWORD lpw;
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+
+ for (i=0; i<n; i++) {
+ GLint y2 = FLIP(y[i]);
+ lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y2)) + x[i];
+ pixel = *lpw;
+ /* Windows uses 5,5,5 for 16-bit */
+ rgba[i][RCOMP] = (pixel & 0x7c00) >> 7;
+ rgba[i][GCOMP] = (pixel & 0x03e0) >> 2;
+ rgba[i][BCOMP] = (pixel & 0x001f) << 3;
+ rgba[i][ACOMP] = 255;
+ }
+}
+
+
+
+
+/**********************************************************************/
+/***** BUFFER Functions *****/
+/**********************************************************************/
+
+
+
+
+static void
+wmesa_delete_renderbuffer(struct gl_renderbuffer *rb)
+{
+ free(rb);
+}
+
+
+/**
+ * This is called by Mesa whenever it determines that the window size
+ * has changed. Do whatever's needed to cope with that.
+ */
+static GLboolean
+wmesa_renderbuffer_storage(struct gl_context *ctx,
+ struct gl_renderbuffer *rb,
+ GLenum internalFormat,
+ GLuint width,
+ GLuint height)
+{
+ rb->Width = width;
+ rb->Height = height;
+ return GL_TRUE;
+}
+
+
+/**
+ * Plug in the Get/PutRow/Values functions for a renderbuffer depending
+ * on if we're drawing to the front or back color buffer.
+ */
+void wmesa_set_renderbuffer_funcs(struct gl_renderbuffer *rb, int pixelformat,
+ int cColorBits, int double_buffer)
+{
+ if (double_buffer) {
+ /* back buffer */
+ /* Picking the correct span functions is important because
+ * the DIB was allocated with the indicated depth. */
+ switch(pixelformat) {
+ case PF_5R6G5B:
+ rb->PutRow = write_rgba_span_16;
+ rb->PutRowRGB = write_rgb_span_16;
+ rb->PutMonoRow = write_mono_rgba_span_16;
+ rb->PutValues = write_rgba_pixels_16;
+ rb->PutMonoValues = write_mono_rgba_pixels_16;
+ rb->GetRow = read_rgba_span_16;
+ rb->GetValues = read_rgba_pixels_16;
+ break;
+ case PF_8R8G8B:
+ if (cColorBits == 24)
+ {
+ rb->PutRow = write_rgba_span_24;
+ rb->PutRowRGB = write_rgb_span_24;
+ rb->PutMonoRow = write_mono_rgba_span_24;
+ rb->PutValues = write_rgba_pixels_24;
+ rb->PutMonoValues = write_mono_rgba_pixels_24;
+ rb->GetRow = read_rgba_span_24;
+ rb->GetValues = read_rgba_pixels_24;
+ }
+ else
+ {
+ rb->PutRow = write_rgba_span_32;
+ rb->PutRowRGB = write_rgb_span_32;
+ rb->PutMonoRow = write_mono_rgba_span_32;
+ rb->PutValues = write_rgba_pixels_32;
+ rb->PutMonoValues = write_mono_rgba_pixels_32;
+ rb->GetRow = read_rgba_span_32;
+ rb->GetValues = read_rgba_pixels_32;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ else {
+ /* front buffer (actual Windows window) */
+ rb->PutRow = write_rgba_span_front;
+ rb->PutRowRGB = write_rgb_span_front;
+ rb->PutMonoRow = write_mono_rgba_span_front;
+ rb->PutValues = write_rgba_pixels_front;
+ rb->PutMonoValues = write_mono_rgba_pixels_front;
+ rb->GetRow = read_rgba_span_front;
+ rb->GetValues = read_rgba_pixels_front;
+ }
+}
+
+/**
+ * Called by ctx->Driver.ResizeBuffers()
+ * Resize the front/back colorbuffers to match the latest window size.
+ */
+static void
+wmesa_resize_buffers(struct gl_context *ctx, struct gl_framebuffer *buffer,
+ GLuint width, GLuint height)
+{
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(buffer);
+
+ if (pwfb->Base.Width != width || pwfb->Base.Height != height) {
+ /* Realloc back buffer */
+ if (ctx->Visual.doubleBufferMode == 1) {
+ wmDeleteBackingStore(pwfb);
+ wmCreateBackingStore(pwfb, width, height);
+ }
+ }
+ _mesa_resize_framebuffer(ctx, buffer, width, height);
+}
+
+
+/**
+ * Called by glViewport.
+ * This is a good time for us to poll the current window size and adjust
+ * our renderbuffers to match the current window size.
+ * Remember, we have no opportunity to respond to conventional
+ * resize events since the driver has no event loop.
+ * Thus, we poll.
+ * MakeCurrent also ends up making a call here, so that ensures
+ * we get the viewport set correctly, even if the app does not call
+ * glViewport and relies on the defaults.
+ */
+static void wmesa_viewport(struct gl_context *ctx,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height)
+{
+ WMesaContext pwc = wmesa_context(ctx);
+ GLuint new_width, new_height;
+
+ wmesa_get_buffer_size(ctx->WinSysDrawBuffer, &new_width, &new_height);
+
+ /**
+ * Resize buffers if the window size changed.
+ */
+ wmesa_resize_buffers(ctx, ctx->WinSysDrawBuffer, new_width, new_height);
+ ctx->NewState |= _NEW_BUFFERS; /* to update scissor / window bounds */
+}
+
+
+
+
+/**
+ * Called when the driver should update it's state, based on the new_state
+ * flags.
+ */
+static void wmesa_update_state(struct gl_context *ctx, GLuint new_state)
+{
+ _swrast_InvalidateState(ctx, new_state);
+ _swsetup_InvalidateState(ctx, new_state);
+ _vbo_InvalidateState(ctx, new_state);
+ _tnl_InvalidateState(ctx, new_state);
+
+ /* TODO - This code is not complete yet because I
+ * don't know what to do for all state updates.
+ */
+
+ if (new_state & _NEW_BUFFERS) {
+ }
+}
+
+
+
+
+
+/**********************************************************************/
+/***** WMESA Functions *****/
+/**********************************************************************/
+
+WMesaContext WMesaCreateContext(HDC hDC,
+ HPALETTE* Pal,
+ GLboolean rgb_flag,
+ GLboolean db_flag,
+ GLboolean alpha_flag)
+{
+ WMesaContext c;
+ struct dd_function_table functions;
+ GLint red_bits, green_bits, blue_bits, alpha_bits;
+ struct gl_context *ctx;
+ struct gl_config *visual;
+
+ (void) Pal;
+
+ /* Indexed mode not supported */
+ if (!rgb_flag)
+ return NULL;
+
+ /* Allocate wmesa context */
+ c = CALLOC_STRUCT(wmesa_context);
+ if (!c)
+ return NULL;
+
+#if 0
+ /* I do not understand this contributed code */
+ /* Support memory and device contexts */
+ if(WindowFromDC(hDC) != NULL) {
+ c->hDC = GetDC(WindowFromDC(hDC)); /* huh ???? */
+ }
+ else {
+ c->hDC = hDC;
+ }
+#else
+ c->hDC = hDC;
+#endif
+
+ /* Get data for visual */
+ /* Dealing with this is actually a bit of overkill because Mesa will end
+ * up treating all color component size requests less than 8 by using
+ * a single byte per channel. In addition, the interface to the span
+ * routines passes colors as an entire byte per channel anyway, so there
+ * is nothing to be saved by telling the visual to be 16 bits if the device
+ * is 16 bits. That is, Mesa is going to compute colors down to 8 bits per
+ * channel anyway.
+ * But we go through the motions here anyway.
+ */
+ switch (GetDeviceCaps(c->hDC, BITSPIXEL)) {
+ case 16:
+ red_bits = green_bits = blue_bits = 5;
+ alpha_bits = 0;
+ break;
+ default:
+ red_bits = green_bits = blue_bits = 8;
+ alpha_bits = 8;
+ break;
+ }
+ /* Create visual based on flags */
+ visual = _mesa_create_visual(db_flag, /* db_flag */
+ GL_FALSE, /* stereo */
+ red_bits, green_bits, blue_bits, /* color RGB */
+ alpha_flag ? alpha_bits : 0, /* color A */
+ DEFAULT_SOFTWARE_DEPTH_BITS, /* depth_bits */
+ 8, /* stencil_bits */
+ 16,16,16, /* accum RGB */
+ alpha_flag ? 16 : 0, /* accum A */
+ 1); /* num samples */
+
+ if (!visual) {
+ free(c);
+ return NULL;
+ }
+
+ /* Set up driver functions */
+ _mesa_init_driver_functions(&functions);
+ functions.GetString = wmesa_get_string;
+ functions.UpdateState = wmesa_update_state;
+ functions.GetBufferSize = wmesa_get_buffer_size;
+ functions.Flush = wmesa_flush;
+ functions.Clear = clear;
+ functions.ClearColor = clear_color;
+ functions.ResizeBuffers = wmesa_resize_buffers;
+ functions.Viewport = wmesa_viewport;
+
+ /* initialize the Mesa context data */
+ ctx = &c->gl_ctx;
+ _mesa_initialize_context(ctx, visual, NULL, &functions, (void *)c);
+
+ /* visual no longer needed - it was copied by _mesa_initialize_context() */
+ _mesa_destroy_visual(visual);
+
+ _mesa_enable_sw_extensions(ctx);
+ _mesa_enable_1_3_extensions(ctx);
+ _mesa_enable_1_4_extensions(ctx);
+ _mesa_enable_1_5_extensions(ctx);
+ _mesa_enable_2_0_extensions(ctx);
+ _mesa_enable_2_1_extensions(ctx);
+
+ _mesa_meta_init(ctx);
+
+ /* Initialize the software rasterizer and helper modules. */
+ if (!_swrast_CreateContext(ctx) ||
+ !_vbo_CreateContext(ctx) ||
+ !_tnl_CreateContext(ctx) ||
+ !_swsetup_CreateContext(ctx)) {
+ _mesa_free_context_data(ctx);
+ free(c);
+ return NULL;
+ }
+ _swsetup_Wakeup(ctx);
+ TNL_CONTEXT(ctx)->Driver.RunPipeline = _tnl_run_pipeline;
+
+ return c;
+}
+
+
+void WMesaDestroyContext( WMesaContext pwc )
+{
+ struct gl_context *ctx = &pwc->gl_ctx;
+ WMesaFramebuffer pwfb;
+ GET_CURRENT_CONTEXT(cur_ctx);
+
+ if (cur_ctx == ctx) {
+ /* unbind current if deleting current context */
+ WMesaMakeCurrent(NULL, NULL);
+ }
+
+ /* clean up frame buffer resources */
+ pwfb = wmesa_lookup_framebuffer(pwc->hDC);
+ if (pwfb) {
+ if (ctx->Visual.doubleBufferMode == 1)
+ wmDeleteBackingStore(pwfb);
+ wmesa_free_framebuffer(pwc->hDC);
+ }
+
+ /* Release for device, not memory contexts */
+ if (WindowFromDC(pwc->hDC) != NULL)
+ {
+ ReleaseDC(WindowFromDC(pwc->hDC), pwc->hDC);
+ }
+ DeleteObject(pwc->clearPen);
+ DeleteObject(pwc->clearBrush);
+
+ _mesa_meta_free(ctx);
+
+ _swsetup_DestroyContext(ctx);
+ _tnl_DestroyContext(ctx);
+ _vbo_DestroyContext(ctx);
+ _swrast_DestroyContext(ctx);
+
+ _mesa_free_context_data(ctx);
+ free(pwc);
+}
+
+
+/**
+ * Create a new color renderbuffer.
+ */
+struct gl_renderbuffer *
+wmesa_new_renderbuffer(void)
+{
+ struct gl_renderbuffer *rb = CALLOC_STRUCT(gl_renderbuffer);
+ if (!rb)
+ return NULL;
+
+ _mesa_init_renderbuffer(rb, (GLuint)0);
+
+ rb->_BaseFormat = GL_RGBA;
+ rb->InternalFormat = GL_RGBA;
+ rb->DataType = CHAN_TYPE;
+ rb->Delete = wmesa_delete_renderbuffer;
+ rb->AllocStorage = wmesa_renderbuffer_storage;
+ return rb;
+}
+
+
+void WMesaMakeCurrent(WMesaContext c, HDC hdc)
+{
+ WMesaFramebuffer pwfb;
+
+ {
+ /* return if already current */
+ GET_CURRENT_CONTEXT(ctx);
+ WMesaContext pwc = wmesa_context(ctx);
+ if (pwc && c == pwc && pwc->hDC == hdc)
+ return;
+ }
+
+ pwfb = wmesa_lookup_framebuffer(hdc);
+
+ /* Lazy creation of framebuffers */
+ if (c && !pwfb && hdc) {
+ struct gl_renderbuffer *rb;
+ struct gl_config *visual = &c->gl_ctx.Visual;
+ GLuint width, height;
+
+ get_window_size(hdc, &width, &height);
+
+ c->clearPen = CreatePen(PS_SOLID, 1, 0);
+ c->clearBrush = CreateSolidBrush(0);
+
+ pwfb = wmesa_new_framebuffer(hdc, visual);
+
+ /* Create back buffer if double buffered */
+ if (visual->doubleBufferMode == 1) {
+ wmCreateBackingStore(pwfb, width, height);
+ }
+
+ /* make render buffers */
+ if (visual->doubleBufferMode == 1) {
+ rb = wmesa_new_renderbuffer();
+ _mesa_add_renderbuffer(&pwfb->Base, BUFFER_BACK_LEFT, rb);
+ wmesa_set_renderbuffer_funcs(rb, pwfb->pixelformat, pwfb->cColorBits, 1);
+ }
+ rb = wmesa_new_renderbuffer();
+ _mesa_add_renderbuffer(&pwfb->Base, BUFFER_FRONT_LEFT, rb);
+ wmesa_set_renderbuffer_funcs(rb, pwfb->pixelformat, pwfb->cColorBits, 0);
+
+ /* Let Mesa own the Depth, Stencil, and Accum buffers */
+ _mesa_add_soft_renderbuffers(&pwfb->Base,
+ GL_FALSE, /* color */
+ visual->depthBits > 0,
+ visual->stencilBits > 0,
+ visual->accumRedBits > 0,
+ visual->alphaBits >0,
+ GL_FALSE);
+ }
+
+ if (c && pwfb)
+ _mesa_make_current(&c->gl_ctx, &pwfb->Base, &pwfb->Base);
+ else
+ _mesa_make_current(NULL, NULL, NULL);
+}
+
+
+void WMesaSwapBuffers( HDC hdc )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_lookup_framebuffer(hdc);
+
+ if (!pwfb) {
+ _mesa_problem(NULL, "wmesa: swapbuffers on unknown hdc");
+ return;
+ }
+
+ /* If we're swapping the buffer associated with the current context
+ * we have to flush any pending rendering commands first.
+ */
+ if (pwc->hDC == hdc) {
+ _mesa_notifySwapBuffers(ctx);
+
+ BitBlt(pwfb->hDC, 0, 0, pwfb->Base.Width, pwfb->Base.Height,
+ pwfb->dib_hDC, 0, 0, SRCCOPY);
+ }
+ else {
+ /* XXX for now only allow swapping current window */
+ _mesa_problem(NULL, "wmesa: can't swap non-current window");
+ }
+}
+
+void WMesaShareLists(WMesaContext ctx_to_share, WMesaContext ctx)
+{
+ _mesa_share_state(&ctx->gl_ctx, &ctx_to_share->gl_ctx);
+}
+
diff --git a/mesalib/src/mesa/drivers/windows/gdi/wmesadef.h b/mesalib/src/mesa/drivers/windows/gdi/wmesadef.h
index 1c0e24511..530673373 100644
--- a/mesalib/src/mesa/drivers/windows/gdi/wmesadef.h
+++ b/mesalib/src/mesa/drivers/windows/gdi/wmesadef.h
@@ -1,43 +1,43 @@
-#ifndef WMESADEF_H
-#define WMESADEF_H
-#ifdef __MINGW32__
-#include <windows.h>
-#endif
-#include "context.h"
-
-
-/**
- * The Windows Mesa rendering context, derived from GLcontext.
- */
-struct wmesa_context {
- GLcontext gl_ctx; /* The core GL/Mesa context */
- HDC hDC;
- COLORREF clearColorRef;
- HPEN clearPen;
- HBRUSH clearBrush;
-};
-
-
-/**
- * Windows framebuffer, derived from gl_framebuffer
- */
-struct wmesa_framebuffer
-{
- struct gl_framebuffer Base;
- HDC hDC;
- int pixelformat;
- GLuint ScanWidth;
- int cColorBits;
- /* back buffer DIB fields */
- HDC dib_hDC;
- BITMAPINFO bmi;
- HBITMAP hbmDIB;
- HBITMAP hOldBitmap;
- PBYTE pbPixels;
- struct wmesa_framebuffer *next;
-};
-
-typedef struct wmesa_framebuffer *WMesaFramebuffer;
-
-
-#endif /* WMESADEF_H */
+#ifndef WMESADEF_H
+#define WMESADEF_H
+#ifdef __MINGW32__
+#include <windows.h>
+#endif
+#include "context.h"
+
+
+/**
+ * The Windows Mesa rendering context, derived from struct gl_context.
+ */
+struct wmesa_context {
+ struct gl_context gl_ctx; /* The core GL/Mesa context */
+ HDC hDC;
+ COLORREF clearColorRef;
+ HPEN clearPen;
+ HBRUSH clearBrush;
+};
+
+
+/**
+ * Windows framebuffer, derived from gl_framebuffer
+ */
+struct wmesa_framebuffer
+{
+ struct gl_framebuffer Base;
+ HDC hDC;
+ int pixelformat;
+ GLuint ScanWidth;
+ int cColorBits;
+ /* back buffer DIB fields */
+ HDC dib_hDC;
+ BITMAPINFO bmi;
+ HBITMAP hbmDIB;
+ HBITMAP hOldBitmap;
+ PBYTE pbPixels;
+ struct wmesa_framebuffer *next;
+};
+
+typedef struct wmesa_framebuffer *WMesaFramebuffer;
+
+
+#endif /* WMESADEF_H */
diff --git a/mesalib/src/mesa/drivers/windows/gldirect/dglcontext.c b/mesalib/src/mesa/drivers/windows/gldirect/dglcontext.c
index a420b36ff..fabce4c0b 100644
--- a/mesalib/src/mesa/drivers/windows/gldirect/dglcontext.c
+++ b/mesalib/src/mesa/drivers/windows/gldirect/dglcontext.c
@@ -1,2212 +1,2212 @@
-/****************************************************************************
-*
-* Mesa 3-D graphics library
-* Direct3D Driver Interface
-*
-* ========================================================================
-*
-* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
-*
-* Permission is hereby granted, free of charge, to any person obtaining a
-* copy of this software and associated documentation files (the "Software"),
-* to deal in the Software without restriction, including without limitation
-* the rights to use, copy, modify, merge, publish, distribute, sublicense,
-* and/or sell copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included
-* in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
-* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-* SOFTWARE.
-*
-* ======================================================================
-*
-* Language: ANSI C
-* Environment: Windows 9x (Win32)
-*
-* Description: Context handling.
-*
-****************************************************************************/
-
-#include "dglcontext.h"
-
-// Get compile errors without this. KeithH
-//#include "scitech.h" // ibool, etc.
-
-#ifdef _USE_GLD3_WGL
-#include "gld_driver.h"
-
-extern void _gld_mesa_warning(GLcontext *, char *);
-extern void _gld_mesa_fatal(GLcontext *, char *);
-#endif // _USE_GLD3_WGL
-
-// TODO: Clean out old DX6-specific code from GLD 2.x CAD driver
-// if it is no longer being built as part of GLDirect. (DaveM)
-
-// ***********************************************************************
-
-#define GLDERR_NONE 0
-#define GLDERR_MEM 1
-#define GLDERR_DDRAW 2
-#define GLDERR_D3D 3
-#define GLDERR_BPP 4
-
-char szResourceWarning[] =
-"GLDirect does not have enough video memory resources\n"
-"to support the requested OpenGL rendering context.\n\n"
-"You may have to reduce the current display resolution\n"
-"to obtain satisfactory OpenGL performance.\n";
-
-char szDDrawWarning[] =
-"GLDirect is unable to initialize DirectDraw for the\n"
-"requested OpenGL rendering context.\n\n"
-"You will have to check the DirectX control panel\n"
-"for further information.\n";
-
-char szD3DWarning[] =
-"GLDirect is unable to initialize Direct3D for the\n"
-"requested OpenGL rendering context.\n\n"
-"You may have to change the display mode resolution\n"
-"color depth or check the DirectX control panel for\n"
-"further information.\n";
-
-char szBPPWarning[] =
-"GLDirect is unable to use the selected color depth for\n"
-"the requested OpenGL rendering context.\n\n"
-"You will have to change the display mode resolution\n"
-"color depth with the Display Settings control panel.\n";
-
-int nContextError = GLDERR_NONE;
-
-// ***********************************************************************
-
-#define VENDORID_ATI 0x1002
-
-static DWORD devATIRagePro[] = {
- 0x4742, // 3D RAGE PRO BGA AGP 1X/2X
- 0x4744, // 3D RAGE PRO BGA AGP 1X only
- 0x4749, // 3D RAGE PRO BGA PCI 33 MHz
- 0x4750, // 3D RAGE PRO PQFP PCI 33 MHz
- 0x4751, // 3D RAGE PRO PQFP PCI 33 MHz limited 3D
- 0x4C42, // 3D RAGE LT PRO BGA-312 AGP 133 MHz
- 0x4C44, // 3D RAGE LT PRO BGA-312 AGP 66 MHz
- 0x4C49, // 3D RAGE LT PRO BGA-312 PCI 33 MHz
- 0x4C50, // 3D RAGE LT PRO BGA-256 PCI 33 MHz
- 0x4C51, // 3D RAGE LT PRO BGA-256 PCI 33 MHz limited 3D
-};
-
-static DWORD devATIRageIIplus[] = {
- 0x4755, // 3D RAGE II+
- 0x4756, // 3D RAGE IIC PQFP PCI
- 0x4757, // 3D RAGE IIC BGA AGP
- 0x475A, // 3D RAGE IIC PQFP AGP
- 0x4C47, // 3D RAGE LT-G
-};
-
-// ***********************************************************************
-
-#ifndef _USE_GLD3_WGL
-extern DGL_mesaFuncs mesaFuncs;
-#endif
-
-extern DWORD dwLogging;
-
-#ifdef GLD_THREADS
-#pragma message("compiling DGLCONTEXT.C vars for multi-threaded support")
-CRITICAL_SECTION CriticalSection; // for serialized access
-DWORD dwTLSCurrentContext = 0xFFFFFFFF; // TLS index for current context
-DWORD dwTLSPixelFormat = 0xFFFFFFFF; // TLS index for current pixel format
-#endif
-HGLRC iCurrentContext = 0; // Index of current context (static)
-BOOL bContextReady = FALSE; // Context state ready ?
-
-DGL_ctx ctxlist[DGL_MAX_CONTEXTS]; // Context list
-
-// ***********************************************************************
-
-static BOOL bHaveWin95 = FALSE;
-static BOOL bHaveWinNT = FALSE;
-static BOOL bHaveWin2K = FALSE;
-
-/****************************************************************************
-REMARKS:
-Detect the installed OS type.
-****************************************************************************/
-static void DetectOS(void)
-{
- OSVERSIONINFO VersionInformation;
- LPOSVERSIONINFO lpVersionInformation = &VersionInformation;
-
- VersionInformation.dwOSVersionInfoSize = sizeof(VersionInformation);
-
- GetVersionEx(lpVersionInformation);
-
- switch (VersionInformation.dwPlatformId) {
- case VER_PLATFORM_WIN32_WINDOWS:
- bHaveWin95 = TRUE;
- bHaveWinNT = FALSE;
- bHaveWin2K = FALSE;
- break;
- case VER_PLATFORM_WIN32_NT:
- bHaveWin95 = FALSE;
- if (VersionInformation.dwMajorVersion <= 4) {
- bHaveWinNT = TRUE;
- bHaveWin2K = FALSE;
- }
- else {
- bHaveWinNT = FALSE;
- bHaveWin2K = TRUE;
- }
- break;
- case VER_PLATFORM_WIN32s:
- bHaveWin95 = FALSE;
- bHaveWinNT = FALSE;
- bHaveWin2K = FALSE;
- break;
- }
-}
-
-// ***********************************************************************
-
-HWND hWndEvent = NULL; // event monitor window
-HWND hWndLastActive = NULL; // last active client window
-LONG __stdcall GLD_EventWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam);
-
-// ***********************************************************************
-
-// Checks if the HGLRC is valid in range of context list.
-BOOL dglIsValidContext(
- HGLRC a)
-{
- return ((int)a > 0 && (int)a <= DGL_MAX_CONTEXTS);
-}
-
-// ***********************************************************************
-
-// Convert a HGLRC to a pointer into the context list.
-DGL_ctx* dglGetContextAddress(
- const HGLRC a)
-{
- if (dglIsValidContext(a))
- return &ctxlist[(int)a-1];
- return NULL;
-}
-
-// ***********************************************************************
-
-// Return the current HGLRC (however it may be stored for multi-threading).
-HGLRC dglGetCurrentContext(void)
-{
-#ifdef GLD_THREADS
- HGLRC hGLRC;
- // load from thread-specific instance
- if (glb.bMultiThreaded) {
- // protect against calls from arbitrary threads
- __try {
- hGLRC = (HGLRC)TlsGetValue(dwTLSCurrentContext);
- }
- __except(EXCEPTION_EXECUTE_HANDLER) {
- hGLRC = iCurrentContext;
- }
- }
- // load from global static var
- else {
- hGLRC = iCurrentContext;
- }
- return hGLRC;
-#else
- return iCurrentContext;
-#endif
-}
-
-// ***********************************************************************
-
-// Set the current HGLRC (however it may be stored for multi-threading).
-void dglSetCurrentContext(HGLRC hGLRC)
-{
-#ifdef GLD_THREADS
- // store in thread-specific instance
- if (glb.bMultiThreaded) {
- // protect against calls from arbitrary threads
- __try {
- TlsSetValue(dwTLSCurrentContext, (LPVOID)hGLRC);
- }
- __except(EXCEPTION_EXECUTE_HANDLER) {
- iCurrentContext = hGLRC;
- }
- }
- // store in global static var
- else {
- iCurrentContext = hGLRC;
- }
-#else
- iCurrentContext = hGLRC;
-#endif
-}
-
-// ***********************************************************************
-
-// Return the current HDC only for a currently active HGLRC.
-HDC dglGetCurrentDC(void)
-{
- HGLRC hGLRC;
- DGL_ctx* lpCtx;
-
- hGLRC = dglGetCurrentContext();
- if (hGLRC) {
- lpCtx = dglGetContextAddress(hGLRC);
- return lpCtx->hDC;
- }
- return 0;
-}
-
-// ***********************************************************************
-
-void dglInitContextState()
-{
- int i;
- WNDCLASS wc;
-
-#ifdef GLD_THREADS
- // Allocate thread local storage indexes for current context and pixel format
- dwTLSCurrentContext = TlsAlloc();
- dwTLSPixelFormat = TlsAlloc();
-#endif
-
- dglSetCurrentContext(NULL); // No current rendering context
-
- // Clear all context data
- ZeroMemory(ctxlist, sizeof(ctxlist[0]) * DGL_MAX_CONTEXTS);
-
- for (i=0; i<DGL_MAX_CONTEXTS; i++)
- ctxlist[i].bAllocated = FALSE; // Flag context as unused
-
- // This section of code crashes the dll in circumstances where the app
- // creates and destroys contexts.
-/*
- // Register the class for our event monitor window
- wc.style = 0;
- wc.lpfnWndProc = GLD_EventWndProc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- wc.hInstance = GetModuleHandle(NULL);
- wc.hIcon = LoadIcon(GetModuleHandle(NULL), IDI_APPLICATION);
- wc.hCursor = LoadCursor(NULL, IDC_ARROW);
- wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
- wc.lpszMenuName = NULL;
- wc.lpszClassName = "GLDIRECT";
- RegisterClass(&wc);
-
- // Create the non-visible window to monitor all broadcast messages
- hWndEvent = CreateWindowEx(
- WS_EX_TOOLWINDOW,"GLDIRECT","GLDIRECT",WS_POPUP,
- 0,0,0,0,
- NULL,NULL,GetModuleHandle(NULL),NULL);
-*/
-
-#ifdef GLD_THREADS
- // Create a critical section object for serializing access to
- // DirectDraw and DDStereo create/destroy functions in multiple threads
- if (glb.bMultiThreaded)
- InitializeCriticalSection(&CriticalSection);
-#endif
-
- // Context state is now initialized and ready
- bContextReady = TRUE;
-}
-
-// ***********************************************************************
-
-void dglDeleteContextState()
-{
- int i;
- static BOOL bOnceIsEnough = FALSE;
-
- // Only call once, from either DGL_exitDriver(), or DLL_PROCESS_DETACH
- if (bOnceIsEnough)
- return;
- bOnceIsEnough = TRUE;
-
- for (i=0; i<DGL_MAX_CONTEXTS; i++) {
- if (ctxlist[i].bAllocated == TRUE) {
- ddlogPrintf(DDLOG_WARN, "** Context %i not deleted - cleaning up.", (i+1));
- dglDeleteContext((HGLRC)(i+1));
- }
- }
-
- // Context state is no longer ready
- bContextReady = FALSE;
-
- // If executed when DLL unloads, DDraw objects may be invalid.
- // So catch any page faults with this exception handler.
-__try {
-
- // Release final DirectDraw interfaces
- if (glb.bDirectDrawPersistant) {
-// RELEASE(glb.lpGlobalPalette);
-// RELEASE(glb.lpDepth4);
-// RELEASE(glb.lpBack4);
-// RELEASE(glb.lpPrimary4);
-// RELEASE(glb.lpDD4);
- }
-}
-__except(EXCEPTION_EXECUTE_HANDLER) {
- ddlogPrintf(DDLOG_WARN, "Exception raised in dglDeleteContextState.");
-}
-
- // Destroy our event monitor window
- if (hWndEvent) {
- DestroyWindow(hWndEvent);
- hWndEvent = hWndLastActive = NULL;
- }
-
-#ifdef GLD_THREADS
- // Destroy the critical section object
- if (glb.bMultiThreaded)
- DeleteCriticalSection(&CriticalSection);
-
- // Release thread local storage indexes for current HGLRC and pixel format
- TlsFree(dwTLSPixelFormat);
- TlsFree(dwTLSCurrentContext);
-#endif
-}
-
-// ***********************************************************************
-
-// Application Window message handler interception
-static LONG __stdcall dglWndProc(
- HWND hwnd,
- UINT msg,
- WPARAM wParam,
- LPARAM lParam)
-{
- DGL_ctx* lpCtx = NULL;
- LONG lpfnWndProc = 0L;
- int i;
- HGLRC hGLRC;
- RECT rect;
- PAINTSTRUCT ps;
- BOOL bQuit = FALSE;
- BOOL bMain = FALSE;
- LONG rc;
-
- // Get the window's message handler *before* it is unhooked in WM_DESTROY
-
- // Is this the main window?
- if (hwnd == glb.hWndActive) {
- bMain = TRUE;
- lpfnWndProc = glb.lpfnWndProc;
- }
- // Search for DGL context matching window handle
- for (i=0; i<DGL_MAX_CONTEXTS; i++) {
- if (ctxlist[i].hWnd == hwnd) {
- lpCtx = &ctxlist[i];
- lpfnWndProc = lpCtx->lpfnWndProc;
- break;
- }
- }
- // Not one of ours...
- if (!lpfnWndProc)
- return DefWindowProc(hwnd, msg, wParam, lParam);
-
- // Intercept messages amd process *before* passing on to window
- switch (msg) {
-#ifdef _USE_GLD3_WGL
- case WM_DISPLAYCHANGE:
- glb.bPixelformatsDirty = TRUE;
- break;
-#endif
- case WM_ACTIVATEAPP:
- glb.bAppActive = (BOOL)wParam;
- ddlogPrintf(DDLOG_INFO, "Calling app has been %s", glb.bAppActive ? "activated" : "de-activated");
- break;
- case WM_ERASEBKGND:
- // Eat the GDI erase event for the GL window
- if (!lpCtx || !lpCtx->bHasBeenCurrent)
- break;
- lpCtx->bGDIEraseBkgnd = TRUE;
- return TRUE;
- case WM_PAINT:
- // Eat the invalidated update region if render scene is in progress
- if (!lpCtx || !lpCtx->bHasBeenCurrent)
- break;
- if (lpCtx->bFrameStarted) {
- if (GetUpdateRect(hwnd, &rect, FALSE)) {
- BeginPaint(hwnd, &ps);
- EndPaint(hwnd, &ps);
- ValidateRect(hwnd, &rect);
- return TRUE;
- }
- }
- break;
- }
- // Call the appropriate window message handler
- rc = CallWindowProc((WNDPROC)lpfnWndProc, hwnd, msg, wParam, lParam);
-
- // Intercept messages and process *after* passing on to window
- switch (msg) {
- case WM_QUIT:
- case WM_DESTROY:
- bQuit = TRUE;
- if (lpCtx && lpCtx->bAllocated) {
- ddlogPrintf(DDLOG_WARN, "WM_DESTROY detected for HWND=%X, HDC=%X, HGLRC=%d", hwnd, lpCtx->hDC, i+1);
- dglDeleteContext((HGLRC)(i+1));
- }
- break;
-#if 0
- case WM_SIZE:
- // Resize surfaces to fit window but not viewport (in case app did not bother)
- if (!lpCtx || !lpCtx->bHasBeenCurrent)
- break;
- w = LOWORD(lParam);
- h = HIWORD(lParam);
- if (lpCtx->dwWidth < w || lpCtx->dwHeight < h) {
- if (!dglWglResizeBuffers(lpCtx->glCtx, TRUE))
- dglWglResizeBuffers(lpCtx->glCtx, FALSE);
- }
- break;
-#endif
- }
-
- // If the main window is quitting, then so should we...
- if (bMain && bQuit) {
- ddlogPrintf(DDLOG_SYSTEM, "shutting down after WM_DESTROY detected for main HWND=%X", hwnd);
- dglDeleteContextState();
- dglExitDriver();
- }
-
- return rc;
-}
-
-// ***********************************************************************
-
-// Driver Window message handler
-static LONG __stdcall GLD_EventWndProc(
- HWND hwnd,
- UINT msg,
- WPARAM wParam,
- LPARAM lParam)
-{
- switch (msg) {
- // May be sent by splash screen dialog on exit
- case WM_ACTIVATE:
- if (LOWORD(wParam) == WA_ACTIVE && glb.hWndActive) {
- SetForegroundWindow(glb.hWndActive);
- return 0;
- }
- break;
- }
- return DefWindowProc(hwnd, msg, wParam, lParam);
-}
-
-// ***********************************************************************
-
-// Intercepted Keyboard handler for detecting hot keys.
-LRESULT CALLBACK dglKeyProc(
- int code,
- WPARAM wParam,
- LPARAM lParam)
-{
- HWND hWnd, hWndFrame;
- HGLRC hGLRC = NULL;
- DGL_ctx* lpCtx = NULL;
- int cmd = 0, dx1 = 0, dx2 = 0, i;
- static BOOL bAltPressed = FALSE;
- static BOOL bCtrlPressed = FALSE;
- static BOOL bShiftPressed = FALSE;
- RECT r, rf, rc;
- POINT pt;
- BOOL bForceReshape = FALSE;
-
- return CallNextHookEx(hKeyHook, code, wParam, lParam);
-}
-
-// ***********************************************************************
-
-HWND hWndMatch;
-
-// Window handle enumeration procedure.
-BOOL CALLBACK dglEnumChildProc(
- HWND hWnd,
- LPARAM lParam)
-{
- RECT rect;
-
- // Find window handle with matching client rect.
- GetClientRect(hWnd, &rect);
- if (EqualRect(&rect, (RECT*)lParam)) {
- hWndMatch = hWnd;
- return FALSE;
- }
- // Continue with next child window.
- return TRUE;
-}
-
-// ***********************************************************************
-
-// Find window handle with matching client rect.
-HWND dglFindWindowRect(
- RECT* pRect)
-{
- hWndMatch = NULL;
- EnumChildWindows(GetForegroundWindow(), dglEnumChildProc, (LPARAM)pRect);
- return hWndMatch;
-}
-
-// ***********************************************************************
-#ifndef _USE_GLD3_WGL
-void dglChooseDisplayMode(
- DGL_ctx *lpCtx)
-{
- // Note: Choose an exact match if possible.
-
- int i;
- DWORD area;
- DWORD bestarea;
- DDSURFACEDESC2 *lpDDSD = NULL; // Mode list pointer
- DDSURFACEDESC2 *lpBestDDSD = NULL; // Pointer to best
-
- lpDDSD = glb.lpDisplayModes;
- for (i=0; i<glb.nDisplayModeCount; i++, lpDDSD++) {
- if ((lpDDSD->dwWidth == lpCtx->dwWidth) &&
- (lpDDSD->dwHeight == lpCtx->dwHeight))
- goto matched; // Mode has been exactly matched
- // Choose modes that are larger in both dimensions than
- // the window, but smaller in area than the current best.
- if ( (lpDDSD->dwWidth >= lpCtx->dwWidth) &&
- (lpDDSD->dwHeight >= lpCtx->dwHeight))
- {
- if (lpBestDDSD == NULL) {
- lpBestDDSD = lpDDSD;
- bestarea = lpDDSD->dwWidth * lpDDSD->dwHeight;
- continue;
- }
- area = lpDDSD->dwWidth * lpDDSD->dwHeight;
- if (area < bestarea) {
- lpBestDDSD = lpDDSD;
- bestarea = area;
- }
- }
- }
-
- // Safety check
- if (lpBestDDSD == NULL) {
- ddlogMessage(DDLOG_CRITICAL, "dglChooseDisplayMode");
- return;
- }
-
- lpCtx->dwModeWidth = lpBestDDSD->dwWidth;
- lpCtx->dwModeHeight = lpBestDDSD->dwHeight;
-matched:
- ddlogPrintf(DDLOG_INFO, "Matched (%ldx%ld) to (%ldx%ld)",
- lpCtx->dwWidth, lpCtx->dwHeight, lpCtx->dwModeWidth, lpCtx->dwModeHeight);
-}
-#endif // _USE_GLD3_WGL
-// ***********************************************************************
-
-static BOOL IsDevice(
- DWORD *lpDeviceIdList,
- DWORD dwDeviceId,
- int count)
-{
- int i;
-
- for (i=0; i<count; i++)
- if (dwDeviceId == lpDeviceIdList[i])
- return TRUE;
-
- return FALSE;
-}
-
-// ***********************************************************************
-
-void dglTestForBrokenCards(
- DGL_ctx *lpCtx)
-{
-#ifndef _GLD3
- DDDEVICEIDENTIFIER dddi; // DX6 device identifier
-
- // Sanity check.
- if (lpCtx == NULL) {
- // Testing for broken cards is sensitive area, so we don't want
- // anything saying "broken cards" in the error message. ;)
- ddlogMessage(DDLOG_ERROR, "Null context passed to TFBC\n");
- return;
- }
-
- if (lpCtx->lpDD4 == NULL) {
- // Testing for broken cards is sensitive area, so we don't want
- // anything saying "broken cards" in the error message. ;)
- ddlogMessage(DDLOG_ERROR, "Null DD4 passed to TFBC\n");
- return;
- }
-
- // Microsoft really fucked up with the GetDeviceIdentifier function
- // on Windows 2000, since it locks up on stock driers on the CD. Updated
- // drivers from vendors appear to work, but we can't identify the drivers
- // without this function!!! For now we skip these tests on Windows 2000.
- if ((GetVersion() & 0x80000000UL) == 0)
- return;
-
- // Obtain device info
- if (FAILED(IDirectDraw4_GetDeviceIdentifier(lpCtx->lpDD4, &dddi, 0)))
- return;
-
- // Useful info. Log it.
- ddlogPrintf(DDLOG_INFO, "DirectDraw: VendorId=0x%x, DeviceId=0x%x", dddi.dwVendorId, dddi.dwDeviceId);
-
- // Vendor 1: ATI
- if (dddi.dwVendorId == VENDORID_ATI) {
- // Test A: ATI Rage PRO
- if (IsDevice(devATIRagePro, dddi.dwDeviceId, sizeof(devATIRagePro)))
- glb.bUseMipmaps = FALSE;
- // Test B: ATI Rage II+
- if (IsDevice(devATIRageIIplus, dddi.dwDeviceId, sizeof(devATIRageIIplus)))
- glb.bEmulateAlphaTest = TRUE;
- }
-
- // Vendor 2: Matrox
- if (dddi.dwVendorId == 0x102B) {
- // Test: Matrox G400 stencil buffer support does not work for AutoCAD
- if (dddi.dwDeviceId == 0x0525) {
- lpCtx->lpPF->pfd.cStencilBits = 0;
- if (lpCtx->lpPF->iZBufferPF != -1) {
- glb.lpZBufferPF[lpCtx->lpPF->iZBufferPF].dwStencilBitDepth = 0;
- glb.lpZBufferPF[lpCtx->lpPF->iZBufferPF].dwStencilBitMask = 0;
- glb.lpZBufferPF[lpCtx->lpPF->iZBufferPF].dwFlags &= ~DDPF_STENCILBUFFER;
- }
- }
- }
-#endif // _GLD3
-}
-
-// ***********************************************************************
-
-BOOL dglCreateContextBuffers(
- HDC a,
- DGL_ctx *lpCtx,
- BOOL bFallback)
-{
- HRESULT hResult;
-
- int i;
-// HGLRC hGLRC;
-// DGL_ctx* lpCtx;
-
-#ifndef _USE_GLD3_WGL
- DWORD dwFlags;
- DDSURFACEDESC2 ddsd2;
- DDSCAPS2 ddscaps2;
- LPDIRECTDRAWCLIPPER lpddClipper;
- D3DDEVICEDESC D3DHWDevDesc; // Direct3D Hardware description
- D3DDEVICEDESC D3DHELDevDesc; // Direct3D Hardware Emulation Layer
-#endif // _USE_GLD3_WGL
-
- float inv_aspect;
-
- GLenum bDoubleBuffer; // TRUE if double buffer required
- GLenum bDepthBuffer; // TRUE if depth buffer required
-
- const PIXELFORMATDESCRIPTOR *lpPFD = &lpCtx->lpPF->pfd;
-
- // Vars for Mesa visual
- DWORD dwDepthBits = 0;
- DWORD dwStencilBits = 0;
- DWORD dwAlphaBits = 0;
- DWORD bAlphaSW = GL_FALSE;
- DWORD bDouble = GL_FALSE;
-
- DDSURFACEDESC2 ddsd2DisplayMode;
- BOOL bFullScrnWin = FALSE; // fullscreen-size window ?
- DDBLTFX ddbltfx;
- DWORD dwMemoryType = (bFallback) ? DDSCAPS_SYSTEMMEMORY : glb.dwMemoryType;
- BOOL bBogusWindow = FALSE; // non-drawable window ?
- DWORD dwColorRef = 0; // GDI background color
- RECT rcDst; // GDI window rect
- POINT pt; // GDI window point
-
- // Palette used for creating default global palette
- PALETTEENTRY ppe[256];
-
-#ifndef _USE_GLD3_WGL
- // Vertex buffer description. Used for creation of vertex buffers
- D3DVERTEXBUFFERDESC vbufdesc;
-#endif // _USE_GLD3_WGL
-
-#define DDLOG_CRITICAL_OR_WARN (bFallback ? DDLOG_CRITICAL : DDLOG_WARN)
-
- ddlogPrintf(DDLOG_SYSTEM, "dglCreateContextBuffers for HDC=%X", a);
- nContextError = GLDERR_NONE;
-
-#ifdef GLD_THREADS
- // Serialize access to DirectDraw object creation or DDS start
- if (glb.bMultiThreaded)
- EnterCriticalSection(&CriticalSection);
-#endif
-
- // Check for back buffer
- bDoubleBuffer = GL_TRUE; //(lpPFD->dwFlags & PFD_DOUBLEBUFFER) ? GL_TRUE : GL_FALSE;
- // Since we always do back buffering, check if we emulate front buffering
- lpCtx->EmulateSingle =
- (lpPFD->dwFlags & PFD_DOUBLEBUFFER) ? FALSE : TRUE;
-#if 0 // Don't have to mimic MS OpenGL behavior for front-buffering (DaveM)
- lpCtx->EmulateSingle |=
- (lpPFD->dwFlags & PFD_SUPPORT_GDI) ? TRUE : FALSE;
-#endif
-
- // Check for depth buffer
- bDepthBuffer = (lpPFD->cDepthBits) ? GL_TRUE : GL_FALSE;
-
- lpCtx->bDoubleBuffer = bDoubleBuffer;
- lpCtx->bDepthBuffer = bDepthBuffer;
-
- // Set the Fullscreen flag for the context.
-// lpCtx->bFullscreen = glb.bFullscreen;
-
- // Obtain the dimensions of the rendering window
- lpCtx->hDC = a; // Cache DC
- lpCtx->hWnd = WindowFromDC(lpCtx->hDC);
- // Check for non-window DC = memory DC ?
- if (lpCtx->hWnd == NULL) {
- // bitmap memory contexts are always single-buffered
- lpCtx->EmulateSingle = TRUE;
- bBogusWindow = TRUE;
- ddlogPrintf(DDLOG_INFO, "Non-Window Memory Device Context");
- if (GetClipBox(lpCtx->hDC, &lpCtx->rcScreenRect) == ERROR) {
- ddlogMessage(DDLOG_WARN, "GetClipBox failed in dglCreateContext\n");
- SetRect(&lpCtx->rcScreenRect, 0, 0, 0, 0);
- }
- }
- else if (!GetClientRect(lpCtx->hWnd, &lpCtx->rcScreenRect)) {
- bBogusWindow = TRUE;
- ddlogMessage(DDLOG_WARN, "GetClientRect failed in dglCreateContext\n");
- SetRect(&lpCtx->rcScreenRect, 0, 0, 0, 0);
- }
- lpCtx->dwWidth = lpCtx->rcScreenRect.right - lpCtx->rcScreenRect.left;
- lpCtx->dwHeight = lpCtx->rcScreenRect.bottom - lpCtx->rcScreenRect.top;
-
- ddlogPrintf(DDLOG_INFO, "Input window %X: w=%i, h=%i",
- lpCtx->hWnd, lpCtx->dwWidth, lpCtx->dwHeight);
-
- // What if app only zeroes one dimension instead of both? (DaveM)
- if ( (lpCtx->dwWidth == 0) || (lpCtx->dwHeight == 0) ) {
- // Make the buffer size something sensible
- lpCtx->dwWidth = 8;
- lpCtx->dwHeight = 8;
- }
-
- // Set defaults
- lpCtx->dwModeWidth = lpCtx->dwWidth;
- lpCtx->dwModeHeight = lpCtx->dwHeight;
-/*
- // Find best display mode for fullscreen
- if (glb.bFullscreen || !glb.bPrimary) {
- dglChooseDisplayMode(lpCtx);
- }
-*/
- // Misc initialisation
- lpCtx->bCanRender = FALSE; // No rendering allowed yet
- lpCtx->bSceneStarted = FALSE;
- lpCtx->bFrameStarted = FALSE;
-
- // Detect OS (specifically 'Windows 2000' or 'Windows XP')
- DetectOS();
-
- // NOTE: WinNT not supported
- ddlogPrintf(DDLOG_INFO, "OS: %s", bHaveWin95 ? "Win9x" : (bHaveWin2K ? "Win2000/XP" : "Unsupported") );
-
- // Test for Fullscreen
- if (bHaveWin95) { // Problems with fullscreen on Win2K/XP
- if ((GetSystemMetrics(SM_CXSCREEN) == lpCtx->dwWidth) &&
- (GetSystemMetrics(SM_CYSCREEN) == lpCtx->dwHeight))
- {
- // Workaround for some apps that crash when going fullscreen.
- //lpCtx->bFullscreen = TRUE;
- }
-
- }
-
-#ifdef _USE_GLD3_WGL
- _gldDriver.CreateDrawable(lpCtx, glb.bDirectDrawPersistant, glb.bPersistantBuffers);
-#else
- // Check if DirectDraw has already been created by original GLRC (DaveM)
- if (glb.bDirectDrawPersistant && glb.bDirectDraw) {
- lpCtx->lpDD4 = glb.lpDD4;
- IDirectDraw4_AddRef(lpCtx->lpDD4);
- goto SkipDirectDrawCreate;
- }
-
- // Create DirectDraw object
- if (glb.bPrimary)
- hResult = DirectDrawCreate(NULL, &lpCtx->lpDD1, NULL);
- else {
- // A non-primary device is to be used.
- // Force context to be Fullscreen, secondary adaptors can not
- // be used in a window.
- hResult = DirectDrawCreate(&glb.ddGuid, &lpCtx->lpDD1, NULL);
- lpCtx->bFullscreen = TRUE;
- }
- if (FAILED(hResult)) {
- MessageBox(NULL, "Unable to initialize DirectDraw", "GLDirect", MB_OK);
- ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to create DirectDraw interface", hResult);
- nContextError = GLDERR_DDRAW;
- goto return_with_error;
- }
-
- // Query for DX6 IDirectDraw4.
- hResult = IDirectDraw_QueryInterface(lpCtx->lpDD1,
- &IID_IDirectDraw4,
- (void**)&lpCtx->lpDD4);
- if (FAILED(hResult)) {
- MessageBox(NULL, "GLDirect requires DirectX 6.0 or above", "GLDirect", MB_OK);
- ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to create DirectDraw4 interface", hResult);
- nContextError = GLDERR_DDRAW;
- goto return_with_error;
- }
-
- // Cache DirectDraw interface for subsequent GLRCs
- if (glb.bDirectDrawPersistant && !glb.bDirectDraw) {
- glb.lpDD4 = lpCtx->lpDD4;
- IDirectDraw4_AddRef(glb.lpDD4);
- glb.bDirectDraw = TRUE;
- }
-SkipDirectDrawCreate:
-
- // Now we have a DD4 interface we can check for broken cards
- dglTestForBrokenCards(lpCtx);
-
- // Test if primary device can use flipping instead of blitting
- ZeroMemory(&ddsd2DisplayMode, sizeof(ddsd2DisplayMode));
- ddsd2DisplayMode.dwSize = sizeof(ddsd2DisplayMode);
- hResult = IDirectDraw4_GetDisplayMode(
- lpCtx->lpDD4,
- &ddsd2DisplayMode);
- if (SUCCEEDED(hResult)) {
- if ( (lpCtx->dwWidth == ddsd2DisplayMode.dwWidth) &&
- (lpCtx->dwHeight == ddsd2DisplayMode.dwHeight) ) {
- // We have a fullscreen-size window
- bFullScrnWin = TRUE;
- // OK to use DirectDraw fullscreen mode ?
- if (glb.bPrimary && !glb.bFullscreenBlit && !lpCtx->EmulateSingle && !glb.bDirectDrawPersistant) {
- lpCtx->bFullscreen = TRUE;
- ddlogMessage(DDLOG_INFO, "Primary upgraded to page flipping.\n");
- }
- }
- // Cache the display mode dimensions
- lpCtx->dwModeWidth = ddsd2DisplayMode.dwWidth;
- lpCtx->dwModeHeight = ddsd2DisplayMode.dwHeight;
- }
-
- // Clamp the effective window dimensions to primary surface.
- // We need to do this for D3D viewport dimensions even if wide
- // surfaces are supported. This also is a good idea for handling
- // whacked-out window dimensions passed for non-drawable windows
- // like Solid Edge. (DaveM)
- if (lpCtx->dwWidth > ddsd2DisplayMode.dwWidth)
- lpCtx->dwWidth = ddsd2DisplayMode.dwWidth;
- if (lpCtx->dwHeight > ddsd2DisplayMode.dwHeight)
- lpCtx->dwHeight = ddsd2DisplayMode.dwHeight;
-
- // Check for non-RGB desktop resolution
- if (!lpCtx->bFullscreen && ddsd2DisplayMode.ddpfPixelFormat.dwRGBBitCount <= 8) {
- ddlogPrintf(DDLOG_CRITICAL_OR_WARN, "Desktop color depth %d bpp not supported",
- ddsd2DisplayMode.ddpfPixelFormat.dwRGBBitCount);
- nContextError = GLDERR_BPP;
- goto return_with_error;
- }
-#endif // _USE_GLD3_WGL
-
- ddlogPrintf(DDLOG_INFO, "Window: w=%i, h=%i (%s)",
- lpCtx->dwWidth,
- lpCtx->dwHeight,
- lpCtx->bFullscreen ? "fullscreen" : "windowed");
-
-#ifndef _USE_GLD3_WGL
- // Obtain ddraw caps
- ZeroMemory(&lpCtx->ddCaps, sizeof(DDCAPS));
- lpCtx->ddCaps.dwSize = sizeof(DDCAPS);
- if (glb.bHardware) {
- // Get HAL caps
- IDirectDraw4_GetCaps(lpCtx->lpDD4, &lpCtx->ddCaps, NULL);
- } else {
- // Get HEL caps
- IDirectDraw4_GetCaps(lpCtx->lpDD4, NULL, &lpCtx->ddCaps);
- }
-
- // If this flag is present then we can't default to Mesa
- // SW rendering between BeginScene() and EndScene().
- if (lpCtx->ddCaps.dwCaps2 & DDCAPS2_NO2DDURING3DSCENE) {
- ddlogMessage(DDLOG_INFO,
- "Warning : No 2D allowed during 3D scene.\n");
- }
-
- // Query for DX6 Direct3D3 interface
- hResult = IDirectDraw4_QueryInterface(lpCtx->lpDD4,
- &IID_IDirect3D3,
- (void**)&lpCtx->lpD3D3);
- if (FAILED(hResult)) {
- MessageBox(NULL, "Unable to initialize Direct3D", "GLDirect", MB_OK);
- ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to create Direct3D interface", hResult);
- nContextError = GLDERR_D3D;
- goto return_with_error;
- }
-
- // Context creation
- if (lpCtx->bFullscreen) {
- // FULLSCREEN
-
- // Disable warning popups when in fullscreen mode
- ddlogWarnOption(FALSE);
-
- // Have to release persistant primary surface if fullscreen mode
- if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary) {
- RELEASE(glb.lpPrimary4);
- glb.bDirectDrawPrimary = FALSE;
- }
-
- dwFlags = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT;
- if (glb.bFastFPU)
- dwFlags |= DDSCL_FPUSETUP; // fast FPU setup optional (DaveM)
- hResult = IDirectDraw4_SetCooperativeLevel(lpCtx->lpDD4, lpCtx->hWnd, dwFlags);
- if (FAILED(hResult)) {
- ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to set Exclusive Fullscreen mode", hResult);
- goto return_with_error;
- }
-
- hResult = IDirectDraw4_SetDisplayMode(lpCtx->lpDD4,
- lpCtx->dwModeWidth,
- lpCtx->dwModeHeight,
- lpPFD->cColorBits,
- 0,
- 0);
- if (FAILED(hResult)) {
- ddlogError(DDLOG_CRITICAL_OR_WARN, "SetDisplayMode failed", hResult);
- goto return_with_error;
- }
-
- // ** The display mode has changed, so dont use MessageBox! **
-
- ZeroMemory(&ddsd2, sizeof(ddsd2));
- ddsd2.dwSize = sizeof(ddsd2);
-
- if (bDoubleBuffer) {
- // Double buffered
- // Primary surface
- ddsd2.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
- ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
- DDSCAPS_FLIP |
- DDSCAPS_COMPLEX |
- DDSCAPS_3DDEVICE |
- dwMemoryType;
- ddsd2.dwBackBufferCount = 1;
-
- hResult = IDirectDraw4_CreateSurface(lpCtx->lpDD4, &ddsd2, &lpCtx->lpFront4, NULL);
- if (FAILED(hResult)) {
- ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateSurface (primary) failed", hResult);
- nContextError = GLDERR_MEM;
- goto return_with_error;
- }
-
- // Render target surface
- ZeroMemory(&ddscaps2, sizeof(ddscaps2)); // Clear the entire struct.
- ddscaps2.dwCaps = DDSCAPS_BACKBUFFER;
- hResult = IDirectDrawSurface4_GetAttachedSurface(lpCtx->lpFront4, &ddscaps2, &lpCtx->lpBack4);
- if (FAILED(hResult)) {
- ddlogError(DDLOG_CRITICAL_OR_WARN, "GetAttachedSurface failed", hResult);
- nContextError = GLDERR_MEM;
- goto return_with_error;
- }
- } else {
- // Single buffered
- // Primary surface
- ddsd2.dwFlags = DDSD_CAPS;
- ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
- //DDSCAPS_3DDEVICE |
- dwMemoryType;
-
- hResult = IDirectDraw4_CreateSurface(lpCtx->lpDD4, &ddsd2, &lpCtx->lpFront4, NULL);
- if (FAILED(hResult)) {
- ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateSurface (primary) failed", hResult);
- nContextError = GLDERR_MEM;
- goto return_with_error;
- }
-
- lpCtx->lpBack4 = NULL;
- }
- } else {
- // WINDOWED
-
- // OK to enable warning popups in windowed mode
- ddlogWarnOption(glb.bMessageBoxWarnings);
-
- dwFlags = DDSCL_NORMAL;
- if (glb.bMultiThreaded)
- dwFlags |= DDSCL_MULTITHREADED;
- if (glb.bFastFPU)
- dwFlags |= DDSCL_FPUSETUP; // fast FPU setup optional (DaveM)
- hResult = IDirectDraw4_SetCooperativeLevel(lpCtx->lpDD4,
- lpCtx->hWnd,
- dwFlags);
- if (FAILED(hResult)) {
- ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to set Normal coop level", hResult);
- goto return_with_error;
- }
- // Has Primary surface already been created for original GLRC ?
- // Note this can only be applicable for windowed modes
- if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary) {
- lpCtx->lpFront4 = glb.lpPrimary4;
- IDirectDrawSurface4_AddRef(lpCtx->lpFront4);
- // Update the window on the default clipper
- IDirectDrawSurface4_GetClipper(lpCtx->lpFront4, &lpddClipper);
- IDirectDrawClipper_SetHWnd(lpddClipper, 0, lpCtx->hWnd);
- IDirectDrawClipper_Release(lpddClipper);
- goto SkipPrimaryCreate;
- }
-
- // Primary surface
- ZeroMemory(&ddsd2, sizeof(ddsd2));
- ddsd2.dwSize = sizeof(ddsd2);
- ddsd2.dwFlags = DDSD_CAPS;
- ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
- hResult = IDirectDraw4_CreateSurface(lpCtx->lpDD4, &ddsd2, &lpCtx->lpFront4, NULL);
- if (FAILED(hResult)) {
- ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateSurface (primary) failed", hResult);
- nContextError = GLDERR_MEM;
- goto return_with_error;
- }
-
- // Cache Primary surface for subsequent GLRCs
- // Note this can only be applicable to subsequent windowed modes
- if (glb.bDirectDrawPersistant && !glb.bDirectDrawPrimary) {
- glb.lpPrimary4 = lpCtx->lpFront4;
- IDirectDrawSurface4_AddRef(glb.lpPrimary4);
- glb.bDirectDrawPrimary = TRUE;
- }
-
- // Clipper object
- hResult = DirectDrawCreateClipper(0, &lpddClipper, NULL);
- if (FAILED(hResult)) {
- ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateClipper failed", hResult);
- goto return_with_error;
- }
- hResult = IDirectDrawClipper_SetHWnd(lpddClipper, 0, lpCtx->hWnd);
- if (FAILED(hResult)) {
- RELEASE(lpddClipper);
- ddlogError(DDLOG_CRITICAL_OR_WARN, "SetHWnd failed", hResult);
- goto return_with_error;
- }
- hResult = IDirectDrawSurface4_SetClipper(lpCtx->lpFront4, lpddClipper);
- RELEASE(lpddClipper); // We have finished with it.
- if (FAILED(hResult)) {
- ddlogError(DDLOG_CRITICAL_OR_WARN, "SetClipper failed", hResult);
- goto return_with_error;
- }
-SkipPrimaryCreate:
-
- if (bDoubleBuffer) {
- // Render target surface
- ZeroMemory(&ddsd2, sizeof(ddsd2));
- ddsd2.dwSize = sizeof(ddsd2);
- ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
- ddsd2.dwWidth = lpCtx->dwWidth;
- ddsd2.dwHeight = lpCtx->dwHeight;
- ddsd2.ddsCaps.dwCaps = DDSCAPS_3DDEVICE |
- DDSCAPS_OFFSCREENPLAIN |
- dwMemoryType;
-
- // Reserve the entire desktop size for persistant buffers option
- if (glb.bDirectDrawPersistant && glb.bPersistantBuffers) {
- ddsd2.dwWidth = ddsd2DisplayMode.dwWidth;
- ddsd2.dwHeight = ddsd2DisplayMode.dwHeight;
- }
- // Re-use original back buffer if persistant buffers exist
- if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && glb.lpBack4)
- hResult = IDirectDrawSurface4_AddRef(lpCtx->lpBack4 = glb.lpBack4);
- else
- hResult = IDirectDraw4_CreateSurface(lpCtx->lpDD4, &ddsd2, &lpCtx->lpBack4, NULL);
- if (FAILED(hResult)) {
- ddlogError(DDLOG_CRITICAL_OR_WARN, "Create Backbuffer failed", hResult);
- nContextError = GLDERR_MEM;
- goto return_with_error;
- }
- if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && !glb.lpBack4)
- IDirectDrawSurface4_AddRef(glb.lpBack4 = lpCtx->lpBack4);
- } else {
- lpCtx->lpBack4 = NULL;
- }
- }
-
- //
- // Now create the Z-buffer
- //
- lpCtx->bStencil = FALSE; // Default to no stencil buffer
- if (bDepthBuffer && (lpCtx->lpPF->iZBufferPF != -1)) {
- // Get z-buffer dimensions from the render target
- // Setup the surface desc for the z-buffer.
- ZeroMemory(&ddsd2, sizeof(ddsd2));
- ddsd2.dwSize = sizeof(ddsd2);
- ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
- ddsd2.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | dwMemoryType;
- ddsd2.dwWidth = lpCtx->dwWidth;
- ddsd2.dwHeight = lpCtx->dwHeight;
- memcpy(&ddsd2.ddpfPixelFormat,
- &glb.lpZBufferPF[lpCtx->lpPF->iZBufferPF],
- sizeof(DDPIXELFORMAT) );
-
- // Reserve the entire desktop size for persistant buffers option
- if (glb.bDirectDrawPersistant && glb.bPersistantBuffers) {
- ddsd2.dwWidth = ddsd2DisplayMode.dwWidth;
- ddsd2.dwHeight = ddsd2DisplayMode.dwHeight;
- }
-
- // Create a z-buffer
- if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && glb.lpDepth4)
- hResult = IDirectDrawSurface4_AddRef(lpCtx->lpDepth4 = glb.lpDepth4);
- else
- hResult = IDirectDraw4_CreateSurface(lpCtx->lpDD4, &ddsd2, &lpCtx->lpDepth4, NULL);
- if (FAILED(hResult)) {
- ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateSurface (ZBuffer) failed", hResult);
- nContextError = GLDERR_MEM;
- goto return_with_error;
- }
- if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && !glb.lpDepth4)
- IDirectDrawSurface4_AddRef(glb.lpDepth4 = lpCtx->lpDepth4);
- else if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && glb.lpDepth4 && glb.lpBack4)
- IDirectDrawSurface4_DeleteAttachedSurface(glb.lpBack4, 0, glb.lpDepth4);
-
- // Attach Zbuffer to render target
- TRY(IDirectDrawSurface4_AddAttachedSurface(
- bDoubleBuffer ? lpCtx->lpBack4 : lpCtx->lpFront4,
- lpCtx->lpDepth4),
- "dglCreateContext: Attach Zbuffer");
- if (glb.lpZBufferPF[lpCtx->lpPF->iZBufferPF].dwFlags & DDPF_STENCILBUFFER) {
- lpCtx->bStencil = TRUE;
- ddlogMessage(DDLOG_INFO, "Depth buffer has stencil\n");
- }
- }
-
- // Clear all back buffers and Z-buffers in case of memory recycling.
- ZeroMemory(&ddbltfx, sizeof(ddbltfx));
- ddbltfx.dwSize = sizeof(ddbltfx);
- IDirectDrawSurface4_Blt(lpCtx->lpBack4, NULL, NULL, NULL,
- DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
- if (lpCtx->lpDepth4)
- IDirectDrawSurface4_Blt(lpCtx->lpDepth4, NULL, NULL, NULL,
- DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
-
- // Now that we have a Z-buffer we can create the 3D device
- hResult = IDirect3D3_CreateDevice(lpCtx->lpD3D3,
- &glb.d3dGuid,
- bDoubleBuffer ? lpCtx->lpBack4 : lpCtx->lpFront4,
- &lpCtx->lpDev3,
- NULL);
- if (FAILED(hResult)) {
- ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to create Direct3D device", hResult);
- nContextError = GLDERR_D3D;
- goto return_with_error;
- }
-
- // We must do this as soon as the device is created
- dglInitStateCaches(lpCtx);
-
- // Obtain the D3D Device Description
- D3DHWDevDesc.dwSize = D3DHELDevDesc.dwSize = sizeof(D3DDEVICEDESC);
- TRY(IDirect3DDevice3_GetCaps(lpCtx->lpDev3,
- &D3DHWDevDesc,
- &D3DHELDevDesc),
- "dglCreateContext: GetCaps failed");
-
- // Choose the relevant description and cache it in the context.
- // We will use this description later for caps checking
- memcpy( &lpCtx->D3DDevDesc,
- glb.bHardware ? &D3DHWDevDesc : &D3DHELDevDesc,
- sizeof(D3DDEVICEDESC));
-
- // Now we can examine the texture formats
- if (!dglBuildTextureFormatList(lpCtx->lpDev3)) {
- ddlogMessage(DDLOG_CRITICAL_OR_WARN, "dglBuildTextureFormatList failed\n");
- goto return_with_error;
- }
-
- // Get the pixel format of the back buffer
- lpCtx->ddpfRender.dwSize = sizeof(lpCtx->ddpfRender);
- if (bDoubleBuffer)
- hResult = IDirectDrawSurface4_GetPixelFormat(
- lpCtx->lpBack4,
- &lpCtx->ddpfRender);
- else
- hResult = IDirectDrawSurface4_GetPixelFormat(
- lpCtx->lpFront4,
- &lpCtx->ddpfRender);
-
- if (FAILED(hResult)) {
- ddlogError(DDLOG_CRITICAL_OR_WARN, "GetPixelFormat failed", hResult);
- goto return_with_error;
- }
- // Find a pixel packing function suitable for this surface
- pxClassifyPixelFormat(&lpCtx->ddpfRender,
- &lpCtx->fnPackFunc,
- &lpCtx->fnUnpackFunc,
- &lpCtx->fnPackSpanFunc);
-
- // Viewport
- hResult = IDirect3D3_CreateViewport(lpCtx->lpD3D3, &lpCtx->lpViewport3, NULL);
- if (FAILED(hResult)) {
- ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateViewport failed", hResult);
- goto return_with_error;
- }
-
- hResult = IDirect3DDevice3_AddViewport(lpCtx->lpDev3, lpCtx->lpViewport3);
- if (FAILED(hResult)) {
- ddlogError(DDLOG_CRITICAL_OR_WARN, "AddViewport failed", hResult);
- goto return_with_error;
- }
-
- // Initialise the viewport
- // Note screen coordinates are used for viewport clipping since D3D
- // transform operations are not used in the GLD CAD driver. (DaveM)
- inv_aspect = (float)lpCtx->dwHeight/(float)lpCtx->dwWidth;
-
- lpCtx->d3dViewport.dwSize = sizeof(lpCtx->d3dViewport);
- lpCtx->d3dViewport.dwX = 0;
- lpCtx->d3dViewport.dwY = 0;
- lpCtx->d3dViewport.dwWidth = lpCtx->dwWidth;
- lpCtx->d3dViewport.dwHeight = lpCtx->dwHeight;
- lpCtx->d3dViewport.dvClipX = 0; // -1.0f;
- lpCtx->d3dViewport.dvClipY = 0; // inv_aspect;
- lpCtx->d3dViewport.dvClipWidth = lpCtx->dwWidth; // 2.0f;
- lpCtx->d3dViewport.dvClipHeight = lpCtx->dwHeight; // 2.0f * inv_aspect;
- lpCtx->d3dViewport.dvMinZ = 0.0f;
- lpCtx->d3dViewport.dvMaxZ = 1.0f;
- TRY(IDirect3DViewport3_SetViewport2(lpCtx->lpViewport3, &lpCtx->d3dViewport), "dglCreateContext: SetViewport2");
-
- hResult = IDirect3DDevice3_SetCurrentViewport(lpCtx->lpDev3, lpCtx->lpViewport3);
- if (FAILED(hResult)) {
- ddlogError(DDLOG_CRITICAL_OR_WARN, "SetCurrentViewport failed", hResult);
- goto return_with_error;
- }
-
- lpCtx->dwBPP = lpPFD->cColorBits;
- lpCtx->iZBufferPF = lpCtx->lpPF->iZBufferPF;
-
- // Set last texture to NULL
- for (i=0; i<MAX_TEXTURE_UNITS; i++) {
- lpCtx->ColorOp[i] = D3DTOP_DISABLE;
- lpCtx->AlphaOp[i] = D3DTOP_DISABLE;
- lpCtx->tObj[i] = NULL;
- }
-
- // Default to perspective correct texture mapping
- dglSetRenderState(lpCtx, D3DRENDERSTATE_TEXTUREPERSPECTIVE, TRUE, "TexturePersp");
-
- // Set the default culling mode
- lpCtx->cullmode = D3DCULL_NONE;
- dglSetRenderState(lpCtx, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE, "CullMode");
-
- // Disable specular
- dglSetRenderState(lpCtx, D3DRENDERSTATE_SPECULARENABLE, FALSE, "SpecularEnable");
- // Disable subpixel correction
-// dglSetRenderState(lpCtx, D3DRENDERSTATE_SUBPIXEL, FALSE, "SubpixelEnable");
- // Disable dithering
- dglSetRenderState(lpCtx, D3DRENDERSTATE_DITHERENABLE, FALSE, "DitherEnable");
-
- // Initialise the primitive caches
-// lpCtx->dwNextLineVert = 0;
-// lpCtx->dwNextTriVert = 0;
-
- // Init the global texture palette
- lpCtx->lpGlobalPalette = NULL;
-
- // Init the HW/SW usage counters
-// lpCtx->dwHWUsageCount = lpCtx->dwSWUsageCount = 0L;
-
- //
- // Create two D3D vertex buffers.
- // One will hold the pre-transformed data with the other one
- // being used to hold the post-transformed & clipped verts.
- //
-#if 0 // never used (DaveM)
- vbufdesc.dwSize = sizeof(D3DVERTEXBUFFERDESC);
- vbufdesc.dwCaps = D3DVBCAPS_WRITEONLY;
- if (glb.bHardware == FALSE)
- vbufdesc.dwCaps = D3DVBCAPS_SYSTEMMEMORY;
- vbufdesc.dwNumVertices = 32768; // For the time being
-
- // Source vertex buffer
- vbufdesc.dwFVF = DGL_LVERTEX;
- hResult = IDirect3D3_CreateVertexBuffer(lpCtx->lpD3D3, &vbufdesc, &lpCtx->m_vbuf, 0, NULL);
- if (FAILED(hResult)) {
- ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateVertexBuffer(src) failed", hResult);
- goto return_with_error;
- }
-
- // Destination vertex buffer
- vbufdesc.dwFVF = (glb.bMultitexture == FALSE) ? D3DFVF_TLVERTEX : (D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX2);
- hResult = IDirect3D3_CreateVertexBuffer(lpCtx->lpD3D3, &vbufdesc, &lpCtx->m_pvbuf, 0, NULL);
- if(FAILED(hResult)) {
- ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateVertexBuffer(dst) failed", hResult);
- goto return_with_error;
- }
-#endif
-
-#endif _USE_GLD3_WGL
-
- //
- // Now create the Mesa context
- //
-
- // Create the Mesa visual
- if (lpPFD->cDepthBits)
- dwDepthBits = 16;
- if (lpPFD->cStencilBits)
- dwStencilBits = 8;
- if (lpPFD->cAlphaBits) {
- dwAlphaBits = 8;
- bAlphaSW = GL_TRUE;
- }
- if (lpPFD->dwFlags & PFD_DOUBLEBUFFER)
- bDouble = GL_TRUE;
-// lpCtx->EmulateSingle =
-// (lpPFD->dwFlags & PFD_DOUBLEBUFFER) ? FALSE : TRUE;
-
-#ifdef _USE_GLD3_WGL
- lpCtx->glVis = _mesa_create_visual(
- bDouble, /* double buffer */
- GL_FALSE, // stereo
- lpPFD->cRedBits,
- lpPFD->cGreenBits,
- lpPFD->cBlueBits,
- dwAlphaBits,
- dwDepthBits,
- dwStencilBits,
- lpPFD->cAccumRedBits, // accum bits
- lpPFD->cAccumGreenBits, // accum bits
- lpPFD->cAccumBlueBits, // accum bits
- lpPFD->cAccumAlphaBits, // accum alpha bits
- 1 // num samples
- );
-#else // _USE_GLD3_WGL
- lpCtx->glVis = (*mesaFuncs.gl_create_visual)(
- GL_TRUE, // RGB mode
- bAlphaSW, // Is an alpha buffer required?
- bDouble, // Is an double-buffering required?
- GL_FALSE, // stereo
- dwDepthBits, // depth_size
- dwStencilBits, // stencil_size
- lpPFD->cAccumBits, // accum_size
- 0, // colour-index bits
- lpPFD->cRedBits, // Red bit count
- lpPFD->cGreenBits, // Green bit count
- lpPFD->cBlueBits, // Blue bit count
- dwAlphaBits // Alpha bit count
- );
-#endif // _USE_GLD3_WGL
-
- if (lpCtx->glVis == NULL) {
- ddlogMessage(DDLOG_CRITICAL_OR_WARN, "gl_create_visual failed\n");
- goto return_with_error;
- }
-
-#ifdef _USE_GLD3_WGL
- lpCtx->glCtx = _mesa_create_context(lpCtx->glVis, NULL, (void *)lpCtx, GL_TRUE);
-#else
- // Create the Mesa context
- lpCtx->glCtx = (*mesaFuncs.gl_create_context)(
- lpCtx->glVis, // Mesa visual
- NULL, // share list context
- (void *)lpCtx, // Pointer to our driver context
- GL_TRUE // Direct context flag
- );
-#endif // _USE_GLD3_WGL
-
- if (lpCtx->glCtx == NULL) {
- ddlogMessage(DDLOG_CRITICAL_OR_WARN, "gl_create_context failed\n");
- goto return_with_error;
- }
-
- // Create the Mesa framebuffer
-#ifdef _USE_GLD3_WGL
- lpCtx->glBuffer = _mesa_create_framebuffer(
- lpCtx->glVis,
- lpCtx->glVis->depthBits > 0,
- lpCtx->glVis->stencilBits > 0,
- lpCtx->glVis->accumRedBits > 0,
- GL_FALSE //swalpha
- );
-#else
- lpCtx->glBuffer = (*mesaFuncs.gl_create_framebuffer)(lpCtx->glVis);
-#endif // _USE_GLD3_WGL
-
- if (lpCtx->glBuffer == NULL) {
- ddlogMessage(DDLOG_CRITICAL_OR_WARN, "gl_create_framebuffer failed\n");
- goto return_with_error;
- }
-
-#ifdef _USE_GLD3_WGL
- // Init Mesa internals
- _swrast_CreateContext( lpCtx->glCtx );
- _vbo_CreateContext( lpCtx->glCtx );
- _tnl_CreateContext( lpCtx->glCtx );
- _swsetup_CreateContext( lpCtx->glCtx );
-
- _gldDriver.InitialiseMesa(lpCtx);
-
- lpCtx->glCtx->imports.warning = _gld_mesa_warning;
- lpCtx->glCtx->imports.fatal = _gld_mesa_fatal;
-
-#else
- // Tell Mesa how many texture stages we have
- glb.wMaxSimultaneousTextures = lpCtx->D3DDevDesc.wMaxSimultaneousTextures;
- // Only use as many Units as the spec requires
- if (glb.wMaxSimultaneousTextures > MAX_TEXTURE_UNITS)
- glb.wMaxSimultaneousTextures = MAX_TEXTURE_UNITS;
- lpCtx->glCtx->Const.MaxTextureUnits = glb.wMaxSimultaneousTextures;
- ddlogPrintf(DDLOG_INFO, "Texture stages : %d", glb.wMaxSimultaneousTextures);
-
- // Set the max texture size.
- // NOTE: clamped to a max of 1024 for extra performance!
- lpCtx->dwMaxTextureSize = (lpCtx->D3DDevDesc.dwMaxTextureWidth <= 1024) ? lpCtx->D3DDevDesc.dwMaxTextureWidth : 1024;
-
-// Texture resize takes place elsewhere. KH
-// NOTE: This was added to workaround an issue with the Intel app.
-#if 0
- lpCtx->glCtx->Const.MaxTextureSize = lpCtx->dwMaxTextureSize;
-#else
- lpCtx->glCtx->Const.MaxTextureSize = 1024;
-#endif
- lpCtx->glCtx->Const.MaxDrawBuffers = 1;
-
- // Setup the Display Driver pointers
- dglSetupDDPointers(lpCtx->glCtx);
-
- // Initialise all the Direct3D renderstates
- dglInitStateD3D(lpCtx->glCtx);
-
-#if 0
- // Signal a reload of texture state on next glBegin
- lpCtx->m_texHandleValid = FALSE;
- lpCtx->m_mtex = FALSE;
- lpCtx->m_texturing = FALSE;
-#else
- // Set default texture unit state
-// dglSetTexture(lpCtx, 0, NULL);
-// dglSetTexture(lpCtx, 1, NULL);
-#endif
-
- //
- // Set the global texture palette to default values.
- //
-
- // Clear the entire palette
- ZeroMemory(ppe, sizeof(PALETTEENTRY) * 256);
-
- // Fill the palette with a default colour.
- // A garish colour is used to catch bugs. Here Magenta is used.
- for (i=0; i < 256; i++) {
- ppe[i].peRed = 255;
- ppe[i].peGreen = 0;
- ppe[i].peBlue = 255;
- }
-
- RELEASE(lpCtx->lpGlobalPalette);
-
- if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && glb.lpGlobalPalette)
- hResult = IDirectDrawPalette_AddRef(lpCtx->lpGlobalPalette = glb.lpGlobalPalette);
- else
- hResult = IDirectDraw4_CreatePalette(
- lpCtx->lpDD4,
- DDPCAPS_INITIALIZE | DDPCAPS_8BIT | DDPCAPS_ALLOW256,
- ppe,
- &(lpCtx->lpGlobalPalette),
- NULL);
- if (FAILED(hResult)) {
- ddlogError(DDLOG_ERROR, "Default CreatePalette failed\n", hResult);
- lpCtx->lpGlobalPalette = NULL;
- goto return_with_error;
- }
- if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && !glb.lpGlobalPalette)
- IDirectDrawPalette_AddRef(glb.lpGlobalPalette = lpCtx->lpGlobalPalette);
-
-#endif // _USE_GLD3_WGL
-
- // ** If we have made it to here then we can enable rendering **
- lpCtx->bCanRender = TRUE;
-
-// ddlogMessage(DDLOG_SYSTEM, "dglCreateContextBuffers succeded\n");
-
-#ifdef GLD_THREADS
- // Release serialized access
- if (glb.bMultiThreaded)
- LeaveCriticalSection(&CriticalSection);
-#endif
-
- return TRUE;
-
-return_with_error:
- // Clean up before returning.
- // This is critical for secondary devices.
-
- lpCtx->bCanRender = FALSE;
-
-#ifdef _USE_GLD3_WGL
- // Destroy the Mesa context
- if (lpCtx->glBuffer)
- _mesa_destroy_framebuffer(lpCtx->glBuffer);
- if (lpCtx->glCtx)
- _mesa_destroy_context(lpCtx->glCtx);
- if (lpCtx->glVis)
- _mesa_destroy_visual(lpCtx->glVis);
-
- // Destroy driver data
- _gldDriver.DestroyDrawable(lpCtx);
-#else
- // Destroy the Mesa context
- if (lpCtx->glBuffer)
- (*mesaFuncs.gl_destroy_framebuffer)(lpCtx->glBuffer);
- if (lpCtx->glCtx)
- (*mesaFuncs.gl_destroy_context)(lpCtx->glCtx);
- if (lpCtx->glVis)
- (*mesaFuncs.gl_destroy_visual)(lpCtx->glVis);
-
- RELEASE(lpCtx->m_pvbuf); // Release D3D vertex buffer
- RELEASE(lpCtx->m_vbuf); // Release D3D vertex buffer
-
- if (lpCtx->lpViewport3) {
- if (lpCtx->lpDev3) IDirect3DDevice3_DeleteViewport(lpCtx->lpDev3, lpCtx->lpViewport3);
- RELEASE(lpCtx->lpViewport3);
- lpCtx->lpViewport3 = NULL;
- }
-
- RELEASE(lpCtx->lpDev3);
- if (lpCtx->lpDepth4) {
- if (lpCtx->lpBack4)
- IDirectDrawSurface4_DeleteAttachedSurface(lpCtx->lpBack4, 0L, lpCtx->lpDepth4);
- else
- IDirectDrawSurface4_DeleteAttachedSurface(lpCtx->lpFront4, 0L, lpCtx->lpDepth4);
- RELEASE(lpCtx->lpDepth4);
- lpCtx->lpDepth4 = NULL;
- }
- RELEASE(lpCtx->lpBack4);
- RELEASE(lpCtx->lpFront4);
- else
- if (lpCtx->bFullscreen) {
- IDirectDraw4_RestoreDisplayMode(lpCtx->lpDD4);
- IDirectDraw4_SetCooperativeLevel(lpCtx->lpDD4, NULL, DDSCL_NORMAL);
- }
- RELEASE(lpCtx->lpD3D3);
- RELEASE(lpCtx->lpDD4);
- RELEASE(lpCtx->lpDD1);
-#endif // _USE_GLD3_WGL
-
- lpCtx->bAllocated = FALSE;
-
-#ifdef GLD_THREADS
- // Release serialized access
- if (glb.bMultiThreaded)
- LeaveCriticalSection(&CriticalSection);
-#endif
-
- return FALSE;
-
-#undef DDLOG_CRITICAL_OR_WARN
-}
-
-// ***********************************************************************
-
-HGLRC dglCreateContext(
- HDC a,
- const DGL_pixelFormat *lpPF)
-{
- int i;
- HGLRC hGLRC;
- DGL_ctx* lpCtx;
- static BOOL bWarnOnce = TRUE;
- DWORD dwThreadId = GetCurrentThreadId();
- char szMsg[256];
- HWND hWnd;
- LONG lpfnWndProc;
-
- // Validate license
- if (!dglValidate())
- return NULL;
-
- // Is context state ready ?
- if (!bContextReady)
- return NULL;
-
- ddlogPrintf(DDLOG_SYSTEM, "dglCreateContext for HDC=%X, ThreadId=%X", a, dwThreadId);
-
- // Find next free context.
- // Also ensure that only one Fullscreen context is created at any one time.
- hGLRC = 0; // Default to Not Found
- for (i=0; i<DGL_MAX_CONTEXTS; i++) {
- if (ctxlist[i].bAllocated) {
- if (/*glb.bFullscreen && */ctxlist[i].bFullscreen)
- break;
- } else {
- hGLRC = (HGLRC)(i+1);
- break;
- }
- }
-
- // Bail if no GLRC was found
- if (!hGLRC)
- return NULL;
-
- // Set the context pointer
- lpCtx = dglGetContextAddress(hGLRC);
- // Make sure that context is zeroed before we do anything.
- // MFC and C++ apps call wglCreateContext() and wglDeleteContext() multiple times,
- // even though only one context is ever used by the app, so keep it clean. (DaveM)
- ZeroMemory(lpCtx, sizeof(DGL_ctx));
- lpCtx->bAllocated = TRUE;
- // Flag that buffers need creating on next wglMakeCurrent call.
- lpCtx->bHasBeenCurrent = FALSE;
- lpCtx->lpPF = (DGL_pixelFormat *)lpPF; // cache pixel format
- lpCtx->bCanRender = FALSE;
-
- // Create all the internal resources here, not in dglMakeCurrent().
- // We do a re-size check in dglMakeCurrent in case of re-allocations. (DaveM)
- // We now try context allocations twice, first with video memory,
- // then again with system memory. This is similar to technique
- // used for dglWglResizeBuffers(). (DaveM)
- if (lpCtx->bHasBeenCurrent == FALSE) {
- if (!dglCreateContextBuffers(a, lpCtx, FALSE)) {
- if (glb.bMessageBoxWarnings && bWarnOnce && dwLogging) {
- bWarnOnce = FALSE;
- switch (nContextError) {
- case GLDERR_DDRAW: strcpy(szMsg, szDDrawWarning); break;
- case GLDERR_D3D: strcpy(szMsg, szD3DWarning); break;
- case GLDERR_MEM: strcpy(szMsg, szResourceWarning); break;
- case GLDERR_BPP: strcpy(szMsg, szBPPWarning); break;
- default: strcpy(szMsg, "");
- }
- if (strlen(szMsg))
- MessageBox(NULL, szMsg, "GLDirect", MB_OK | MB_ICONWARNING);
- }
- // Only need to try again if memory error
- if (nContextError == GLDERR_MEM) {
- ddlogPrintf(DDLOG_WARN, "dglCreateContext failed 1st time with video memory");
- }
- else {
- ddlogPrintf(DDLOG_ERROR, "dglCreateContext failed");
- return NULL;
- }
- }
- }
-
- // Now that we have a hWnd, we can intercept the WindowProc.
- hWnd = lpCtx->hWnd;
- if (hWnd) {
- // Only hook individual window handler once if not hooked before.
- lpfnWndProc = GetWindowLong(hWnd, GWL_WNDPROC);
- if (lpfnWndProc != (LONG)dglWndProc) {
- lpCtx->lpfnWndProc = lpfnWndProc;
- SetWindowLong(hWnd, GWL_WNDPROC, (LONG)dglWndProc);
- }
- // Find the parent window of the app too.
- if (glb.hWndActive == NULL) {
- while (hWnd != NULL) {
- glb.hWndActive = hWnd;
- hWnd = GetParent(hWnd);
- }
- // Hook the parent window too.
- lpfnWndProc = GetWindowLong(glb.hWndActive, GWL_WNDPROC);
- if (glb.hWndActive == lpCtx->hWnd)
- glb.lpfnWndProc = lpCtx->lpfnWndProc;
- else if (lpfnWndProc != (LONG)dglWndProc)
- glb.lpfnWndProc = lpfnWndProc;
- if (glb.lpfnWndProc)
- SetWindowLong(glb.hWndActive, GWL_WNDPROC, (LONG)dglWndProc);
- }
- }
-
- ddlogPrintf(DDLOG_SYSTEM, "dglCreateContext succeeded for HGLRC=%d", (int)hGLRC);
-
- return hGLRC;
-}
-
-// ***********************************************************************
-// Make a DirectGL context current
-// Used by wgl functions and dgl functions
-BOOL dglMakeCurrent(
- HDC a,
- HGLRC b)
-{
- int context;
- DGL_ctx* lpCtx;
- HWND hWnd;
- BOOL bNeedResize = FALSE;
- BOOL bWindowChanged, bContextChanged;
- LPDIRECTDRAWCLIPPER lpddClipper;
- DWORD dwThreadId = GetCurrentThreadId();
- LONG lpfnWndProc;
-
- // Validate license
- if (!dglValidate())
- return FALSE;
-
- // Is context state ready ?
- if (!bContextReady)
- return FALSE;
-
- context = (int)b; // This is as a result of STRICT!
- ddlogPrintf(DDLOG_SYSTEM, "dglMakeCurrent: HDC=%X, HGLRC=%d, ThreadId=%X", a, context, dwThreadId);
-
- // If the HGLRC is NULL then make no context current;
- // Ditto if the HDC is NULL either. (DaveM)
- if (context == 0 || a == 0) {
- // Corresponding Mesa operation
-#ifdef _USE_GLD3_WGL
- _mesa_make_current(NULL, NULL);
-#else
- (*mesaFuncs.gl_make_current)(NULL, NULL);
-#endif
- dglSetCurrentContext(0);
- return TRUE;
- }
-
- // Make sure the HGLRC is in range
- if ((context > DGL_MAX_CONTEXTS) || (context < 0)) {
- ddlogMessage(DDLOG_ERROR, "dglMakeCurrent: HGLRC out of range\n");
- return FALSE;
- }
-
- // Find address of context and make sure that it has been allocated
- lpCtx = dglGetContextAddress(b);
- if (!lpCtx->bAllocated) {
- ddlogMessage(DDLOG_ERROR, "dglMakeCurrent: Context not allocated\n");
-// return FALSE;
- return TRUE; // HACK: Shuts up "WebLab Viewer Pro". KeithH
- }
-
-#ifdef GLD_THREADS
- // Serialize access to DirectDraw or DDS operations
- if (glb.bMultiThreaded)
- EnterCriticalSection(&CriticalSection);
-#endif
-
- // Check if window has changed
- hWnd = (a != lpCtx->hDC) ? WindowFromDC(a) : lpCtx->hWnd;
- bWindowChanged = (hWnd != lpCtx->hWnd) ? TRUE : FALSE;
- bContextChanged = (b != dglGetCurrentContext()) ? TRUE : FALSE;
-
- // If the window has changed, make sure the clipper is updated. (DaveM)
- if (glb.bDirectDrawPersistant && !lpCtx->bFullscreen && (bWindowChanged || bContextChanged)) {
- lpCtx->hWnd = hWnd;
-#ifndef _USE_GLD3_WGL
- IDirectDrawSurface4_GetClipper(lpCtx->lpFront4, &lpddClipper);
- IDirectDrawClipper_SetHWnd(lpddClipper, 0, lpCtx->hWnd);
- IDirectDrawClipper_Release(lpddClipper);
-#endif // _USE_GLD3_WGL
- }
-
- // Make sure hDC and hWnd is current. (DaveM)
- // Obtain the dimensions of the rendering window
- lpCtx->hDC = a; // Cache DC
- lpCtx->hWnd = hWnd;
- hWndLastActive = hWnd;
-
- // Check for non-window DC = memory DC ?
- if (hWnd == NULL) {
- if (GetClipBox(a, &lpCtx->rcScreenRect) == ERROR) {
- ddlogMessage(DDLOG_WARN, "GetClipBox failed in dglMakeCurrent\n");
- SetRect(&lpCtx->rcScreenRect, 0, 0, 0, 0);
- }
- }
- else if (!GetClientRect(lpCtx->hWnd, &lpCtx->rcScreenRect)) {
- ddlogMessage(DDLOG_WARN, "GetClientRect failed in dglMakeCurrent\n");
- SetRect(&lpCtx->rcScreenRect, 0, 0, 0, 0);
- }
- // Check if buffers need to be re-sized;
- // If so, wait until Mesa GL stuff is setup before re-sizing;
- if (lpCtx->dwWidth != lpCtx->rcScreenRect.right - lpCtx->rcScreenRect.left ||
- lpCtx->dwHeight != lpCtx->rcScreenRect.bottom - lpCtx->rcScreenRect.top)
- bNeedResize = TRUE;
-
- // Now we can update our globals
- dglSetCurrentContext(b);
-
- // Corresponding Mesa operation
-#ifdef _USE_GLD3_WGL
- _mesa_make_current(lpCtx->glCtx, lpCtx->glBuffer);
- lpCtx->glCtx->Driver.UpdateState(lpCtx->glCtx, _NEW_ALL);
- if (bNeedResize) {
- // Resize buffers (Note Mesa GL needs to be setup beforehand);
- // Resize Mesa internal buffer too via glViewport() command,
- // which subsequently calls dglWglResizeBuffers() too.
- lpCtx->glCtx->Driver.Viewport(lpCtx->glCtx, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
- lpCtx->bHasBeenCurrent = TRUE;
- }
-#else
- (*mesaFuncs.gl_make_current)(lpCtx->glCtx, lpCtx->glBuffer);
-
- dglSetupDDPointers(lpCtx->glCtx);
-
- // Insure DirectDraw surfaces fit current window DC
- if (bNeedResize) {
- // Resize buffers (Note Mesa GL needs to be setup beforehand);
- // Resize Mesa internal buffer too via glViewport() command,
- // which subsequently calls dglWglResizeBuffers() too.
- (*mesaFuncs.gl_Viewport)(lpCtx->glCtx, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
- lpCtx->bHasBeenCurrent = TRUE;
- }
-#endif // _USE_GLD3_WGL
- ddlogPrintf(DDLOG_SYSTEM, "dglMakeCurrent: width = %d, height = %d", lpCtx->dwWidth, lpCtx->dwHeight);
-
- // We have to clear D3D back buffer and render state if emulated front buffering
- // for different window (but not context) like in Solid Edge.
- if (glb.bDirectDrawPersistant && glb.bPersistantBuffers
- && (bWindowChanged /* || bContextChanged */) && lpCtx->EmulateSingle) {
-#ifdef _USE_GLD3_WGL
-// IDirect3DDevice8_EndScene(lpCtx->pDev);
-// lpCtx->bSceneStarted = FALSE;
- lpCtx->glCtx->Driver.Clear(lpCtx->glCtx, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
- GL_TRUE, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
-#else
- IDirect3DDevice3_EndScene(lpCtx->lpDev3);
- lpCtx->bSceneStarted = FALSE;
- dglClearD3D(lpCtx->glCtx, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
- GL_TRUE, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
-#endif // _USE_GLD3_WGL
- }
-
- // The first time we call MakeCurrent we set the initial viewport size
- if (lpCtx->bHasBeenCurrent == FALSE)
-#ifdef _USE_GLD3_WGL
- lpCtx->glCtx->Driver.Viewport(lpCtx->glCtx, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
-#else
- (*mesaFuncs.gl_Viewport)(lpCtx->glCtx, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
-#endif // _USE_GLD3_WGL
- lpCtx->bHasBeenCurrent = TRUE;
-
-#ifdef GLD_THREADS
- // Release serialized access
- if (glb.bMultiThreaded)
- LeaveCriticalSection(&CriticalSection);
-#endif
-
- return TRUE;
-}
-
-// ***********************************************************************
-
-BOOL dglDeleteContext(
- HGLRC a)
-{
- DGL_ctx* lpCtx;
- DWORD dwThreadId = GetCurrentThreadId();
- char argstr[256];
-
-#if 0 // We have enough trouble throwing exceptions as it is... (DaveM)
- // Validate license
- if (!dglValidate())
- return FALSE;
-#endif
-
- // Is context state ready ?
- if (!bContextReady)
- return FALSE;
-
- ddlogPrintf(DDLOG_SYSTEM, "dglDeleteContext: Deleting context HGLRC=%d, ThreadId=%X", (int)a, dwThreadId);
-
- // Make sure the HGLRC is in range
- if (((int) a> DGL_MAX_CONTEXTS) || ((int)a < 0)) {
- ddlogMessage(DDLOG_ERROR, "dglDeleteCurrent: HGLRC out of range\n");
- return FALSE;
- }
-
- // Make sure context is valid
- lpCtx = dglGetContextAddress(a);
- if (!lpCtx->bAllocated) {
- ddlogPrintf(DDLOG_WARN, "Tried to delete unallocated context HGLRC=%d", (int)a);
-// return FALSE;
- return TRUE; // HACK: Shuts up "WebLab Viewer Pro". KeithH
- }
-
- // Make sure context is de-activated
- if (a == dglGetCurrentContext()) {
- ddlogPrintf(DDLOG_WARN, "dglDeleteContext: context HGLRC=%d still active", (int)a);
- dglMakeCurrent(NULL, NULL);
- }
-
-#ifdef GLD_THREADS
- // Serialize access to DirectDraw or DDS operations
- if (glb.bMultiThreaded)
- EnterCriticalSection(&CriticalSection);
-#endif
-
- // We are about to destroy all Direct3D objects.
- // Therefore we must disable rendering
- lpCtx->bCanRender = FALSE;
-
- // This exception handler was installed to catch some
- // particularly nasty apps. Console apps that call exit()
- // fall into this catagory (i.e. Win32 Glut).
-
- // VC cannot successfully implement multiple exception handlers
- // if more than one exception occurs. Therefore reverting back to
- // single exception handler as Keith originally had it. (DaveM)
-
-#define WARN_MESSAGE(p) strcpy(argstr, (#p));
-#define SAFE_RELEASE(p) WARN_MESSAGE(p); RELEASE(p);
-
-__try {
-#ifdef _USE_GLD3_WGL
- WARN_MESSAGE(gl_destroy_framebuffer);
- if (lpCtx->glBuffer)
- _mesa_destroy_framebuffer(lpCtx->glBuffer);
- WARN_MESSAGE(gl_destroy_context);
- if (lpCtx->glCtx)
- _mesa_destroy_context(lpCtx->glCtx);
- WARN_MESSAGE(gl_destroy_visual);
- if (lpCtx->glVis)
- _mesa_destroy_visual(lpCtx->glVis);
-
- _gldDriver.DestroyDrawable(lpCtx);
-#else
- // Destroy the Mesa context
- WARN_MESSAGE(gl_destroy_framebuffer);
- if (lpCtx->glBuffer)
- (*mesaFuncs.gl_destroy_framebuffer)(lpCtx->glBuffer);
- WARN_MESSAGE(gl_destroy_context);
- if (lpCtx->glCtx)
- (*mesaFuncs.gl_destroy_context)(lpCtx->glCtx);
- WARN_MESSAGE(gl_destroy_visual);
- if (lpCtx->glVis)
- (*mesaFuncs.gl_destroy_visual)(lpCtx->glVis);
-
- SAFE_RELEASE(lpCtx->m_pvbuf); // release D3D vertex buffer
- SAFE_RELEASE(lpCtx->m_vbuf); // release D3D vertex buffer
-
- // Delete the global palette
- SAFE_RELEASE(lpCtx->lpGlobalPalette);
-
- // Clean up.
- if (lpCtx->lpViewport3) {
- if (lpCtx->lpDev3) IDirect3DDevice3_DeleteViewport(lpCtx->lpDev3, lpCtx->lpViewport3);
- SAFE_RELEASE(lpCtx->lpViewport3);
- lpCtx->lpViewport3 = NULL;
- }
-
- SAFE_RELEASE(lpCtx->lpDev3);
- if (lpCtx->lpDepth4) {
- if (lpCtx->lpBack4)
- IDirectDrawSurface4_DeleteAttachedSurface(lpCtx->lpBack4, 0L, lpCtx->lpDepth4);
- else
- IDirectDrawSurface4_DeleteAttachedSurface(lpCtx->lpFront4, 0L, lpCtx->lpDepth4);
- SAFE_RELEASE(lpCtx->lpDepth4);
- lpCtx->lpDepth4 = NULL;
- }
- SAFE_RELEASE(lpCtx->lpBack4);
- SAFE_RELEASE(lpCtx->lpFront4);
- if (lpCtx->bFullscreen) {
- IDirectDraw4_RestoreDisplayMode(lpCtx->lpDD4);
- IDirectDraw4_SetCooperativeLevel(lpCtx->lpDD4, NULL, DDSCL_NORMAL);
- }
- SAFE_RELEASE(lpCtx->lpD3D3);
- SAFE_RELEASE(lpCtx->lpDD4);
- SAFE_RELEASE(lpCtx->lpDD1);
-#endif // _ULSE_GLD3_WGL
-
-}
-__except(EXCEPTION_EXECUTE_HANDLER) {
- ddlogPrintf(DDLOG_WARN, "Exception raised in dglDeleteContext: %s", argstr);
-}
-
- // Restore the window message handler because this context may be used
- // again by another window with a *different* message handler. (DaveM)
- if (lpCtx->lpfnWndProc) {
- SetWindowLong(lpCtx->hWnd, GWL_WNDPROC, (LONG)lpCtx->lpfnWndProc);
- lpCtx->lpfnWndProc = (LONG)NULL;
- }
-
- lpCtx->bAllocated = FALSE; // This context is now free for use
-
-#ifdef GLD_THREADS
- // Release serialized access
- if (glb.bMultiThreaded)
- LeaveCriticalSection(&CriticalSection);
-#endif
-
- return TRUE;
-}
-
-// ***********************************************************************
-
-BOOL dglSwapBuffers(
- HDC hDC)
-{
- RECT rSrcRect; // Source rectangle
- RECT rDstRect; // Destination rectangle
- POINT pt;
- HRESULT hResult;
-
- DDBLTFX bltFX;
- DWORD dwBlitFlags;
- DDBLTFX *lpBltFX;
-
-// DWORD dwThreadId = GetCurrentThreadId();
- HGLRC hGLRC = dglGetCurrentContext();
- DGL_ctx *lpCtx = dglGetContextAddress(hGLRC);
- HWND hWnd;
-
- HDC hDCAux; // for memory DC
- int x,y,w,h; // for memory DC BitBlt
-
-#if 0 // Perhaps not a good idea. Called too often. KH
- // Validate license
- if (!dglValidate())
- return FALSE;
-#endif
-
- if (!lpCtx) {
- return TRUE; //FALSE; // No current context
- }
-
- if (!lpCtx->bCanRender) {
- // Don't return false else some apps will bail.
- return TRUE;
- }
-
- hWnd = lpCtx->hWnd;
- if (hDC != lpCtx->hDC) {
- ddlogPrintf(DDLOG_WARN, "dglSwapBuffers: HDC=%X does not match HDC=%X for HGLRC=%d", hDC, lpCtx->hDC, hGLRC);
- hWnd = WindowFromDC(hDC);
- }
-
-#ifndef _USE_GLD3_WGL
- // Ensure that the surfaces exist before we tell
- // the device to render to them.
- IDirectDraw4_RestoreAllSurfaces(lpCtx->lpDD4);
-
- // Make sure that the vertex caches have been emptied
-// dglStateChange(lpCtx);
-
- // Some OpenGL programs don't issue a glFinish - check for it here.
- if (lpCtx->bSceneStarted) {
- IDirect3DDevice3_EndScene(lpCtx->lpDev3);
- lpCtx->bSceneStarted = FALSE;
- }
-#endif
-
-#if 0
- // If the calling app is not active then we don't need to Blit/Flip.
- // We can therefore simply return TRUE.
- if (!glb.bAppActive)
- return TRUE;
- // Addendum: This is WRONG! We should bail if the app is *minimized*,
- // not merely if the app is just plain 'not active'.
- // KeithH, 27/May/2000.
-#endif
-
- // Check for non-window DC = memory DC ?
- if (hWnd == NULL) {
- if (GetClipBox(hDC, &rSrcRect) == ERROR)
- return TRUE;
- // Use GDI BitBlt instead from compatible DirectDraw DC
- x = rSrcRect.left;
- y = rSrcRect.top;
- w = rSrcRect.right - rSrcRect.left;
- h = rSrcRect.bottom - rSrcRect.top;
-
- // Ack. DX8 does not have a GetDC() function...
- // TODO: Defer to DX7 or DX9 drivers... (DaveM)
- return TRUE;
- }
-
- // Bail if window client region is not drawable, like in Solid Edge
- if (!IsWindow(hWnd) /* || !IsWindowVisible(hWnd) */ || !GetClientRect(hWnd, &rSrcRect))
- return TRUE;
-
-#ifdef GLD_THREADS
- // Serialize access to DirectDraw or DDS operations
- if (glb.bMultiThreaded)
- EnterCriticalSection(&CriticalSection);
-#endif
-
-#ifdef _USE_GLD3_WGL
- // Notify Mesa of impending swap, so Mesa can flush internal buffers.
- _mesa_notifySwapBuffers(lpCtx->glCtx);
- // Now perform driver buffer swap
- _gldDriver.SwapBuffers(lpCtx, hDC, hWnd);
-#else
- if (lpCtx->bFullscreen) {
- // Sync with retrace if required
- if (glb.bWaitForRetrace) {
- IDirectDraw4_WaitForVerticalBlank(
- lpCtx->lpDD4,
- DDWAITVB_BLOCKBEGIN,
- 0);
- }
-
- // Perform the fullscreen flip
- TRY(IDirectDrawSurface4_Flip(
- lpCtx->lpFront4,
- NULL,
- DDFLIP_WAIT),
- "dglSwapBuffers: Flip");
- } else {
- // Calculate current window position and size
- pt.x = pt.y = 0;
- ClientToScreen(hWnd, &pt);
- GetClientRect(hWnd, &rDstRect);
- if (rDstRect.right > lpCtx->dwModeWidth)
- rDstRect.right = lpCtx->dwModeWidth;
- if (rDstRect.bottom > lpCtx->dwModeHeight)
- rDstRect.bottom = lpCtx->dwModeHeight;
- OffsetRect(&rDstRect, pt.x, pt.y);
- rSrcRect.left = rSrcRect.top = 0;
- rSrcRect.right = lpCtx->dwWidth;
- rSrcRect.bottom = lpCtx->dwHeight;
- if (rSrcRect.right > lpCtx->dwModeWidth)
- rSrcRect.right = lpCtx->dwModeWidth;
- if (rSrcRect.bottom > lpCtx->dwModeHeight)
- rSrcRect.bottom = lpCtx->dwModeHeight;
-
- if (glb.bWaitForRetrace) {
- // Sync the blit to the vertical retrace
- ZeroMemory(&bltFX, sizeof(bltFX));
- bltFX.dwSize = sizeof(bltFX);
- bltFX.dwDDFX = DDBLTFX_NOTEARING;
- dwBlitFlags = DDBLT_WAIT | DDBLT_DDFX;
- lpBltFX = &bltFX;
- } else {
- dwBlitFlags = DDBLT_WAIT;
- lpBltFX = NULL;
- }
-
- // Perform the actual blit
- TRY(IDirectDrawSurface4_Blt(
- lpCtx->lpFront4,
- &rDstRect,
- lpCtx->lpBack4, // Blit source
- &rSrcRect,
- dwBlitFlags,
- lpBltFX),
- "dglSwapBuffers: Blt");
- }
-#endif // _USE_GLD3_WGL
-
-#ifdef GLD_THREADS
- // Release serialized access
- if (glb.bMultiThreaded)
- LeaveCriticalSection(&CriticalSection);
-#endif
-
- // TODO: Re-instate rendering bitmap snapshot feature??? (DaveM)
-
- // Render frame is completed
- ValidateRect(hWnd, NULL);
- lpCtx->bFrameStarted = FALSE;
-
- return TRUE;
-}
-
-// ***********************************************************************
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x (Win32)
+*
+* Description: Context handling.
+*
+****************************************************************************/
+
+#include "dglcontext.h"
+
+// Get compile errors without this. KeithH
+//#include "scitech.h" // ibool, etc.
+
+#ifdef _USE_GLD3_WGL
+#include "gld_driver.h"
+
+extern void _gld_mesa_warning(struct gl_context *, char *);
+extern void _gld_mesa_fatal(struct gl_context *, char *);
+#endif // _USE_GLD3_WGL
+
+// TODO: Clean out old DX6-specific code from GLD 2.x CAD driver
+// if it is no longer being built as part of GLDirect. (DaveM)
+
+// ***********************************************************************
+
+#define GLDERR_NONE 0
+#define GLDERR_MEM 1
+#define GLDERR_DDRAW 2
+#define GLDERR_D3D 3
+#define GLDERR_BPP 4
+
+char szResourceWarning[] =
+"GLDirect does not have enough video memory resources\n"
+"to support the requested OpenGL rendering context.\n\n"
+"You may have to reduce the current display resolution\n"
+"to obtain satisfactory OpenGL performance.\n";
+
+char szDDrawWarning[] =
+"GLDirect is unable to initialize DirectDraw for the\n"
+"requested OpenGL rendering context.\n\n"
+"You will have to check the DirectX control panel\n"
+"for further information.\n";
+
+char szD3DWarning[] =
+"GLDirect is unable to initialize Direct3D for the\n"
+"requested OpenGL rendering context.\n\n"
+"You may have to change the display mode resolution\n"
+"color depth or check the DirectX control panel for\n"
+"further information.\n";
+
+char szBPPWarning[] =
+"GLDirect is unable to use the selected color depth for\n"
+"the requested OpenGL rendering context.\n\n"
+"You will have to change the display mode resolution\n"
+"color depth with the Display Settings control panel.\n";
+
+int nContextError = GLDERR_NONE;
+
+// ***********************************************************************
+
+#define VENDORID_ATI 0x1002
+
+static DWORD devATIRagePro[] = {
+ 0x4742, // 3D RAGE PRO BGA AGP 1X/2X
+ 0x4744, // 3D RAGE PRO BGA AGP 1X only
+ 0x4749, // 3D RAGE PRO BGA PCI 33 MHz
+ 0x4750, // 3D RAGE PRO PQFP PCI 33 MHz
+ 0x4751, // 3D RAGE PRO PQFP PCI 33 MHz limited 3D
+ 0x4C42, // 3D RAGE LT PRO BGA-312 AGP 133 MHz
+ 0x4C44, // 3D RAGE LT PRO BGA-312 AGP 66 MHz
+ 0x4C49, // 3D RAGE LT PRO BGA-312 PCI 33 MHz
+ 0x4C50, // 3D RAGE LT PRO BGA-256 PCI 33 MHz
+ 0x4C51, // 3D RAGE LT PRO BGA-256 PCI 33 MHz limited 3D
+};
+
+static DWORD devATIRageIIplus[] = {
+ 0x4755, // 3D RAGE II+
+ 0x4756, // 3D RAGE IIC PQFP PCI
+ 0x4757, // 3D RAGE IIC BGA AGP
+ 0x475A, // 3D RAGE IIC PQFP AGP
+ 0x4C47, // 3D RAGE LT-G
+};
+
+// ***********************************************************************
+
+#ifndef _USE_GLD3_WGL
+extern DGL_mesaFuncs mesaFuncs;
+#endif
+
+extern DWORD dwLogging;
+
+#ifdef GLD_THREADS
+#pragma message("compiling DGLCONTEXT.C vars for multi-threaded support")
+CRITICAL_SECTION CriticalSection; // for serialized access
+DWORD dwTLSCurrentContext = 0xFFFFFFFF; // TLS index for current context
+DWORD dwTLSPixelFormat = 0xFFFFFFFF; // TLS index for current pixel format
+#endif
+HGLRC iCurrentContext = 0; // Index of current context (static)
+BOOL bContextReady = FALSE; // Context state ready ?
+
+DGL_ctx ctxlist[DGL_MAX_CONTEXTS]; // Context list
+
+// ***********************************************************************
+
+static BOOL bHaveWin95 = FALSE;
+static BOOL bHaveWinNT = FALSE;
+static BOOL bHaveWin2K = FALSE;
+
+/****************************************************************************
+REMARKS:
+Detect the installed OS type.
+****************************************************************************/
+static void DetectOS(void)
+{
+ OSVERSIONINFO VersionInformation;
+ LPOSVERSIONINFO lpVersionInformation = &VersionInformation;
+
+ VersionInformation.dwOSVersionInfoSize = sizeof(VersionInformation);
+
+ GetVersionEx(lpVersionInformation);
+
+ switch (VersionInformation.dwPlatformId) {
+ case VER_PLATFORM_WIN32_WINDOWS:
+ bHaveWin95 = TRUE;
+ bHaveWinNT = FALSE;
+ bHaveWin2K = FALSE;
+ break;
+ case VER_PLATFORM_WIN32_NT:
+ bHaveWin95 = FALSE;
+ if (VersionInformation.dwMajorVersion <= 4) {
+ bHaveWinNT = TRUE;
+ bHaveWin2K = FALSE;
+ }
+ else {
+ bHaveWinNT = FALSE;
+ bHaveWin2K = TRUE;
+ }
+ break;
+ case VER_PLATFORM_WIN32s:
+ bHaveWin95 = FALSE;
+ bHaveWinNT = FALSE;
+ bHaveWin2K = FALSE;
+ break;
+ }
+}
+
+// ***********************************************************************
+
+HWND hWndEvent = NULL; // event monitor window
+HWND hWndLastActive = NULL; // last active client window
+LONG __stdcall GLD_EventWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam);
+
+// ***********************************************************************
+
+// Checks if the HGLRC is valid in range of context list.
+BOOL dglIsValidContext(
+ HGLRC a)
+{
+ return ((int)a > 0 && (int)a <= DGL_MAX_CONTEXTS);
+}
+
+// ***********************************************************************
+
+// Convert a HGLRC to a pointer into the context list.
+DGL_ctx* dglGetContextAddress(
+ const HGLRC a)
+{
+ if (dglIsValidContext(a))
+ return &ctxlist[(int)a-1];
+ return NULL;
+}
+
+// ***********************************************************************
+
+// Return the current HGLRC (however it may be stored for multi-threading).
+HGLRC dglGetCurrentContext(void)
+{
+#ifdef GLD_THREADS
+ HGLRC hGLRC;
+ // load from thread-specific instance
+ if (glb.bMultiThreaded) {
+ // protect against calls from arbitrary threads
+ __try {
+ hGLRC = (HGLRC)TlsGetValue(dwTLSCurrentContext);
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER) {
+ hGLRC = iCurrentContext;
+ }
+ }
+ // load from global static var
+ else {
+ hGLRC = iCurrentContext;
+ }
+ return hGLRC;
+#else
+ return iCurrentContext;
+#endif
+}
+
+// ***********************************************************************
+
+// Set the current HGLRC (however it may be stored for multi-threading).
+void dglSetCurrentContext(HGLRC hGLRC)
+{
+#ifdef GLD_THREADS
+ // store in thread-specific instance
+ if (glb.bMultiThreaded) {
+ // protect against calls from arbitrary threads
+ __try {
+ TlsSetValue(dwTLSCurrentContext, (LPVOID)hGLRC);
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER) {
+ iCurrentContext = hGLRC;
+ }
+ }
+ // store in global static var
+ else {
+ iCurrentContext = hGLRC;
+ }
+#else
+ iCurrentContext = hGLRC;
+#endif
+}
+
+// ***********************************************************************
+
+// Return the current HDC only for a currently active HGLRC.
+HDC dglGetCurrentDC(void)
+{
+ HGLRC hGLRC;
+ DGL_ctx* lpCtx;
+
+ hGLRC = dglGetCurrentContext();
+ if (hGLRC) {
+ lpCtx = dglGetContextAddress(hGLRC);
+ return lpCtx->hDC;
+ }
+ return 0;
+}
+
+// ***********************************************************************
+
+void dglInitContextState()
+{
+ int i;
+ WNDCLASS wc;
+
+#ifdef GLD_THREADS
+ // Allocate thread local storage indexes for current context and pixel format
+ dwTLSCurrentContext = TlsAlloc();
+ dwTLSPixelFormat = TlsAlloc();
+#endif
+
+ dglSetCurrentContext(NULL); // No current rendering context
+
+ // Clear all context data
+ ZeroMemory(ctxlist, sizeof(ctxlist[0]) * DGL_MAX_CONTEXTS);
+
+ for (i=0; i<DGL_MAX_CONTEXTS; i++)
+ ctxlist[i].bAllocated = FALSE; // Flag context as unused
+
+ // This section of code crashes the dll in circumstances where the app
+ // creates and destroys contexts.
+/*
+ // Register the class for our event monitor window
+ wc.style = 0;
+ wc.lpfnWndProc = GLD_EventWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = GetModuleHandle(NULL);
+ wc.hIcon = LoadIcon(GetModuleHandle(NULL), IDI_APPLICATION);
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = "GLDIRECT";
+ RegisterClass(&wc);
+
+ // Create the non-visible window to monitor all broadcast messages
+ hWndEvent = CreateWindowEx(
+ WS_EX_TOOLWINDOW,"GLDIRECT","GLDIRECT",WS_POPUP,
+ 0,0,0,0,
+ NULL,NULL,GetModuleHandle(NULL),NULL);
+*/
+
+#ifdef GLD_THREADS
+ // Create a critical section object for serializing access to
+ // DirectDraw and DDStereo create/destroy functions in multiple threads
+ if (glb.bMultiThreaded)
+ InitializeCriticalSection(&CriticalSection);
+#endif
+
+ // Context state is now initialized and ready
+ bContextReady = TRUE;
+}
+
+// ***********************************************************************
+
+void dglDeleteContextState()
+{
+ int i;
+ static BOOL bOnceIsEnough = FALSE;
+
+ // Only call once, from either DGL_exitDriver(), or DLL_PROCESS_DETACH
+ if (bOnceIsEnough)
+ return;
+ bOnceIsEnough = TRUE;
+
+ for (i=0; i<DGL_MAX_CONTEXTS; i++) {
+ if (ctxlist[i].bAllocated == TRUE) {
+ ddlogPrintf(DDLOG_WARN, "** Context %i not deleted - cleaning up.", (i+1));
+ dglDeleteContext((HGLRC)(i+1));
+ }
+ }
+
+ // Context state is no longer ready
+ bContextReady = FALSE;
+
+ // If executed when DLL unloads, DDraw objects may be invalid.
+ // So catch any page faults with this exception handler.
+__try {
+
+ // Release final DirectDraw interfaces
+ if (glb.bDirectDrawPersistant) {
+// RELEASE(glb.lpGlobalPalette);
+// RELEASE(glb.lpDepth4);
+// RELEASE(glb.lpBack4);
+// RELEASE(glb.lpPrimary4);
+// RELEASE(glb.lpDD4);
+ }
+}
+__except(EXCEPTION_EXECUTE_HANDLER) {
+ ddlogPrintf(DDLOG_WARN, "Exception raised in dglDeleteContextState.");
+}
+
+ // Destroy our event monitor window
+ if (hWndEvent) {
+ DestroyWindow(hWndEvent);
+ hWndEvent = hWndLastActive = NULL;
+ }
+
+#ifdef GLD_THREADS
+ // Destroy the critical section object
+ if (glb.bMultiThreaded)
+ DeleteCriticalSection(&CriticalSection);
+
+ // Release thread local storage indexes for current HGLRC and pixel format
+ TlsFree(dwTLSPixelFormat);
+ TlsFree(dwTLSCurrentContext);
+#endif
+}
+
+// ***********************************************************************
+
+// Application Window message handler interception
+static LONG __stdcall dglWndProc(
+ HWND hwnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ DGL_ctx* lpCtx = NULL;
+ LONG lpfnWndProc = 0L;
+ int i;
+ HGLRC hGLRC;
+ RECT rect;
+ PAINTSTRUCT ps;
+ BOOL bQuit = FALSE;
+ BOOL bMain = FALSE;
+ LONG rc;
+
+ // Get the window's message handler *before* it is unhooked in WM_DESTROY
+
+ // Is this the main window?
+ if (hwnd == glb.hWndActive) {
+ bMain = TRUE;
+ lpfnWndProc = glb.lpfnWndProc;
+ }
+ // Search for DGL context matching window handle
+ for (i=0; i<DGL_MAX_CONTEXTS; i++) {
+ if (ctxlist[i].hWnd == hwnd) {
+ lpCtx = &ctxlist[i];
+ lpfnWndProc = lpCtx->lpfnWndProc;
+ break;
+ }
+ }
+ // Not one of ours...
+ if (!lpfnWndProc)
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+
+ // Intercept messages amd process *before* passing on to window
+ switch (msg) {
+#ifdef _USE_GLD3_WGL
+ case WM_DISPLAYCHANGE:
+ glb.bPixelformatsDirty = TRUE;
+ break;
+#endif
+ case WM_ACTIVATEAPP:
+ glb.bAppActive = (BOOL)wParam;
+ ddlogPrintf(DDLOG_INFO, "Calling app has been %s", glb.bAppActive ? "activated" : "de-activated");
+ break;
+ case WM_ERASEBKGND:
+ // Eat the GDI erase event for the GL window
+ if (!lpCtx || !lpCtx->bHasBeenCurrent)
+ break;
+ lpCtx->bGDIEraseBkgnd = TRUE;
+ return TRUE;
+ case WM_PAINT:
+ // Eat the invalidated update region if render scene is in progress
+ if (!lpCtx || !lpCtx->bHasBeenCurrent)
+ break;
+ if (lpCtx->bFrameStarted) {
+ if (GetUpdateRect(hwnd, &rect, FALSE)) {
+ BeginPaint(hwnd, &ps);
+ EndPaint(hwnd, &ps);
+ ValidateRect(hwnd, &rect);
+ return TRUE;
+ }
+ }
+ break;
+ }
+ // Call the appropriate window message handler
+ rc = CallWindowProc((WNDPROC)lpfnWndProc, hwnd, msg, wParam, lParam);
+
+ // Intercept messages and process *after* passing on to window
+ switch (msg) {
+ case WM_QUIT:
+ case WM_DESTROY:
+ bQuit = TRUE;
+ if (lpCtx && lpCtx->bAllocated) {
+ ddlogPrintf(DDLOG_WARN, "WM_DESTROY detected for HWND=%X, HDC=%X, HGLRC=%d", hwnd, lpCtx->hDC, i+1);
+ dglDeleteContext((HGLRC)(i+1));
+ }
+ break;
+#if 0
+ case WM_SIZE:
+ // Resize surfaces to fit window but not viewport (in case app did not bother)
+ if (!lpCtx || !lpCtx->bHasBeenCurrent)
+ break;
+ w = LOWORD(lParam);
+ h = HIWORD(lParam);
+ if (lpCtx->dwWidth < w || lpCtx->dwHeight < h) {
+ if (!dglWglResizeBuffers(lpCtx->glCtx, TRUE))
+ dglWglResizeBuffers(lpCtx->glCtx, FALSE);
+ }
+ break;
+#endif
+ }
+
+ // If the main window is quitting, then so should we...
+ if (bMain && bQuit) {
+ ddlogPrintf(DDLOG_SYSTEM, "shutting down after WM_DESTROY detected for main HWND=%X", hwnd);
+ dglDeleteContextState();
+ dglExitDriver();
+ }
+
+ return rc;
+}
+
+// ***********************************************************************
+
+// Driver Window message handler
+static LONG __stdcall GLD_EventWndProc(
+ HWND hwnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ switch (msg) {
+ // May be sent by splash screen dialog on exit
+ case WM_ACTIVATE:
+ if (LOWORD(wParam) == WA_ACTIVE && glb.hWndActive) {
+ SetForegroundWindow(glb.hWndActive);
+ return 0;
+ }
+ break;
+ }
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+}
+
+// ***********************************************************************
+
+// Intercepted Keyboard handler for detecting hot keys.
+LRESULT CALLBACK dglKeyProc(
+ int code,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ HWND hWnd, hWndFrame;
+ HGLRC hGLRC = NULL;
+ DGL_ctx* lpCtx = NULL;
+ int cmd = 0, dx1 = 0, dx2 = 0, i;
+ static BOOL bAltPressed = FALSE;
+ static BOOL bCtrlPressed = FALSE;
+ static BOOL bShiftPressed = FALSE;
+ RECT r, rf, rc;
+ POINT pt;
+ BOOL bForceReshape = FALSE;
+
+ return CallNextHookEx(hKeyHook, code, wParam, lParam);
+}
+
+// ***********************************************************************
+
+HWND hWndMatch;
+
+// Window handle enumeration procedure.
+BOOL CALLBACK dglEnumChildProc(
+ HWND hWnd,
+ LPARAM lParam)
+{
+ RECT rect;
+
+ // Find window handle with matching client rect.
+ GetClientRect(hWnd, &rect);
+ if (EqualRect(&rect, (RECT*)lParam)) {
+ hWndMatch = hWnd;
+ return FALSE;
+ }
+ // Continue with next child window.
+ return TRUE;
+}
+
+// ***********************************************************************
+
+// Find window handle with matching client rect.
+HWND dglFindWindowRect(
+ RECT* pRect)
+{
+ hWndMatch = NULL;
+ EnumChildWindows(GetForegroundWindow(), dglEnumChildProc, (LPARAM)pRect);
+ return hWndMatch;
+}
+
+// ***********************************************************************
+#ifndef _USE_GLD3_WGL
+void dglChooseDisplayMode(
+ DGL_ctx *lpCtx)
+{
+ // Note: Choose an exact match if possible.
+
+ int i;
+ DWORD area;
+ DWORD bestarea;
+ DDSURFACEDESC2 *lpDDSD = NULL; // Mode list pointer
+ DDSURFACEDESC2 *lpBestDDSD = NULL; // Pointer to best
+
+ lpDDSD = glb.lpDisplayModes;
+ for (i=0; i<glb.nDisplayModeCount; i++, lpDDSD++) {
+ if ((lpDDSD->dwWidth == lpCtx->dwWidth) &&
+ (lpDDSD->dwHeight == lpCtx->dwHeight))
+ goto matched; // Mode has been exactly matched
+ // Choose modes that are larger in both dimensions than
+ // the window, but smaller in area than the current best.
+ if ( (lpDDSD->dwWidth >= lpCtx->dwWidth) &&
+ (lpDDSD->dwHeight >= lpCtx->dwHeight))
+ {
+ if (lpBestDDSD == NULL) {
+ lpBestDDSD = lpDDSD;
+ bestarea = lpDDSD->dwWidth * lpDDSD->dwHeight;
+ continue;
+ }
+ area = lpDDSD->dwWidth * lpDDSD->dwHeight;
+ if (area < bestarea) {
+ lpBestDDSD = lpDDSD;
+ bestarea = area;
+ }
+ }
+ }
+
+ // Safety check
+ if (lpBestDDSD == NULL) {
+ ddlogMessage(DDLOG_CRITICAL, "dglChooseDisplayMode");
+ return;
+ }
+
+ lpCtx->dwModeWidth = lpBestDDSD->dwWidth;
+ lpCtx->dwModeHeight = lpBestDDSD->dwHeight;
+matched:
+ ddlogPrintf(DDLOG_INFO, "Matched (%ldx%ld) to (%ldx%ld)",
+ lpCtx->dwWidth, lpCtx->dwHeight, lpCtx->dwModeWidth, lpCtx->dwModeHeight);
+}
+#endif // _USE_GLD3_WGL
+// ***********************************************************************
+
+static BOOL IsDevice(
+ DWORD *lpDeviceIdList,
+ DWORD dwDeviceId,
+ int count)
+{
+ int i;
+
+ for (i=0; i<count; i++)
+ if (dwDeviceId == lpDeviceIdList[i])
+ return TRUE;
+
+ return FALSE;
+}
+
+// ***********************************************************************
+
+void dglTestForBrokenCards(
+ DGL_ctx *lpCtx)
+{
+#ifndef _GLD3
+ DDDEVICEIDENTIFIER dddi; // DX6 device identifier
+
+ // Sanity check.
+ if (lpCtx == NULL) {
+ // Testing for broken cards is sensitive area, so we don't want
+ // anything saying "broken cards" in the error message. ;)
+ ddlogMessage(DDLOG_ERROR, "Null context passed to TFBC\n");
+ return;
+ }
+
+ if (lpCtx->lpDD4 == NULL) {
+ // Testing for broken cards is sensitive area, so we don't want
+ // anything saying "broken cards" in the error message. ;)
+ ddlogMessage(DDLOG_ERROR, "Null DD4 passed to TFBC\n");
+ return;
+ }
+
+ // Microsoft really fucked up with the GetDeviceIdentifier function
+ // on Windows 2000, since it locks up on stock driers on the CD. Updated
+ // drivers from vendors appear to work, but we can't identify the drivers
+ // without this function!!! For now we skip these tests on Windows 2000.
+ if ((GetVersion() & 0x80000000UL) == 0)
+ return;
+
+ // Obtain device info
+ if (FAILED(IDirectDraw4_GetDeviceIdentifier(lpCtx->lpDD4, &dddi, 0)))
+ return;
+
+ // Useful info. Log it.
+ ddlogPrintf(DDLOG_INFO, "DirectDraw: VendorId=0x%x, DeviceId=0x%x", dddi.dwVendorId, dddi.dwDeviceId);
+
+ // Vendor 1: ATI
+ if (dddi.dwVendorId == VENDORID_ATI) {
+ // Test A: ATI Rage PRO
+ if (IsDevice(devATIRagePro, dddi.dwDeviceId, sizeof(devATIRagePro)))
+ glb.bUseMipmaps = FALSE;
+ // Test B: ATI Rage II+
+ if (IsDevice(devATIRageIIplus, dddi.dwDeviceId, sizeof(devATIRageIIplus)))
+ glb.bEmulateAlphaTest = TRUE;
+ }
+
+ // Vendor 2: Matrox
+ if (dddi.dwVendorId == 0x102B) {
+ // Test: Matrox G400 stencil buffer support does not work for AutoCAD
+ if (dddi.dwDeviceId == 0x0525) {
+ lpCtx->lpPF->pfd.cStencilBits = 0;
+ if (lpCtx->lpPF->iZBufferPF != -1) {
+ glb.lpZBufferPF[lpCtx->lpPF->iZBufferPF].dwStencilBitDepth = 0;
+ glb.lpZBufferPF[lpCtx->lpPF->iZBufferPF].dwStencilBitMask = 0;
+ glb.lpZBufferPF[lpCtx->lpPF->iZBufferPF].dwFlags &= ~DDPF_STENCILBUFFER;
+ }
+ }
+ }
+#endif // _GLD3
+}
+
+// ***********************************************************************
+
+BOOL dglCreateContextBuffers(
+ HDC a,
+ DGL_ctx *lpCtx,
+ BOOL bFallback)
+{
+ HRESULT hResult;
+
+ int i;
+// HGLRC hGLRC;
+// DGL_ctx* lpCtx;
+
+#ifndef _USE_GLD3_WGL
+ DWORD dwFlags;
+ DDSURFACEDESC2 ddsd2;
+ DDSCAPS2 ddscaps2;
+ LPDIRECTDRAWCLIPPER lpddClipper;
+ D3DDEVICEDESC D3DHWDevDesc; // Direct3D Hardware description
+ D3DDEVICEDESC D3DHELDevDesc; // Direct3D Hardware Emulation Layer
+#endif // _USE_GLD3_WGL
+
+ float inv_aspect;
+
+ GLenum bDoubleBuffer; // TRUE if double buffer required
+ GLenum bDepthBuffer; // TRUE if depth buffer required
+
+ const PIXELFORMATDESCRIPTOR *lpPFD = &lpCtx->lpPF->pfd;
+
+ // Vars for Mesa visual
+ DWORD dwDepthBits = 0;
+ DWORD dwStencilBits = 0;
+ DWORD dwAlphaBits = 0;
+ DWORD bAlphaSW = GL_FALSE;
+ DWORD bDouble = GL_FALSE;
+
+ DDSURFACEDESC2 ddsd2DisplayMode;
+ BOOL bFullScrnWin = FALSE; // fullscreen-size window ?
+ DDBLTFX ddbltfx;
+ DWORD dwMemoryType = (bFallback) ? DDSCAPS_SYSTEMMEMORY : glb.dwMemoryType;
+ BOOL bBogusWindow = FALSE; // non-drawable window ?
+ DWORD dwColorRef = 0; // GDI background color
+ RECT rcDst; // GDI window rect
+ POINT pt; // GDI window point
+
+ // Palette used for creating default global palette
+ PALETTEENTRY ppe[256];
+
+#ifndef _USE_GLD3_WGL
+ // Vertex buffer description. Used for creation of vertex buffers
+ D3DVERTEXBUFFERDESC vbufdesc;
+#endif // _USE_GLD3_WGL
+
+#define DDLOG_CRITICAL_OR_WARN (bFallback ? DDLOG_CRITICAL : DDLOG_WARN)
+
+ ddlogPrintf(DDLOG_SYSTEM, "dglCreateContextBuffers for HDC=%X", a);
+ nContextError = GLDERR_NONE;
+
+#ifdef GLD_THREADS
+ // Serialize access to DirectDraw object creation or DDS start
+ if (glb.bMultiThreaded)
+ EnterCriticalSection(&CriticalSection);
+#endif
+
+ // Check for back buffer
+ bDoubleBuffer = GL_TRUE; //(lpPFD->dwFlags & PFD_DOUBLEBUFFER) ? GL_TRUE : GL_FALSE;
+ // Since we always do back buffering, check if we emulate front buffering
+ lpCtx->EmulateSingle =
+ (lpPFD->dwFlags & PFD_DOUBLEBUFFER) ? FALSE : TRUE;
+#if 0 // Don't have to mimic MS OpenGL behavior for front-buffering (DaveM)
+ lpCtx->EmulateSingle |=
+ (lpPFD->dwFlags & PFD_SUPPORT_GDI) ? TRUE : FALSE;
+#endif
+
+ // Check for depth buffer
+ bDepthBuffer = (lpPFD->cDepthBits) ? GL_TRUE : GL_FALSE;
+
+ lpCtx->bDoubleBuffer = bDoubleBuffer;
+ lpCtx->bDepthBuffer = bDepthBuffer;
+
+ // Set the Fullscreen flag for the context.
+// lpCtx->bFullscreen = glb.bFullscreen;
+
+ // Obtain the dimensions of the rendering window
+ lpCtx->hDC = a; // Cache DC
+ lpCtx->hWnd = WindowFromDC(lpCtx->hDC);
+ // Check for non-window DC = memory DC ?
+ if (lpCtx->hWnd == NULL) {
+ // bitmap memory contexts are always single-buffered
+ lpCtx->EmulateSingle = TRUE;
+ bBogusWindow = TRUE;
+ ddlogPrintf(DDLOG_INFO, "Non-Window Memory Device Context");
+ if (GetClipBox(lpCtx->hDC, &lpCtx->rcScreenRect) == ERROR) {
+ ddlogMessage(DDLOG_WARN, "GetClipBox failed in dglCreateContext\n");
+ SetRect(&lpCtx->rcScreenRect, 0, 0, 0, 0);
+ }
+ }
+ else if (!GetClientRect(lpCtx->hWnd, &lpCtx->rcScreenRect)) {
+ bBogusWindow = TRUE;
+ ddlogMessage(DDLOG_WARN, "GetClientRect failed in dglCreateContext\n");
+ SetRect(&lpCtx->rcScreenRect, 0, 0, 0, 0);
+ }
+ lpCtx->dwWidth = lpCtx->rcScreenRect.right - lpCtx->rcScreenRect.left;
+ lpCtx->dwHeight = lpCtx->rcScreenRect.bottom - lpCtx->rcScreenRect.top;
+
+ ddlogPrintf(DDLOG_INFO, "Input window %X: w=%i, h=%i",
+ lpCtx->hWnd, lpCtx->dwWidth, lpCtx->dwHeight);
+
+ // What if app only zeroes one dimension instead of both? (DaveM)
+ if ( (lpCtx->dwWidth == 0) || (lpCtx->dwHeight == 0) ) {
+ // Make the buffer size something sensible
+ lpCtx->dwWidth = 8;
+ lpCtx->dwHeight = 8;
+ }
+
+ // Set defaults
+ lpCtx->dwModeWidth = lpCtx->dwWidth;
+ lpCtx->dwModeHeight = lpCtx->dwHeight;
+/*
+ // Find best display mode for fullscreen
+ if (glb.bFullscreen || !glb.bPrimary) {
+ dglChooseDisplayMode(lpCtx);
+ }
+*/
+ // Misc initialisation
+ lpCtx->bCanRender = FALSE; // No rendering allowed yet
+ lpCtx->bSceneStarted = FALSE;
+ lpCtx->bFrameStarted = FALSE;
+
+ // Detect OS (specifically 'Windows 2000' or 'Windows XP')
+ DetectOS();
+
+ // NOTE: WinNT not supported
+ ddlogPrintf(DDLOG_INFO, "OS: %s", bHaveWin95 ? "Win9x" : (bHaveWin2K ? "Win2000/XP" : "Unsupported") );
+
+ // Test for Fullscreen
+ if (bHaveWin95) { // Problems with fullscreen on Win2K/XP
+ if ((GetSystemMetrics(SM_CXSCREEN) == lpCtx->dwWidth) &&
+ (GetSystemMetrics(SM_CYSCREEN) == lpCtx->dwHeight))
+ {
+ // Workaround for some apps that crash when going fullscreen.
+ //lpCtx->bFullscreen = TRUE;
+ }
+
+ }
+
+#ifdef _USE_GLD3_WGL
+ _gldDriver.CreateDrawable(lpCtx, glb.bDirectDrawPersistant, glb.bPersistantBuffers);
+#else
+ // Check if DirectDraw has already been created by original GLRC (DaveM)
+ if (glb.bDirectDrawPersistant && glb.bDirectDraw) {
+ lpCtx->lpDD4 = glb.lpDD4;
+ IDirectDraw4_AddRef(lpCtx->lpDD4);
+ goto SkipDirectDrawCreate;
+ }
+
+ // Create DirectDraw object
+ if (glb.bPrimary)
+ hResult = DirectDrawCreate(NULL, &lpCtx->lpDD1, NULL);
+ else {
+ // A non-primary device is to be used.
+ // Force context to be Fullscreen, secondary adaptors can not
+ // be used in a window.
+ hResult = DirectDrawCreate(&glb.ddGuid, &lpCtx->lpDD1, NULL);
+ lpCtx->bFullscreen = TRUE;
+ }
+ if (FAILED(hResult)) {
+ MessageBox(NULL, "Unable to initialize DirectDraw", "GLDirect", MB_OK);
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to create DirectDraw interface", hResult);
+ nContextError = GLDERR_DDRAW;
+ goto return_with_error;
+ }
+
+ // Query for DX6 IDirectDraw4.
+ hResult = IDirectDraw_QueryInterface(lpCtx->lpDD1,
+ &IID_IDirectDraw4,
+ (void**)&lpCtx->lpDD4);
+ if (FAILED(hResult)) {
+ MessageBox(NULL, "GLDirect requires DirectX 6.0 or above", "GLDirect", MB_OK);
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to create DirectDraw4 interface", hResult);
+ nContextError = GLDERR_DDRAW;
+ goto return_with_error;
+ }
+
+ // Cache DirectDraw interface for subsequent GLRCs
+ if (glb.bDirectDrawPersistant && !glb.bDirectDraw) {
+ glb.lpDD4 = lpCtx->lpDD4;
+ IDirectDraw4_AddRef(glb.lpDD4);
+ glb.bDirectDraw = TRUE;
+ }
+SkipDirectDrawCreate:
+
+ // Now we have a DD4 interface we can check for broken cards
+ dglTestForBrokenCards(lpCtx);
+
+ // Test if primary device can use flipping instead of blitting
+ ZeroMemory(&ddsd2DisplayMode, sizeof(ddsd2DisplayMode));
+ ddsd2DisplayMode.dwSize = sizeof(ddsd2DisplayMode);
+ hResult = IDirectDraw4_GetDisplayMode(
+ lpCtx->lpDD4,
+ &ddsd2DisplayMode);
+ if (SUCCEEDED(hResult)) {
+ if ( (lpCtx->dwWidth == ddsd2DisplayMode.dwWidth) &&
+ (lpCtx->dwHeight == ddsd2DisplayMode.dwHeight) ) {
+ // We have a fullscreen-size window
+ bFullScrnWin = TRUE;
+ // OK to use DirectDraw fullscreen mode ?
+ if (glb.bPrimary && !glb.bFullscreenBlit && !lpCtx->EmulateSingle && !glb.bDirectDrawPersistant) {
+ lpCtx->bFullscreen = TRUE;
+ ddlogMessage(DDLOG_INFO, "Primary upgraded to page flipping.\n");
+ }
+ }
+ // Cache the display mode dimensions
+ lpCtx->dwModeWidth = ddsd2DisplayMode.dwWidth;
+ lpCtx->dwModeHeight = ddsd2DisplayMode.dwHeight;
+ }
+
+ // Clamp the effective window dimensions to primary surface.
+ // We need to do this for D3D viewport dimensions even if wide
+ // surfaces are supported. This also is a good idea for handling
+ // whacked-out window dimensions passed for non-drawable windows
+ // like Solid Edge. (DaveM)
+ if (lpCtx->dwWidth > ddsd2DisplayMode.dwWidth)
+ lpCtx->dwWidth = ddsd2DisplayMode.dwWidth;
+ if (lpCtx->dwHeight > ddsd2DisplayMode.dwHeight)
+ lpCtx->dwHeight = ddsd2DisplayMode.dwHeight;
+
+ // Check for non-RGB desktop resolution
+ if (!lpCtx->bFullscreen && ddsd2DisplayMode.ddpfPixelFormat.dwRGBBitCount <= 8) {
+ ddlogPrintf(DDLOG_CRITICAL_OR_WARN, "Desktop color depth %d bpp not supported",
+ ddsd2DisplayMode.ddpfPixelFormat.dwRGBBitCount);
+ nContextError = GLDERR_BPP;
+ goto return_with_error;
+ }
+#endif // _USE_GLD3_WGL
+
+ ddlogPrintf(DDLOG_INFO, "Window: w=%i, h=%i (%s)",
+ lpCtx->dwWidth,
+ lpCtx->dwHeight,
+ lpCtx->bFullscreen ? "fullscreen" : "windowed");
+
+#ifndef _USE_GLD3_WGL
+ // Obtain ddraw caps
+ ZeroMemory(&lpCtx->ddCaps, sizeof(DDCAPS));
+ lpCtx->ddCaps.dwSize = sizeof(DDCAPS);
+ if (glb.bHardware) {
+ // Get HAL caps
+ IDirectDraw4_GetCaps(lpCtx->lpDD4, &lpCtx->ddCaps, NULL);
+ } else {
+ // Get HEL caps
+ IDirectDraw4_GetCaps(lpCtx->lpDD4, NULL, &lpCtx->ddCaps);
+ }
+
+ // If this flag is present then we can't default to Mesa
+ // SW rendering between BeginScene() and EndScene().
+ if (lpCtx->ddCaps.dwCaps2 & DDCAPS2_NO2DDURING3DSCENE) {
+ ddlogMessage(DDLOG_INFO,
+ "Warning : No 2D allowed during 3D scene.\n");
+ }
+
+ // Query for DX6 Direct3D3 interface
+ hResult = IDirectDraw4_QueryInterface(lpCtx->lpDD4,
+ &IID_IDirect3D3,
+ (void**)&lpCtx->lpD3D3);
+ if (FAILED(hResult)) {
+ MessageBox(NULL, "Unable to initialize Direct3D", "GLDirect", MB_OK);
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to create Direct3D interface", hResult);
+ nContextError = GLDERR_D3D;
+ goto return_with_error;
+ }
+
+ // Context creation
+ if (lpCtx->bFullscreen) {
+ // FULLSCREEN
+
+ // Disable warning popups when in fullscreen mode
+ ddlogWarnOption(FALSE);
+
+ // Have to release persistant primary surface if fullscreen mode
+ if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary) {
+ RELEASE(glb.lpPrimary4);
+ glb.bDirectDrawPrimary = FALSE;
+ }
+
+ dwFlags = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT;
+ if (glb.bFastFPU)
+ dwFlags |= DDSCL_FPUSETUP; // fast FPU setup optional (DaveM)
+ hResult = IDirectDraw4_SetCooperativeLevel(lpCtx->lpDD4, lpCtx->hWnd, dwFlags);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to set Exclusive Fullscreen mode", hResult);
+ goto return_with_error;
+ }
+
+ hResult = IDirectDraw4_SetDisplayMode(lpCtx->lpDD4,
+ lpCtx->dwModeWidth,
+ lpCtx->dwModeHeight,
+ lpPFD->cColorBits,
+ 0,
+ 0);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "SetDisplayMode failed", hResult);
+ goto return_with_error;
+ }
+
+ // ** The display mode has changed, so dont use MessageBox! **
+
+ ZeroMemory(&ddsd2, sizeof(ddsd2));
+ ddsd2.dwSize = sizeof(ddsd2);
+
+ if (bDoubleBuffer) {
+ // Double buffered
+ // Primary surface
+ ddsd2.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
+ DDSCAPS_FLIP |
+ DDSCAPS_COMPLEX |
+ DDSCAPS_3DDEVICE |
+ dwMemoryType;
+ ddsd2.dwBackBufferCount = 1;
+
+ hResult = IDirectDraw4_CreateSurface(lpCtx->lpDD4, &ddsd2, &lpCtx->lpFront4, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateSurface (primary) failed", hResult);
+ nContextError = GLDERR_MEM;
+ goto return_with_error;
+ }
+
+ // Render target surface
+ ZeroMemory(&ddscaps2, sizeof(ddscaps2)); // Clear the entire struct.
+ ddscaps2.dwCaps = DDSCAPS_BACKBUFFER;
+ hResult = IDirectDrawSurface4_GetAttachedSurface(lpCtx->lpFront4, &ddscaps2, &lpCtx->lpBack4);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "GetAttachedSurface failed", hResult);
+ nContextError = GLDERR_MEM;
+ goto return_with_error;
+ }
+ } else {
+ // Single buffered
+ // Primary surface
+ ddsd2.dwFlags = DDSD_CAPS;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
+ //DDSCAPS_3DDEVICE |
+ dwMemoryType;
+
+ hResult = IDirectDraw4_CreateSurface(lpCtx->lpDD4, &ddsd2, &lpCtx->lpFront4, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateSurface (primary) failed", hResult);
+ nContextError = GLDERR_MEM;
+ goto return_with_error;
+ }
+
+ lpCtx->lpBack4 = NULL;
+ }
+ } else {
+ // WINDOWED
+
+ // OK to enable warning popups in windowed mode
+ ddlogWarnOption(glb.bMessageBoxWarnings);
+
+ dwFlags = DDSCL_NORMAL;
+ if (glb.bMultiThreaded)
+ dwFlags |= DDSCL_MULTITHREADED;
+ if (glb.bFastFPU)
+ dwFlags |= DDSCL_FPUSETUP; // fast FPU setup optional (DaveM)
+ hResult = IDirectDraw4_SetCooperativeLevel(lpCtx->lpDD4,
+ lpCtx->hWnd,
+ dwFlags);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to set Normal coop level", hResult);
+ goto return_with_error;
+ }
+ // Has Primary surface already been created for original GLRC ?
+ // Note this can only be applicable for windowed modes
+ if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary) {
+ lpCtx->lpFront4 = glb.lpPrimary4;
+ IDirectDrawSurface4_AddRef(lpCtx->lpFront4);
+ // Update the window on the default clipper
+ IDirectDrawSurface4_GetClipper(lpCtx->lpFront4, &lpddClipper);
+ IDirectDrawClipper_SetHWnd(lpddClipper, 0, lpCtx->hWnd);
+ IDirectDrawClipper_Release(lpddClipper);
+ goto SkipPrimaryCreate;
+ }
+
+ // Primary surface
+ ZeroMemory(&ddsd2, sizeof(ddsd2));
+ ddsd2.dwSize = sizeof(ddsd2);
+ ddsd2.dwFlags = DDSD_CAPS;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+ hResult = IDirectDraw4_CreateSurface(lpCtx->lpDD4, &ddsd2, &lpCtx->lpFront4, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateSurface (primary) failed", hResult);
+ nContextError = GLDERR_MEM;
+ goto return_with_error;
+ }
+
+ // Cache Primary surface for subsequent GLRCs
+ // Note this can only be applicable to subsequent windowed modes
+ if (glb.bDirectDrawPersistant && !glb.bDirectDrawPrimary) {
+ glb.lpPrimary4 = lpCtx->lpFront4;
+ IDirectDrawSurface4_AddRef(glb.lpPrimary4);
+ glb.bDirectDrawPrimary = TRUE;
+ }
+
+ // Clipper object
+ hResult = DirectDrawCreateClipper(0, &lpddClipper, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateClipper failed", hResult);
+ goto return_with_error;
+ }
+ hResult = IDirectDrawClipper_SetHWnd(lpddClipper, 0, lpCtx->hWnd);
+ if (FAILED(hResult)) {
+ RELEASE(lpddClipper);
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "SetHWnd failed", hResult);
+ goto return_with_error;
+ }
+ hResult = IDirectDrawSurface4_SetClipper(lpCtx->lpFront4, lpddClipper);
+ RELEASE(lpddClipper); // We have finished with it.
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "SetClipper failed", hResult);
+ goto return_with_error;
+ }
+SkipPrimaryCreate:
+
+ if (bDoubleBuffer) {
+ // Render target surface
+ ZeroMemory(&ddsd2, sizeof(ddsd2));
+ ddsd2.dwSize = sizeof(ddsd2);
+ ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
+ ddsd2.dwWidth = lpCtx->dwWidth;
+ ddsd2.dwHeight = lpCtx->dwHeight;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_3DDEVICE |
+ DDSCAPS_OFFSCREENPLAIN |
+ dwMemoryType;
+
+ // Reserve the entire desktop size for persistant buffers option
+ if (glb.bDirectDrawPersistant && glb.bPersistantBuffers) {
+ ddsd2.dwWidth = ddsd2DisplayMode.dwWidth;
+ ddsd2.dwHeight = ddsd2DisplayMode.dwHeight;
+ }
+ // Re-use original back buffer if persistant buffers exist
+ if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && glb.lpBack4)
+ hResult = IDirectDrawSurface4_AddRef(lpCtx->lpBack4 = glb.lpBack4);
+ else
+ hResult = IDirectDraw4_CreateSurface(lpCtx->lpDD4, &ddsd2, &lpCtx->lpBack4, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "Create Backbuffer failed", hResult);
+ nContextError = GLDERR_MEM;
+ goto return_with_error;
+ }
+ if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && !glb.lpBack4)
+ IDirectDrawSurface4_AddRef(glb.lpBack4 = lpCtx->lpBack4);
+ } else {
+ lpCtx->lpBack4 = NULL;
+ }
+ }
+
+ //
+ // Now create the Z-buffer
+ //
+ lpCtx->bStencil = FALSE; // Default to no stencil buffer
+ if (bDepthBuffer && (lpCtx->lpPF->iZBufferPF != -1)) {
+ // Get z-buffer dimensions from the render target
+ // Setup the surface desc for the z-buffer.
+ ZeroMemory(&ddsd2, sizeof(ddsd2));
+ ddsd2.dwSize = sizeof(ddsd2);
+ ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | dwMemoryType;
+ ddsd2.dwWidth = lpCtx->dwWidth;
+ ddsd2.dwHeight = lpCtx->dwHeight;
+ memcpy(&ddsd2.ddpfPixelFormat,
+ &glb.lpZBufferPF[lpCtx->lpPF->iZBufferPF],
+ sizeof(DDPIXELFORMAT) );
+
+ // Reserve the entire desktop size for persistant buffers option
+ if (glb.bDirectDrawPersistant && glb.bPersistantBuffers) {
+ ddsd2.dwWidth = ddsd2DisplayMode.dwWidth;
+ ddsd2.dwHeight = ddsd2DisplayMode.dwHeight;
+ }
+
+ // Create a z-buffer
+ if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && glb.lpDepth4)
+ hResult = IDirectDrawSurface4_AddRef(lpCtx->lpDepth4 = glb.lpDepth4);
+ else
+ hResult = IDirectDraw4_CreateSurface(lpCtx->lpDD4, &ddsd2, &lpCtx->lpDepth4, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateSurface (ZBuffer) failed", hResult);
+ nContextError = GLDERR_MEM;
+ goto return_with_error;
+ }
+ if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && !glb.lpDepth4)
+ IDirectDrawSurface4_AddRef(glb.lpDepth4 = lpCtx->lpDepth4);
+ else if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && glb.lpDepth4 && glb.lpBack4)
+ IDirectDrawSurface4_DeleteAttachedSurface(glb.lpBack4, 0, glb.lpDepth4);
+
+ // Attach Zbuffer to render target
+ TRY(IDirectDrawSurface4_AddAttachedSurface(
+ bDoubleBuffer ? lpCtx->lpBack4 : lpCtx->lpFront4,
+ lpCtx->lpDepth4),
+ "dglCreateContext: Attach Zbuffer");
+ if (glb.lpZBufferPF[lpCtx->lpPF->iZBufferPF].dwFlags & DDPF_STENCILBUFFER) {
+ lpCtx->bStencil = TRUE;
+ ddlogMessage(DDLOG_INFO, "Depth buffer has stencil\n");
+ }
+ }
+
+ // Clear all back buffers and Z-buffers in case of memory recycling.
+ ZeroMemory(&ddbltfx, sizeof(ddbltfx));
+ ddbltfx.dwSize = sizeof(ddbltfx);
+ IDirectDrawSurface4_Blt(lpCtx->lpBack4, NULL, NULL, NULL,
+ DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
+ if (lpCtx->lpDepth4)
+ IDirectDrawSurface4_Blt(lpCtx->lpDepth4, NULL, NULL, NULL,
+ DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
+
+ // Now that we have a Z-buffer we can create the 3D device
+ hResult = IDirect3D3_CreateDevice(lpCtx->lpD3D3,
+ &glb.d3dGuid,
+ bDoubleBuffer ? lpCtx->lpBack4 : lpCtx->lpFront4,
+ &lpCtx->lpDev3,
+ NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to create Direct3D device", hResult);
+ nContextError = GLDERR_D3D;
+ goto return_with_error;
+ }
+
+ // We must do this as soon as the device is created
+ dglInitStateCaches(lpCtx);
+
+ // Obtain the D3D Device Description
+ D3DHWDevDesc.dwSize = D3DHELDevDesc.dwSize = sizeof(D3DDEVICEDESC);
+ TRY(IDirect3DDevice3_GetCaps(lpCtx->lpDev3,
+ &D3DHWDevDesc,
+ &D3DHELDevDesc),
+ "dglCreateContext: GetCaps failed");
+
+ // Choose the relevant description and cache it in the context.
+ // We will use this description later for caps checking
+ memcpy( &lpCtx->D3DDevDesc,
+ glb.bHardware ? &D3DHWDevDesc : &D3DHELDevDesc,
+ sizeof(D3DDEVICEDESC));
+
+ // Now we can examine the texture formats
+ if (!dglBuildTextureFormatList(lpCtx->lpDev3)) {
+ ddlogMessage(DDLOG_CRITICAL_OR_WARN, "dglBuildTextureFormatList failed\n");
+ goto return_with_error;
+ }
+
+ // Get the pixel format of the back buffer
+ lpCtx->ddpfRender.dwSize = sizeof(lpCtx->ddpfRender);
+ if (bDoubleBuffer)
+ hResult = IDirectDrawSurface4_GetPixelFormat(
+ lpCtx->lpBack4,
+ &lpCtx->ddpfRender);
+ else
+ hResult = IDirectDrawSurface4_GetPixelFormat(
+ lpCtx->lpFront4,
+ &lpCtx->ddpfRender);
+
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "GetPixelFormat failed", hResult);
+ goto return_with_error;
+ }
+ // Find a pixel packing function suitable for this surface
+ pxClassifyPixelFormat(&lpCtx->ddpfRender,
+ &lpCtx->fnPackFunc,
+ &lpCtx->fnUnpackFunc,
+ &lpCtx->fnPackSpanFunc);
+
+ // Viewport
+ hResult = IDirect3D3_CreateViewport(lpCtx->lpD3D3, &lpCtx->lpViewport3, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateViewport failed", hResult);
+ goto return_with_error;
+ }
+
+ hResult = IDirect3DDevice3_AddViewport(lpCtx->lpDev3, lpCtx->lpViewport3);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "AddViewport failed", hResult);
+ goto return_with_error;
+ }
+
+ // Initialise the viewport
+ // Note screen coordinates are used for viewport clipping since D3D
+ // transform operations are not used in the GLD CAD driver. (DaveM)
+ inv_aspect = (float)lpCtx->dwHeight/(float)lpCtx->dwWidth;
+
+ lpCtx->d3dViewport.dwSize = sizeof(lpCtx->d3dViewport);
+ lpCtx->d3dViewport.dwX = 0;
+ lpCtx->d3dViewport.dwY = 0;
+ lpCtx->d3dViewport.dwWidth = lpCtx->dwWidth;
+ lpCtx->d3dViewport.dwHeight = lpCtx->dwHeight;
+ lpCtx->d3dViewport.dvClipX = 0; // -1.0f;
+ lpCtx->d3dViewport.dvClipY = 0; // inv_aspect;
+ lpCtx->d3dViewport.dvClipWidth = lpCtx->dwWidth; // 2.0f;
+ lpCtx->d3dViewport.dvClipHeight = lpCtx->dwHeight; // 2.0f * inv_aspect;
+ lpCtx->d3dViewport.dvMinZ = 0.0f;
+ lpCtx->d3dViewport.dvMaxZ = 1.0f;
+ TRY(IDirect3DViewport3_SetViewport2(lpCtx->lpViewport3, &lpCtx->d3dViewport), "dglCreateContext: SetViewport2");
+
+ hResult = IDirect3DDevice3_SetCurrentViewport(lpCtx->lpDev3, lpCtx->lpViewport3);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "SetCurrentViewport failed", hResult);
+ goto return_with_error;
+ }
+
+ lpCtx->dwBPP = lpPFD->cColorBits;
+ lpCtx->iZBufferPF = lpCtx->lpPF->iZBufferPF;
+
+ // Set last texture to NULL
+ for (i=0; i<MAX_TEXTURE_UNITS; i++) {
+ lpCtx->ColorOp[i] = D3DTOP_DISABLE;
+ lpCtx->AlphaOp[i] = D3DTOP_DISABLE;
+ lpCtx->tObj[i] = NULL;
+ }
+
+ // Default to perspective correct texture mapping
+ dglSetRenderState(lpCtx, D3DRENDERSTATE_TEXTUREPERSPECTIVE, TRUE, "TexturePersp");
+
+ // Set the default culling mode
+ lpCtx->cullmode = D3DCULL_NONE;
+ dglSetRenderState(lpCtx, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE, "CullMode");
+
+ // Disable specular
+ dglSetRenderState(lpCtx, D3DRENDERSTATE_SPECULARENABLE, FALSE, "SpecularEnable");
+ // Disable subpixel correction
+// dglSetRenderState(lpCtx, D3DRENDERSTATE_SUBPIXEL, FALSE, "SubpixelEnable");
+ // Disable dithering
+ dglSetRenderState(lpCtx, D3DRENDERSTATE_DITHERENABLE, FALSE, "DitherEnable");
+
+ // Initialise the primitive caches
+// lpCtx->dwNextLineVert = 0;
+// lpCtx->dwNextTriVert = 0;
+
+ // Init the global texture palette
+ lpCtx->lpGlobalPalette = NULL;
+
+ // Init the HW/SW usage counters
+// lpCtx->dwHWUsageCount = lpCtx->dwSWUsageCount = 0L;
+
+ //
+ // Create two D3D vertex buffers.
+ // One will hold the pre-transformed data with the other one
+ // being used to hold the post-transformed & clipped verts.
+ //
+#if 0 // never used (DaveM)
+ vbufdesc.dwSize = sizeof(D3DVERTEXBUFFERDESC);
+ vbufdesc.dwCaps = D3DVBCAPS_WRITEONLY;
+ if (glb.bHardware == FALSE)
+ vbufdesc.dwCaps = D3DVBCAPS_SYSTEMMEMORY;
+ vbufdesc.dwNumVertices = 32768; // For the time being
+
+ // Source vertex buffer
+ vbufdesc.dwFVF = DGL_LVERTEX;
+ hResult = IDirect3D3_CreateVertexBuffer(lpCtx->lpD3D3, &vbufdesc, &lpCtx->m_vbuf, 0, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateVertexBuffer(src) failed", hResult);
+ goto return_with_error;
+ }
+
+ // Destination vertex buffer
+ vbufdesc.dwFVF = (glb.bMultitexture == FALSE) ? D3DFVF_TLVERTEX : (D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX2);
+ hResult = IDirect3D3_CreateVertexBuffer(lpCtx->lpD3D3, &vbufdesc, &lpCtx->m_pvbuf, 0, NULL);
+ if(FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateVertexBuffer(dst) failed", hResult);
+ goto return_with_error;
+ }
+#endif
+
+#endif _USE_GLD3_WGL
+
+ //
+ // Now create the Mesa context
+ //
+
+ // Create the Mesa visual
+ if (lpPFD->cDepthBits)
+ dwDepthBits = 16;
+ if (lpPFD->cStencilBits)
+ dwStencilBits = 8;
+ if (lpPFD->cAlphaBits) {
+ dwAlphaBits = 8;
+ bAlphaSW = GL_TRUE;
+ }
+ if (lpPFD->dwFlags & PFD_DOUBLEBUFFER)
+ bDouble = GL_TRUE;
+// lpCtx->EmulateSingle =
+// (lpPFD->dwFlags & PFD_DOUBLEBUFFER) ? FALSE : TRUE;
+
+#ifdef _USE_GLD3_WGL
+ lpCtx->glVis = _mesa_create_visual(
+ bDouble, /* double buffer */
+ GL_FALSE, // stereo
+ lpPFD->cRedBits,
+ lpPFD->cGreenBits,
+ lpPFD->cBlueBits,
+ dwAlphaBits,
+ dwDepthBits,
+ dwStencilBits,
+ lpPFD->cAccumRedBits, // accum bits
+ lpPFD->cAccumGreenBits, // accum bits
+ lpPFD->cAccumBlueBits, // accum bits
+ lpPFD->cAccumAlphaBits, // accum alpha bits
+ 1 // num samples
+ );
+#else // _USE_GLD3_WGL
+ lpCtx->glVis = (*mesaFuncs.gl_create_visual)(
+ GL_TRUE, // RGB mode
+ bAlphaSW, // Is an alpha buffer required?
+ bDouble, // Is an double-buffering required?
+ GL_FALSE, // stereo
+ dwDepthBits, // depth_size
+ dwStencilBits, // stencil_size
+ lpPFD->cAccumBits, // accum_size
+ 0, // colour-index bits
+ lpPFD->cRedBits, // Red bit count
+ lpPFD->cGreenBits, // Green bit count
+ lpPFD->cBlueBits, // Blue bit count
+ dwAlphaBits // Alpha bit count
+ );
+#endif // _USE_GLD3_WGL
+
+ if (lpCtx->glVis == NULL) {
+ ddlogMessage(DDLOG_CRITICAL_OR_WARN, "gl_create_visual failed\n");
+ goto return_with_error;
+ }
+
+#ifdef _USE_GLD3_WGL
+ lpCtx->glCtx = _mesa_create_context(lpCtx->glVis, NULL, (void *)lpCtx, GL_TRUE);
+#else
+ // Create the Mesa context
+ lpCtx->glCtx = (*mesaFuncs.gl_create_context)(
+ lpCtx->glVis, // Mesa visual
+ NULL, // share list context
+ (void *)lpCtx, // Pointer to our driver context
+ GL_TRUE // Direct context flag
+ );
+#endif // _USE_GLD3_WGL
+
+ if (lpCtx->glCtx == NULL) {
+ ddlogMessage(DDLOG_CRITICAL_OR_WARN, "gl_create_context failed\n");
+ goto return_with_error;
+ }
+
+ // Create the Mesa framebuffer
+#ifdef _USE_GLD3_WGL
+ lpCtx->glBuffer = _mesa_create_framebuffer(
+ lpCtx->glVis,
+ lpCtx->glVis->depthBits > 0,
+ lpCtx->glVis->stencilBits > 0,
+ lpCtx->glVis->accumRedBits > 0,
+ GL_FALSE //swalpha
+ );
+#else
+ lpCtx->glBuffer = (*mesaFuncs.gl_create_framebuffer)(lpCtx->glVis);
+#endif // _USE_GLD3_WGL
+
+ if (lpCtx->glBuffer == NULL) {
+ ddlogMessage(DDLOG_CRITICAL_OR_WARN, "gl_create_framebuffer failed\n");
+ goto return_with_error;
+ }
+
+#ifdef _USE_GLD3_WGL
+ // Init Mesa internals
+ _swrast_CreateContext( lpCtx->glCtx );
+ _vbo_CreateContext( lpCtx->glCtx );
+ _tnl_CreateContext( lpCtx->glCtx );
+ _swsetup_CreateContext( lpCtx->glCtx );
+
+ _gldDriver.InitialiseMesa(lpCtx);
+
+ lpCtx->glCtx->imports.warning = _gld_mesa_warning;
+ lpCtx->glCtx->imports.fatal = _gld_mesa_fatal;
+
+#else
+ // Tell Mesa how many texture stages we have
+ glb.wMaxSimultaneousTextures = lpCtx->D3DDevDesc.wMaxSimultaneousTextures;
+ // Only use as many Units as the spec requires
+ if (glb.wMaxSimultaneousTextures > MAX_TEXTURE_UNITS)
+ glb.wMaxSimultaneousTextures = MAX_TEXTURE_UNITS;
+ lpCtx->glCtx->Const.MaxTextureUnits = glb.wMaxSimultaneousTextures;
+ ddlogPrintf(DDLOG_INFO, "Texture stages : %d", glb.wMaxSimultaneousTextures);
+
+ // Set the max texture size.
+ // NOTE: clamped to a max of 1024 for extra performance!
+ lpCtx->dwMaxTextureSize = (lpCtx->D3DDevDesc.dwMaxTextureWidth <= 1024) ? lpCtx->D3DDevDesc.dwMaxTextureWidth : 1024;
+
+// Texture resize takes place elsewhere. KH
+// NOTE: This was added to workaround an issue with the Intel app.
+#if 0
+ lpCtx->glCtx->Const.MaxTextureSize = lpCtx->dwMaxTextureSize;
+#else
+ lpCtx->glCtx->Const.MaxTextureSize = 1024;
+#endif
+ lpCtx->glCtx->Const.MaxDrawBuffers = 1;
+
+ // Setup the Display Driver pointers
+ dglSetupDDPointers(lpCtx->glCtx);
+
+ // Initialise all the Direct3D renderstates
+ dglInitStateD3D(lpCtx->glCtx);
+
+#if 0
+ // Signal a reload of texture state on next glBegin
+ lpCtx->m_texHandleValid = FALSE;
+ lpCtx->m_mtex = FALSE;
+ lpCtx->m_texturing = FALSE;
+#else
+ // Set default texture unit state
+// dglSetTexture(lpCtx, 0, NULL);
+// dglSetTexture(lpCtx, 1, NULL);
+#endif
+
+ //
+ // Set the global texture palette to default values.
+ //
+
+ // Clear the entire palette
+ ZeroMemory(ppe, sizeof(PALETTEENTRY) * 256);
+
+ // Fill the palette with a default colour.
+ // A garish colour is used to catch bugs. Here Magenta is used.
+ for (i=0; i < 256; i++) {
+ ppe[i].peRed = 255;
+ ppe[i].peGreen = 0;
+ ppe[i].peBlue = 255;
+ }
+
+ RELEASE(lpCtx->lpGlobalPalette);
+
+ if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && glb.lpGlobalPalette)
+ hResult = IDirectDrawPalette_AddRef(lpCtx->lpGlobalPalette = glb.lpGlobalPalette);
+ else
+ hResult = IDirectDraw4_CreatePalette(
+ lpCtx->lpDD4,
+ DDPCAPS_INITIALIZE | DDPCAPS_8BIT | DDPCAPS_ALLOW256,
+ ppe,
+ &(lpCtx->lpGlobalPalette),
+ NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_ERROR, "Default CreatePalette failed\n", hResult);
+ lpCtx->lpGlobalPalette = NULL;
+ goto return_with_error;
+ }
+ if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && !glb.lpGlobalPalette)
+ IDirectDrawPalette_AddRef(glb.lpGlobalPalette = lpCtx->lpGlobalPalette);
+
+#endif // _USE_GLD3_WGL
+
+ // ** If we have made it to here then we can enable rendering **
+ lpCtx->bCanRender = TRUE;
+
+// ddlogMessage(DDLOG_SYSTEM, "dglCreateContextBuffers succeded\n");
+
+#ifdef GLD_THREADS
+ // Release serialized access
+ if (glb.bMultiThreaded)
+ LeaveCriticalSection(&CriticalSection);
+#endif
+
+ return TRUE;
+
+return_with_error:
+ // Clean up before returning.
+ // This is critical for secondary devices.
+
+ lpCtx->bCanRender = FALSE;
+
+#ifdef _USE_GLD3_WGL
+ // Destroy the Mesa context
+ if (lpCtx->glBuffer)
+ _mesa_destroy_framebuffer(lpCtx->glBuffer);
+ if (lpCtx->glCtx)
+ _mesa_destroy_context(lpCtx->glCtx);
+ if (lpCtx->glVis)
+ _mesa_destroy_visual(lpCtx->glVis);
+
+ // Destroy driver data
+ _gldDriver.DestroyDrawable(lpCtx);
+#else
+ // Destroy the Mesa context
+ if (lpCtx->glBuffer)
+ (*mesaFuncs.gl_destroy_framebuffer)(lpCtx->glBuffer);
+ if (lpCtx->glCtx)
+ (*mesaFuncs.gl_destroy_context)(lpCtx->glCtx);
+ if (lpCtx->glVis)
+ (*mesaFuncs.gl_destroy_visual)(lpCtx->glVis);
+
+ RELEASE(lpCtx->m_pvbuf); // Release D3D vertex buffer
+ RELEASE(lpCtx->m_vbuf); // Release D3D vertex buffer
+
+ if (lpCtx->lpViewport3) {
+ if (lpCtx->lpDev3) IDirect3DDevice3_DeleteViewport(lpCtx->lpDev3, lpCtx->lpViewport3);
+ RELEASE(lpCtx->lpViewport3);
+ lpCtx->lpViewport3 = NULL;
+ }
+
+ RELEASE(lpCtx->lpDev3);
+ if (lpCtx->lpDepth4) {
+ if (lpCtx->lpBack4)
+ IDirectDrawSurface4_DeleteAttachedSurface(lpCtx->lpBack4, 0L, lpCtx->lpDepth4);
+ else
+ IDirectDrawSurface4_DeleteAttachedSurface(lpCtx->lpFront4, 0L, lpCtx->lpDepth4);
+ RELEASE(lpCtx->lpDepth4);
+ lpCtx->lpDepth4 = NULL;
+ }
+ RELEASE(lpCtx->lpBack4);
+ RELEASE(lpCtx->lpFront4);
+ else
+ if (lpCtx->bFullscreen) {
+ IDirectDraw4_RestoreDisplayMode(lpCtx->lpDD4);
+ IDirectDraw4_SetCooperativeLevel(lpCtx->lpDD4, NULL, DDSCL_NORMAL);
+ }
+ RELEASE(lpCtx->lpD3D3);
+ RELEASE(lpCtx->lpDD4);
+ RELEASE(lpCtx->lpDD1);
+#endif // _USE_GLD3_WGL
+
+ lpCtx->bAllocated = FALSE;
+
+#ifdef GLD_THREADS
+ // Release serialized access
+ if (glb.bMultiThreaded)
+ LeaveCriticalSection(&CriticalSection);
+#endif
+
+ return FALSE;
+
+#undef DDLOG_CRITICAL_OR_WARN
+}
+
+// ***********************************************************************
+
+HGLRC dglCreateContext(
+ HDC a,
+ const DGL_pixelFormat *lpPF)
+{
+ int i;
+ HGLRC hGLRC;
+ DGL_ctx* lpCtx;
+ static BOOL bWarnOnce = TRUE;
+ DWORD dwThreadId = GetCurrentThreadId();
+ char szMsg[256];
+ HWND hWnd;
+ LONG lpfnWndProc;
+
+ // Validate license
+ if (!dglValidate())
+ return NULL;
+
+ // Is context state ready ?
+ if (!bContextReady)
+ return NULL;
+
+ ddlogPrintf(DDLOG_SYSTEM, "dglCreateContext for HDC=%X, ThreadId=%X", a, dwThreadId);
+
+ // Find next free context.
+ // Also ensure that only one Fullscreen context is created at any one time.
+ hGLRC = 0; // Default to Not Found
+ for (i=0; i<DGL_MAX_CONTEXTS; i++) {
+ if (ctxlist[i].bAllocated) {
+ if (/*glb.bFullscreen && */ctxlist[i].bFullscreen)
+ break;
+ } else {
+ hGLRC = (HGLRC)(i+1);
+ break;
+ }
+ }
+
+ // Bail if no GLRC was found
+ if (!hGLRC)
+ return NULL;
+
+ // Set the context pointer
+ lpCtx = dglGetContextAddress(hGLRC);
+ // Make sure that context is zeroed before we do anything.
+ // MFC and C++ apps call wglCreateContext() and wglDeleteContext() multiple times,
+ // even though only one context is ever used by the app, so keep it clean. (DaveM)
+ ZeroMemory(lpCtx, sizeof(DGL_ctx));
+ lpCtx->bAllocated = TRUE;
+ // Flag that buffers need creating on next wglMakeCurrent call.
+ lpCtx->bHasBeenCurrent = FALSE;
+ lpCtx->lpPF = (DGL_pixelFormat *)lpPF; // cache pixel format
+ lpCtx->bCanRender = FALSE;
+
+ // Create all the internal resources here, not in dglMakeCurrent().
+ // We do a re-size check in dglMakeCurrent in case of re-allocations. (DaveM)
+ // We now try context allocations twice, first with video memory,
+ // then again with system memory. This is similar to technique
+ // used for dglWglResizeBuffers(). (DaveM)
+ if (lpCtx->bHasBeenCurrent == FALSE) {
+ if (!dglCreateContextBuffers(a, lpCtx, FALSE)) {
+ if (glb.bMessageBoxWarnings && bWarnOnce && dwLogging) {
+ bWarnOnce = FALSE;
+ switch (nContextError) {
+ case GLDERR_DDRAW: strcpy(szMsg, szDDrawWarning); break;
+ case GLDERR_D3D: strcpy(szMsg, szD3DWarning); break;
+ case GLDERR_MEM: strcpy(szMsg, szResourceWarning); break;
+ case GLDERR_BPP: strcpy(szMsg, szBPPWarning); break;
+ default: strcpy(szMsg, "");
+ }
+ if (strlen(szMsg))
+ MessageBox(NULL, szMsg, "GLDirect", MB_OK | MB_ICONWARNING);
+ }
+ // Only need to try again if memory error
+ if (nContextError == GLDERR_MEM) {
+ ddlogPrintf(DDLOG_WARN, "dglCreateContext failed 1st time with video memory");
+ }
+ else {
+ ddlogPrintf(DDLOG_ERROR, "dglCreateContext failed");
+ return NULL;
+ }
+ }
+ }
+
+ // Now that we have a hWnd, we can intercept the WindowProc.
+ hWnd = lpCtx->hWnd;
+ if (hWnd) {
+ // Only hook individual window handler once if not hooked before.
+ lpfnWndProc = GetWindowLong(hWnd, GWL_WNDPROC);
+ if (lpfnWndProc != (LONG)dglWndProc) {
+ lpCtx->lpfnWndProc = lpfnWndProc;
+ SetWindowLong(hWnd, GWL_WNDPROC, (LONG)dglWndProc);
+ }
+ // Find the parent window of the app too.
+ if (glb.hWndActive == NULL) {
+ while (hWnd != NULL) {
+ glb.hWndActive = hWnd;
+ hWnd = GetParent(hWnd);
+ }
+ // Hook the parent window too.
+ lpfnWndProc = GetWindowLong(glb.hWndActive, GWL_WNDPROC);
+ if (glb.hWndActive == lpCtx->hWnd)
+ glb.lpfnWndProc = lpCtx->lpfnWndProc;
+ else if (lpfnWndProc != (LONG)dglWndProc)
+ glb.lpfnWndProc = lpfnWndProc;
+ if (glb.lpfnWndProc)
+ SetWindowLong(glb.hWndActive, GWL_WNDPROC, (LONG)dglWndProc);
+ }
+ }
+
+ ddlogPrintf(DDLOG_SYSTEM, "dglCreateContext succeeded for HGLRC=%d", (int)hGLRC);
+
+ return hGLRC;
+}
+
+// ***********************************************************************
+// Make a DirectGL context current
+// Used by wgl functions and dgl functions
+BOOL dglMakeCurrent(
+ HDC a,
+ HGLRC b)
+{
+ int context;
+ DGL_ctx* lpCtx;
+ HWND hWnd;
+ BOOL bNeedResize = FALSE;
+ BOOL bWindowChanged, bContextChanged;
+ LPDIRECTDRAWCLIPPER lpddClipper;
+ DWORD dwThreadId = GetCurrentThreadId();
+ LONG lpfnWndProc;
+
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ // Is context state ready ?
+ if (!bContextReady)
+ return FALSE;
+
+ context = (int)b; // This is as a result of STRICT!
+ ddlogPrintf(DDLOG_SYSTEM, "dglMakeCurrent: HDC=%X, HGLRC=%d, ThreadId=%X", a, context, dwThreadId);
+
+ // If the HGLRC is NULL then make no context current;
+ // Ditto if the HDC is NULL either. (DaveM)
+ if (context == 0 || a == 0) {
+ // Corresponding Mesa operation
+#ifdef _USE_GLD3_WGL
+ _mesa_make_current(NULL, NULL);
+#else
+ (*mesaFuncs.gl_make_current)(NULL, NULL);
+#endif
+ dglSetCurrentContext(0);
+ return TRUE;
+ }
+
+ // Make sure the HGLRC is in range
+ if ((context > DGL_MAX_CONTEXTS) || (context < 0)) {
+ ddlogMessage(DDLOG_ERROR, "dglMakeCurrent: HGLRC out of range\n");
+ return FALSE;
+ }
+
+ // Find address of context and make sure that it has been allocated
+ lpCtx = dglGetContextAddress(b);
+ if (!lpCtx->bAllocated) {
+ ddlogMessage(DDLOG_ERROR, "dglMakeCurrent: Context not allocated\n");
+// return FALSE;
+ return TRUE; // HACK: Shuts up "WebLab Viewer Pro". KeithH
+ }
+
+#ifdef GLD_THREADS
+ // Serialize access to DirectDraw or DDS operations
+ if (glb.bMultiThreaded)
+ EnterCriticalSection(&CriticalSection);
+#endif
+
+ // Check if window has changed
+ hWnd = (a != lpCtx->hDC) ? WindowFromDC(a) : lpCtx->hWnd;
+ bWindowChanged = (hWnd != lpCtx->hWnd) ? TRUE : FALSE;
+ bContextChanged = (b != dglGetCurrentContext()) ? TRUE : FALSE;
+
+ // If the window has changed, make sure the clipper is updated. (DaveM)
+ if (glb.bDirectDrawPersistant && !lpCtx->bFullscreen && (bWindowChanged || bContextChanged)) {
+ lpCtx->hWnd = hWnd;
+#ifndef _USE_GLD3_WGL
+ IDirectDrawSurface4_GetClipper(lpCtx->lpFront4, &lpddClipper);
+ IDirectDrawClipper_SetHWnd(lpddClipper, 0, lpCtx->hWnd);
+ IDirectDrawClipper_Release(lpddClipper);
+#endif // _USE_GLD3_WGL
+ }
+
+ // Make sure hDC and hWnd is current. (DaveM)
+ // Obtain the dimensions of the rendering window
+ lpCtx->hDC = a; // Cache DC
+ lpCtx->hWnd = hWnd;
+ hWndLastActive = hWnd;
+
+ // Check for non-window DC = memory DC ?
+ if (hWnd == NULL) {
+ if (GetClipBox(a, &lpCtx->rcScreenRect) == ERROR) {
+ ddlogMessage(DDLOG_WARN, "GetClipBox failed in dglMakeCurrent\n");
+ SetRect(&lpCtx->rcScreenRect, 0, 0, 0, 0);
+ }
+ }
+ else if (!GetClientRect(lpCtx->hWnd, &lpCtx->rcScreenRect)) {
+ ddlogMessage(DDLOG_WARN, "GetClientRect failed in dglMakeCurrent\n");
+ SetRect(&lpCtx->rcScreenRect, 0, 0, 0, 0);
+ }
+ // Check if buffers need to be re-sized;
+ // If so, wait until Mesa GL stuff is setup before re-sizing;
+ if (lpCtx->dwWidth != lpCtx->rcScreenRect.right - lpCtx->rcScreenRect.left ||
+ lpCtx->dwHeight != lpCtx->rcScreenRect.bottom - lpCtx->rcScreenRect.top)
+ bNeedResize = TRUE;
+
+ // Now we can update our globals
+ dglSetCurrentContext(b);
+
+ // Corresponding Mesa operation
+#ifdef _USE_GLD3_WGL
+ _mesa_make_current(lpCtx->glCtx, lpCtx->glBuffer);
+ lpCtx->glCtx->Driver.UpdateState(lpCtx->glCtx, _NEW_ALL);
+ if (bNeedResize) {
+ // Resize buffers (Note Mesa GL needs to be setup beforehand);
+ // Resize Mesa internal buffer too via glViewport() command,
+ // which subsequently calls dglWglResizeBuffers() too.
+ lpCtx->glCtx->Driver.Viewport(lpCtx->glCtx, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
+ lpCtx->bHasBeenCurrent = TRUE;
+ }
+#else
+ (*mesaFuncs.gl_make_current)(lpCtx->glCtx, lpCtx->glBuffer);
+
+ dglSetupDDPointers(lpCtx->glCtx);
+
+ // Insure DirectDraw surfaces fit current window DC
+ if (bNeedResize) {
+ // Resize buffers (Note Mesa GL needs to be setup beforehand);
+ // Resize Mesa internal buffer too via glViewport() command,
+ // which subsequently calls dglWglResizeBuffers() too.
+ (*mesaFuncs.gl_Viewport)(lpCtx->glCtx, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
+ lpCtx->bHasBeenCurrent = TRUE;
+ }
+#endif // _USE_GLD3_WGL
+ ddlogPrintf(DDLOG_SYSTEM, "dglMakeCurrent: width = %d, height = %d", lpCtx->dwWidth, lpCtx->dwHeight);
+
+ // We have to clear D3D back buffer and render state if emulated front buffering
+ // for different window (but not context) like in Solid Edge.
+ if (glb.bDirectDrawPersistant && glb.bPersistantBuffers
+ && (bWindowChanged /* || bContextChanged */) && lpCtx->EmulateSingle) {
+#ifdef _USE_GLD3_WGL
+// IDirect3DDevice8_EndScene(lpCtx->pDev);
+// lpCtx->bSceneStarted = FALSE;
+ lpCtx->glCtx->Driver.Clear(lpCtx->glCtx, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
+ GL_TRUE, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
+#else
+ IDirect3DDevice3_EndScene(lpCtx->lpDev3);
+ lpCtx->bSceneStarted = FALSE;
+ dglClearD3D(lpCtx->glCtx, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
+ GL_TRUE, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
+#endif // _USE_GLD3_WGL
+ }
+
+ // The first time we call MakeCurrent we set the initial viewport size
+ if (lpCtx->bHasBeenCurrent == FALSE)
+#ifdef _USE_GLD3_WGL
+ lpCtx->glCtx->Driver.Viewport(lpCtx->glCtx, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
+#else
+ (*mesaFuncs.gl_Viewport)(lpCtx->glCtx, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
+#endif // _USE_GLD3_WGL
+ lpCtx->bHasBeenCurrent = TRUE;
+
+#ifdef GLD_THREADS
+ // Release serialized access
+ if (glb.bMultiThreaded)
+ LeaveCriticalSection(&CriticalSection);
+#endif
+
+ return TRUE;
+}
+
+// ***********************************************************************
+
+BOOL dglDeleteContext(
+ HGLRC a)
+{
+ DGL_ctx* lpCtx;
+ DWORD dwThreadId = GetCurrentThreadId();
+ char argstr[256];
+
+#if 0 // We have enough trouble throwing exceptions as it is... (DaveM)
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+#endif
+
+ // Is context state ready ?
+ if (!bContextReady)
+ return FALSE;
+
+ ddlogPrintf(DDLOG_SYSTEM, "dglDeleteContext: Deleting context HGLRC=%d, ThreadId=%X", (int)a, dwThreadId);
+
+ // Make sure the HGLRC is in range
+ if (((int) a> DGL_MAX_CONTEXTS) || ((int)a < 0)) {
+ ddlogMessage(DDLOG_ERROR, "dglDeleteCurrent: HGLRC out of range\n");
+ return FALSE;
+ }
+
+ // Make sure context is valid
+ lpCtx = dglGetContextAddress(a);
+ if (!lpCtx->bAllocated) {
+ ddlogPrintf(DDLOG_WARN, "Tried to delete unallocated context HGLRC=%d", (int)a);
+// return FALSE;
+ return TRUE; // HACK: Shuts up "WebLab Viewer Pro". KeithH
+ }
+
+ // Make sure context is de-activated
+ if (a == dglGetCurrentContext()) {
+ ddlogPrintf(DDLOG_WARN, "dglDeleteContext: context HGLRC=%d still active", (int)a);
+ dglMakeCurrent(NULL, NULL);
+ }
+
+#ifdef GLD_THREADS
+ // Serialize access to DirectDraw or DDS operations
+ if (glb.bMultiThreaded)
+ EnterCriticalSection(&CriticalSection);
+#endif
+
+ // We are about to destroy all Direct3D objects.
+ // Therefore we must disable rendering
+ lpCtx->bCanRender = FALSE;
+
+ // This exception handler was installed to catch some
+ // particularly nasty apps. Console apps that call exit()
+ // fall into this catagory (i.e. Win32 Glut).
+
+ // VC cannot successfully implement multiple exception handlers
+ // if more than one exception occurs. Therefore reverting back to
+ // single exception handler as Keith originally had it. (DaveM)
+
+#define WARN_MESSAGE(p) strcpy(argstr, (#p));
+#define SAFE_RELEASE(p) WARN_MESSAGE(p); RELEASE(p);
+
+__try {
+#ifdef _USE_GLD3_WGL
+ WARN_MESSAGE(gl_destroy_framebuffer);
+ if (lpCtx->glBuffer)
+ _mesa_destroy_framebuffer(lpCtx->glBuffer);
+ WARN_MESSAGE(gl_destroy_context);
+ if (lpCtx->glCtx)
+ _mesa_destroy_context(lpCtx->glCtx);
+ WARN_MESSAGE(gl_destroy_visual);
+ if (lpCtx->glVis)
+ _mesa_destroy_visual(lpCtx->glVis);
+
+ _gldDriver.DestroyDrawable(lpCtx);
+#else
+ // Destroy the Mesa context
+ WARN_MESSAGE(gl_destroy_framebuffer);
+ if (lpCtx->glBuffer)
+ (*mesaFuncs.gl_destroy_framebuffer)(lpCtx->glBuffer);
+ WARN_MESSAGE(gl_destroy_context);
+ if (lpCtx->glCtx)
+ (*mesaFuncs.gl_destroy_context)(lpCtx->glCtx);
+ WARN_MESSAGE(gl_destroy_visual);
+ if (lpCtx->glVis)
+ (*mesaFuncs.gl_destroy_visual)(lpCtx->glVis);
+
+ SAFE_RELEASE(lpCtx->m_pvbuf); // release D3D vertex buffer
+ SAFE_RELEASE(lpCtx->m_vbuf); // release D3D vertex buffer
+
+ // Delete the global palette
+ SAFE_RELEASE(lpCtx->lpGlobalPalette);
+
+ // Clean up.
+ if (lpCtx->lpViewport3) {
+ if (lpCtx->lpDev3) IDirect3DDevice3_DeleteViewport(lpCtx->lpDev3, lpCtx->lpViewport3);
+ SAFE_RELEASE(lpCtx->lpViewport3);
+ lpCtx->lpViewport3 = NULL;
+ }
+
+ SAFE_RELEASE(lpCtx->lpDev3);
+ if (lpCtx->lpDepth4) {
+ if (lpCtx->lpBack4)
+ IDirectDrawSurface4_DeleteAttachedSurface(lpCtx->lpBack4, 0L, lpCtx->lpDepth4);
+ else
+ IDirectDrawSurface4_DeleteAttachedSurface(lpCtx->lpFront4, 0L, lpCtx->lpDepth4);
+ SAFE_RELEASE(lpCtx->lpDepth4);
+ lpCtx->lpDepth4 = NULL;
+ }
+ SAFE_RELEASE(lpCtx->lpBack4);
+ SAFE_RELEASE(lpCtx->lpFront4);
+ if (lpCtx->bFullscreen) {
+ IDirectDraw4_RestoreDisplayMode(lpCtx->lpDD4);
+ IDirectDraw4_SetCooperativeLevel(lpCtx->lpDD4, NULL, DDSCL_NORMAL);
+ }
+ SAFE_RELEASE(lpCtx->lpD3D3);
+ SAFE_RELEASE(lpCtx->lpDD4);
+ SAFE_RELEASE(lpCtx->lpDD1);
+#endif // _ULSE_GLD3_WGL
+
+}
+__except(EXCEPTION_EXECUTE_HANDLER) {
+ ddlogPrintf(DDLOG_WARN, "Exception raised in dglDeleteContext: %s", argstr);
+}
+
+ // Restore the window message handler because this context may be used
+ // again by another window with a *different* message handler. (DaveM)
+ if (lpCtx->lpfnWndProc) {
+ SetWindowLong(lpCtx->hWnd, GWL_WNDPROC, (LONG)lpCtx->lpfnWndProc);
+ lpCtx->lpfnWndProc = (LONG)NULL;
+ }
+
+ lpCtx->bAllocated = FALSE; // This context is now free for use
+
+#ifdef GLD_THREADS
+ // Release serialized access
+ if (glb.bMultiThreaded)
+ LeaveCriticalSection(&CriticalSection);
+#endif
+
+ return TRUE;
+}
+
+// ***********************************************************************
+
+BOOL dglSwapBuffers(
+ HDC hDC)
+{
+ RECT rSrcRect; // Source rectangle
+ RECT rDstRect; // Destination rectangle
+ POINT pt;
+ HRESULT hResult;
+
+ DDBLTFX bltFX;
+ DWORD dwBlitFlags;
+ DDBLTFX *lpBltFX;
+
+// DWORD dwThreadId = GetCurrentThreadId();
+ HGLRC hGLRC = dglGetCurrentContext();
+ DGL_ctx *lpCtx = dglGetContextAddress(hGLRC);
+ HWND hWnd;
+
+ HDC hDCAux; // for memory DC
+ int x,y,w,h; // for memory DC BitBlt
+
+#if 0 // Perhaps not a good idea. Called too often. KH
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+#endif
+
+ if (!lpCtx) {
+ return TRUE; //FALSE; // No current context
+ }
+
+ if (!lpCtx->bCanRender) {
+ // Don't return false else some apps will bail.
+ return TRUE;
+ }
+
+ hWnd = lpCtx->hWnd;
+ if (hDC != lpCtx->hDC) {
+ ddlogPrintf(DDLOG_WARN, "dglSwapBuffers: HDC=%X does not match HDC=%X for HGLRC=%d", hDC, lpCtx->hDC, hGLRC);
+ hWnd = WindowFromDC(hDC);
+ }
+
+#ifndef _USE_GLD3_WGL
+ // Ensure that the surfaces exist before we tell
+ // the device to render to them.
+ IDirectDraw4_RestoreAllSurfaces(lpCtx->lpDD4);
+
+ // Make sure that the vertex caches have been emptied
+// dglStateChange(lpCtx);
+
+ // Some OpenGL programs don't issue a glFinish - check for it here.
+ if (lpCtx->bSceneStarted) {
+ IDirect3DDevice3_EndScene(lpCtx->lpDev3);
+ lpCtx->bSceneStarted = FALSE;
+ }
+#endif
+
+#if 0
+ // If the calling app is not active then we don't need to Blit/Flip.
+ // We can therefore simply return TRUE.
+ if (!glb.bAppActive)
+ return TRUE;
+ // Addendum: This is WRONG! We should bail if the app is *minimized*,
+ // not merely if the app is just plain 'not active'.
+ // KeithH, 27/May/2000.
+#endif
+
+ // Check for non-window DC = memory DC ?
+ if (hWnd == NULL) {
+ if (GetClipBox(hDC, &rSrcRect) == ERROR)
+ return TRUE;
+ // Use GDI BitBlt instead from compatible DirectDraw DC
+ x = rSrcRect.left;
+ y = rSrcRect.top;
+ w = rSrcRect.right - rSrcRect.left;
+ h = rSrcRect.bottom - rSrcRect.top;
+
+ // Ack. DX8 does not have a GetDC() function...
+ // TODO: Defer to DX7 or DX9 drivers... (DaveM)
+ return TRUE;
+ }
+
+ // Bail if window client region is not drawable, like in Solid Edge
+ if (!IsWindow(hWnd) /* || !IsWindowVisible(hWnd) */ || !GetClientRect(hWnd, &rSrcRect))
+ return TRUE;
+
+#ifdef GLD_THREADS
+ // Serialize access to DirectDraw or DDS operations
+ if (glb.bMultiThreaded)
+ EnterCriticalSection(&CriticalSection);
+#endif
+
+#ifdef _USE_GLD3_WGL
+ // Notify Mesa of impending swap, so Mesa can flush internal buffers.
+ _mesa_notifySwapBuffers(lpCtx->glCtx);
+ // Now perform driver buffer swap
+ _gldDriver.SwapBuffers(lpCtx, hDC, hWnd);
+#else
+ if (lpCtx->bFullscreen) {
+ // Sync with retrace if required
+ if (glb.bWaitForRetrace) {
+ IDirectDraw4_WaitForVerticalBlank(
+ lpCtx->lpDD4,
+ DDWAITVB_BLOCKBEGIN,
+ 0);
+ }
+
+ // Perform the fullscreen flip
+ TRY(IDirectDrawSurface4_Flip(
+ lpCtx->lpFront4,
+ NULL,
+ DDFLIP_WAIT),
+ "dglSwapBuffers: Flip");
+ } else {
+ // Calculate current window position and size
+ pt.x = pt.y = 0;
+ ClientToScreen(hWnd, &pt);
+ GetClientRect(hWnd, &rDstRect);
+ if (rDstRect.right > lpCtx->dwModeWidth)
+ rDstRect.right = lpCtx->dwModeWidth;
+ if (rDstRect.bottom > lpCtx->dwModeHeight)
+ rDstRect.bottom = lpCtx->dwModeHeight;
+ OffsetRect(&rDstRect, pt.x, pt.y);
+ rSrcRect.left = rSrcRect.top = 0;
+ rSrcRect.right = lpCtx->dwWidth;
+ rSrcRect.bottom = lpCtx->dwHeight;
+ if (rSrcRect.right > lpCtx->dwModeWidth)
+ rSrcRect.right = lpCtx->dwModeWidth;
+ if (rSrcRect.bottom > lpCtx->dwModeHeight)
+ rSrcRect.bottom = lpCtx->dwModeHeight;
+
+ if (glb.bWaitForRetrace) {
+ // Sync the blit to the vertical retrace
+ ZeroMemory(&bltFX, sizeof(bltFX));
+ bltFX.dwSize = sizeof(bltFX);
+ bltFX.dwDDFX = DDBLTFX_NOTEARING;
+ dwBlitFlags = DDBLT_WAIT | DDBLT_DDFX;
+ lpBltFX = &bltFX;
+ } else {
+ dwBlitFlags = DDBLT_WAIT;
+ lpBltFX = NULL;
+ }
+
+ // Perform the actual blit
+ TRY(IDirectDrawSurface4_Blt(
+ lpCtx->lpFront4,
+ &rDstRect,
+ lpCtx->lpBack4, // Blit source
+ &rSrcRect,
+ dwBlitFlags,
+ lpBltFX),
+ "dglSwapBuffers: Blt");
+ }
+#endif // _USE_GLD3_WGL
+
+#ifdef GLD_THREADS
+ // Release serialized access
+ if (glb.bMultiThreaded)
+ LeaveCriticalSection(&CriticalSection);
+#endif
+
+ // TODO: Re-instate rendering bitmap snapshot feature??? (DaveM)
+
+ // Render frame is completed
+ ValidateRect(hWnd, NULL);
+ lpCtx->bFrameStarted = FALSE;
+
+ return TRUE;
+}
+
+// ***********************************************************************
diff --git a/mesalib/src/mesa/drivers/windows/gldirect/dglcontext.h b/mesalib/src/mesa/drivers/windows/gldirect/dglcontext.h
index 5c433b857..5eea9de3d 100644
--- a/mesalib/src/mesa/drivers/windows/gldirect/dglcontext.h
+++ b/mesalib/src/mesa/drivers/windows/gldirect/dglcontext.h
@@ -1,281 +1,281 @@
-/****************************************************************************
-*
-* Mesa 3-D graphics library
-* Direct3D Driver Interface
-*
-* ========================================================================
-*
-* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
-*
-* Permission is hereby granted, free of charge, to any person obtaining a
-* copy of this software and associated documentation files (the "Software"),
-* to deal in the Software without restriction, including without limitation
-* the rights to use, copy, modify, merge, publish, distribute, sublicense,
-* and/or sell copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included
-* in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
-* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-* SOFTWARE.
-*
-* ======================================================================
-*
-* Language: ANSI C
-* Environment: Windows 9x (Win32)
-*
-* Description: OpenGL context handling.
-*
-****************************************************************************/
-
-#ifndef __DGLCONTEXT_H
-#define __DGLCONTEXT_H
-
-// Disable compiler complaints about DLL linkage
-#pragma warning (disable:4273)
-
-// Macros to control compilation
-#ifndef STRICT
-#define STRICT
-#endif // STRICT
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <GL\gl.h>
-
-#ifdef _USE_GLD3_WGL
- #include "dglmacros.h"
- #include "dglglobals.h"
- #include "pixpack.h"
- #include "ddlog.h"
- #include "dglpf.h"
- #include "context.h" // Mesa context
-#else
- #include <ddraw.h>
- #include <d3d.h>
-
- #include "dglmacros.h"
- #include "dglglobals.h"
- #include "pixpack.h"
- #include "ddlog.h"
- #include "dglpf.h"
- #include "d3dvertex.h"
-
- #include "DirectGL.h"
-
- #include "context.h" // Mesa context
- #include "vb.h" // Mesa vertex buffer
-#endif // _USE_GLD3_WGL
-
-/*---------------------- Macros and type definitions ----------------------*/
-
-// TODO: Use a list instead of this constant!
-#define DGL_MAX_CONTEXTS 32
-
-// Structure for describing an OpenGL context
-#ifdef _USE_GLD3_WGL
-typedef struct {
- BOOL bHasBeenCurrent;
- DGL_pixelFormat *lpPF;
-
- // Pointer to private driver data (this also contains the drawable).
- void *glPriv;
-
- // Mesa vars:
- GLcontext *glCtx; // The core Mesa context
- GLvisual *glVis; // Describes the color buffer
- GLframebuffer *glBuffer; // Ancillary buffers
-
- GLuint ClearIndex;
- GLuint CurrentIndex;
- GLubyte ClearColor[4];
- GLubyte CurrentColor[4];
-
- BOOL EmulateSingle; // Emulate single-buffering
- BOOL bDoubleBuffer;
- BOOL bDepthBuffer;
-
- // Shared driver vars:
- BOOL bAllocated;
- BOOL bFullscreen; // Is this a fullscreen context?
- BOOL bSceneStarted; // Has a lpDev->BeginScene been issued?
- BOOL bCanRender; // Flag: states whether rendering is OK
- BOOL bFrameStarted; // Has frame update started at all?
- BOOL bStencil; // TRUE if this context has stencil
- BOOL bGDIEraseBkgnd; // GDI Erase Background command
-
- // Window information
- HWND hWnd; // Window handle
- HDC hDC; // Windows' Device Context of the window
- DWORD dwWidth; // Window width
- DWORD dwHeight; // Window height
- DWORD dwBPP; // Window bits-per-pixel;
- RECT rcScreenRect; // Screen rectangle
- DWORD dwModeWidth; // Display mode width
- DWORD dwModeHeight; // Display mode height
- float dvClipX;
- float dvClipY;
- LONG lpfnWndProc; // window message handler function
-
-} DGL_ctx;
-
-#define GLD_context DGL_ctx
-#define GLD_GET_CONTEXT(c) (GLD_context*)(c)->DriverCtx
-
-#else // _USE_GLD3_WGL
-
-typedef struct {
- BOOL bHasBeenCurrent;
- DGL_pixelFormat *lpPF;
- //
- // Mesa context vars:
- //
- GLcontext *glCtx; // The core Mesa context
- GLvisual *glVis; // Describes the color buffer
- GLframebuffer *glBuffer; // Ancillary buffers
-
- GLuint ClearIndex;
- GLuint CurrentIndex;
- GLubyte ClearColor[4];
- GLubyte CurrentColor[4];
-
- BOOL EmulateSingle; // Emulate single-buffering
- BOOL bDoubleBuffer;
- BOOL bDepthBuffer;
- int iZBufferPF; // Index of Zbuffer pixel format
-
- // Vertex buffer: one-to-one correlation with Mesa's vertex buffer.
- // This will be filled by our setup function (see d3dvsetup.c)
- DGL_TLvertex gWin[VB_SIZE]; // Transformed and lit vertices
-// DGL_Lvertex gObj[VB_SIZE]; // Lit vertices in object coordinates.
-
- // Indices for DrawIndexedPrimitive.
- // Clipped quads are drawn seperately, so use VB_SIZE.
- // 6 indices are needed to make 2 triangles for each possible quad
-// WORD wIndices[(VB_SIZE / 4) * 6];
- WORD wIndices[32768];
-
- //
- // Device driver vars:
- //
- BOOL bAllocated;
- BOOL bFullscreen; // Is this a fullscreen context?
- BOOL bSceneStarted; // Has a lpDev->BeginScene been issued?
- BOOL bCanRender; // Flag: states whether rendering is OK
- BOOL bFrameStarted; // Has frame update started at all?
-
- // DirectX COM interfaces, postfixed with the interface number
- IDirectDraw *lpDD1;
- IDirectDraw4 *lpDD4;
- IDirect3D3 *lpD3D3;
- IDirect3DDevice3 *lpDev3;
- IDirect3DViewport3 *lpViewport3;
- IDirectDrawSurface4 *lpFront4;
- IDirectDrawSurface4 *lpBack4;
- IDirectDrawSurface4 *lpDepth4;
-
- // Vertex buffers
- BOOL bD3DPipeline; // True if using D3D geometry pipeline
- IDirect3DVertexBuffer *m_vbuf; // Unprocessed vertices
- IDirect3DVertexBuffer *m_pvbuf; // Processed vertices ready to be rendered
-
- D3DTEXTUREOP ColorOp[MAX_TEXTURE_UNITS]; // Used for re-enabling texturing
- D3DTEXTUREOP AlphaOp[MAX_TEXTURE_UNITS]; // Used for re-enabling texturing
- struct gl_texture_object *tObj[MAX_TEXTURE_UNITS];
-
- DDCAPS ddCaps; // DirectDraw caps
- D3DDEVICEDESC D3DDevDesc; // Direct3D Device description
-
- DDPIXELFORMAT ddpfRender; // Pixel format of the render buffer
- DDPIXELFORMAT ddpfDepth; // Pixel format of the depth buffer
-
- BOOL bStencil; // TRUE is this context has stencil
-
- PX_packFunc fnPackFunc; // Pixel packing function for SW
- PX_unpackFunc fnUnpackFunc; // Pixel unpacking function for SW
- PX_packSpanFunc fnPackSpanFunc; // Pixel span packer
-
- D3DVIEWPORT2 d3dViewport; // D3D Viewport object
-
- D3DCULL cullmode; // Direct3D cull mode
- D3DCOLOR curcolor; // Current color
- DWORD dwColorPF; // Current color, in format of target surface
- D3DCOLOR d3dClearColor; // Clear color
- D3DCOLOR ConstantColor; // For flat shading
- DWORD dwClearColorPF; // Clear color, in format of target surface
- BOOL bGDIEraseBkgnd; // GDI Erase Background command
-
- // Primitive caches
-// DGL_vertex LineCache[DGL_MAX_LINE_VERTS];
-// DGL_vertex TriCache[DGL_MAX_TRI_VERTS];
-// DWORD dwNextLineVert;
-// DWORD dwNextTriVert;
-
- // Window information
- HWND hWnd; // Window handle
- HDC hDC; // Windows' Device Context of the window
- DWORD dwWidth; // Window width
- DWORD dwHeight; // Window height
- DWORD dwBPP; // Window bits-per-pixel;
- RECT rcScreenRect; // Screen rectangle
- DWORD dwModeWidth; // Display mode width
- DWORD dwModeHeight; // Display mode height
- float dvClipX;
- float dvClipY;
- LONG lpfnWndProc; // window message handler function
-
- // Shared texture palette
- IDirectDrawPalette *lpGlobalPalette;
-
- // Usage counters.
- // One of these counters will be incremented when we choose
- // between hardware and software rendering functions.
-// DWORD dwHWUsageCount; // Hardware usage count
-// DWORD dwSWUsageCount; // Software usage count
-
- // Texture state flags.
-// BOOL m_texturing; // TRUE is texturing
-// BOOL m_mtex; // TRUE if multitexture
-// BOOL m_texHandleValid; // TRUE if tex state valid
-
- // Renderstate caches to ensure no redundant state changes
- DWORD dwRS[256]; // Renderstates
- DWORD dwTSS[2][24]; // Texture-stage states
- LPDIRECT3DTEXTURE2 lpTex[2]; // Texture (1 per stage)
-
- DWORD dwMaxTextureSize; // Max texture size:
- // clamped to 1024.
-
-} DGL_ctx;
-#endif // _USE_GLD3_WGL
-
-/*------------------------- Function Prototypes ---------------------------*/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-HHOOK hKeyHook;
-LRESULT CALLBACK dglKeyProc(int code,WPARAM wParam,LPARAM lParam);
-
-void dglInitContextState();
-void dglDeleteContextState();
-BOOL dglIsValidContext(HGLRC a);
-DGL_ctx* dglGetContextAddress(const HGLRC a);
-HDC dglGetCurrentDC(void);
-HGLRC dglGetCurrentContext(void);
-HGLRC dglCreateContext(HDC a, const DGL_pixelFormat *lpPF);
-BOOL dglMakeCurrent(HDC a, HGLRC b);
-BOOL dglDeleteContext(HGLRC a);
-BOOL dglSwapBuffers(HDC hDC);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x (Win32)
+*
+* Description: OpenGL context handling.
+*
+****************************************************************************/
+
+#ifndef __DGLCONTEXT_H
+#define __DGLCONTEXT_H
+
+// Disable compiler complaints about DLL linkage
+#pragma warning (disable:4273)
+
+// Macros to control compilation
+#ifndef STRICT
+#define STRICT
+#endif // STRICT
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <GL\gl.h>
+
+#ifdef _USE_GLD3_WGL
+ #include "dglmacros.h"
+ #include "dglglobals.h"
+ #include "pixpack.h"
+ #include "ddlog.h"
+ #include "dglpf.h"
+ #include "context.h" // Mesa context
+#else
+ #include <ddraw.h>
+ #include <d3d.h>
+
+ #include "dglmacros.h"
+ #include "dglglobals.h"
+ #include "pixpack.h"
+ #include "ddlog.h"
+ #include "dglpf.h"
+ #include "d3dvertex.h"
+
+ #include "DirectGL.h"
+
+ #include "context.h" // Mesa context
+ #include "vb.h" // Mesa vertex buffer
+#endif // _USE_GLD3_WGL
+
+/*---------------------- Macros and type definitions ----------------------*/
+
+// TODO: Use a list instead of this constant!
+#define DGL_MAX_CONTEXTS 32
+
+// Structure for describing an OpenGL context
+#ifdef _USE_GLD3_WGL
+typedef struct {
+ BOOL bHasBeenCurrent;
+ DGL_pixelFormat *lpPF;
+
+ // Pointer to private driver data (this also contains the drawable).
+ void *glPriv;
+
+ // Mesa vars:
+ struct gl_context *glCtx; // The core Mesa context
+ struct gl_config *glVis; // Describes the color buffer
+ struct gl_framebuffer *glBuffer; // Ancillary buffers
+
+ GLuint ClearIndex;
+ GLuint CurrentIndex;
+ GLubyte ClearColor[4];
+ GLubyte CurrentColor[4];
+
+ BOOL EmulateSingle; // Emulate single-buffering
+ BOOL bDoubleBuffer;
+ BOOL bDepthBuffer;
+
+ // Shared driver vars:
+ BOOL bAllocated;
+ BOOL bFullscreen; // Is this a fullscreen context?
+ BOOL bSceneStarted; // Has a lpDev->BeginScene been issued?
+ BOOL bCanRender; // Flag: states whether rendering is OK
+ BOOL bFrameStarted; // Has frame update started at all?
+ BOOL bStencil; // TRUE if this context has stencil
+ BOOL bGDIEraseBkgnd; // GDI Erase Background command
+
+ // Window information
+ HWND hWnd; // Window handle
+ HDC hDC; // Windows' Device Context of the window
+ DWORD dwWidth; // Window width
+ DWORD dwHeight; // Window height
+ DWORD dwBPP; // Window bits-per-pixel;
+ RECT rcScreenRect; // Screen rectangle
+ DWORD dwModeWidth; // Display mode width
+ DWORD dwModeHeight; // Display mode height
+ float dvClipX;
+ float dvClipY;
+ LONG lpfnWndProc; // window message handler function
+
+} DGL_ctx;
+
+#define GLD_context DGL_ctx
+#define GLD_GET_CONTEXT(c) (GLD_context*)(c)->DriverCtx
+
+#else // _USE_GLD3_WGL
+
+typedef struct {
+ BOOL bHasBeenCurrent;
+ DGL_pixelFormat *lpPF;
+ //
+ // Mesa context vars:
+ //
+ struct gl_context *glCtx; // The core Mesa context
+ struct gl_config *glVis; // Describes the color buffer
+ struct gl_framebuffer *glBuffer; // Ancillary buffers
+
+ GLuint ClearIndex;
+ GLuint CurrentIndex;
+ GLubyte ClearColor[4];
+ GLubyte CurrentColor[4];
+
+ BOOL EmulateSingle; // Emulate single-buffering
+ BOOL bDoubleBuffer;
+ BOOL bDepthBuffer;
+ int iZBufferPF; // Index of Zbuffer pixel format
+
+ // Vertex buffer: one-to-one correlation with Mesa's vertex buffer.
+ // This will be filled by our setup function (see d3dvsetup.c)
+ DGL_TLvertex gWin[VB_SIZE]; // Transformed and lit vertices
+// DGL_Lvertex gObj[VB_SIZE]; // Lit vertices in object coordinates.
+
+ // Indices for DrawIndexedPrimitive.
+ // Clipped quads are drawn seperately, so use VB_SIZE.
+ // 6 indices are needed to make 2 triangles for each possible quad
+// WORD wIndices[(VB_SIZE / 4) * 6];
+ WORD wIndices[32768];
+
+ //
+ // Device driver vars:
+ //
+ BOOL bAllocated;
+ BOOL bFullscreen; // Is this a fullscreen context?
+ BOOL bSceneStarted; // Has a lpDev->BeginScene been issued?
+ BOOL bCanRender; // Flag: states whether rendering is OK
+ BOOL bFrameStarted; // Has frame update started at all?
+
+ // DirectX COM interfaces, postfixed with the interface number
+ IDirectDraw *lpDD1;
+ IDirectDraw4 *lpDD4;
+ IDirect3D3 *lpD3D3;
+ IDirect3DDevice3 *lpDev3;
+ IDirect3DViewport3 *lpViewport3;
+ IDirectDrawSurface4 *lpFront4;
+ IDirectDrawSurface4 *lpBack4;
+ IDirectDrawSurface4 *lpDepth4;
+
+ // Vertex buffers
+ BOOL bD3DPipeline; // True if using D3D geometry pipeline
+ IDirect3DVertexBuffer *m_vbuf; // Unprocessed vertices
+ IDirect3DVertexBuffer *m_pvbuf; // Processed vertices ready to be rendered
+
+ D3DTEXTUREOP ColorOp[MAX_TEXTURE_UNITS]; // Used for re-enabling texturing
+ D3DTEXTUREOP AlphaOp[MAX_TEXTURE_UNITS]; // Used for re-enabling texturing
+ struct gl_texture_object *tObj[MAX_TEXTURE_UNITS];
+
+ DDCAPS ddCaps; // DirectDraw caps
+ D3DDEVICEDESC D3DDevDesc; // Direct3D Device description
+
+ DDPIXELFORMAT ddpfRender; // Pixel format of the render buffer
+ DDPIXELFORMAT ddpfDepth; // Pixel format of the depth buffer
+
+ BOOL bStencil; // TRUE is this context has stencil
+
+ PX_packFunc fnPackFunc; // Pixel packing function for SW
+ PX_unpackFunc fnUnpackFunc; // Pixel unpacking function for SW
+ PX_packSpanFunc fnPackSpanFunc; // Pixel span packer
+
+ D3DVIEWPORT2 d3dViewport; // D3D Viewport object
+
+ D3DCULL cullmode; // Direct3D cull mode
+ D3DCOLOR curcolor; // Current color
+ DWORD dwColorPF; // Current color, in format of target surface
+ D3DCOLOR d3dClearColor; // Clear color
+ D3DCOLOR ConstantColor; // For flat shading
+ DWORD dwClearColorPF; // Clear color, in format of target surface
+ BOOL bGDIEraseBkgnd; // GDI Erase Background command
+
+ // Primitive caches
+// DGL_vertex LineCache[DGL_MAX_LINE_VERTS];
+// DGL_vertex TriCache[DGL_MAX_TRI_VERTS];
+// DWORD dwNextLineVert;
+// DWORD dwNextTriVert;
+
+ // Window information
+ HWND hWnd; // Window handle
+ HDC hDC; // Windows' Device Context of the window
+ DWORD dwWidth; // Window width
+ DWORD dwHeight; // Window height
+ DWORD dwBPP; // Window bits-per-pixel;
+ RECT rcScreenRect; // Screen rectangle
+ DWORD dwModeWidth; // Display mode width
+ DWORD dwModeHeight; // Display mode height
+ float dvClipX;
+ float dvClipY;
+ LONG lpfnWndProc; // window message handler function
+
+ // Shared texture palette
+ IDirectDrawPalette *lpGlobalPalette;
+
+ // Usage counters.
+ // One of these counters will be incremented when we choose
+ // between hardware and software rendering functions.
+// DWORD dwHWUsageCount; // Hardware usage count
+// DWORD dwSWUsageCount; // Software usage count
+
+ // Texture state flags.
+// BOOL m_texturing; // TRUE is texturing
+// BOOL m_mtex; // TRUE if multitexture
+// BOOL m_texHandleValid; // TRUE if tex state valid
+
+ // Renderstate caches to ensure no redundant state changes
+ DWORD dwRS[256]; // Renderstates
+ DWORD dwTSS[2][24]; // Texture-stage states
+ LPDIRECT3DTEXTURE2 lpTex[2]; // Texture (1 per stage)
+
+ DWORD dwMaxTextureSize; // Max texture size:
+ // clamped to 1024.
+
+} DGL_ctx;
+#endif // _USE_GLD3_WGL
+
+/*------------------------- Function Prototypes ---------------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+HHOOK hKeyHook;
+LRESULT CALLBACK dglKeyProc(int code,WPARAM wParam,LPARAM lParam);
+
+void dglInitContextState();
+void dglDeleteContextState();
+BOOL dglIsValidContext(HGLRC a);
+DGL_ctx* dglGetContextAddress(const HGLRC a);
+HDC dglGetCurrentDC(void);
+HGLRC dglGetCurrentContext(void);
+HGLRC dglCreateContext(HDC a, const DGL_pixelFormat *lpPF);
+BOOL dglMakeCurrent(HDC a, HGLRC b);
+BOOL dglDeleteContext(HGLRC a);
+BOOL dglSwapBuffers(HDC hDC);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/mesalib/src/mesa/drivers/windows/gldirect/dglwgl.c b/mesalib/src/mesa/drivers/windows/gldirect/dglwgl.c
index 74ecb01a5..37e681dfc 100644
--- a/mesalib/src/mesa/drivers/windows/gldirect/dglwgl.c
+++ b/mesalib/src/mesa/drivers/windows/gldirect/dglwgl.c
@@ -1,2964 +1,2964 @@
-/****************************************************************************
-*
-* Mesa 3-D graphics library
-* Direct3D Driver Interface
-*
-* ========================================================================
-*
-* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
-*
-* Permission is hereby granted, free of charge, to any person obtaining a
-* copy of this software and associated documentation files (the "Software"),
-* to deal in the Software without restriction, including without limitation
-* the rights to use, copy, modify, merge, publish, distribute, sublicense,
-* and/or sell copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included
-* in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
-* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-* SOFTWARE.
-*
-* ======================================================================
-*
-* Language: ANSI C
-* Environment: Windows 9x (Win32)
-*
-* Description: OpenGL window functions (wgl*).
-*
-****************************************************************************/
-
-#include "dglwgl.h"
-#ifdef _USE_GLD3_WGL
-#include "gld_driver.h"
-#endif
-
-#include "gl/glu.h" // MUST USE MICROSOFT'S GLU32!
-
-#ifndef _USE_GLD3_WGL
-extern DGL_mesaFuncs mesaFuncs;
-#endif
-
-// Need to export wgl* functions if using GLD3,
-// otherwise export GLD2 DGL_* functions.
-#ifdef _USE_GLD3_WGL
-#define _GLD_WGL_EXPORT(a) wgl##a
-#else
-#define _GLD_WGL_EXPORT(a) DGL_##a
-#endif
-
-// Calls into Mesa 4.x are different
-#ifdef _USE_GLD3_WGL
-#include "dlist.h"
-#include "drawpix.h"
-#include "get.h"
-#include "matrix.h"
-// NOTE: All the _GLD* macros now call the gl* functions direct.
-// This ensures that the correct internal pathway is taken. KeithH
-#define _GLD_glNewList glNewList
-#define _GLD_glBitmap glBitmap
-#define _GLD_glEndList glEndList
-#define _GLD_glDeleteLists glDeleteLists
-#define _GLD_glGetError glGetError
-#define _GLD_glTranslatef glTranslatef
-#define _GLD_glBegin glBegin
-#define _GLD_glVertex2fv glVertex2fv
-#define _GLD_glEnd glEnd
-#define _GLD_glNormal3f glNormal3f
-#define _GLD_glVertex3f glVertex3f
-#define _GLD_glVertex3fv glVertex3fv
-#else // _USE_GLD3_WGL
-#define _GLD_glNewList (*mesaFuncs.glNewList)
-#define _GLD_glBitmap (*mesaFuncs.glBitmap)
-#define _GLD_glEndList (*mesaFuncs.glEndList)
-#define _GLD_glDeleteLists (*mesaFuncs.glDeleteLists)
-#define _GLD_glGetError (*mesaFuncs.glGetError)
-#define _GLD_glTranslatef (*mesaFuncs.glTranslatef)
-#define _GLD_glBegin (*mesaFuncs.glBegin)
-#define _GLD_glVertex2fv (*mesaFuncs.glVertex2fv)
-#define _GLD_glEnd (*mesaFuncs.glEnd)
-#define _GLD_glNormal3f (*mesaFuncs.glNormal3f)
-#define _GLD_glVertex3f (*mesaFuncs.glVertex3f)
-#define _GLD_glVertex3fv (*mesaFuncs.glVertex3fv)
-#endif // _USE_GLD3_WGL
-
-// ***********************************************************************
-
-// Emulate SGI DDK calls.
-#define __wglMalloc(a) GlobalAlloc(GPTR, (a))
-#define __wglFree(a) GlobalFree((a))
-
-// ***********************************************************************
-
-// Mesa glu.h and MS glu.h call these different things...
-//#define GLUtesselator GLUtriangulatorObj
-//#define GLU_TESS_VERTEX_DATA GLU_VERTEX_DATA
-
-// For wglFontOutlines
-
-typedef GLUtesselator *(APIENTRY *gluNewTessProto)(void);
-typedef void (APIENTRY *gluDeleteTessProto)(GLUtesselator *tess);
-typedef void (APIENTRY *gluTessBeginPolygonProto)(GLUtesselator *tess, void *polygon_data);
-typedef void (APIENTRY *gluTessBeginContourProto)(GLUtesselator *tess);
-typedef void (APIENTRY *gluTessVertexProto)(GLUtesselator *tess, GLdouble coords[3], void *data);
-typedef void (APIENTRY *gluTessEndContourProto)(GLUtesselator *tess);
-typedef void (APIENTRY *gluTessEndPolygonProto)(GLUtesselator *tess);
-typedef void (APIENTRY *gluTessPropertyProto)(GLUtesselator *tess, GLenum which, GLdouble value);
-typedef void (APIENTRY *gluTessNormalProto)(GLUtesselator *tess, GLdouble x, GLdouble y, GLdouble z);
-typedef void (APIENTRY *gluTessCallbackProto)(GLUtesselator *tess, GLenum which, void (CALLBACK *)());
-
-static HINSTANCE gluModuleHandle;
-static gluNewTessProto gluNewTessProc;
-static gluDeleteTessProto gluDeleteTessProc;
-static gluTessBeginPolygonProto gluTessBeginPolygonProc;
-static gluTessBeginContourProto gluTessBeginContourProc;
-static gluTessVertexProto gluTessVertexProc;
-static gluTessEndContourProto gluTessEndContourProc;
-static gluTessEndPolygonProto gluTessEndPolygonProc;
-static gluTessPropertyProto gluTessPropertyProc;
-static gluTessNormalProto gluTessNormalProc;
-static gluTessCallbackProto gluTessCallbackProc;
-
-static HFONT hNewFont, hOldFont;
-static FLOAT ScaleFactor;
-
-#define LINE_BUF_QUANT 4000
-#define VERT_BUF_QUANT 4000
-
-static FLOAT* LineBuf;
-static DWORD LineBufSize;
-static DWORD LineBufIndex;
-static FLOAT* VertBuf;
-static DWORD VertBufSize;
-static DWORD VertBufIndex;
-static GLenum TessErrorOccurred;
-
-static int AppendToLineBuf(
- FLOAT value);
-
-static int AppendToVertBuf(
- FLOAT value);
-
-static int DrawGlyph(
- UCHAR* glyphBuf,
- DWORD glyphSize,
- FLOAT chordalDeviation,
- FLOAT extrusion,
- INT format);
-
-static void FreeLineBuf(void);
-
-static void FreeVertBuf(void);
-
-static long GetWord(
- UCHAR** p);
-
-static long GetDWord(
- UCHAR** p);
-
-static double GetFixed(
- UCHAR** p);
-
-static int InitLineBuf(void);
-
-static int InitVertBuf(void);
-
-static HFONT CreateHighResolutionFont(
- HDC hDC);
-
-static int MakeDisplayListFromGlyph(
- DWORD listName,
- UCHAR* glyphBuf,
- DWORD glyphSize,
- LPGLYPHMETRICSFLOAT glyphMetricsFloat,
- FLOAT chordalDeviation,
- FLOAT extrusion,
- INT format);
-
-static BOOL LoadGLUTesselator(void);
-static BOOL UnloadGLUTesselator(void);
-
-static int MakeLinesFromArc(
- FLOAT x0,
- FLOAT y0,
- FLOAT x1,
- FLOAT y1,
- FLOAT x2,
- FLOAT y2,
- DWORD vertexCountIndex,
- FLOAT chordalDeviationSquared);
-
-static int MakeLinesFromGlyph( UCHAR* glyphBuf,
- DWORD glyphSize,
- FLOAT chordalDeviation);
-
-static int MakeLinesFromTTLine( UCHAR** pp,
- DWORD vertexCountIndex,
- WORD pointCount);
-
-static int MakeLinesFromTTPolycurve( UCHAR** pp,
- DWORD vertexCountIndex,
- FLOAT chordalDeviation);
-
-static int MakeLinesFromTTPolygon( UCHAR** pp,
- FLOAT chordalDeviation);
-
-static int MakeLinesFromTTQSpline( UCHAR** pp,
- DWORD vertexCountIndex,
- WORD pointCount,
- FLOAT chordalDeviation);
-
-static void CALLBACK TessCombine( double coords[3],
- void* vertex_data[4],
- FLOAT weight[4],
- void** outData);
-
-static void CALLBACK TessError( GLenum error);
-
-static void CALLBACK TessVertexOutData( FLOAT p[3],
- GLfloat z);
-
-// ***********************************************************************
-
-#ifdef GLD_THREADS
-#pragma message("compiling DGLWGL.C vars for multi-threaded support")
-extern CRITICAL_SECTION CriticalSection;
-extern DWORD dwTLSPixelFormat; // TLS index for current pixel format
-#endif
-int curPFD = 0; // Current PFD (static)
-
-// ***********************************************************************
-
-int dglGetPixelFormat(void)
-{
-#ifdef GLD_THREADS
- int iPixelFormat;
- // get thread-specific instance
- if (glb.bMultiThreaded) {
- __try {
- iPixelFormat = (int)TlsGetValue(dwTLSPixelFormat);
- }
- __except(EXCEPTION_EXECUTE_HANDLER) {
- iPixelFormat = curPFD;
- }
- }
- // get global static var
- else {
- iPixelFormat = curPFD;
- }
- return iPixelFormat;
-#else
- return curPFD;
-#endif
-}
-
-// ***********************************************************************
-
-void dglSetPixelFormat(int iPixelFormat)
-{
-#ifdef GLD_THREADS
- // set thread-specific instance
- if (glb.bMultiThreaded) {
- __try {
- TlsSetValue(dwTLSPixelFormat, (LPVOID)iPixelFormat);
- }
- __except(EXCEPTION_EXECUTE_HANDLER) {
- curPFD = iPixelFormat;
- }
- }
- // set global static var
- else {
- curPFD = iPixelFormat;
- }
-#else
- curPFD = iPixelFormat;
-#endif
-}
-
-// ***********************************************************************
-
-int APIENTRY _GLD_WGL_EXPORT(ChoosePixelFormat)(
- HDC a,
- CONST PIXELFORMATDESCRIPTOR *ppfd)
-{
- DGL_pixelFormat *lpPF = glb.lpPF;
-
- PIXELFORMATDESCRIPTOR ppfdBest;
- int i;
- int bestIndex = -1;
- int numPixelFormats;
- DWORD dwFlags;
-
- char buf[128];
- char cat[8];
-
- DWORD dwAllFlags =
- PFD_DRAW_TO_WINDOW |
- PFD_DRAW_TO_BITMAP |
- PFD_SUPPORT_GDI |
- PFD_SUPPORT_OPENGL |
- PFD_GENERIC_FORMAT |
- PFD_NEED_PALETTE |
- PFD_NEED_SYSTEM_PALETTE |
- PFD_DOUBLEBUFFER |
- PFD_STEREO |
- /*PFD_SWAP_LAYER_BUFFERS |*/
- PFD_DOUBLEBUFFER_DONTCARE |
- PFD_STEREO_DONTCARE |
- PFD_SWAP_COPY |
- PFD_SWAP_EXCHANGE |
- PFD_GENERIC_ACCELERATED |
- 0;
-
- // Validate license
- if (!dglValidate())
- return 0;
-
- // List may not be built until dglValidate() is called! KeithH
- lpPF = glb.lpPF;
-
- //
- // Lets print the input pixel format to the log
- // ** Based on "wglinfo" by Nate Robins **
- //
- ddlogMessage(DDLOG_SYSTEM, "ChoosePixelFormat:\n");
- ddlogMessage(DDLOG_INFO, "Input pixel format for ChoosePixelFormat:\n");
- ddlogMessage(DDLOG_INFO,
- " visual x bf lv rg d st r g b a ax dp st accum buffs ms\n");
- ddlogMessage(DDLOG_INFO,
- " id dep cl sp sz l ci b ro sz sz sz sz bf th cl r g b a ns b\n");
- ddlogMessage(DDLOG_INFO,
- "-----------------------------------------------------------------\n");
- sprintf(buf, " . ");
-
- sprintf(cat, "%2d ", ppfd->cColorBits);
- strcat(buf, cat);
- if(ppfd->dwFlags & PFD_DRAW_TO_WINDOW) sprintf(cat, "wn ");
- else if(ppfd->dwFlags & PFD_DRAW_TO_BITMAP) sprintf(cat, "bm ");
- else sprintf(cat, ". ");
- strcat(buf, cat);
-
- /* should find transparent pixel from LAYERPLANEDESCRIPTOR */
- sprintf(cat, " . ");
- strcat(buf, cat);
-
- sprintf(cat, "%2d ", ppfd->cColorBits);
- strcat(buf, cat);
-
- /* bReserved field indicates number of over/underlays */
- if(ppfd->bReserved) sprintf(cat, " %d ", ppfd->bReserved);
- else sprintf(cat, " . ");
- strcat(buf, cat);
-
- sprintf(cat, " %c ", ppfd->iPixelType == PFD_TYPE_RGBA ? 'r' : 'c');
- strcat(buf, cat);
-
- sprintf(cat, "%c ", ppfd->dwFlags & PFD_DOUBLEBUFFER ? 'y' : '.');
- strcat(buf, cat);
-
- sprintf(cat, " %c ", ppfd->dwFlags & PFD_STEREO ? 'y' : '.');
- strcat(buf, cat);
-
- if(ppfd->cRedBits && ppfd->iPixelType == PFD_TYPE_RGBA)
- sprintf(cat, "%2d ", ppfd->cRedBits);
- else sprintf(cat, " . ");
- strcat(buf, cat);
-
- if(ppfd->cGreenBits && ppfd->iPixelType == PFD_TYPE_RGBA)
- sprintf(cat, "%2d ", ppfd->cGreenBits);
- else sprintf(cat, " . ");
- strcat(buf, cat);
-
- if(ppfd->cBlueBits && ppfd->iPixelType == PFD_TYPE_RGBA)
- sprintf(cat, "%2d ", ppfd->cBlueBits);
- else sprintf(cat, " . ");
- strcat(buf, cat);
-
- if(ppfd->cAlphaBits && ppfd->iPixelType == PFD_TYPE_RGBA)
- sprintf(cat, "%2d ", ppfd->cAlphaBits);
- else sprintf(cat, " . ");
- strcat(buf, cat);
-
- if(ppfd->cAuxBuffers) sprintf(cat, "%2d ", ppfd->cAuxBuffers);
- else sprintf(cat, " . ");
- strcat(buf, cat);
-
- if(ppfd->cDepthBits) sprintf(cat, "%2d ", ppfd->cDepthBits);
- else sprintf(cat, " . ");
- strcat(buf, cat);
-
- if(ppfd->cStencilBits) sprintf(cat, "%2d ", ppfd->cStencilBits);
- else sprintf(cat, " . ");
- strcat(buf, cat);
-
- if(ppfd->cAccumRedBits) sprintf(cat, "%2d ", ppfd->cAccumRedBits);
- else sprintf(cat, " . ");
- strcat(buf, cat);
-
- if(ppfd->cAccumGreenBits) sprintf(cat, "%2d ", ppfd->cAccumGreenBits);
- else sprintf(cat, " . ");
- strcat(buf, cat);
-
- if(ppfd->cAccumBlueBits) sprintf(cat, "%2d ", ppfd->cAccumBlueBits);
- else sprintf(cat, " . ");
- strcat(buf, cat);
-
- if(ppfd->cAccumAlphaBits) sprintf(cat, "%2d ", ppfd->cAccumAlphaBits);
- else sprintf(cat, " . ");
- strcat(buf, cat);
-
- /* no multisample in Win32 */
- sprintf(cat, " . .\n");
- strcat(buf, cat);
-
- ddlogMessage(DDLOG_INFO, buf);
- ddlogMessage(DDLOG_INFO,
- "-----------------------------------------------------------------\n");
- ddlogMessage(DDLOG_INFO, "\n");
-
- //
- // Examine the flags for correctness
- //
- dwFlags = ppfd->dwFlags;
- if (dwFlags != (dwFlags & dwAllFlags))
- {
- /* error: bad dwFlags */
- ddlogPrintf(DDLOG_WARN,
- "ChoosePixelFormat: bad flags (0x%x)",
- dwFlags & (~dwAllFlags));
- // Mask illegal flags and continue
- dwFlags = dwFlags & dwAllFlags;
- }
-
- switch (ppfd->iPixelType) {
- case PFD_TYPE_RGBA:
- case PFD_TYPE_COLORINDEX:
- break;
- default:
- /* error: bad iPixelType */
- ddlogMessage(DDLOG_WARN, "ChoosePixelFormat: bad pixel type\n");
- return 0;
- }
-
- switch (ppfd->iLayerType) {
- case PFD_MAIN_PLANE:
- case PFD_OVERLAY_PLANE:
- case PFD_UNDERLAY_PLANE:
- break;
- default:
- /* error: bad iLayerType */
- ddlogMessage(DDLOG_WARN, "ChoosePixelFormat: bad layer type\n");
- return 0;
- }
-
- numPixelFormats = glb.nPixelFormatCount;
-
- /* loop through candidate pixel format descriptors */
- for (i=0; i<numPixelFormats; ++i) {
- PIXELFORMATDESCRIPTOR ppfdCandidate;
-
- memcpy(&ppfdCandidate, &lpPF[i].pfd, sizeof(PIXELFORMATDESCRIPTOR));
-
- /*
- ** Check attributes which must match
- */
- if (ppfd->iPixelType != ppfdCandidate.iPixelType) {
- continue;
- }
-
- if (ppfd->iLayerType != ppfdCandidate.iLayerType) {
- continue;
- }
-
- if (((dwFlags ^ ppfdCandidate.dwFlags) & dwFlags) &
- (PFD_DRAW_TO_WINDOW | PFD_DRAW_TO_BITMAP |
- PFD_SUPPORT_GDI | PFD_SUPPORT_OPENGL))
- {
- continue;
- }
-
- if (!(dwFlags & PFD_DOUBLEBUFFER_DONTCARE)) {
- if ((dwFlags & PFD_DOUBLEBUFFER) !=
- (ppfdCandidate.dwFlags & PFD_DOUBLEBUFFER))
- {
- continue;
- }
- }
-
-// if (!(dwFlags & PFD_STEREO_DONTCARE)) {
- if ((dwFlags & PFD_STEREO) !=
- (ppfdCandidate.dwFlags & PFD_STEREO))
- {
- continue;
- }
-// }
-
- if (ppfd->iPixelType==PFD_TYPE_RGBA
- && ppfd->cAlphaBits && !ppfdCandidate.cAlphaBits) {
- continue;
- }
-
- if (ppfd->iPixelType==PFD_TYPE_RGBA
- && ppfd->cAccumBits && !ppfdCandidate.cAccumBits) {
- continue;
- }
-
- if (ppfd->cDepthBits && !ppfdCandidate.cDepthBits) {
- continue;
- }
-
- if (ppfd->cStencilBits && !ppfdCandidate.cStencilBits) {
- continue;
- }
-
- if (ppfd->cAuxBuffers && !ppfdCandidate.cAuxBuffers) {
- continue;
- }
-
- /*
- ** See if candidate is better than the previous best choice
- */
- if (bestIndex == -1) {
- ppfdBest = ppfdCandidate;
- bestIndex = i;
- continue;
- }
-
- if ((ppfd->cColorBits > ppfdBest.cColorBits &&
- ppfdCandidate.cColorBits > ppfdBest.cColorBits) ||
- (ppfd->cColorBits <= ppfdCandidate.cColorBits &&
- ppfdCandidate.cColorBits < ppfdBest.cColorBits))
- {
- ppfdBest = ppfdCandidate;
- bestIndex = i;
- continue;
- }
-
- if (ppfd->iPixelType==PFD_TYPE_RGBA
- && ppfd->cAlphaBits
- && ppfdCandidate.cAlphaBits > ppfdBest.cAlphaBits)
- {
- ppfdBest = ppfdCandidate;
- bestIndex = i;
- continue;
- }
-
- if (ppfd->iPixelType==PFD_TYPE_RGBA
- && ppfd->cAccumBits
- && ppfdCandidate.cAccumBits > ppfdBest.cAccumBits)
- {
- ppfdBest = ppfdCandidate;
- bestIndex = i;
- continue;
- }
-
- if ((ppfd->cDepthBits > ppfdBest.cDepthBits &&
- ppfdCandidate.cDepthBits > ppfdBest.cDepthBits) ||
- (ppfd->cDepthBits <= ppfdCandidate.cDepthBits &&
- ppfdCandidate.cDepthBits < ppfdBest.cDepthBits))
- {
- ppfdBest = ppfdCandidate;
- bestIndex = i;
- continue;
- }
-
- if (ppfd->cStencilBits &&
- ppfdCandidate.cStencilBits > ppfdBest.cStencilBits)
- {
- ppfdBest = ppfdCandidate;
- bestIndex = i;
- continue;
- }
-
- if (ppfd->cAuxBuffers &&
- ppfdCandidate.cAuxBuffers > ppfdBest.cAuxBuffers)
- {
- ppfdBest = ppfdCandidate;
- bestIndex = i;
- continue;
- }
- }
-
- if (bestIndex != -1) {
- ddlogPrintf(DDLOG_SYSTEM, "Pixel Format %d chosen as best match", bestIndex+1);
- return bestIndex + 1;
- }
-
- // Return the pixelformat that has the most capabilities.
- // ** NOTE: This is only possible due to the way the list
- // of pixelformats is built. **
- // Now picks best pixelformat. KeithH
- bestIndex = numPixelFormats; // most capable double buffer format
- ddlogPrintf(DDLOG_SYSTEM, "Pixel Format %d chosen by default", bestIndex);
- return (bestIndex);
-}
-
-// ***********************************************************************
-
-BOOL APIENTRY _GLD_WGL_EXPORT(CopyContext)(
- HGLRC a,
- HGLRC b,
- UINT c)
-{
- // Validate license
- if (!dglValidate())
- return FALSE;
- UNSUPPORTED("wglCopyContext")
- return FALSE; // Failed
-}
-
-// ***********************************************************************
-
-HGLRC APIENTRY _GLD_WGL_EXPORT(CreateContext)(
- HDC a)
-{
- int ipf;
-
- // Validate license
- if (!dglValidate())
- return 0;
-
- // Check that the current PFD is valid
- ipf = dglGetPixelFormat();
- if (!IsValidPFD(ipf))
- return (HGLRC)0;
-
- return dglCreateContext(a, &glb.lpPF[ipf-1]);
-}
-
-// ***********************************************************************
-
-HGLRC APIENTRY _GLD_WGL_EXPORT(CreateLayerContext)(
- HDC a,
- int b)
-{
- // Validate license
- if (!dglValidate())
- return 0;
-
- UNSUPPORTED("wglCreateLayerContext")
- return NULL; // Failed
-}
-
-// ***********************************************************************
-
-BOOL APIENTRY _GLD_WGL_EXPORT(DeleteContext)(
- HGLRC a)
-{
- // Validate license
- if (!dglValidate())
- return FALSE;
-
- return dglDeleteContext(a);
-}
-
-// ***********************************************************************
-
-BOOL APIENTRY _GLD_WGL_EXPORT(DescribeLayerPlane)(
- HDC hDC,
- int iPixelFormat,
- int iLayerPlane,
- UINT nBytes,
- LPLAYERPLANEDESCRIPTOR plpd)
-{
- // Validate license
- if (!dglValidate())
- return FALSE;
-
- UNSUPPORTED("DGL_DescribeLayerPlane")
-
-// gldLogPrintf(GLDLOG_INFO, "DescribeLayerPlane: %d, %d", iPixelFormat, iLayerPlane);
-
- return FALSE;
-}
-
-// ***********************************************************************
-
-int APIENTRY _GLD_WGL_EXPORT(DescribePixelFormat)(
- HDC a,
- int b,
- UINT c,
- LPPIXELFORMATDESCRIPTOR d)
-{
- UINT nSize;
-
- // Validate license
- if (!dglValidate())
- return 0;
-
- if (d == NULL) // Calling app requires max number of PF's
- return glb.nPixelFormatCount;
-
- // The supplied buffer may be larger than the info that we
- // will be copying.
- if (c > sizeof(PIXELFORMATDESCRIPTOR))
- nSize = sizeof(PIXELFORMATDESCRIPTOR);
- else
- nSize = c;
-
- // Setup an empty PFD before doing validation check
- memset(d, 0, nSize);
- d->nSize = nSize;
- d->nVersion = 1;
-
- if (!IsValidPFD(b))
- return 0; // Bail if PFD index is invalid
-
- memcpy(d, &glb.lpPF[b-1].pfd, nSize);
-
- return glb.nPixelFormatCount;
-}
-
-// ***********************************************************************
-
-HGLRC APIENTRY _GLD_WGL_EXPORT(GetCurrentContext)(void)
-{
- // Validate license
- if (!dglValidate())
- return 0;
-
- return dglGetCurrentContext();
-}
-
-// ***********************************************************************
-
-HDC APIENTRY _GLD_WGL_EXPORT(GetCurrentDC)(void)
-{
- // Validate license
- if (!dglValidate())
- return 0;
-
- return dglGetCurrentDC();
-}
-
-// ***********************************************************************
-
-PROC APIENTRY _GLD_WGL_EXPORT(GetDefaultProcAddress)(
- LPCSTR a)
-{
- // Validate license
- if (!dglValidate())
- return NULL;
-
- UNSUPPORTED("DGL_GetDefaultProcAddress")
- return NULL;
-}
-
-// ***********************************************************************
-
-int APIENTRY _GLD_WGL_EXPORT(GetLayerPaletteEntries)(
- HDC a,
- int b,
- int c,
- int d,
- COLORREF *e)
-{
- // Validate license
- if (!dglValidate())
- return 0;
-
- UNSUPPORTED("DGL_GetLayerPaletteEntries")
- return 0;
-}
-
-// ***********************************************************************
-
-int APIENTRY _GLD_WGL_EXPORT(GetPixelFormat)(
- HDC a)
-{
- // Validate license
- if (!dglValidate())
- return 0;
-
- return dglGetPixelFormat();
-}
-
-// ***********************************************************************
-
-PROC APIENTRY _GLD_WGL_EXPORT(GetProcAddress)(
- LPCSTR a)
-{
- PROC dglGetProcAddressD3D(LPCSTR a);
-
- // Validate license
- if (!dglValidate())
- return NULL;
-
-#ifdef _USE_GLD3_WGL
- return _gldDriver.wglGetProcAddress(a);
-#else
- return dglGetProcAddressD3D(a);
-#endif
-}
-
-// ***********************************************************************
-
-BOOL APIENTRY _GLD_WGL_EXPORT(MakeCurrent)(
- HDC a,
- HGLRC b)
-{
- // Validate license
- if (!dglValidate())
- return FALSE;
-
- return dglMakeCurrent(a, b);
-}
-
-// ***********************************************************************
-
-BOOL APIENTRY _GLD_WGL_EXPORT(RealizeLayerPalette)(
- HDC a,
- int b,
- BOOL c)
-{
- // Validate license
- if (!dglValidate())
- return FALSE;
-
- UNSUPPORTED("DGL_RealizeLayerPalette")
- return FALSE;
-}
-
-// ***********************************************************************
-
-int APIENTRY _GLD_WGL_EXPORT(SetLayerPaletteEntries)(
- HDC a,
- int b,
- int c,
- int d,
- CONST COLORREF *e)
-{
- // Validate license
- if (!dglValidate())
- return 0;
-
- UNSUPPORTED("DGL_SetLayerPaletteEntries")
- return 0;
-}
-
-// ***********************************************************************
-
-BOOL APIENTRY _GLD_WGL_EXPORT(SetPixelFormat)(
- HDC a,
- int b,
- CONST PIXELFORMATDESCRIPTOR *c)
-{
- // Validate license
- if (!dglValidate())
- return FALSE;
-
- if (IsValidPFD(b)) {
- ddlogPrintf(DDLOG_SYSTEM, "SetPixelFormat: PixelFormat %d has been set", b);
- dglSetPixelFormat(b);
- return TRUE;
- } else {
- ddlogPrintf(DDLOG_ERROR,
- "SetPixelFormat: PixelFormat %d is invalid and cannot be set", b);
- return FALSE;
- }
-}
-
-// ***********************************************************************
-/*
- * Share lists between two gl_context structures.
- * This was added for WIN32 WGL function support, since wglShareLists()
- * must be called *after* wglCreateContext() with valid GLRCs. (DaveM)
- */
-//
-// Copied from GLD2.x. KeithH
-//
-static GLboolean _gldShareLists(
- GLcontext *ctx1,
- GLcontext *ctx2)
-{
- /* Sanity check context pointers */
- if (ctx1 == NULL || ctx2 == NULL)
- return GL_FALSE;
- /* Sanity check shared list pointers */
- if (ctx1->Shared == NULL || ctx2->Shared == NULL)
- return GL_FALSE;
- /* Decrement reference count on sharee to release previous list */
- ctx2->Shared->RefCount--;
-#if 0 /* 3DStudio exits on this memory release */
- if (ctx2->Shared->RefCount == 0)
- free_shared_state(ctx2, ctx2->Shared);
-#endif
- /* Re-assign list from sharer to sharee and increment reference count */
- ctx2->Shared = ctx1->Shared;
- ctx1->Shared->RefCount++;
- return GL_TRUE;
-}
-
-// ***********************************************************************
-
-BOOL APIENTRY _GLD_WGL_EXPORT(ShareLists)(
- HGLRC a,
- HGLRC b)
-{
- DGL_ctx *dgl1, *dgl2;
-
- // Validate license
- if (!dglValidate())
- return FALSE;
-
- // Mesa supports shared lists, but you need to supply the shared
- // GL context info when calling gl_create_context(). An auxiliary
- // function gl_share_lists() has been added to update the shared
- // list info after the GL contexts have been created. (DaveM)
- dgl1 = dglGetContextAddress(a);
- dgl2 = dglGetContextAddress(b);
- if (dgl1->bAllocated && dgl2->bAllocated) {
-#ifdef _USE_GLD3_WGL
- return _gldShareLists(dgl1->glCtx, dgl2->glCtx);
-#else
- return (*mesaFuncs.gl_share_lists)(dgl1->glCtx, dgl2->glCtx);
-#endif
- }
- return FALSE;
-}
-
-// ***********************************************************************
-
-BOOL APIENTRY _GLD_WGL_EXPORT(SwapBuffers)(
- HDC a)
-{
- // Validate license
- if (!dglValidate())
- return FALSE;
-
- return dglSwapBuffers(a);
-}
-
-// ***********************************************************************
-
-BOOL APIENTRY _GLD_WGL_EXPORT(SwapLayerBuffers)(
- HDC a,
- UINT b)
-{
- // Validate license
- if (!dglValidate())
- return FALSE;
-
- return dglSwapBuffers(a);
-}
-
-// ***********************************************************************
-
-// ***********************************************************************
-// Note: This ResizeBuffers() function may be called from
-// either MESA glViewport() or GLD wglMakeCurrent().
-
-BOOL dglWglResizeBuffers(
- GLcontext *ctx,
- BOOL bDefaultDriver)
-{
- DGL_ctx *dgl = NULL;
- RECT rcScreenRect;
- DWORD dwWidth;
- DWORD dwHeight;
- DDSURFACEDESC2 ddsd2;
- DDSCAPS2 ddscaps2;
- IDirectDrawClipper *lpddClipper = NULL;
- DWORD dwFlags;
- HRESULT hResult;
-
- DWORD dwMemoryType;
-
- int i;
- struct gl_texture_object *tObj;
- struct gl_texture_image *image;
-
- BOOL bWasFullscreen;
- BOOL bSaveDesktop;
- BOOL bFullScrnWin = FALSE;
- DDSURFACEDESC2 ddsd2DisplayMode;
-
- DDBLTFX ddbltfx;
- POINT pt;
- RECT rcDst;
-#ifdef _USE_GLD3_WGL
- GLD_displayMode glddm;
-#endif
-
-#define DDLOG_CRITICAL_OR_WARN (bDefaultDriver ? DDLOG_WARN : DDLOG_CRITICAL)
-
- // Validate license
- if (!dglValidate())
- return FALSE;
-
- // Sanity checks
- if (ctx == NULL)
- return FALSE;
- dgl = ctx->DriverCtx;
- if (dgl == NULL)
- return FALSE;
-
- // Get the window size and calculate its dimensions
- if (dgl->hWnd == NULL) {
- // Check for non-window DC = memory DC ?
- if (GetClipBox(dgl->hDC, &rcScreenRect) == ERROR)
- SetRect(&rcScreenRect, 0, 0, 0, 0);
- }
- else if (!GetClientRect(dgl->hWnd, &rcScreenRect))
- SetRect(&rcScreenRect, 0, 0, 0, 0);
- dwWidth = rcScreenRect.right - rcScreenRect.left;
- dwHeight = rcScreenRect.bottom - rcScreenRect.top;
- CopyRect(&dgl->rcScreenRect, &rcScreenRect);
-
- // This will occur on Alt-Tab
- if ((dwWidth == 0) && (dwHeight == 0)) {
- //dgl->bCanRender = FALSE;
- return TRUE; // No resize possible!
- }
-
- // Some apps zero only 1 dimension for non-visible window... (DaveM)
- if ((dwWidth == 0) || (dwHeight == 0)) {
- dwWidth = 8;
- dwHeight = 8;
- }
-
- // Test to see if a resize is required.
- // Note that the dimensions will be the same if a prior resize attempt failed.
- if ((dwWidth == dgl->dwWidth) && (dwHeight == dgl->dwHeight) && bDefaultDriver) {
- return TRUE; // No resize required
- }
-
- ddlogPrintf(DDLOG_SYSTEM, "dglResize: %dx%d", dwWidth, dwHeight);
-#ifndef _USE_GLD3_WGL
- // Work out where we want our surfaces created
- dwMemoryType = (bDefaultDriver) ? glb.dwMemoryType : DDSCAPS_SYSTEMMEMORY;
-#endif // _USE_GLD3_WGL
-
- // Note previous fullscreen vs window display status
- bWasFullscreen = dgl->bFullscreen;
-
-#ifdef _USE_GLD3_WGL
- if (_gldDriver.GetDisplayMode(dgl, &glddm)) {
- if ( (dwWidth == glddm.Width) &&
- (dwHeight == glddm.Height) ) {
- bFullScrnWin = TRUE;
- }
- if (bFullScrnWin && glb.bPrimary && !glb.bFullscreenBlit && !glb.bDirectDrawPersistant) {
- dgl->bFullscreen = TRUE;
- ddlogMessage(DDLOG_INFO, "Fullscreen window after resize.\n");
- }
- else {
- dgl->bFullscreen = FALSE;
- ddlogMessage(DDLOG_INFO, "Non-Fullscreen window after resize.\n");
- }
- // Cache the display mode dimensions
- dgl->dwModeWidth = glddm.Width;
- dgl->dwModeHeight = glddm.Height;
- }
-
- // Clamp the effective window dimensions to primary surface.
- // We need to do this for D3D viewport dimensions even if wide
- // surfaces are supported. This also is a good idea for handling
- // whacked-out window dimensions passed for non-drawable windows
- // like Solid Edge. (DaveM)
- if (dgl->dwWidth > glddm.Width)
- dgl->dwWidth = glddm.Width;
- if (dgl->dwHeight > glddm.Height)
- dgl->dwHeight = glddm.Height;
-#else // _USE_GLD3_WGL
- // Window resize may have changed to fullscreen
- ZeroMemory(&ddsd2DisplayMode, sizeof(ddsd2DisplayMode));
- ddsd2DisplayMode.dwSize = sizeof(ddsd2DisplayMode);
- hResult = IDirectDraw4_GetDisplayMode(
- dgl->lpDD4,
- &ddsd2DisplayMode);
- if (SUCCEEDED(hResult)) {
- if ( (dwWidth == ddsd2DisplayMode.dwWidth) &&
- (dwHeight == ddsd2DisplayMode.dwHeight) ) {
- bFullScrnWin = TRUE;
- }
- if (bFullScrnWin && glb.bPrimary && !glb.bFullscreenBlit && !glb.bDirectDrawPersistant) {
- dgl->bFullscreen = TRUE;
- ddlogMessage(DDLOG_INFO, "Fullscreen window after resize.\n");
- }
- else {
- dgl->bFullscreen = FALSE;
- ddlogMessage(DDLOG_INFO, "Non-Fullscreen window after resize.\n");
- }
- // Cache the display mode dimensions
- dgl->dwModeWidth = ddsd2DisplayMode.dwWidth;
- dgl->dwModeHeight = ddsd2DisplayMode.dwHeight;
- }
-
- // Clamp the effective window dimensions to primary surface.
- // We need to do this for D3D viewport dimensions even if wide
- // surfaces are supported. This also is a good idea for handling
- // whacked-out window dimensions passed for non-drawable windows
- // like Solid Edge. (DaveM)
- if (dgl->dwWidth > ddsd2DisplayMode.dwWidth)
- dgl->dwWidth = ddsd2DisplayMode.dwWidth;
- if (dgl->dwHeight > ddsd2DisplayMode.dwHeight)
- dgl->dwHeight = ddsd2DisplayMode.dwHeight;
-#endif // _USE_GLD3_WGL
-
- // Note if fullscreen vs window display has changed?
- bSaveDesktop = (!bWasFullscreen && !dgl->bFullscreen) ? TRUE : FALSE;
- // Save the desktop primary surface from being destroyed
- // whenever remaining in windowed mode, since the stereo mode
- // switches are expensive...
-
-#ifndef _USE_GLD3_WGL
- // Don't need to re-allocate persistant buffers. (DaveM)
- // Though we should clear the back buffers to hide artifacts.
- if (glb.bDirectDrawPersistant && glb.bPersistantBuffers) {
- dgl->dwWidth = dwWidth;
- dgl->dwHeight = dwHeight;
- ZeroMemory(&ddbltfx, sizeof(ddbltfx));
- ddbltfx.dwSize = sizeof(ddbltfx);
- ddbltfx.dwFillColor = dgl->dwClearColorPF;
- IDirectDrawSurface4_Blt(dgl->lpBack4, &rcScreenRect, NULL, NULL,
- DDBLT_WAIT | DDBLT_COLORFILL, &ddbltfx);
- return TRUE;
- }
-
- // Ensure all rendering is complete
- if (ctx->Driver.Finish)
- (*ctx->Driver.Finish)(ctx);
- if (dgl->bSceneStarted == TRUE) {
- IDirect3DDevice3_EndScene(dgl->lpDev3);
- dgl->bSceneStarted = FALSE;
- }
-#endif // _USE_GLD3_WGL
- dgl->bCanRender = FALSE;
-
-#ifdef GLD_THREADS
- // Serialize access to DirectDraw and DDS operations
- if (glb.bMultiThreaded)
- EnterCriticalSection(&CriticalSection);
-#endif
-
-#ifndef _USE_GLD3_WGL
- // Release existing surfaces
- RELEASE(dgl->lpDev3);
- RELEASE(dgl->lpDepth4);
- RELEASE(dgl->lpBack4);
- if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary)
- ;
- else
- RELEASE(dgl->lpFront4);
-#endif // _USE_GLD3_WGL
- dgl->dwWidth = dwWidth;
- dgl->dwHeight = dwHeight;
-
- // Set defaults
- dgl->dwModeWidth = dgl->dwWidth;
- dgl->dwModeHeight = dgl->dwHeight;
-
-#ifdef _USE_GLD3_WGL
- if (!_gldDriver.ResizeDrawable(dgl, bDefaultDriver, glb.bDirectDrawPersistant, glb.bPersistantBuffers))
- goto cleanup_and_return_with_error;
-#else // _USE_GLD3_WGL
-
- if (dgl->bFullscreen) {
- //
- // FULLSCREEN
- //
-
- // Disable warning popups when in fullscreen mode
- ddlogWarnOption(FALSE);
-
- // Have to release the persistant DirectDraw primary surface
- // if switching to fullscreen mode. So if application wants
- // persistant display in fullscreen mode, a fullscreen-size
- // window should be used instead via fullscreen-blit option.
- if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary) {
- RELEASE(glb.lpPrimary4);
- glb.bDirectDrawPrimary = FALSE;
- }
-
- dwFlags = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT;
- if (glb.bFastFPU)
- dwFlags |= DDSCL_FPUSETUP; // optional
- hResult = IDirectDraw4_SetCooperativeLevel(dgl->lpDD4, dgl->hWnd, dwFlags);
- if (FAILED(hResult)) {
- ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Unable to set Exclusive Fullscreen mode", hResult);
- goto cleanup_and_return_with_error;
- }
-
- hResult = IDirectDraw4_SetDisplayMode(dgl->lpDD4,
- dgl->dwModeWidth,
- dgl->dwModeHeight,
- dgl->dwBPP,
- 0,
- 0);
- if (FAILED(hResult)) {
- ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: SetDisplayMode failed", hResult);
- goto cleanup_and_return_with_error;
- }
-
- // ** The display mode has changed, so dont use MessageBox! **
-
- ZeroMemory(&ddsd2, sizeof(ddsd2));
- ddsd2.dwSize = sizeof(ddsd2);
-
- if (dgl->bDoubleBuffer) {
- // Double buffered
- // Primary surface
- ddsd2.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
- ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
- DDSCAPS_FLIP |
- DDSCAPS_COMPLEX |
- DDSCAPS_3DDEVICE |
- dwMemoryType;
- ddsd2.dwBackBufferCount = 1;
- hResult = IDirectDraw4_CreateSurface(dgl->lpDD4, &ddsd2, &dgl->lpFront4, NULL);
- if (FAILED(hResult)) {
- ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: CreateSurface (primary) failed", hResult);
- goto cleanup_and_return_with_error;
- }
- // Render target surface
- ZeroMemory(&ddscaps2, sizeof(ddscaps2)); // Clear the entire struct.
- ddscaps2.dwCaps = DDSCAPS_BACKBUFFER;
- hResult = IDirectDrawSurface4_GetAttachedSurface(dgl->lpFront4, &ddscaps2, &dgl->lpBack4);
- if (FAILED(hResult)) {
- ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: GetAttachedSurface failed", hResult);
- goto cleanup_and_return_with_error;
- }
- } else {
- // Single buffered
- // Primary surface
- ddsd2.dwFlags = DDSD_CAPS;
- ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
- //DDSCAPS_3DDEVICE |
- dwMemoryType;
-
- hResult = IDirectDraw4_CreateSurface(dgl->lpDD4, &ddsd2, &dgl->lpFront4, NULL);
- if (FAILED(hResult)) {
- ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: CreateSurface (primary) failed", hResult);
- goto cleanup_and_return_with_error;
- }
-
- dgl->lpBack4 = NULL;
- }
- } else {
- // WINDOWED
-
- // OK to enable warning popups in windowed mode
- ddlogWarnOption(glb.bMessageBoxWarnings);
-
- // Ditto if persistant DirectDraw primary
- if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary)
- goto DoClipperOnly;
-
- // WINDOWED
- dwFlags = DDSCL_NORMAL;
- if (glb.bMultiThreaded)
- dwFlags |= DDSCL_MULTITHREADED;
- if (glb.bFastFPU)
- dwFlags |= DDSCL_FPUSETUP; // optional
- hResult = IDirectDraw4_SetCooperativeLevel(dgl->lpDD4,
- dgl->hWnd,
- dwFlags);
- if (FAILED(hResult)) {
- ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Unable to set Normal coop level", hResult);
- goto cleanup_and_return_with_error;
- }
- // Primary surface
- ZeroMemory(&ddsd2, sizeof(ddsd2));
- ddsd2.dwSize = sizeof(ddsd2);
- ddsd2.dwFlags = DDSD_CAPS;
- ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
- hResult = IDirectDraw4_CreateSurface(dgl->lpDD4, &ddsd2, &dgl->lpFront4, NULL);
- if (FAILED(hResult)) {
- ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: CreateSurface (primary) failed", hResult);
- goto cleanup_and_return_with_error;
- }
-
- // Cache the primary surface for persistant DirectDraw state
- if (glb.bDirectDrawPersistant && !glb.bDirectDrawPrimary) {
- glb.lpPrimary4 = dgl->lpFront4;
- IDirectDrawSurface4_AddRef(glb.lpPrimary4);
- glb.bDirectDrawPrimary = TRUE;
- }
-
- // Clipper object
- hResult = DirectDrawCreateClipper(0, &lpddClipper, NULL);
- if (FAILED(hResult)) {
- ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: CreateClipper failed", hResult);
- goto cleanup_and_return_with_error;
- }
- hResult = IDirectDrawClipper_SetHWnd(lpddClipper, 0, dgl->hWnd);
- if (FAILED(hResult)) {
- RELEASE(lpddClipper);
- ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: SetHWnd failed", hResult);
- goto cleanup_and_return_with_error;
- }
- hResult = IDirectDrawSurface4_SetClipper(dgl->lpFront4, lpddClipper);
- RELEASE(lpddClipper); // We have finished with it.
- if (FAILED(hResult)) {
- ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: SetClipper failed", hResult);
- goto cleanup_and_return_with_error;
- }
-DoClipperOnly:
- // Update the window for the original clipper
- if ((glb.bDirectDrawPersistant && glb.bDirectDrawPrimary) || bSaveDesktop) {
- IDirectDrawSurface4_GetClipper(dgl->lpFront4, &lpddClipper);
- IDirectDrawClipper_SetHWnd(lpddClipper, 0, dgl->hWnd);
- RELEASE(lpddClipper);
- }
-
- if (dgl->bDoubleBuffer) {
- // Render target surface
- ZeroMemory(&ddsd2, sizeof(ddsd2));
- ddsd2.dwSize = sizeof(ddsd2);
- ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
- ddsd2.dwWidth = dgl->dwWidth;
- ddsd2.dwHeight = dgl->dwHeight;
- ddsd2.ddsCaps.dwCaps = DDSCAPS_3DDEVICE |
- DDSCAPS_OFFSCREENPLAIN |
- dwMemoryType;
- hResult = IDirectDraw4_CreateSurface(dgl->lpDD4, &ddsd2, &dgl->lpBack4, NULL);
- if (FAILED(hResult)) {
- ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Create Backbuffer failed", hResult);
- goto cleanup_and_return_with_error;
- }
-
- } else {
- dgl->lpBack4 = NULL;
- }
- }
-
- //
- // Now create the Zbuffer
- //
- if (dgl->bDepthBuffer) {
- // Get z-buffer dimensions from the render target
- // Setup the surface desc for the z-buffer.
- ZeroMemory(&ddsd2, sizeof(ddsd2));
- ddsd2.dwSize = sizeof(ddsd2);
- ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
- ddsd2.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | dwMemoryType;
- ddsd2.dwWidth = dgl->dwWidth;
- ddsd2.dwHeight = dgl->dwHeight;
- memcpy(&ddsd2.ddpfPixelFormat,
- &glb.lpZBufferPF[dgl->iZBufferPF],
- sizeof(DDPIXELFORMAT) );
-
- // Create a z-buffer
- hResult = IDirectDraw4_CreateSurface(dgl->lpDD4, &ddsd2, &dgl->lpDepth4, NULL);
- if (FAILED(hResult)) {
- ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: CreateSurface (ZBuffer) failed", hResult);
- goto cleanup_and_return_with_error;
- }
-
- // Attach Zbuffer to render target
- TRY(IDirectDrawSurface4_AddAttachedSurface(
- dgl->bDoubleBuffer ? dgl->lpBack4 : dgl->lpFront4,
- dgl->lpDepth4),
- "dglResize: Attach Zbuffer");
-
- }
-
- // Clear the newly resized back buffers for the window client area.
- ZeroMemory(&ddbltfx, sizeof(ddbltfx));
- ddbltfx.dwSize = sizeof(ddbltfx);
- ddbltfx.dwFillColor = dgl->dwClearColorPF;
- IDirectDrawSurface4_Blt(dgl->lpBack4, &rcScreenRect, NULL, NULL,
- DDBLT_WAIT | DDBLT_COLORFILL, &ddbltfx);
-
- //
- // Now that we have a zbuffer we can create the 3D device
- //
- hResult = IDirect3D3_CreateDevice(dgl->lpD3D3,
- bDefaultDriver ? &glb.d3dGuid : &IID_IDirect3DRGBDevice,
- dgl->bDoubleBuffer ? dgl->lpBack4 : dgl->lpFront4,
- &dgl->lpDev3,
- NULL);
- if (FAILED(hResult)) {
- ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Could not create Direct3D device", hResult);
- goto cleanup_and_return_with_error;
- }
-
- // We must do this as soon as the device is created
- dglInitStateCaches(dgl);
-
- //
- // Viewport
- //
- hResult = IDirect3DDevice3_AddViewport(dgl->lpDev3, dgl->lpViewport3);
- if (FAILED(hResult)) {
- ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: AddViewport failed", hResult);
- goto cleanup_and_return_with_error;
- }
-
- // Initialise the viewport
- dgl->d3dViewport.dwSize = sizeof(dgl->d3dViewport);
- dgl->d3dViewport.dwX = 0;
- dgl->d3dViewport.dwY = 0;
- dgl->d3dViewport.dwWidth = dgl->dwWidth;
- dgl->d3dViewport.dwHeight = dgl->dwHeight;
- dgl->d3dViewport.dvClipX = 0;
- dgl->d3dViewport.dvClipY = 0;
- dgl->d3dViewport.dvClipWidth = dgl->dwWidth;
- dgl->d3dViewport.dvClipHeight = dgl->dwHeight;
-// dgl->d3dViewport.dvMinZ = 0.0f;
-// dgl->d3dViewport.dvMaxZ = 1.0f;
- TRY(IDirect3DViewport3_SetViewport2(dgl->lpViewport3, &dgl->d3dViewport),
- "dglResize: SetViewport2");
-
- hResult = IDirect3DDevice3_SetCurrentViewport(dgl->lpDev3, dgl->lpViewport3);
- if (FAILED(hResult)) {
- ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: SetCurrentViewport failed", hResult);
- goto cleanup_and_return_with_error;
- }
-
- // (Re)Initialise all the Direct3D renderstates
- dglInitStateD3D(ctx);
-
- // Now we have to recreate all of our textures (+ mipmaps).
- // Walk over all textures in hash table
- // XXX what about the default texture objects (id=0)?
- {
- struct _mesa_HashTable *textures = ctx->Shared->TexObjects;
- GLuint id;
- for (id = _mesa_HashFirstEntry(textures);
- id;
- id = _mesa_HashNextEntry(textures, id)) {
- tObj = (struct gl_texture_object *) _mesa_HashLookup(textures, id);
- if (tObj->DriverData) {
- // We could call our TexImage function directly, but it's
- // safer to use the driver pointer.
- for (i=0; i<MAX_TEXTURE_LEVELS; i++) {
- image = tObj->Image[i];
- if (image) {
- switch (tObj->Dimensions){
- case 1:
- if (ctx->Driver.TexImage)
- (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_1D, tObj, i, image->Format, image);
- break;
- case 2:
- if (ctx->Driver.TexImage)
- (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_2D, tObj, i, image->Format, image);
- break;
- default:
- break;
- }
- }
- }
- }
- }
- }
-
- // Re-Bind each texture Unit
- for (i=0; i<glb.wMaxSimultaneousTextures; i++) {
- tObj = ctx->Texture.Unit[i].Current;
- if (tObj) {
- DGL_texture *lpTex = (DGL_texture *)tObj->DriverData;
- hResult = dglSetTexture(dgl, i, lpTex ? lpTex->lpTexture : NULL);
- if (FAILED(hResult)) {
- ddlogError(DDLOG_ERROR, "dglResize: SetTexture failed", hResult);
- }
- }
- }
-#endif // _USE_GLD3_WGL
-
- dgl->bCanRender = TRUE;
-
-#ifdef GLD_THREADS
- // Release serialized access
- if (glb.bMultiThreaded)
- LeaveCriticalSection(&CriticalSection);
-#endif
-
- // SUCCESS.
- return TRUE;
-
-cleanup_and_return_with_error:
- // Relase all interfaces before returning.
-#ifdef _USE_GLD3_WGL
- _gldDriver.DestroyDrawable(dgl);
-#else // _USE_GLD3_WGL
- RELEASE(dgl->lpDev3);
- RELEASE(dgl->lpDepth4);
- RELEASE(dgl->lpBack4);
- if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary)
- ;
- else
- RELEASE(dgl->lpFront4);
-
-#undef DDLOG_CRITICAL_OR_WARN
-#endif // _USE_GLD3_WGL
-
- // Mark context as not being able to render
- dgl->bCanRender = FALSE;
-
-#ifdef GLD_THREADS
- // Release serialized access
- if (glb.bMultiThreaded)
- LeaveCriticalSection(&CriticalSection);
-#endif
-
- return FALSE;
-}
-
-// ***********************************************************************
-// ***********************************************************************
-// Support for bitmap fonts.
-// ***********************************************************************
-// ***********************************************************************
-
-/*****************************************************************************
-**
-** InvertGlyphBitmap.
-**
-** Invert the bitmap so that it suits OpenGL's representation.
-** Each row starts on a double word boundary.
-**
-*****************************************************************************/
-
-static void InvertGlyphBitmap(
- int w,
- int h,
- DWORD *fptr,
- DWORD *tptr)
-{
- int dWordsInRow = (w+31)/32;
- int i, j;
- DWORD *tmp = tptr;
-
- if (w <= 0 || h <= 0) {
- return;
- }
-
- tptr += ((h-1)*dWordsInRow);
- for (i = 0; i < h; i++) {
- for (j = 0; j < dWordsInRow; j++) {
- *(tptr + j) = *(fptr + j);
- }
- tptr -= dWordsInRow;
- fptr += dWordsInRow;
- }
-}
-
-// ***********************************************************************
-
-/*****************************************************************************
- * wglUseFontBitmaps
- *
- * Converts a subrange of the glyphs in a GDI font to OpenGL display
- * lists.
- *
- * Extended to support any GDI font, not just TrueType fonts. (DaveM)
- *
- *****************************************************************************/
-
-BOOL APIENTRY _GLD_WGL_EXPORT(UseFontBitmapsA)(
- HDC hDC,
- DWORD first,
- DWORD count,
- DWORD listBase)
-{
- int i, ox, oy, ix, iy;
- int w, h;
- int iBufSize, iCurBufSize = 0;
- DWORD *bitmapBuffer = NULL;
- DWORD *invertedBitmapBuffer = NULL;
- BOOL bSuccessOrFail = TRUE;
- BOOL bTrueType = FALSE;
- TEXTMETRIC tm;
- GLYPHMETRICS gm;
- RASTERIZER_STATUS rs;
- MAT2 mat;
- SIZE size;
- RECT rect;
- HDC hDCMem;
- HBITMAP hBitmap;
- BITMAPINFO bmi;
- HFONT hFont;
-
- // Validate SciTech DirectGL license
- if (!dglValidate())
- return FALSE;
-
- // Set up a unity matrix.
- ZeroMemory(&mat, sizeof(mat));
- mat.eM11.value = 1;
- mat.eM22.value = 1;
-
- // Test to see if selected font is TrueType or not
- ZeroMemory(&tm, sizeof(tm));
- if (!GetTextMetrics(hDC, &tm)) {
- ddlogMessage(DDLOG_ERROR, "DGL_UseFontBitmaps: Font metrics error\n");
- return (FALSE);
- }
- bTrueType = (tm.tmPitchAndFamily & TMPF_TRUETYPE) ? TRUE : FALSE;
-
- // Test to see if TRUE-TYPE capabilities are installed
- // (only necessary if TrueType font selected)
- ZeroMemory(&rs, sizeof(rs));
- if (bTrueType) {
- if (!GetRasterizerCaps (&rs, sizeof (RASTERIZER_STATUS))) {
- ddlogMessage(DDLOG_ERROR, "DGL_UseFontBitmaps: Raster caps error\n");
- return (FALSE);
- }
- if (!(rs.wFlags & TT_ENABLED)) {
- ddlogMessage(DDLOG_ERROR, "DGL_UseFontBitmaps: No TrueType caps\n");
- return (FALSE);
- }
- }
-
- // Trick to get the current font handle
- hFont = SelectObject(hDC, GetStockObject(SYSTEM_FONT));
- SelectObject(hDC, hFont);
-
- // Have memory device context available for holding bitmaps of font glyphs
- hDCMem = CreateCompatibleDC(hDC);
- SelectObject(hDCMem, hFont);
- SetTextColor(hDCMem, RGB(0xFF, 0xFF, 0xFF));
- SetBkColor(hDCMem, 0);
-
- for (i = first; (DWORD) i < (first + count); i++) {
- // Find out how much space is needed for the bitmap so we can
- // Set the buffer size correctly.
- if (bTrueType) {
- // Use TrueType support to get bitmap size of glyph
- iBufSize = GetGlyphOutline(hDC, i, GGO_BITMAP, &gm,
- 0, NULL, &mat);
- if (iBufSize == GDI_ERROR) {
- bSuccessOrFail = FALSE;
- break;
- }
- }
- else {
- // Use generic GDI support to compute bitmap size of glyph
- w = tm.tmMaxCharWidth;
- h = tm.tmHeight;
- if (GetTextExtentPoint32(hDC, (LPCTSTR)&i, 1, &size)) {
- w = size.cx;
- h = size.cy;
- }
- iBufSize = w * h;
- // Use DWORD multiple for compatibility
- iBufSize += 3;
- iBufSize /= 4;
- iBufSize *= 4;
- }
-
- // If we need to allocate Larger Buffers, then do so - but allocate
- // An extra 50 % so that we don't do too many mallocs !
- if (iBufSize > iCurBufSize) {
- if (bitmapBuffer) {
- __wglFree(bitmapBuffer);
- }
- if (invertedBitmapBuffer) {
- __wglFree(invertedBitmapBuffer);
- }
-
- iCurBufSize = iBufSize * 2;
- bitmapBuffer = (DWORD *) __wglMalloc(iCurBufSize);
- invertedBitmapBuffer = (DWORD *) __wglMalloc(iCurBufSize);
-
- if (bitmapBuffer == NULL || invertedBitmapBuffer == NULL) {
- bSuccessOrFail = FALSE;
- break;
- }
- }
-
- // If we fail to get the Glyph data, delete the display lists
- // Created so far and return FALSE.
- if (bTrueType) {
- // Use TrueType support to get bitmap of glyph
- if (GetGlyphOutline(hDC, i, GGO_BITMAP, &gm,
- iBufSize, bitmapBuffer, &mat) == GDI_ERROR) {
- bSuccessOrFail = FALSE;
- break;
- }
-
- // Setup glBitmap parameters for current font glyph
- w = gm.gmBlackBoxX;
- h = gm.gmBlackBoxY;
- ox = gm.gmptGlyphOrigin.x;
- oy = gm.gmptGlyphOrigin.y;
- ix = gm.gmCellIncX;
- iy = gm.gmCellIncY;
- }
- else {
- // Use generic GDI support to create bitmap of glyph
- ZeroMemory(bitmapBuffer, iBufSize);
-
- if (i >= tm.tmFirstChar && i <= tm.tmLastChar) {
- // Only create bitmaps for actual font glyphs
- hBitmap = CreateBitmap(w, h, 1, 1, NULL);
- SelectObject(hDCMem, hBitmap);
- // Make bitmap of current font glyph
- SetRect(&rect, 0, 0, w, h);
- DrawText(hDCMem, (LPCTSTR)&i, 1, &rect,
- DT_LEFT | DT_BOTTOM | DT_SINGLELINE | DT_NOCLIP);
- // Make copy of bitmap in our local buffer
- ZeroMemory(&bmi, sizeof(bmi));
- bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- bmi.bmiHeader.biWidth = w;
- bmi.bmiHeader.biHeight = -h;
- bmi.bmiHeader.biPlanes = 1;
- bmi.bmiHeader.biBitCount = 1;
- bmi.bmiHeader.biCompression = BI_RGB;
- GetDIBits(hDCMem, hBitmap, 0, h, bitmapBuffer, &bmi, 0);
- DeleteObject(hBitmap);
- }
- else {
- // Otherwise use empty display list for non-existing glyph
- iBufSize = 0;
- }
-
- // Setup glBitmap parameters for current font glyph
- ox = 0;
- oy = tm.tmDescent;
- ix = w;
- iy = 0;
- }
-
- // Create an OpenGL display list.
- _GLD_glNewList((listBase + i), GL_COMPILE);
-
- // Some fonts have no data for the space character, yet advertise
- // a non-zero size.
- if (0 == iBufSize) {
- _GLD_glBitmap(0, 0, 0.0f, 0.0f, (GLfloat) ix, (GLfloat) iy, NULL);
- } else {
- // Invert the Glyph data.
- InvertGlyphBitmap(w, h, bitmapBuffer, invertedBitmapBuffer);
-
- // Render an OpenGL bitmap and invert the origin.
- _GLD_glBitmap(w, h,
- (GLfloat) ox, (GLfloat) (h-oy),
- (GLfloat) ix, (GLfloat) iy,
- (GLubyte *) invertedBitmapBuffer);
- }
-
- // Close this display list.
- _GLD_glEndList();
- }
-
- if (bSuccessOrFail == FALSE) {
- ddlogMessage(DDLOG_ERROR, "DGL_UseFontBitmaps: Get glyph failed\n");
- _GLD_glDeleteLists((i+listBase), (i-first));
- }
-
- // Release resources used
- DeleteObject(hFont);
- DeleteDC(hDCMem);
-
- if (bitmapBuffer)
- __wglFree(bitmapBuffer);
- if (invertedBitmapBuffer)
- __wglFree(invertedBitmapBuffer);
-
- return(bSuccessOrFail);
-}
-
-// ***********************************************************************
-
-BOOL APIENTRY _GLD_WGL_EXPORT(UseFontBitmapsW)(
- HDC a,
- DWORD b,
- DWORD c,
- DWORD d)
-{
- // Validate license
- if (!dglValidate())
- return FALSE;
-
- return _GLD_WGL_EXPORT(UseFontBitmapsA)(a, b, c, d);
-}
-
-// ***********************************************************************
-// ***********************************************************************
-// Support for outline TrueType fonts.
-// ***********************************************************************
-// ***********************************************************************
-
-void * __wglRealloc(
- void *oldPtr,
- size_t newSize)
-{
- void *newPtr = NULL;
-
- if (newSize != 0) {
- newPtr = (void *) GlobalAlloc(GPTR, newSize);
- if (oldPtr && newPtr) {
- DWORD oldSize = GlobalSize(oldPtr);
-
- memcpy(newPtr, oldPtr, (oldSize <= newSize ? oldSize : newSize));
- GlobalFree(oldPtr);
- }
- } else if (oldPtr) {
- GlobalFree(oldPtr);
- }
- if (newPtr == NULL) {
- return NULL; /* XXX out of memory error */
- }
- return newPtr;
-}
-
-// ***********************************************************************
-
-
-/*****************************************************************************
- * wglUseFontOutlinesW
- *
- * Converts a subrange of the glyphs in a TrueType font to OpenGL display
- * lists.
- *****************************************************************************/
-
-BOOL APIENTRY _GLD_WGL_EXPORT(UseFontOutlinesW)(
- IN HDC hDC,
- IN DWORD first,
- IN DWORD count,
- IN DWORD listBase,
- IN FLOAT chordalDeviation,
- IN FLOAT extrusion,
- IN INT format,
- OUT LPGLYPHMETRICSFLOAT lpgmf)
-{
- return _GLD_WGL_EXPORT(UseFontOutlinesA)(hDC, first, count, listBase,
- chordalDeviation, extrusion, format, lpgmf);
-}
-
-/*****************************************************************************
- * wglUseFontOutlinesA
- *
- * Converts a subrange of the glyphs in a TrueType font to OpenGL display
- * lists.
- *****************************************************************************/
-
-BOOL APIENTRY _GLD_WGL_EXPORT(UseFontOutlinesA)(
- IN HDC hDC,
- IN DWORD first,
- IN DWORD count,
- IN DWORD listBase,
- IN FLOAT chordalDeviation,
- IN FLOAT extrusion,
- IN INT format,
- OUT LPGLYPHMETRICSFLOAT glyphMetricsFloatArray)
- {
- DWORD glyphIndex;
- UCHAR* glyphBuf;
- DWORD glyphBufSize;
-
-
- /*
- * Flush any previous OpenGL errors. This allows us to check for
- * new errors so they can be reported via the function return value.
- */
- while (_GLD_glGetError() != GL_NO_ERROR)
- ;
-
- /*
- * Make sure that the current font can be sampled accurately.
- */
- hNewFont = CreateHighResolutionFont(hDC);
- if (!hNewFont)
- return FALSE;
-
- hOldFont = SelectObject(hDC, hNewFont);
- if (!hOldFont)
- return FALSE;
-
- /*
- * Preallocate a buffer for the outline data, and track its size:
- */
- glyphBuf = (UCHAR*) __wglMalloc(glyphBufSize = 10240);
- if (!glyphBuf)
- return FALSE; /*WGL_STATUS_NOT_ENOUGH_MEMORY*/
-
- /*
- * Process each glyph in the given range:
- */
- for (glyphIndex = first; glyphIndex - first < count; ++glyphIndex)
- {
- GLYPHMETRICS glyphMetrics;
- DWORD glyphSize;
- static MAT2 matrix =
- {
- {0, 1}, {0, 0},
- {0, 0}, {0, 1}
- };
- LPGLYPHMETRICSFLOAT glyphMetricsFloat =
- &glyphMetricsFloatArray[glyphIndex - first];
-
-
- /*
- * Determine how much space is needed to store the glyph's
- * outlines. If our glyph buffer isn't large enough,
- * resize it.
- */
- glyphSize = GetGlyphOutline( hDC,
- glyphIndex,
- GGO_NATIVE,
- &glyphMetrics,
- 0,
- NULL,
- &matrix
- );
- if (glyphSize < 0)
- return FALSE; /*WGL_STATUS_FAILURE*/
- if (glyphSize > glyphBufSize)
- {
- __wglFree(glyphBuf);
- glyphBuf = (UCHAR*) __wglMalloc(glyphBufSize = glyphSize);
- if (!glyphBuf)
- return FALSE; /*WGL_STATUS_NOT_ENOUGH_MEMORY*/
- }
-
-
- /*
- * Get the glyph's outlines.
- */
- if (GetGlyphOutline( hDC,
- glyphIndex,
- GGO_NATIVE,
- &glyphMetrics,
- glyphBufSize,
- glyphBuf,
- &matrix
- ) < 0)
- {
- __wglFree(glyphBuf);
- return FALSE; /*WGL_STATUS_FAILURE*/
- }
-
- glyphMetricsFloat->gmfBlackBoxX =
- (FLOAT) glyphMetrics.gmBlackBoxX * ScaleFactor;
- glyphMetricsFloat->gmfBlackBoxY =
- (FLOAT) glyphMetrics.gmBlackBoxY * ScaleFactor;
- glyphMetricsFloat->gmfptGlyphOrigin.x =
- (FLOAT) glyphMetrics.gmptGlyphOrigin.x * ScaleFactor;
- glyphMetricsFloat->gmfptGlyphOrigin.y =
- (FLOAT) glyphMetrics.gmptGlyphOrigin.y * ScaleFactor;
- glyphMetricsFloat->gmfCellIncX =
- (FLOAT) glyphMetrics.gmCellIncX * ScaleFactor;
- glyphMetricsFloat->gmfCellIncY =
- (FLOAT) glyphMetrics.gmCellIncY * ScaleFactor;
-
- /*
- * Turn the glyph into a display list:
- */
- if (!MakeDisplayListFromGlyph( (glyphIndex - first) + listBase,
- glyphBuf,
- glyphSize,
- glyphMetricsFloat,
- chordalDeviation + ScaleFactor,
- extrusion,
- format))
- {
- __wglFree(glyphBuf);
- return FALSE; /*WGL_STATUS_FAILURE*/
- }
- }
-
-
- /*
- * Clean up temporary storage and return. If an error occurred,
- * clear all OpenGL error flags and return FAILURE status;
- * otherwise just return SUCCESS.
- */
- __wglFree(glyphBuf);
-
- SelectObject(hDC, hOldFont);
-
- if (_GLD_glGetError() == GL_NO_ERROR)
- return TRUE; /*WGL_STATUS_SUCCESS*/
- else
- {
- while (_GLD_glGetError() != GL_NO_ERROR)
- ;
- return FALSE; /*WGL_STATUS_FAILURE*/
- }
- }
-
-
-
-/*****************************************************************************
- * CreateHighResolutionFont
- *
- * Gets metrics for the current font and creates an equivalent font
- * scaled to the design units of the font.
- *
- *****************************************************************************/
-
-static HFONT
-CreateHighResolutionFont(HDC hDC)
- {
- UINT otmSize;
- OUTLINETEXTMETRIC *otm;
- LONG fontHeight, fontWidth, fontUnits;
- LOGFONT logFont;
-
- otmSize = GetOutlineTextMetrics(hDC, 0, NULL);
- if (otmSize == 0)
- return NULL;
-
- otm = (OUTLINETEXTMETRIC *) __wglMalloc(otmSize);
- if (otm == NULL)
- return NULL;
-
- otm->otmSize = otmSize;
- if (GetOutlineTextMetrics(hDC, otmSize, otm) == 0)
- return NULL;
-
- fontHeight = otm->otmTextMetrics.tmHeight -
- otm->otmTextMetrics.tmInternalLeading;
- fontWidth = otm->otmTextMetrics.tmAveCharWidth;
- fontUnits = (LONG) otm->otmEMSquare;
-
- ScaleFactor = 1.0F / (FLOAT) fontUnits;
-
- logFont.lfHeight = - ((LONG) fontUnits);
- logFont.lfWidth = (LONG)
- ((FLOAT) (fontWidth * fontUnits) / (FLOAT) fontHeight);
- logFont.lfEscapement = 0;
- logFont.lfOrientation = 0;
- logFont.lfWeight = otm->otmTextMetrics.tmWeight;
- logFont.lfItalic = otm->otmTextMetrics.tmItalic;
- logFont.lfUnderline = otm->otmTextMetrics.tmUnderlined;
- logFont.lfStrikeOut = otm->otmTextMetrics.tmStruckOut;
- logFont.lfCharSet = otm->otmTextMetrics.tmCharSet;
- logFont.lfOutPrecision = OUT_OUTLINE_PRECIS;
- logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
- logFont.lfQuality = DEFAULT_QUALITY;
- logFont.lfPitchAndFamily =
- otm->otmTextMetrics.tmPitchAndFamily & 0xf0;
- strcpy(logFont.lfFaceName,
- (char *)otm + (int)otm->otmpFaceName);
-
- hNewFont = CreateFontIndirect(&logFont);
- if (hNewFont == NULL)
- return NULL;
-
- __wglFree(otm);
-
- return hNewFont;
- }
-
-
-
-/*****************************************************************************
- * MakeDisplayListFromGlyph
- *
- * Converts the outline of a glyph to an OpenGL display list.
- *
- * Return value is nonzero for success, zero for failure.
- *
- * Does not check for OpenGL errors, so if the caller needs to know about them,
- * it should call glGetError().
- *****************************************************************************/
-
-static int
-MakeDisplayListFromGlyph( IN DWORD listName,
- IN UCHAR* glyphBuf,
- IN DWORD glyphSize,
- IN LPGLYPHMETRICSFLOAT glyphMetricsFloat,
- IN FLOAT chordalDeviation,
- IN FLOAT extrusion,
- IN INT format)
- {
- int status;
-
- _GLD_glNewList(listName, GL_COMPILE);
- status = DrawGlyph( glyphBuf,
- glyphSize,
- chordalDeviation,
- extrusion,
- format);
-
- _GLD_glTranslatef(glyphMetricsFloat->gmfCellIncX,
- glyphMetricsFloat->gmfCellIncY,
- 0.0F);
- _GLD_glEndList();
-
- return status;
- }
-
-
-
-/*****************************************************************************
- * DrawGlyph
- *
- * Converts the outline of a glyph to OpenGL drawing primitives, tessellating
- * as needed, and then draws the glyph. Tessellation of the quadratic splines
- * in the outline is controlled by "chordalDeviation", and the drawing
- * primitives (lines or polygons) are selected by "format".
- *
- * Return value is nonzero for success, zero for failure.
- *
- * Does not check for OpenGL errors, so if the caller needs to know about them,
- * it should call glGetError().
- *****************************************************************************/
-
-static int
-DrawGlyph( IN UCHAR* glyphBuf,
- IN DWORD glyphSize,
- IN FLOAT chordalDeviation,
- IN FLOAT extrusion,
- IN INT format)
- {
- INT status = 0;
- FLOAT* p;
- DWORD loop;
- DWORD point;
- GLUtesselator* tess = NULL;
-
-
- /*
- * Initialize the global buffer into which we place the outlines:
- */
- if (!InitLineBuf())
- goto exit;
-
-
- /*
- * Convert the glyph outlines to a set of polyline loops.
- * (See MakeLinesFromGlyph() for the format of the loop data
- * structure.)
- */
- if (!MakeLinesFromGlyph(glyphBuf, glyphSize, chordalDeviation))
- goto exit;
- p = LineBuf;
-
-
- /*
- * Now draw the loops in the appropriate format:
- */
- if (format == WGL_FONT_LINES)
- {
- /*
- * This is the easy case. Just draw the outlines.
- */
- for (loop = (DWORD) *p++; loop; --loop)
- {
- _GLD_glBegin(GL_LINE_LOOP);
- for (point = (DWORD) *p++; point; --point)
- {
- _GLD_glVertex2fv(p);
- p += 2;
- }
- _GLD_glEnd();
- }
- status = 1;
- }
-
- else if (format == WGL_FONT_POLYGONS)
- {
- double v[3];
- FLOAT *save_p = p;
- GLfloat z_value;
-
- /*
- * This is the hard case. We have to set up a tessellator
- * to convert the outlines into a set of polygonal
- * primitives, which the tessellator passes to some
- * auxiliary routines for drawing.
- */
- if (!LoadGLUTesselator())
- goto exit;
- if (!InitVertBuf())
- goto exit;
- if (!(tess = gluNewTessProc()))
- goto exit;
- gluTessCallbackProc(tess, GLU_BEGIN, (void(CALLBACK *)()) _GLD_glBegin);
- gluTessCallbackProc(tess, GLU_TESS_VERTEX_DATA,
- (void(CALLBACK *)()) TessVertexOutData);
- gluTessCallbackProc(tess, GLU_END, (void(CALLBACK *)()) _GLD_glEnd);
- gluTessCallbackProc(tess, GLU_ERROR, (void(CALLBACK *)()) TessError);
- gluTessCallbackProc(tess, GLU_TESS_COMBINE, (void(CALLBACK *)()) TessCombine);
- gluTessNormalProc(tess, 0.0F, 0.0F, 1.0F);
-
- TessErrorOccurred = 0;
- _GLD_glNormal3f(0.0f, 0.0f, 1.0f);
- v[2] = 0.0;
- z_value = 0.0f;
-
- gluTessBeginPolygonProc(tess, (void *)*(int *)&z_value);
- for (loop = (DWORD) *p++; loop; --loop)
- {
- gluTessBeginContourProc(tess);
-
- for (point = (DWORD) *p++; point; --point)
- {
- v[0] = p[0];
- v[1] = p[1];
- gluTessVertexProc(tess, v, p);
- p += 2;
- }
-
- gluTessEndContourProc(tess);
- }
- gluTessEndPolygonProc(tess);
-
- status = !TessErrorOccurred;
-
- /* Extrusion code */
- if (extrusion) {
- DWORD loops;
- GLfloat thickness = (GLfloat) -extrusion;
- FLOAT *vert, *vert2;
- DWORD count;
-
- p = save_p;
- loops = (DWORD) *p++;
-
- for (loop = 0; loop < loops; loop++) {
- GLfloat dx, dy, len;
- DWORD last;
-
- count = (DWORD) *p++;
- _GLD_glBegin(GL_QUAD_STRIP);
-
- /* Check if the first and last vertex are identical
- * so we don't draw the same quad twice.
- */
- vert = p + (count-1)*2;
- last = (p[0] == vert[0] && p[1] == vert[1]) ? count-1 : count;
-
- for (point = 0; point <= last; point++) {
- vert = p + 2 * (point % last);
- vert2 = p + 2 * ((point+1) % last);
-
- dx = vert[0] - vert2[0];
- dy = vert[1] - vert2[1];
- len = (GLfloat)sqrt(dx * dx + dy * dy);
-
- _GLD_glNormal3f(dy / len, -dx / len, 0.0f);
- _GLD_glVertex3f((GLfloat) vert[0],
- (GLfloat) vert[1], thickness);
- _GLD_glVertex3f((GLfloat) vert[0],
- (GLfloat) vert[1], 0.0f);
- }
-
- _GLD_glEnd();
- p += count*2;
- }
-
- /* Draw the back face */
- p = save_p;
- v[2] = thickness;
- _GLD_glNormal3f(0.0f, 0.0f, -1.0f);
- gluTessNormalProc(tess, 0.0F, 0.0F, -1.0F);
-
- gluTessBeginPolygonProc(tess, (void *)*(int *)&thickness);
-
- for (loop = (DWORD) *p++; loop; --loop)
- {
- count = (DWORD) *p++;
-
- gluTessBeginContourProc(tess);
-
- for (point = 0; point < count; point++)
- {
- vert = p + ((count-point-1)<<1);
- v[0] = vert[0];
- v[1] = vert[1];
- gluTessVertexProc(tess, v, vert);
- }
- p += count*2;
-
- gluTessEndContourProc(tess);
- }
- gluTessEndPolygonProc(tess);
- }
-
-#if DEBUG
- if (TessErrorOccurred)
- printf("Tessellation error %s\n",
- gluErrorString(TessErrorOccurred));
-#endif
- }
-
-
-exit:
- FreeLineBuf();
- if (tess)
- gluDeleteTessProc(tess);
- // UnloadGLUTesselator();
- FreeVertBuf();
- return status;
- }
-
-
-
-/*****************************************************************************
- * LoadGLUTesselator
- *
- * Maps the glu32.dll module and gets function pointers for the
- * tesselator functions.
- *****************************************************************************/
-
-static BOOL
-LoadGLUTesselator(void)
- {
- if (gluModuleHandle != NULL)
- return TRUE;
-
- {
- extern HINSTANCE hInstanceOpenGL;
- char *gluName = "GLU32.DLL";
-// char name[256];
-// char *ptr;
-// int len;
-
-/*
- len = GetModuleFileName(hInstanceOpenGL, name, 255);
- if (len != 0)
- {
- ptr = name+len-1;
- while (ptr > name && *ptr != '\\')
- ptr--;
- if (*ptr == '\\')
- ptr++;
- if (!stricmp(ptr, "cosmogl.dll"))
- {
- gluName = "COSMOGLU.DLL";
- }
- else if (!stricmp(ptr, "opengl32.dll"))
- {
- gluName = "GLU32.DLL";
- }
- }
-*/
- if ((gluModuleHandle = LoadLibrary(gluName)) == NULL)
- return FALSE;
- }
-
- if ((gluNewTessProc = (gluNewTessProto)
- GetProcAddress(gluModuleHandle, "gluNewTess")) == NULL)
- return FALSE;
-
- if ((gluDeleteTessProc = (gluDeleteTessProto)
- GetProcAddress(gluModuleHandle, "gluDeleteTess")) == NULL)
- return FALSE;
-
- if ((gluTessBeginPolygonProc = (gluTessBeginPolygonProto)
- GetProcAddress(gluModuleHandle, "gluTessBeginPolygon")) == NULL)
- return FALSE;
-
- if ((gluTessBeginContourProc = (gluTessBeginContourProto)
- GetProcAddress(gluModuleHandle, "gluTessBeginContour")) == NULL)
- return FALSE;
-
- if ((gluTessVertexProc = (gluTessVertexProto)
- GetProcAddress(gluModuleHandle, "gluTessVertex")) == NULL)
- return FALSE;
-
- if ((gluTessEndContourProc = (gluTessEndContourProto)
- GetProcAddress(gluModuleHandle, "gluTessEndContour")) == NULL)
- return FALSE;
-
- if ((gluTessEndPolygonProc = (gluTessEndPolygonProto)
- GetProcAddress(gluModuleHandle, "gluTessEndPolygon")) == NULL)
- return FALSE;
-
- if ((gluTessPropertyProc = (gluTessPropertyProto)
- GetProcAddress(gluModuleHandle, "gluTessProperty")) == NULL)
- return FALSE;
-
- if ((gluTessNormalProc = (gluTessNormalProto)
- GetProcAddress(gluModuleHandle, "gluTessNormal")) == NULL)
- return FALSE;
-
- if ((gluTessCallbackProc = (gluTessCallbackProto)
- GetProcAddress(gluModuleHandle, "gluTessCallback")) == NULL)
- return FALSE;
-
- return TRUE;
- }
-
-
-
-/*****************************************************************************
- * UnloadGLUTesselator
- *
- * Unmaps the glu32.dll module.
- *****************************************************************************/
-
-static BOOL
-UnloadGLUTesselator(void)
- {
- if (gluModuleHandle != NULL)
- if (FreeLibrary(gluModuleHandle) == FALSE)
- return FALSE;
- gluModuleHandle = NULL;
- }
-
-
-
-/*****************************************************************************
- * TessVertexOut
- *
- * Used by tessellator to handle output vertexes.
- *****************************************************************************/
-
-static void CALLBACK
-TessVertexOut(FLOAT p[3])
- {
- GLfloat v[2];
-
- v[0] = p[0] * ScaleFactor;
- v[1] = p[1] * ScaleFactor;
- _GLD_glVertex2fv(v);
- }
-
-static void CALLBACK
-TessVertexOutData(FLOAT p[3], GLfloat z)
-{
- GLfloat v[3];
-
- v[0] = (GLfloat) p[0];
- v[1] = (GLfloat) p[1];
- v[2] = z;
- _GLD_glVertex3fv(v);
-}
-
-
-/*****************************************************************************
- * TessCombine
- *
- * Used by tessellator to handle self-intersecting contours and degenerate
- * geometry.
- *****************************************************************************/
-
-static void CALLBACK
-TessCombine(double coords[3],
- void* vertex_data[4],
- FLOAT weight[4],
- void** outData)
- {
- if (!AppendToVertBuf((FLOAT) coords[0])
- || !AppendToVertBuf((FLOAT) coords[1])
- || !AppendToVertBuf((FLOAT) coords[2]))
- TessErrorOccurred = GL_OUT_OF_MEMORY;
- *outData = VertBuf + (VertBufIndex - 3);
- }
-
-
-
-/*****************************************************************************
- * TessError
- *
- * Saves the last tessellator error code in the global TessErrorOccurred.
- *****************************************************************************/
-
-static void CALLBACK
-TessError(GLenum error)
- {
- TessErrorOccurred = error;
- }
-
-
-
-/*****************************************************************************
- * MakeLinesFromGlyph
- *
- * Converts the outline of a glyph from the TTPOLYGON format to a simple
- * array of floating-point values containing one or more loops.
- *
- * The first element of the output array is a count of the number of loops.
- * The loop data follows this count. Each loop consists of a count of the
- * number of vertices it contains, followed by the vertices. Each vertex
- * is an X and Y coordinate. For example, a single triangle might be
- * described by this array:
- *
- * 1., 3., 0., 0., 1., 0., 0., 1.
- * ^ ^ ^ ^ ^ ^ ^ ^
- * #loops #verts x1 y1 x2 y2 x3 y3
- *
- * A two-loop glyph would look like this:
- *
- * 2., 3., 0.,0., 1.,0., 0.,1., 3., .2,.2, .4,.2, .2,.4
- *
- * Line segments from the TTPOLYGON are transferred to the output array in
- * the obvious way. Quadratic splines in the TTPOLYGON are converted to
- * collections of line segments
- *****************************************************************************/
-
-static int
-MakeLinesFromGlyph(IN UCHAR* glyphBuf,
- IN DWORD glyphSize,
- IN FLOAT chordalDeviation)
- {
- UCHAR* p;
- int status = 0;
-
-
- /*
- * Pick up all the polygons (aka loops) that make up the glyph:
- */
- if (!AppendToLineBuf(0.0F)) /* loop count at LineBuf[0] */
- goto exit;
-
- p = glyphBuf;
- while (p < glyphBuf + glyphSize)
- {
- if (!MakeLinesFromTTPolygon(&p, chordalDeviation))
- goto exit;
- LineBuf[0] += 1.0F; /* increment loop count */
- }
-
- status = 1;
-
-exit:
- return status;
- }
-
-
-
-/*****************************************************************************
- * MakeLinesFromTTPolygon
- *
- * Converts a TTPOLYGONHEADER and its associated curve structures into a
- * single polyline loop in the global LineBuf.
- *****************************************************************************/
-
-static int
-MakeLinesFromTTPolygon( IN OUT UCHAR** pp,
- IN FLOAT chordalDeviation)
- {
- DWORD polySize;
- UCHAR* polyStart;
- DWORD vertexCountIndex;
-
- /*
- * Record where the polygon data begins, and where the loop's
- * vertex count resides:
- */
- polyStart = *pp;
- vertexCountIndex = LineBufIndex;
- if (!AppendToLineBuf(0.0F))
- return 0;
-
- /*
- * Extract relevant data from the TTPOLYGONHEADER:
- */
- polySize = GetDWord(pp);
- if (GetDWord(pp) != TT_POLYGON_TYPE) /* polygon type */
- return 0;
- if (!AppendToLineBuf((FLOAT) GetFixed(pp))) /* first X coord */
- return 0;
- if (!AppendToLineBuf((FLOAT) GetFixed(pp))) /* first Y coord */
- return 0;
- LineBuf[vertexCountIndex] += 1.0F;
-
- /*
- * Process each of the TTPOLYCURVE structures in the polygon:
- */
- while (*pp < polyStart + polySize)
- if (!MakeLinesFromTTPolycurve( pp,
- vertexCountIndex,
- chordalDeviation))
- return 0;
-
- return 1;
- }
-
-
-
-/*****************************************************************************
- * MakeLinesFromTTPolyCurve
- *
- * Converts the lines and splines in a single TTPOLYCURVE structure to points
- * in the global LineBuf.
- *****************************************************************************/
-
-static int
-MakeLinesFromTTPolycurve( IN OUT UCHAR** pp,
- IN DWORD vertexCountIndex,
- IN FLOAT chordalDeviation)
- {
- WORD type;
- WORD pointCount;
-
-
- /*
- * Pick up the relevant fields of the TTPOLYCURVE structure:
- */
- type = (WORD) GetWord(pp);
- pointCount = (WORD) GetWord(pp);
-
- /*
- * Convert the "curve" to line segments:
- */
- if (type == TT_PRIM_LINE)
- return MakeLinesFromTTLine( pp,
- vertexCountIndex,
- pointCount);
- else if (type == TT_PRIM_QSPLINE)
- return MakeLinesFromTTQSpline( pp,
- vertexCountIndex,
- pointCount,
- chordalDeviation);
- else
- return 0;
- }
-
-
-
-/*****************************************************************************
- * MakeLinesFromTTLine
- *
- * Converts points from the polyline in a TT_PRIM_LINE structure to
- * equivalent points in the global LineBuf.
- *****************************************************************************/
-static int
-MakeLinesFromTTLine( IN OUT UCHAR** pp,
- IN DWORD vertexCountIndex,
- IN WORD pointCount)
- {
- /*
- * Just copy the line segments into the line buffer (converting
- * type as we go):
- */
- LineBuf[vertexCountIndex] += pointCount;
- while (pointCount--)
- {
- if (!AppendToLineBuf((FLOAT) GetFixed(pp)) /* X coord */
- || !AppendToLineBuf((FLOAT) GetFixed(pp))) /* Y coord */
- return 0;
- }
-
- return 1;
- }
-
-
-
-/*****************************************************************************
- * MakeLinesFromTTQSpline
- *
- * Converts points from the poly quadratic spline in a TT_PRIM_QSPLINE
- * structure to polyline points in the global LineBuf.
- *****************************************************************************/
-
-static int
-MakeLinesFromTTQSpline( IN OUT UCHAR** pp,
- IN DWORD vertexCountIndex,
- IN WORD pointCount,
- IN FLOAT chordalDeviation)
- {
- FLOAT x0, y0, x1, y1, x2, y2;
- WORD point;
-
- /*
- * Process each of the non-interpolated points in the outline.
- * To do this, we need to generate two interpolated points (the
- * start and end of the arc) for each non-interpolated point.
- * The first interpolated point is always the one most recently
- * stored in LineBuf, so we just extract it from there. The
- * second interpolated point is either the average of the next
- * two points in the QSpline, or the last point in the QSpline
- * if only one remains.
- */
- for (point = 0; point < pointCount - 1; ++point)
- {
- x0 = LineBuf[LineBufIndex - 2];
- y0 = LineBuf[LineBufIndex - 1];
-
- x1 = (FLOAT) GetFixed(pp);
- y1 = (FLOAT) GetFixed(pp);
-
- if (point == pointCount - 2)
- {
- /*
- * This is the last arc in the QSpline. The final
- * point is the end of the arc.
- */
- x2 = (FLOAT) GetFixed(pp);
- y2 = (FLOAT) GetFixed(pp);
- }
- else
- {
- /*
- * Peek at the next point in the input to compute
- * the end of the arc:
- */
- x2 = 0.5F * (x1 + (FLOAT) GetFixed(pp));
- y2 = 0.5F * (y1 + (FLOAT) GetFixed(pp));
- /*
- * Push the point back onto the input so it will
- * be reused as the next off-curve point:
- */
- *pp -= 8;
- }
-
- if (!MakeLinesFromArc( x0, y0,
- x1, y1,
- x2, y2,
- vertexCountIndex,
- chordalDeviation * chordalDeviation))
- return 0;
- }
-
- return 1;
- }
-
-
-
-/*****************************************************************************
- * MakeLinesFromArc
- *
- * Subdivides one arc of a quadratic spline until the chordal deviation
- * tolerance requirement is met, then places the resulting set of line
- * segments in the global LineBuf.
- *****************************************************************************/
-
-static int
-MakeLinesFromArc( IN FLOAT x0,
- IN FLOAT y0,
- IN FLOAT x1,
- IN FLOAT y1,
- IN FLOAT x2,
- IN FLOAT y2,
- IN DWORD vertexCountIndex,
- IN FLOAT chordalDeviationSquared)
- {
- FLOAT x01;
- FLOAT y01;
- FLOAT x12;
- FLOAT y12;
- FLOAT midPointX;
- FLOAT midPointY;
- FLOAT deltaX;
- FLOAT deltaY;
-
- /*
- * Calculate midpoint of the curve by de Casteljau:
- */
- x01 = 0.5F * (x0 + x1);
- y01 = 0.5F * (y0 + y1);
- x12 = 0.5F * (x1 + x2);
- y12 = 0.5F * (y1 + y2);
- midPointX = 0.5F * (x01 + x12);
- midPointY = 0.5F * (y01 + y12);
-
-
- /*
- * Estimate chordal deviation by the distance from the midpoint
- * of the curve to its non-interpolated control point. If this
- * distance is greater than the specified chordal deviation
- * constraint, then subdivide. Otherwise, generate polylines
- * from the three control points.
- */
- deltaX = midPointX - x1;
- deltaY = midPointY - y1;
- if (deltaX * deltaX + deltaY * deltaY > chordalDeviationSquared)
- {
- MakeLinesFromArc( x0, y0,
- x01, y01,
- midPointX, midPointY,
- vertexCountIndex,
- chordalDeviationSquared);
-
- MakeLinesFromArc( midPointX, midPointY,
- x12, y12,
- x2, y2,
- vertexCountIndex,
- chordalDeviationSquared);
- }
- else
- {
- /*
- * The "pen" is already at (x0, y0), so we don't need to
- * add that point to the LineBuf.
- */
- if (!AppendToLineBuf(x1)
- || !AppendToLineBuf(y1)
- || !AppendToLineBuf(x2)
- || !AppendToLineBuf(y2))
- return 0;
- LineBuf[vertexCountIndex] += 2.0F;
- }
-
- return 1;
- }
-
-
-
-/*****************************************************************************
- * InitLineBuf
- *
- * Initializes the global LineBuf and its associated size and current-element
- * counters.
- *****************************************************************************/
-
-static int
-InitLineBuf(void)
- {
- if (!(LineBuf = (FLOAT*)
- __wglMalloc((LineBufSize = LINE_BUF_QUANT) * sizeof(FLOAT))))
- return 0;
- LineBufIndex = 0;
- return 1;
- }
-
-
-
-/*****************************************************************************
- * InitVertBuf
- *
- * Initializes the global VertBuf and its associated size and current-element
- * counters.
- *****************************************************************************/
-
-static int
-InitVertBuf(void)
- {
- if (!(VertBuf = (FLOAT*)
- __wglMalloc((VertBufSize = VERT_BUF_QUANT) * sizeof(FLOAT))))
- return 0;
- VertBufIndex = 0;
- return 1;
- }
-
-
-
-/*****************************************************************************
- * AppendToLineBuf
- *
- * Appends one floating-point value to the global LineBuf array. Return value
- * is non-zero for success, zero for failure.
- *****************************************************************************/
-
-static int
-AppendToLineBuf(FLOAT value)
- {
- if (LineBufIndex >= LineBufSize)
- {
- FLOAT* f;
-
- f = (FLOAT*) __wglRealloc(LineBuf,
- (LineBufSize += LINE_BUF_QUANT) * sizeof(FLOAT));
- if (!f)
- return 0;
- LineBuf = f;
- }
- LineBuf[LineBufIndex++] = value;
- return 1;
- }
-
-
-
-/*****************************************************************************
- * AppendToVertBuf
- *
- * Appends one floating-point value to the global VertBuf array. Return value
- * is non-zero for success, zero for failure.
- *
- * Note that we can't realloc this one, because the tessellator is using
- * pointers into it.
- *****************************************************************************/
-
-static int
-AppendToVertBuf(FLOAT value)
- {
- if (VertBufIndex >= VertBufSize)
- return 0;
- VertBuf[VertBufIndex++] = value;
- return 1;
- }
-
-
-
-/*****************************************************************************
- * FreeLineBuf
- *
- * Cleans up vertex buffer structure.
- *****************************************************************************/
-
-static void
-FreeLineBuf(void)
- {
- if (LineBuf)
- {
- __wglFree(LineBuf);
- LineBuf = NULL;
- }
- }
-
-
-
-/*****************************************************************************
- * FreeVertBuf
- *
- * Cleans up vertex buffer structure.
- *****************************************************************************/
-
-static void
-FreeVertBuf(void)
- {
- if (VertBuf)
- {
- __wglFree(VertBuf);
- VertBuf = NULL;
- }
- }
-
-
-
-/*****************************************************************************
- * GetWord
- *
- * Fetch the next 16-bit word from a little-endian byte stream, and increment
- * the stream pointer to the next unscanned byte.
- *****************************************************************************/
-
-static long GetWord(UCHAR** p)
- {
- long value;
-
- value = ((*p)[1] << 8) + (*p)[0];
- *p += 2;
- return value;
- }
-
-
-
-/*****************************************************************************
- * GetDWord
- *
- * Fetch the next 32-bit word from a little-endian byte stream, and increment
- * the stream pointer to the next unscanned byte.
- *****************************************************************************/
-
-static long GetDWord(UCHAR** p)
- {
- long value;
-
- value = ((*p)[3] << 24) + ((*p)[2] << 16) + ((*p)[1] << 8) + (*p)[0];
- *p += 4;
- return value;
- }
-
-
-
-
-/*****************************************************************************
- * GetFixed
- *
- * Fetch the next 32-bit fixed-point value from a little-endian byte stream,
- * convert it to floating-point, and increment the stream pointer to the next
- * unscanned byte.
- *****************************************************************************/
-
-static double GetFixed(
- UCHAR** p)
-{
- long hiBits, loBits;
- double value;
-
- loBits = GetWord(p);
- hiBits = GetWord(p);
- value = (double) ((hiBits << 16) | loBits) / 65536.0;
-
- return value * ScaleFactor;
-}
-
-// ***********************************************************************
-
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x (Win32)
+*
+* Description: OpenGL window functions (wgl*).
+*
+****************************************************************************/
+
+#include "dglwgl.h"
+#ifdef _USE_GLD3_WGL
+#include "gld_driver.h"
+#endif
+
+#include "gl/glu.h" // MUST USE MICROSOFT'S GLU32!
+
+#ifndef _USE_GLD3_WGL
+extern DGL_mesaFuncs mesaFuncs;
+#endif
+
+// Need to export wgl* functions if using GLD3,
+// otherwise export GLD2 DGL_* functions.
+#ifdef _USE_GLD3_WGL
+#define _GLD_WGL_EXPORT(a) wgl##a
+#else
+#define _GLD_WGL_EXPORT(a) DGL_##a
+#endif
+
+// Calls into Mesa 4.x are different
+#ifdef _USE_GLD3_WGL
+#include "dlist.h"
+#include "drawpix.h"
+#include "get.h"
+#include "matrix.h"
+// NOTE: All the _GLD* macros now call the gl* functions direct.
+// This ensures that the correct internal pathway is taken. KeithH
+#define _GLD_glNewList glNewList
+#define _GLD_glBitmap glBitmap
+#define _GLD_glEndList glEndList
+#define _GLD_glDeleteLists glDeleteLists
+#define _GLD_glGetError glGetError
+#define _GLD_glTranslatef glTranslatef
+#define _GLD_glBegin glBegin
+#define _GLD_glVertex2fv glVertex2fv
+#define _GLD_glEnd glEnd
+#define _GLD_glNormal3f glNormal3f
+#define _GLD_glVertex3f glVertex3f
+#define _GLD_glVertex3fv glVertex3fv
+#else // _USE_GLD3_WGL
+#define _GLD_glNewList (*mesaFuncs.glNewList)
+#define _GLD_glBitmap (*mesaFuncs.glBitmap)
+#define _GLD_glEndList (*mesaFuncs.glEndList)
+#define _GLD_glDeleteLists (*mesaFuncs.glDeleteLists)
+#define _GLD_glGetError (*mesaFuncs.glGetError)
+#define _GLD_glTranslatef (*mesaFuncs.glTranslatef)
+#define _GLD_glBegin (*mesaFuncs.glBegin)
+#define _GLD_glVertex2fv (*mesaFuncs.glVertex2fv)
+#define _GLD_glEnd (*mesaFuncs.glEnd)
+#define _GLD_glNormal3f (*mesaFuncs.glNormal3f)
+#define _GLD_glVertex3f (*mesaFuncs.glVertex3f)
+#define _GLD_glVertex3fv (*mesaFuncs.glVertex3fv)
+#endif // _USE_GLD3_WGL
+
+// ***********************************************************************
+
+// Emulate SGI DDK calls.
+#define __wglMalloc(a) GlobalAlloc(GPTR, (a))
+#define __wglFree(a) GlobalFree((a))
+
+// ***********************************************************************
+
+// Mesa glu.h and MS glu.h call these different things...
+//#define GLUtesselator GLUtriangulatorObj
+//#define GLU_TESS_VERTEX_DATA GLU_VERTEX_DATA
+
+// For wglFontOutlines
+
+typedef GLUtesselator *(APIENTRY *gluNewTessProto)(void);
+typedef void (APIENTRY *gluDeleteTessProto)(GLUtesselator *tess);
+typedef void (APIENTRY *gluTessBeginPolygonProto)(GLUtesselator *tess, void *polygon_data);
+typedef void (APIENTRY *gluTessBeginContourProto)(GLUtesselator *tess);
+typedef void (APIENTRY *gluTessVertexProto)(GLUtesselator *tess, GLdouble coords[3], void *data);
+typedef void (APIENTRY *gluTessEndContourProto)(GLUtesselator *tess);
+typedef void (APIENTRY *gluTessEndPolygonProto)(GLUtesselator *tess);
+typedef void (APIENTRY *gluTessPropertyProto)(GLUtesselator *tess, GLenum which, GLdouble value);
+typedef void (APIENTRY *gluTessNormalProto)(GLUtesselator *tess, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRY *gluTessCallbackProto)(GLUtesselator *tess, GLenum which, void (CALLBACK *)());
+
+static HINSTANCE gluModuleHandle;
+static gluNewTessProto gluNewTessProc;
+static gluDeleteTessProto gluDeleteTessProc;
+static gluTessBeginPolygonProto gluTessBeginPolygonProc;
+static gluTessBeginContourProto gluTessBeginContourProc;
+static gluTessVertexProto gluTessVertexProc;
+static gluTessEndContourProto gluTessEndContourProc;
+static gluTessEndPolygonProto gluTessEndPolygonProc;
+static gluTessPropertyProto gluTessPropertyProc;
+static gluTessNormalProto gluTessNormalProc;
+static gluTessCallbackProto gluTessCallbackProc;
+
+static HFONT hNewFont, hOldFont;
+static FLOAT ScaleFactor;
+
+#define LINE_BUF_QUANT 4000
+#define VERT_BUF_QUANT 4000
+
+static FLOAT* LineBuf;
+static DWORD LineBufSize;
+static DWORD LineBufIndex;
+static FLOAT* VertBuf;
+static DWORD VertBufSize;
+static DWORD VertBufIndex;
+static GLenum TessErrorOccurred;
+
+static int AppendToLineBuf(
+ FLOAT value);
+
+static int AppendToVertBuf(
+ FLOAT value);
+
+static int DrawGlyph(
+ UCHAR* glyphBuf,
+ DWORD glyphSize,
+ FLOAT chordalDeviation,
+ FLOAT extrusion,
+ INT format);
+
+static void FreeLineBuf(void);
+
+static void FreeVertBuf(void);
+
+static long GetWord(
+ UCHAR** p);
+
+static long GetDWord(
+ UCHAR** p);
+
+static double GetFixed(
+ UCHAR** p);
+
+static int InitLineBuf(void);
+
+static int InitVertBuf(void);
+
+static HFONT CreateHighResolutionFont(
+ HDC hDC);
+
+static int MakeDisplayListFromGlyph(
+ DWORD listName,
+ UCHAR* glyphBuf,
+ DWORD glyphSize,
+ LPGLYPHMETRICSFLOAT glyphMetricsFloat,
+ FLOAT chordalDeviation,
+ FLOAT extrusion,
+ INT format);
+
+static BOOL LoadGLUTesselator(void);
+static BOOL UnloadGLUTesselator(void);
+
+static int MakeLinesFromArc(
+ FLOAT x0,
+ FLOAT y0,
+ FLOAT x1,
+ FLOAT y1,
+ FLOAT x2,
+ FLOAT y2,
+ DWORD vertexCountIndex,
+ FLOAT chordalDeviationSquared);
+
+static int MakeLinesFromGlyph( UCHAR* glyphBuf,
+ DWORD glyphSize,
+ FLOAT chordalDeviation);
+
+static int MakeLinesFromTTLine( UCHAR** pp,
+ DWORD vertexCountIndex,
+ WORD pointCount);
+
+static int MakeLinesFromTTPolycurve( UCHAR** pp,
+ DWORD vertexCountIndex,
+ FLOAT chordalDeviation);
+
+static int MakeLinesFromTTPolygon( UCHAR** pp,
+ FLOAT chordalDeviation);
+
+static int MakeLinesFromTTQSpline( UCHAR** pp,
+ DWORD vertexCountIndex,
+ WORD pointCount,
+ FLOAT chordalDeviation);
+
+static void CALLBACK TessCombine( double coords[3],
+ void* vertex_data[4],
+ FLOAT weight[4],
+ void** outData);
+
+static void CALLBACK TessError( GLenum error);
+
+static void CALLBACK TessVertexOutData( FLOAT p[3],
+ GLfloat z);
+
+// ***********************************************************************
+
+#ifdef GLD_THREADS
+#pragma message("compiling DGLWGL.C vars for multi-threaded support")
+extern CRITICAL_SECTION CriticalSection;
+extern DWORD dwTLSPixelFormat; // TLS index for current pixel format
+#endif
+int curPFD = 0; // Current PFD (static)
+
+// ***********************************************************************
+
+int dglGetPixelFormat(void)
+{
+#ifdef GLD_THREADS
+ int iPixelFormat;
+ // get thread-specific instance
+ if (glb.bMultiThreaded) {
+ __try {
+ iPixelFormat = (int)TlsGetValue(dwTLSPixelFormat);
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER) {
+ iPixelFormat = curPFD;
+ }
+ }
+ // get global static var
+ else {
+ iPixelFormat = curPFD;
+ }
+ return iPixelFormat;
+#else
+ return curPFD;
+#endif
+}
+
+// ***********************************************************************
+
+void dglSetPixelFormat(int iPixelFormat)
+{
+#ifdef GLD_THREADS
+ // set thread-specific instance
+ if (glb.bMultiThreaded) {
+ __try {
+ TlsSetValue(dwTLSPixelFormat, (LPVOID)iPixelFormat);
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER) {
+ curPFD = iPixelFormat;
+ }
+ }
+ // set global static var
+ else {
+ curPFD = iPixelFormat;
+ }
+#else
+ curPFD = iPixelFormat;
+#endif
+}
+
+// ***********************************************************************
+
+int APIENTRY _GLD_WGL_EXPORT(ChoosePixelFormat)(
+ HDC a,
+ CONST PIXELFORMATDESCRIPTOR *ppfd)
+{
+ DGL_pixelFormat *lpPF = glb.lpPF;
+
+ PIXELFORMATDESCRIPTOR ppfdBest;
+ int i;
+ int bestIndex = -1;
+ int numPixelFormats;
+ DWORD dwFlags;
+
+ char buf[128];
+ char cat[8];
+
+ DWORD dwAllFlags =
+ PFD_DRAW_TO_WINDOW |
+ PFD_DRAW_TO_BITMAP |
+ PFD_SUPPORT_GDI |
+ PFD_SUPPORT_OPENGL |
+ PFD_GENERIC_FORMAT |
+ PFD_NEED_PALETTE |
+ PFD_NEED_SYSTEM_PALETTE |
+ PFD_DOUBLEBUFFER |
+ PFD_STEREO |
+ /*PFD_SWAP_LAYER_BUFFERS |*/
+ PFD_DOUBLEBUFFER_DONTCARE |
+ PFD_STEREO_DONTCARE |
+ PFD_SWAP_COPY |
+ PFD_SWAP_EXCHANGE |
+ PFD_GENERIC_ACCELERATED |
+ 0;
+
+ // Validate license
+ if (!dglValidate())
+ return 0;
+
+ // List may not be built until dglValidate() is called! KeithH
+ lpPF = glb.lpPF;
+
+ //
+ // Lets print the input pixel format to the log
+ // ** Based on "wglinfo" by Nate Robins **
+ //
+ ddlogMessage(DDLOG_SYSTEM, "ChoosePixelFormat:\n");
+ ddlogMessage(DDLOG_INFO, "Input pixel format for ChoosePixelFormat:\n");
+ ddlogMessage(DDLOG_INFO,
+ " visual x bf lv rg d st r g b a ax dp st accum buffs ms\n");
+ ddlogMessage(DDLOG_INFO,
+ " id dep cl sp sz l ci b ro sz sz sz sz bf th cl r g b a ns b\n");
+ ddlogMessage(DDLOG_INFO,
+ "-----------------------------------------------------------------\n");
+ sprintf(buf, " . ");
+
+ sprintf(cat, "%2d ", ppfd->cColorBits);
+ strcat(buf, cat);
+ if(ppfd->dwFlags & PFD_DRAW_TO_WINDOW) sprintf(cat, "wn ");
+ else if(ppfd->dwFlags & PFD_DRAW_TO_BITMAP) sprintf(cat, "bm ");
+ else sprintf(cat, ". ");
+ strcat(buf, cat);
+
+ /* should find transparent pixel from LAYERPLANEDESCRIPTOR */
+ sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ sprintf(cat, "%2d ", ppfd->cColorBits);
+ strcat(buf, cat);
+
+ /* bReserved field indicates number of over/underlays */
+ if(ppfd->bReserved) sprintf(cat, " %d ", ppfd->bReserved);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ sprintf(cat, " %c ", ppfd->iPixelType == PFD_TYPE_RGBA ? 'r' : 'c');
+ strcat(buf, cat);
+
+ sprintf(cat, "%c ", ppfd->dwFlags & PFD_DOUBLEBUFFER ? 'y' : '.');
+ strcat(buf, cat);
+
+ sprintf(cat, " %c ", ppfd->dwFlags & PFD_STEREO ? 'y' : '.');
+ strcat(buf, cat);
+
+ if(ppfd->cRedBits && ppfd->iPixelType == PFD_TYPE_RGBA)
+ sprintf(cat, "%2d ", ppfd->cRedBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cGreenBits && ppfd->iPixelType == PFD_TYPE_RGBA)
+ sprintf(cat, "%2d ", ppfd->cGreenBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cBlueBits && ppfd->iPixelType == PFD_TYPE_RGBA)
+ sprintf(cat, "%2d ", ppfd->cBlueBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cAlphaBits && ppfd->iPixelType == PFD_TYPE_RGBA)
+ sprintf(cat, "%2d ", ppfd->cAlphaBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cAuxBuffers) sprintf(cat, "%2d ", ppfd->cAuxBuffers);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cDepthBits) sprintf(cat, "%2d ", ppfd->cDepthBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cStencilBits) sprintf(cat, "%2d ", ppfd->cStencilBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cAccumRedBits) sprintf(cat, "%2d ", ppfd->cAccumRedBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cAccumGreenBits) sprintf(cat, "%2d ", ppfd->cAccumGreenBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cAccumBlueBits) sprintf(cat, "%2d ", ppfd->cAccumBlueBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cAccumAlphaBits) sprintf(cat, "%2d ", ppfd->cAccumAlphaBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ /* no multisample in Win32 */
+ sprintf(cat, " . .\n");
+ strcat(buf, cat);
+
+ ddlogMessage(DDLOG_INFO, buf);
+ ddlogMessage(DDLOG_INFO,
+ "-----------------------------------------------------------------\n");
+ ddlogMessage(DDLOG_INFO, "\n");
+
+ //
+ // Examine the flags for correctness
+ //
+ dwFlags = ppfd->dwFlags;
+ if (dwFlags != (dwFlags & dwAllFlags))
+ {
+ /* error: bad dwFlags */
+ ddlogPrintf(DDLOG_WARN,
+ "ChoosePixelFormat: bad flags (0x%x)",
+ dwFlags & (~dwAllFlags));
+ // Mask illegal flags and continue
+ dwFlags = dwFlags & dwAllFlags;
+ }
+
+ switch (ppfd->iPixelType) {
+ case PFD_TYPE_RGBA:
+ case PFD_TYPE_COLORINDEX:
+ break;
+ default:
+ /* error: bad iPixelType */
+ ddlogMessage(DDLOG_WARN, "ChoosePixelFormat: bad pixel type\n");
+ return 0;
+ }
+
+ switch (ppfd->iLayerType) {
+ case PFD_MAIN_PLANE:
+ case PFD_OVERLAY_PLANE:
+ case PFD_UNDERLAY_PLANE:
+ break;
+ default:
+ /* error: bad iLayerType */
+ ddlogMessage(DDLOG_WARN, "ChoosePixelFormat: bad layer type\n");
+ return 0;
+ }
+
+ numPixelFormats = glb.nPixelFormatCount;
+
+ /* loop through candidate pixel format descriptors */
+ for (i=0; i<numPixelFormats; ++i) {
+ PIXELFORMATDESCRIPTOR ppfdCandidate;
+
+ memcpy(&ppfdCandidate, &lpPF[i].pfd, sizeof(PIXELFORMATDESCRIPTOR));
+
+ /*
+ ** Check attributes which must match
+ */
+ if (ppfd->iPixelType != ppfdCandidate.iPixelType) {
+ continue;
+ }
+
+ if (ppfd->iLayerType != ppfdCandidate.iLayerType) {
+ continue;
+ }
+
+ if (((dwFlags ^ ppfdCandidate.dwFlags) & dwFlags) &
+ (PFD_DRAW_TO_WINDOW | PFD_DRAW_TO_BITMAP |
+ PFD_SUPPORT_GDI | PFD_SUPPORT_OPENGL))
+ {
+ continue;
+ }
+
+ if (!(dwFlags & PFD_DOUBLEBUFFER_DONTCARE)) {
+ if ((dwFlags & PFD_DOUBLEBUFFER) !=
+ (ppfdCandidate.dwFlags & PFD_DOUBLEBUFFER))
+ {
+ continue;
+ }
+ }
+
+// if (!(dwFlags & PFD_STEREO_DONTCARE)) {
+ if ((dwFlags & PFD_STEREO) !=
+ (ppfdCandidate.dwFlags & PFD_STEREO))
+ {
+ continue;
+ }
+// }
+
+ if (ppfd->iPixelType==PFD_TYPE_RGBA
+ && ppfd->cAlphaBits && !ppfdCandidate.cAlphaBits) {
+ continue;
+ }
+
+ if (ppfd->iPixelType==PFD_TYPE_RGBA
+ && ppfd->cAccumBits && !ppfdCandidate.cAccumBits) {
+ continue;
+ }
+
+ if (ppfd->cDepthBits && !ppfdCandidate.cDepthBits) {
+ continue;
+ }
+
+ if (ppfd->cStencilBits && !ppfdCandidate.cStencilBits) {
+ continue;
+ }
+
+ if (ppfd->cAuxBuffers && !ppfdCandidate.cAuxBuffers) {
+ continue;
+ }
+
+ /*
+ ** See if candidate is better than the previous best choice
+ */
+ if (bestIndex == -1) {
+ ppfdBest = ppfdCandidate;
+ bestIndex = i;
+ continue;
+ }
+
+ if ((ppfd->cColorBits > ppfdBest.cColorBits &&
+ ppfdCandidate.cColorBits > ppfdBest.cColorBits) ||
+ (ppfd->cColorBits <= ppfdCandidate.cColorBits &&
+ ppfdCandidate.cColorBits < ppfdBest.cColorBits))
+ {
+ ppfdBest = ppfdCandidate;
+ bestIndex = i;
+ continue;
+ }
+
+ if (ppfd->iPixelType==PFD_TYPE_RGBA
+ && ppfd->cAlphaBits
+ && ppfdCandidate.cAlphaBits > ppfdBest.cAlphaBits)
+ {
+ ppfdBest = ppfdCandidate;
+ bestIndex = i;
+ continue;
+ }
+
+ if (ppfd->iPixelType==PFD_TYPE_RGBA
+ && ppfd->cAccumBits
+ && ppfdCandidate.cAccumBits > ppfdBest.cAccumBits)
+ {
+ ppfdBest = ppfdCandidate;
+ bestIndex = i;
+ continue;
+ }
+
+ if ((ppfd->cDepthBits > ppfdBest.cDepthBits &&
+ ppfdCandidate.cDepthBits > ppfdBest.cDepthBits) ||
+ (ppfd->cDepthBits <= ppfdCandidate.cDepthBits &&
+ ppfdCandidate.cDepthBits < ppfdBest.cDepthBits))
+ {
+ ppfdBest = ppfdCandidate;
+ bestIndex = i;
+ continue;
+ }
+
+ if (ppfd->cStencilBits &&
+ ppfdCandidate.cStencilBits > ppfdBest.cStencilBits)
+ {
+ ppfdBest = ppfdCandidate;
+ bestIndex = i;
+ continue;
+ }
+
+ if (ppfd->cAuxBuffers &&
+ ppfdCandidate.cAuxBuffers > ppfdBest.cAuxBuffers)
+ {
+ ppfdBest = ppfdCandidate;
+ bestIndex = i;
+ continue;
+ }
+ }
+
+ if (bestIndex != -1) {
+ ddlogPrintf(DDLOG_SYSTEM, "Pixel Format %d chosen as best match", bestIndex+1);
+ return bestIndex + 1;
+ }
+
+ // Return the pixelformat that has the most capabilities.
+ // ** NOTE: This is only possible due to the way the list
+ // of pixelformats is built. **
+ // Now picks best pixelformat. KeithH
+ bestIndex = numPixelFormats; // most capable double buffer format
+ ddlogPrintf(DDLOG_SYSTEM, "Pixel Format %d chosen by default", bestIndex);
+ return (bestIndex);
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(CopyContext)(
+ HGLRC a,
+ HGLRC b,
+ UINT c)
+{
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+ UNSUPPORTED("wglCopyContext")
+ return FALSE; // Failed
+}
+
+// ***********************************************************************
+
+HGLRC APIENTRY _GLD_WGL_EXPORT(CreateContext)(
+ HDC a)
+{
+ int ipf;
+
+ // Validate license
+ if (!dglValidate())
+ return 0;
+
+ // Check that the current PFD is valid
+ ipf = dglGetPixelFormat();
+ if (!IsValidPFD(ipf))
+ return (HGLRC)0;
+
+ return dglCreateContext(a, &glb.lpPF[ipf-1]);
+}
+
+// ***********************************************************************
+
+HGLRC APIENTRY _GLD_WGL_EXPORT(CreateLayerContext)(
+ HDC a,
+ int b)
+{
+ // Validate license
+ if (!dglValidate())
+ return 0;
+
+ UNSUPPORTED("wglCreateLayerContext")
+ return NULL; // Failed
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(DeleteContext)(
+ HGLRC a)
+{
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ return dglDeleteContext(a);
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(DescribeLayerPlane)(
+ HDC hDC,
+ int iPixelFormat,
+ int iLayerPlane,
+ UINT nBytes,
+ LPLAYERPLANEDESCRIPTOR plpd)
+{
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ UNSUPPORTED("DGL_DescribeLayerPlane")
+
+// gldLogPrintf(GLDLOG_INFO, "DescribeLayerPlane: %d, %d", iPixelFormat, iLayerPlane);
+
+ return FALSE;
+}
+
+// ***********************************************************************
+
+int APIENTRY _GLD_WGL_EXPORT(DescribePixelFormat)(
+ HDC a,
+ int b,
+ UINT c,
+ LPPIXELFORMATDESCRIPTOR d)
+{
+ UINT nSize;
+
+ // Validate license
+ if (!dglValidate())
+ return 0;
+
+ if (d == NULL) // Calling app requires max number of PF's
+ return glb.nPixelFormatCount;
+
+ // The supplied buffer may be larger than the info that we
+ // will be copying.
+ if (c > sizeof(PIXELFORMATDESCRIPTOR))
+ nSize = sizeof(PIXELFORMATDESCRIPTOR);
+ else
+ nSize = c;
+
+ // Setup an empty PFD before doing validation check
+ memset(d, 0, nSize);
+ d->nSize = nSize;
+ d->nVersion = 1;
+
+ if (!IsValidPFD(b))
+ return 0; // Bail if PFD index is invalid
+
+ memcpy(d, &glb.lpPF[b-1].pfd, nSize);
+
+ return glb.nPixelFormatCount;
+}
+
+// ***********************************************************************
+
+HGLRC APIENTRY _GLD_WGL_EXPORT(GetCurrentContext)(void)
+{
+ // Validate license
+ if (!dglValidate())
+ return 0;
+
+ return dglGetCurrentContext();
+}
+
+// ***********************************************************************
+
+HDC APIENTRY _GLD_WGL_EXPORT(GetCurrentDC)(void)
+{
+ // Validate license
+ if (!dglValidate())
+ return 0;
+
+ return dglGetCurrentDC();
+}
+
+// ***********************************************************************
+
+PROC APIENTRY _GLD_WGL_EXPORT(GetDefaultProcAddress)(
+ LPCSTR a)
+{
+ // Validate license
+ if (!dglValidate())
+ return NULL;
+
+ UNSUPPORTED("DGL_GetDefaultProcAddress")
+ return NULL;
+}
+
+// ***********************************************************************
+
+int APIENTRY _GLD_WGL_EXPORT(GetLayerPaletteEntries)(
+ HDC a,
+ int b,
+ int c,
+ int d,
+ COLORREF *e)
+{
+ // Validate license
+ if (!dglValidate())
+ return 0;
+
+ UNSUPPORTED("DGL_GetLayerPaletteEntries")
+ return 0;
+}
+
+// ***********************************************************************
+
+int APIENTRY _GLD_WGL_EXPORT(GetPixelFormat)(
+ HDC a)
+{
+ // Validate license
+ if (!dglValidate())
+ return 0;
+
+ return dglGetPixelFormat();
+}
+
+// ***********************************************************************
+
+PROC APIENTRY _GLD_WGL_EXPORT(GetProcAddress)(
+ LPCSTR a)
+{
+ PROC dglGetProcAddressD3D(LPCSTR a);
+
+ // Validate license
+ if (!dglValidate())
+ return NULL;
+
+#ifdef _USE_GLD3_WGL
+ return _gldDriver.wglGetProcAddress(a);
+#else
+ return dglGetProcAddressD3D(a);
+#endif
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(MakeCurrent)(
+ HDC a,
+ HGLRC b)
+{
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ return dglMakeCurrent(a, b);
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(RealizeLayerPalette)(
+ HDC a,
+ int b,
+ BOOL c)
+{
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ UNSUPPORTED("DGL_RealizeLayerPalette")
+ return FALSE;
+}
+
+// ***********************************************************************
+
+int APIENTRY _GLD_WGL_EXPORT(SetLayerPaletteEntries)(
+ HDC a,
+ int b,
+ int c,
+ int d,
+ CONST COLORREF *e)
+{
+ // Validate license
+ if (!dglValidate())
+ return 0;
+
+ UNSUPPORTED("DGL_SetLayerPaletteEntries")
+ return 0;
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(SetPixelFormat)(
+ HDC a,
+ int b,
+ CONST PIXELFORMATDESCRIPTOR *c)
+{
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ if (IsValidPFD(b)) {
+ ddlogPrintf(DDLOG_SYSTEM, "SetPixelFormat: PixelFormat %d has been set", b);
+ dglSetPixelFormat(b);
+ return TRUE;
+ } else {
+ ddlogPrintf(DDLOG_ERROR,
+ "SetPixelFormat: PixelFormat %d is invalid and cannot be set", b);
+ return FALSE;
+ }
+}
+
+// ***********************************************************************
+/*
+ * Share lists between two gl_context structures.
+ * This was added for WIN32 WGL function support, since wglShareLists()
+ * must be called *after* wglCreateContext() with valid GLRCs. (DaveM)
+ */
+//
+// Copied from GLD2.x. KeithH
+//
+static GLboolean _gldShareLists(
+ struct gl_context *ctx1,
+ struct gl_context *ctx2)
+{
+ /* Sanity check context pointers */
+ if (ctx1 == NULL || ctx2 == NULL)
+ return GL_FALSE;
+ /* Sanity check shared list pointers */
+ if (ctx1->Shared == NULL || ctx2->Shared == NULL)
+ return GL_FALSE;
+ /* Decrement reference count on sharee to release previous list */
+ ctx2->Shared->RefCount--;
+#if 0 /* 3DStudio exits on this memory release */
+ if (ctx2->Shared->RefCount == 0)
+ free_shared_state(ctx2, ctx2->Shared);
+#endif
+ /* Re-assign list from sharer to sharee and increment reference count */
+ ctx2->Shared = ctx1->Shared;
+ ctx1->Shared->RefCount++;
+ return GL_TRUE;
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(ShareLists)(
+ HGLRC a,
+ HGLRC b)
+{
+ DGL_ctx *dgl1, *dgl2;
+
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ // Mesa supports shared lists, but you need to supply the shared
+ // GL context info when calling gl_create_context(). An auxiliary
+ // function gl_share_lists() has been added to update the shared
+ // list info after the GL contexts have been created. (DaveM)
+ dgl1 = dglGetContextAddress(a);
+ dgl2 = dglGetContextAddress(b);
+ if (dgl1->bAllocated && dgl2->bAllocated) {
+#ifdef _USE_GLD3_WGL
+ return _gldShareLists(dgl1->glCtx, dgl2->glCtx);
+#else
+ return (*mesaFuncs.gl_share_lists)(dgl1->glCtx, dgl2->glCtx);
+#endif
+ }
+ return FALSE;
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(SwapBuffers)(
+ HDC a)
+{
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ return dglSwapBuffers(a);
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(SwapLayerBuffers)(
+ HDC a,
+ UINT b)
+{
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ return dglSwapBuffers(a);
+}
+
+// ***********************************************************************
+
+// ***********************************************************************
+// Note: This ResizeBuffers() function may be called from
+// either MESA glViewport() or GLD wglMakeCurrent().
+
+BOOL dglWglResizeBuffers(
+ struct gl_context *ctx,
+ BOOL bDefaultDriver)
+{
+ DGL_ctx *dgl = NULL;
+ RECT rcScreenRect;
+ DWORD dwWidth;
+ DWORD dwHeight;
+ DDSURFACEDESC2 ddsd2;
+ DDSCAPS2 ddscaps2;
+ IDirectDrawClipper *lpddClipper = NULL;
+ DWORD dwFlags;
+ HRESULT hResult;
+
+ DWORD dwMemoryType;
+
+ int i;
+ struct gl_texture_object *tObj;
+ struct gl_texture_image *image;
+
+ BOOL bWasFullscreen;
+ BOOL bSaveDesktop;
+ BOOL bFullScrnWin = FALSE;
+ DDSURFACEDESC2 ddsd2DisplayMode;
+
+ DDBLTFX ddbltfx;
+ POINT pt;
+ RECT rcDst;
+#ifdef _USE_GLD3_WGL
+ GLD_displayMode glddm;
+#endif
+
+#define DDLOG_CRITICAL_OR_WARN (bDefaultDriver ? DDLOG_WARN : DDLOG_CRITICAL)
+
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ // Sanity checks
+ if (ctx == NULL)
+ return FALSE;
+ dgl = ctx->DriverCtx;
+ if (dgl == NULL)
+ return FALSE;
+
+ // Get the window size and calculate its dimensions
+ if (dgl->hWnd == NULL) {
+ // Check for non-window DC = memory DC ?
+ if (GetClipBox(dgl->hDC, &rcScreenRect) == ERROR)
+ SetRect(&rcScreenRect, 0, 0, 0, 0);
+ }
+ else if (!GetClientRect(dgl->hWnd, &rcScreenRect))
+ SetRect(&rcScreenRect, 0, 0, 0, 0);
+ dwWidth = rcScreenRect.right - rcScreenRect.left;
+ dwHeight = rcScreenRect.bottom - rcScreenRect.top;
+ CopyRect(&dgl->rcScreenRect, &rcScreenRect);
+
+ // This will occur on Alt-Tab
+ if ((dwWidth == 0) && (dwHeight == 0)) {
+ //dgl->bCanRender = FALSE;
+ return TRUE; // No resize possible!
+ }
+
+ // Some apps zero only 1 dimension for non-visible window... (DaveM)
+ if ((dwWidth == 0) || (dwHeight == 0)) {
+ dwWidth = 8;
+ dwHeight = 8;
+ }
+
+ // Test to see if a resize is required.
+ // Note that the dimensions will be the same if a prior resize attempt failed.
+ if ((dwWidth == dgl->dwWidth) && (dwHeight == dgl->dwHeight) && bDefaultDriver) {
+ return TRUE; // No resize required
+ }
+
+ ddlogPrintf(DDLOG_SYSTEM, "dglResize: %dx%d", dwWidth, dwHeight);
+#ifndef _USE_GLD3_WGL
+ // Work out where we want our surfaces created
+ dwMemoryType = (bDefaultDriver) ? glb.dwMemoryType : DDSCAPS_SYSTEMMEMORY;
+#endif // _USE_GLD3_WGL
+
+ // Note previous fullscreen vs window display status
+ bWasFullscreen = dgl->bFullscreen;
+
+#ifdef _USE_GLD3_WGL
+ if (_gldDriver.GetDisplayMode(dgl, &glddm)) {
+ if ( (dwWidth == glddm.Width) &&
+ (dwHeight == glddm.Height) ) {
+ bFullScrnWin = TRUE;
+ }
+ if (bFullScrnWin && glb.bPrimary && !glb.bFullscreenBlit && !glb.bDirectDrawPersistant) {
+ dgl->bFullscreen = TRUE;
+ ddlogMessage(DDLOG_INFO, "Fullscreen window after resize.\n");
+ }
+ else {
+ dgl->bFullscreen = FALSE;
+ ddlogMessage(DDLOG_INFO, "Non-Fullscreen window after resize.\n");
+ }
+ // Cache the display mode dimensions
+ dgl->dwModeWidth = glddm.Width;
+ dgl->dwModeHeight = glddm.Height;
+ }
+
+ // Clamp the effective window dimensions to primary surface.
+ // We need to do this for D3D viewport dimensions even if wide
+ // surfaces are supported. This also is a good idea for handling
+ // whacked-out window dimensions passed for non-drawable windows
+ // like Solid Edge. (DaveM)
+ if (dgl->dwWidth > glddm.Width)
+ dgl->dwWidth = glddm.Width;
+ if (dgl->dwHeight > glddm.Height)
+ dgl->dwHeight = glddm.Height;
+#else // _USE_GLD3_WGL
+ // Window resize may have changed to fullscreen
+ ZeroMemory(&ddsd2DisplayMode, sizeof(ddsd2DisplayMode));
+ ddsd2DisplayMode.dwSize = sizeof(ddsd2DisplayMode);
+ hResult = IDirectDraw4_GetDisplayMode(
+ dgl->lpDD4,
+ &ddsd2DisplayMode);
+ if (SUCCEEDED(hResult)) {
+ if ( (dwWidth == ddsd2DisplayMode.dwWidth) &&
+ (dwHeight == ddsd2DisplayMode.dwHeight) ) {
+ bFullScrnWin = TRUE;
+ }
+ if (bFullScrnWin && glb.bPrimary && !glb.bFullscreenBlit && !glb.bDirectDrawPersistant) {
+ dgl->bFullscreen = TRUE;
+ ddlogMessage(DDLOG_INFO, "Fullscreen window after resize.\n");
+ }
+ else {
+ dgl->bFullscreen = FALSE;
+ ddlogMessage(DDLOG_INFO, "Non-Fullscreen window after resize.\n");
+ }
+ // Cache the display mode dimensions
+ dgl->dwModeWidth = ddsd2DisplayMode.dwWidth;
+ dgl->dwModeHeight = ddsd2DisplayMode.dwHeight;
+ }
+
+ // Clamp the effective window dimensions to primary surface.
+ // We need to do this for D3D viewport dimensions even if wide
+ // surfaces are supported. This also is a good idea for handling
+ // whacked-out window dimensions passed for non-drawable windows
+ // like Solid Edge. (DaveM)
+ if (dgl->dwWidth > ddsd2DisplayMode.dwWidth)
+ dgl->dwWidth = ddsd2DisplayMode.dwWidth;
+ if (dgl->dwHeight > ddsd2DisplayMode.dwHeight)
+ dgl->dwHeight = ddsd2DisplayMode.dwHeight;
+#endif // _USE_GLD3_WGL
+
+ // Note if fullscreen vs window display has changed?
+ bSaveDesktop = (!bWasFullscreen && !dgl->bFullscreen) ? TRUE : FALSE;
+ // Save the desktop primary surface from being destroyed
+ // whenever remaining in windowed mode, since the stereo mode
+ // switches are expensive...
+
+#ifndef _USE_GLD3_WGL
+ // Don't need to re-allocate persistant buffers. (DaveM)
+ // Though we should clear the back buffers to hide artifacts.
+ if (glb.bDirectDrawPersistant && glb.bPersistantBuffers) {
+ dgl->dwWidth = dwWidth;
+ dgl->dwHeight = dwHeight;
+ ZeroMemory(&ddbltfx, sizeof(ddbltfx));
+ ddbltfx.dwSize = sizeof(ddbltfx);
+ ddbltfx.dwFillColor = dgl->dwClearColorPF;
+ IDirectDrawSurface4_Blt(dgl->lpBack4, &rcScreenRect, NULL, NULL,
+ DDBLT_WAIT | DDBLT_COLORFILL, &ddbltfx);
+ return TRUE;
+ }
+
+ // Ensure all rendering is complete
+ if (ctx->Driver.Finish)
+ (*ctx->Driver.Finish)(ctx);
+ if (dgl->bSceneStarted == TRUE) {
+ IDirect3DDevice3_EndScene(dgl->lpDev3);
+ dgl->bSceneStarted = FALSE;
+ }
+#endif // _USE_GLD3_WGL
+ dgl->bCanRender = FALSE;
+
+#ifdef GLD_THREADS
+ // Serialize access to DirectDraw and DDS operations
+ if (glb.bMultiThreaded)
+ EnterCriticalSection(&CriticalSection);
+#endif
+
+#ifndef _USE_GLD3_WGL
+ // Release existing surfaces
+ RELEASE(dgl->lpDev3);
+ RELEASE(dgl->lpDepth4);
+ RELEASE(dgl->lpBack4);
+ if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary)
+ ;
+ else
+ RELEASE(dgl->lpFront4);
+#endif // _USE_GLD3_WGL
+ dgl->dwWidth = dwWidth;
+ dgl->dwHeight = dwHeight;
+
+ // Set defaults
+ dgl->dwModeWidth = dgl->dwWidth;
+ dgl->dwModeHeight = dgl->dwHeight;
+
+#ifdef _USE_GLD3_WGL
+ if (!_gldDriver.ResizeDrawable(dgl, bDefaultDriver, glb.bDirectDrawPersistant, glb.bPersistantBuffers))
+ goto cleanup_and_return_with_error;
+#else // _USE_GLD3_WGL
+
+ if (dgl->bFullscreen) {
+ //
+ // FULLSCREEN
+ //
+
+ // Disable warning popups when in fullscreen mode
+ ddlogWarnOption(FALSE);
+
+ // Have to release the persistant DirectDraw primary surface
+ // if switching to fullscreen mode. So if application wants
+ // persistant display in fullscreen mode, a fullscreen-size
+ // window should be used instead via fullscreen-blit option.
+ if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary) {
+ RELEASE(glb.lpPrimary4);
+ glb.bDirectDrawPrimary = FALSE;
+ }
+
+ dwFlags = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT;
+ if (glb.bFastFPU)
+ dwFlags |= DDSCL_FPUSETUP; // optional
+ hResult = IDirectDraw4_SetCooperativeLevel(dgl->lpDD4, dgl->hWnd, dwFlags);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Unable to set Exclusive Fullscreen mode", hResult);
+ goto cleanup_and_return_with_error;
+ }
+
+ hResult = IDirectDraw4_SetDisplayMode(dgl->lpDD4,
+ dgl->dwModeWidth,
+ dgl->dwModeHeight,
+ dgl->dwBPP,
+ 0,
+ 0);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: SetDisplayMode failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+
+ // ** The display mode has changed, so dont use MessageBox! **
+
+ ZeroMemory(&ddsd2, sizeof(ddsd2));
+ ddsd2.dwSize = sizeof(ddsd2);
+
+ if (dgl->bDoubleBuffer) {
+ // Double buffered
+ // Primary surface
+ ddsd2.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
+ DDSCAPS_FLIP |
+ DDSCAPS_COMPLEX |
+ DDSCAPS_3DDEVICE |
+ dwMemoryType;
+ ddsd2.dwBackBufferCount = 1;
+ hResult = IDirectDraw4_CreateSurface(dgl->lpDD4, &ddsd2, &dgl->lpFront4, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: CreateSurface (primary) failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+ // Render target surface
+ ZeroMemory(&ddscaps2, sizeof(ddscaps2)); // Clear the entire struct.
+ ddscaps2.dwCaps = DDSCAPS_BACKBUFFER;
+ hResult = IDirectDrawSurface4_GetAttachedSurface(dgl->lpFront4, &ddscaps2, &dgl->lpBack4);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: GetAttachedSurface failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+ } else {
+ // Single buffered
+ // Primary surface
+ ddsd2.dwFlags = DDSD_CAPS;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
+ //DDSCAPS_3DDEVICE |
+ dwMemoryType;
+
+ hResult = IDirectDraw4_CreateSurface(dgl->lpDD4, &ddsd2, &dgl->lpFront4, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: CreateSurface (primary) failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+
+ dgl->lpBack4 = NULL;
+ }
+ } else {
+ // WINDOWED
+
+ // OK to enable warning popups in windowed mode
+ ddlogWarnOption(glb.bMessageBoxWarnings);
+
+ // Ditto if persistant DirectDraw primary
+ if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary)
+ goto DoClipperOnly;
+
+ // WINDOWED
+ dwFlags = DDSCL_NORMAL;
+ if (glb.bMultiThreaded)
+ dwFlags |= DDSCL_MULTITHREADED;
+ if (glb.bFastFPU)
+ dwFlags |= DDSCL_FPUSETUP; // optional
+ hResult = IDirectDraw4_SetCooperativeLevel(dgl->lpDD4,
+ dgl->hWnd,
+ dwFlags);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Unable to set Normal coop level", hResult);
+ goto cleanup_and_return_with_error;
+ }
+ // Primary surface
+ ZeroMemory(&ddsd2, sizeof(ddsd2));
+ ddsd2.dwSize = sizeof(ddsd2);
+ ddsd2.dwFlags = DDSD_CAPS;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+ hResult = IDirectDraw4_CreateSurface(dgl->lpDD4, &ddsd2, &dgl->lpFront4, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: CreateSurface (primary) failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+
+ // Cache the primary surface for persistant DirectDraw state
+ if (glb.bDirectDrawPersistant && !glb.bDirectDrawPrimary) {
+ glb.lpPrimary4 = dgl->lpFront4;
+ IDirectDrawSurface4_AddRef(glb.lpPrimary4);
+ glb.bDirectDrawPrimary = TRUE;
+ }
+
+ // Clipper object
+ hResult = DirectDrawCreateClipper(0, &lpddClipper, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: CreateClipper failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+ hResult = IDirectDrawClipper_SetHWnd(lpddClipper, 0, dgl->hWnd);
+ if (FAILED(hResult)) {
+ RELEASE(lpddClipper);
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: SetHWnd failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+ hResult = IDirectDrawSurface4_SetClipper(dgl->lpFront4, lpddClipper);
+ RELEASE(lpddClipper); // We have finished with it.
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: SetClipper failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+DoClipperOnly:
+ // Update the window for the original clipper
+ if ((glb.bDirectDrawPersistant && glb.bDirectDrawPrimary) || bSaveDesktop) {
+ IDirectDrawSurface4_GetClipper(dgl->lpFront4, &lpddClipper);
+ IDirectDrawClipper_SetHWnd(lpddClipper, 0, dgl->hWnd);
+ RELEASE(lpddClipper);
+ }
+
+ if (dgl->bDoubleBuffer) {
+ // Render target surface
+ ZeroMemory(&ddsd2, sizeof(ddsd2));
+ ddsd2.dwSize = sizeof(ddsd2);
+ ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
+ ddsd2.dwWidth = dgl->dwWidth;
+ ddsd2.dwHeight = dgl->dwHeight;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_3DDEVICE |
+ DDSCAPS_OFFSCREENPLAIN |
+ dwMemoryType;
+ hResult = IDirectDraw4_CreateSurface(dgl->lpDD4, &ddsd2, &dgl->lpBack4, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Create Backbuffer failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+
+ } else {
+ dgl->lpBack4 = NULL;
+ }
+ }
+
+ //
+ // Now create the Zbuffer
+ //
+ if (dgl->bDepthBuffer) {
+ // Get z-buffer dimensions from the render target
+ // Setup the surface desc for the z-buffer.
+ ZeroMemory(&ddsd2, sizeof(ddsd2));
+ ddsd2.dwSize = sizeof(ddsd2);
+ ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | dwMemoryType;
+ ddsd2.dwWidth = dgl->dwWidth;
+ ddsd2.dwHeight = dgl->dwHeight;
+ memcpy(&ddsd2.ddpfPixelFormat,
+ &glb.lpZBufferPF[dgl->iZBufferPF],
+ sizeof(DDPIXELFORMAT) );
+
+ // Create a z-buffer
+ hResult = IDirectDraw4_CreateSurface(dgl->lpDD4, &ddsd2, &dgl->lpDepth4, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: CreateSurface (ZBuffer) failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+
+ // Attach Zbuffer to render target
+ TRY(IDirectDrawSurface4_AddAttachedSurface(
+ dgl->bDoubleBuffer ? dgl->lpBack4 : dgl->lpFront4,
+ dgl->lpDepth4),
+ "dglResize: Attach Zbuffer");
+
+ }
+
+ // Clear the newly resized back buffers for the window client area.
+ ZeroMemory(&ddbltfx, sizeof(ddbltfx));
+ ddbltfx.dwSize = sizeof(ddbltfx);
+ ddbltfx.dwFillColor = dgl->dwClearColorPF;
+ IDirectDrawSurface4_Blt(dgl->lpBack4, &rcScreenRect, NULL, NULL,
+ DDBLT_WAIT | DDBLT_COLORFILL, &ddbltfx);
+
+ //
+ // Now that we have a zbuffer we can create the 3D device
+ //
+ hResult = IDirect3D3_CreateDevice(dgl->lpD3D3,
+ bDefaultDriver ? &glb.d3dGuid : &IID_IDirect3DRGBDevice,
+ dgl->bDoubleBuffer ? dgl->lpBack4 : dgl->lpFront4,
+ &dgl->lpDev3,
+ NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Could not create Direct3D device", hResult);
+ goto cleanup_and_return_with_error;
+ }
+
+ // We must do this as soon as the device is created
+ dglInitStateCaches(dgl);
+
+ //
+ // Viewport
+ //
+ hResult = IDirect3DDevice3_AddViewport(dgl->lpDev3, dgl->lpViewport3);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: AddViewport failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+
+ // Initialise the viewport
+ dgl->d3dViewport.dwSize = sizeof(dgl->d3dViewport);
+ dgl->d3dViewport.dwX = 0;
+ dgl->d3dViewport.dwY = 0;
+ dgl->d3dViewport.dwWidth = dgl->dwWidth;
+ dgl->d3dViewport.dwHeight = dgl->dwHeight;
+ dgl->d3dViewport.dvClipX = 0;
+ dgl->d3dViewport.dvClipY = 0;
+ dgl->d3dViewport.dvClipWidth = dgl->dwWidth;
+ dgl->d3dViewport.dvClipHeight = dgl->dwHeight;
+// dgl->d3dViewport.dvMinZ = 0.0f;
+// dgl->d3dViewport.dvMaxZ = 1.0f;
+ TRY(IDirect3DViewport3_SetViewport2(dgl->lpViewport3, &dgl->d3dViewport),
+ "dglResize: SetViewport2");
+
+ hResult = IDirect3DDevice3_SetCurrentViewport(dgl->lpDev3, dgl->lpViewport3);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: SetCurrentViewport failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+
+ // (Re)Initialise all the Direct3D renderstates
+ dglInitStateD3D(ctx);
+
+ // Now we have to recreate all of our textures (+ mipmaps).
+ // Walk over all textures in hash table
+ // XXX what about the default texture objects (id=0)?
+ {
+ struct _mesa_HashTable *textures = ctx->Shared->TexObjects;
+ GLuint id;
+ for (id = _mesa_HashFirstEntry(textures);
+ id;
+ id = _mesa_HashNextEntry(textures, id)) {
+ tObj = (struct gl_texture_object *) _mesa_HashLookup(textures, id);
+ if (tObj->DriverData) {
+ // We could call our TexImage function directly, but it's
+ // safer to use the driver pointer.
+ for (i=0; i<MAX_TEXTURE_LEVELS; i++) {
+ image = tObj->Image[i];
+ if (image) {
+ switch (tObj->Dimensions){
+ case 1:
+ if (ctx->Driver.TexImage)
+ (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_1D, tObj, i, image->Format, image);
+ break;
+ case 2:
+ if (ctx->Driver.TexImage)
+ (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_2D, tObj, i, image->Format, image);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Re-Bind each texture Unit
+ for (i=0; i<glb.wMaxSimultaneousTextures; i++) {
+ tObj = ctx->Texture.Unit[i].Current;
+ if (tObj) {
+ DGL_texture *lpTex = (DGL_texture *)tObj->DriverData;
+ hResult = dglSetTexture(dgl, i, lpTex ? lpTex->lpTexture : NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_ERROR, "dglResize: SetTexture failed", hResult);
+ }
+ }
+ }
+#endif // _USE_GLD3_WGL
+
+ dgl->bCanRender = TRUE;
+
+#ifdef GLD_THREADS
+ // Release serialized access
+ if (glb.bMultiThreaded)
+ LeaveCriticalSection(&CriticalSection);
+#endif
+
+ // SUCCESS.
+ return TRUE;
+
+cleanup_and_return_with_error:
+ // Relase all interfaces before returning.
+#ifdef _USE_GLD3_WGL
+ _gldDriver.DestroyDrawable(dgl);
+#else // _USE_GLD3_WGL
+ RELEASE(dgl->lpDev3);
+ RELEASE(dgl->lpDepth4);
+ RELEASE(dgl->lpBack4);
+ if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary)
+ ;
+ else
+ RELEASE(dgl->lpFront4);
+
+#undef DDLOG_CRITICAL_OR_WARN
+#endif // _USE_GLD3_WGL
+
+ // Mark context as not being able to render
+ dgl->bCanRender = FALSE;
+
+#ifdef GLD_THREADS
+ // Release serialized access
+ if (glb.bMultiThreaded)
+ LeaveCriticalSection(&CriticalSection);
+#endif
+
+ return FALSE;
+}
+
+// ***********************************************************************
+// ***********************************************************************
+// Support for bitmap fonts.
+// ***********************************************************************
+// ***********************************************************************
+
+/*****************************************************************************
+**
+** InvertGlyphBitmap.
+**
+** Invert the bitmap so that it suits OpenGL's representation.
+** Each row starts on a double word boundary.
+**
+*****************************************************************************/
+
+static void InvertGlyphBitmap(
+ int w,
+ int h,
+ DWORD *fptr,
+ DWORD *tptr)
+{
+ int dWordsInRow = (w+31)/32;
+ int i, j;
+ DWORD *tmp = tptr;
+
+ if (w <= 0 || h <= 0) {
+ return;
+ }
+
+ tptr += ((h-1)*dWordsInRow);
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < dWordsInRow; j++) {
+ *(tptr + j) = *(fptr + j);
+ }
+ tptr -= dWordsInRow;
+ fptr += dWordsInRow;
+ }
+}
+
+// ***********************************************************************
+
+/*****************************************************************************
+ * wglUseFontBitmaps
+ *
+ * Converts a subrange of the glyphs in a GDI font to OpenGL display
+ * lists.
+ *
+ * Extended to support any GDI font, not just TrueType fonts. (DaveM)
+ *
+ *****************************************************************************/
+
+BOOL APIENTRY _GLD_WGL_EXPORT(UseFontBitmapsA)(
+ HDC hDC,
+ DWORD first,
+ DWORD count,
+ DWORD listBase)
+{
+ int i, ox, oy, ix, iy;
+ int w, h;
+ int iBufSize, iCurBufSize = 0;
+ DWORD *bitmapBuffer = NULL;
+ DWORD *invertedBitmapBuffer = NULL;
+ BOOL bSuccessOrFail = TRUE;
+ BOOL bTrueType = FALSE;
+ TEXTMETRIC tm;
+ GLYPHMETRICS gm;
+ RASTERIZER_STATUS rs;
+ MAT2 mat;
+ SIZE size;
+ RECT rect;
+ HDC hDCMem;
+ HBITMAP hBitmap;
+ BITMAPINFO bmi;
+ HFONT hFont;
+
+ // Validate SciTech DirectGL license
+ if (!dglValidate())
+ return FALSE;
+
+ // Set up a unity matrix.
+ ZeroMemory(&mat, sizeof(mat));
+ mat.eM11.value = 1;
+ mat.eM22.value = 1;
+
+ // Test to see if selected font is TrueType or not
+ ZeroMemory(&tm, sizeof(tm));
+ if (!GetTextMetrics(hDC, &tm)) {
+ ddlogMessage(DDLOG_ERROR, "DGL_UseFontBitmaps: Font metrics error\n");
+ return (FALSE);
+ }
+ bTrueType = (tm.tmPitchAndFamily & TMPF_TRUETYPE) ? TRUE : FALSE;
+
+ // Test to see if TRUE-TYPE capabilities are installed
+ // (only necessary if TrueType font selected)
+ ZeroMemory(&rs, sizeof(rs));
+ if (bTrueType) {
+ if (!GetRasterizerCaps (&rs, sizeof (RASTERIZER_STATUS))) {
+ ddlogMessage(DDLOG_ERROR, "DGL_UseFontBitmaps: Raster caps error\n");
+ return (FALSE);
+ }
+ if (!(rs.wFlags & TT_ENABLED)) {
+ ddlogMessage(DDLOG_ERROR, "DGL_UseFontBitmaps: No TrueType caps\n");
+ return (FALSE);
+ }
+ }
+
+ // Trick to get the current font handle
+ hFont = SelectObject(hDC, GetStockObject(SYSTEM_FONT));
+ SelectObject(hDC, hFont);
+
+ // Have memory device context available for holding bitmaps of font glyphs
+ hDCMem = CreateCompatibleDC(hDC);
+ SelectObject(hDCMem, hFont);
+ SetTextColor(hDCMem, RGB(0xFF, 0xFF, 0xFF));
+ SetBkColor(hDCMem, 0);
+
+ for (i = first; (DWORD) i < (first + count); i++) {
+ // Find out how much space is needed for the bitmap so we can
+ // Set the buffer size correctly.
+ if (bTrueType) {
+ // Use TrueType support to get bitmap size of glyph
+ iBufSize = GetGlyphOutline(hDC, i, GGO_BITMAP, &gm,
+ 0, NULL, &mat);
+ if (iBufSize == GDI_ERROR) {
+ bSuccessOrFail = FALSE;
+ break;
+ }
+ }
+ else {
+ // Use generic GDI support to compute bitmap size of glyph
+ w = tm.tmMaxCharWidth;
+ h = tm.tmHeight;
+ if (GetTextExtentPoint32(hDC, (LPCTSTR)&i, 1, &size)) {
+ w = size.cx;
+ h = size.cy;
+ }
+ iBufSize = w * h;
+ // Use DWORD multiple for compatibility
+ iBufSize += 3;
+ iBufSize /= 4;
+ iBufSize *= 4;
+ }
+
+ // If we need to allocate Larger Buffers, then do so - but allocate
+ // An extra 50 % so that we don't do too many mallocs !
+ if (iBufSize > iCurBufSize) {
+ if (bitmapBuffer) {
+ __wglFree(bitmapBuffer);
+ }
+ if (invertedBitmapBuffer) {
+ __wglFree(invertedBitmapBuffer);
+ }
+
+ iCurBufSize = iBufSize * 2;
+ bitmapBuffer = (DWORD *) __wglMalloc(iCurBufSize);
+ invertedBitmapBuffer = (DWORD *) __wglMalloc(iCurBufSize);
+
+ if (bitmapBuffer == NULL || invertedBitmapBuffer == NULL) {
+ bSuccessOrFail = FALSE;
+ break;
+ }
+ }
+
+ // If we fail to get the Glyph data, delete the display lists
+ // Created so far and return FALSE.
+ if (bTrueType) {
+ // Use TrueType support to get bitmap of glyph
+ if (GetGlyphOutline(hDC, i, GGO_BITMAP, &gm,
+ iBufSize, bitmapBuffer, &mat) == GDI_ERROR) {
+ bSuccessOrFail = FALSE;
+ break;
+ }
+
+ // Setup glBitmap parameters for current font glyph
+ w = gm.gmBlackBoxX;
+ h = gm.gmBlackBoxY;
+ ox = gm.gmptGlyphOrigin.x;
+ oy = gm.gmptGlyphOrigin.y;
+ ix = gm.gmCellIncX;
+ iy = gm.gmCellIncY;
+ }
+ else {
+ // Use generic GDI support to create bitmap of glyph
+ ZeroMemory(bitmapBuffer, iBufSize);
+
+ if (i >= tm.tmFirstChar && i <= tm.tmLastChar) {
+ // Only create bitmaps for actual font glyphs
+ hBitmap = CreateBitmap(w, h, 1, 1, NULL);
+ SelectObject(hDCMem, hBitmap);
+ // Make bitmap of current font glyph
+ SetRect(&rect, 0, 0, w, h);
+ DrawText(hDCMem, (LPCTSTR)&i, 1, &rect,
+ DT_LEFT | DT_BOTTOM | DT_SINGLELINE | DT_NOCLIP);
+ // Make copy of bitmap in our local buffer
+ ZeroMemory(&bmi, sizeof(bmi));
+ bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bmi.bmiHeader.biWidth = w;
+ bmi.bmiHeader.biHeight = -h;
+ bmi.bmiHeader.biPlanes = 1;
+ bmi.bmiHeader.biBitCount = 1;
+ bmi.bmiHeader.biCompression = BI_RGB;
+ GetDIBits(hDCMem, hBitmap, 0, h, bitmapBuffer, &bmi, 0);
+ DeleteObject(hBitmap);
+ }
+ else {
+ // Otherwise use empty display list for non-existing glyph
+ iBufSize = 0;
+ }
+
+ // Setup glBitmap parameters for current font glyph
+ ox = 0;
+ oy = tm.tmDescent;
+ ix = w;
+ iy = 0;
+ }
+
+ // Create an OpenGL display list.
+ _GLD_glNewList((listBase + i), GL_COMPILE);
+
+ // Some fonts have no data for the space character, yet advertise
+ // a non-zero size.
+ if (0 == iBufSize) {
+ _GLD_glBitmap(0, 0, 0.0f, 0.0f, (GLfloat) ix, (GLfloat) iy, NULL);
+ } else {
+ // Invert the Glyph data.
+ InvertGlyphBitmap(w, h, bitmapBuffer, invertedBitmapBuffer);
+
+ // Render an OpenGL bitmap and invert the origin.
+ _GLD_glBitmap(w, h,
+ (GLfloat) ox, (GLfloat) (h-oy),
+ (GLfloat) ix, (GLfloat) iy,
+ (GLubyte *) invertedBitmapBuffer);
+ }
+
+ // Close this display list.
+ _GLD_glEndList();
+ }
+
+ if (bSuccessOrFail == FALSE) {
+ ddlogMessage(DDLOG_ERROR, "DGL_UseFontBitmaps: Get glyph failed\n");
+ _GLD_glDeleteLists((i+listBase), (i-first));
+ }
+
+ // Release resources used
+ DeleteObject(hFont);
+ DeleteDC(hDCMem);
+
+ if (bitmapBuffer)
+ __wglFree(bitmapBuffer);
+ if (invertedBitmapBuffer)
+ __wglFree(invertedBitmapBuffer);
+
+ return(bSuccessOrFail);
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(UseFontBitmapsW)(
+ HDC a,
+ DWORD b,
+ DWORD c,
+ DWORD d)
+{
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ return _GLD_WGL_EXPORT(UseFontBitmapsA)(a, b, c, d);
+}
+
+// ***********************************************************************
+// ***********************************************************************
+// Support for outline TrueType fonts.
+// ***********************************************************************
+// ***********************************************************************
+
+void * __wglRealloc(
+ void *oldPtr,
+ size_t newSize)
+{
+ void *newPtr = NULL;
+
+ if (newSize != 0) {
+ newPtr = (void *) GlobalAlloc(GPTR, newSize);
+ if (oldPtr && newPtr) {
+ DWORD oldSize = GlobalSize(oldPtr);
+
+ memcpy(newPtr, oldPtr, (oldSize <= newSize ? oldSize : newSize));
+ GlobalFree(oldPtr);
+ }
+ } else if (oldPtr) {
+ GlobalFree(oldPtr);
+ }
+ if (newPtr == NULL) {
+ return NULL; /* XXX out of memory error */
+ }
+ return newPtr;
+}
+
+// ***********************************************************************
+
+
+/*****************************************************************************
+ * wglUseFontOutlinesW
+ *
+ * Converts a subrange of the glyphs in a TrueType font to OpenGL display
+ * lists.
+ *****************************************************************************/
+
+BOOL APIENTRY _GLD_WGL_EXPORT(UseFontOutlinesW)(
+ IN HDC hDC,
+ IN DWORD first,
+ IN DWORD count,
+ IN DWORD listBase,
+ IN FLOAT chordalDeviation,
+ IN FLOAT extrusion,
+ IN INT format,
+ OUT LPGLYPHMETRICSFLOAT lpgmf)
+{
+ return _GLD_WGL_EXPORT(UseFontOutlinesA)(hDC, first, count, listBase,
+ chordalDeviation, extrusion, format, lpgmf);
+}
+
+/*****************************************************************************
+ * wglUseFontOutlinesA
+ *
+ * Converts a subrange of the glyphs in a TrueType font to OpenGL display
+ * lists.
+ *****************************************************************************/
+
+BOOL APIENTRY _GLD_WGL_EXPORT(UseFontOutlinesA)(
+ IN HDC hDC,
+ IN DWORD first,
+ IN DWORD count,
+ IN DWORD listBase,
+ IN FLOAT chordalDeviation,
+ IN FLOAT extrusion,
+ IN INT format,
+ OUT LPGLYPHMETRICSFLOAT glyphMetricsFloatArray)
+ {
+ DWORD glyphIndex;
+ UCHAR* glyphBuf;
+ DWORD glyphBufSize;
+
+
+ /*
+ * Flush any previous OpenGL errors. This allows us to check for
+ * new errors so they can be reported via the function return value.
+ */
+ while (_GLD_glGetError() != GL_NO_ERROR)
+ ;
+
+ /*
+ * Make sure that the current font can be sampled accurately.
+ */
+ hNewFont = CreateHighResolutionFont(hDC);
+ if (!hNewFont)
+ return FALSE;
+
+ hOldFont = SelectObject(hDC, hNewFont);
+ if (!hOldFont)
+ return FALSE;
+
+ /*
+ * Preallocate a buffer for the outline data, and track its size:
+ */
+ glyphBuf = (UCHAR*) __wglMalloc(glyphBufSize = 10240);
+ if (!glyphBuf)
+ return FALSE; /*WGL_STATUS_NOT_ENOUGH_MEMORY*/
+
+ /*
+ * Process each glyph in the given range:
+ */
+ for (glyphIndex = first; glyphIndex - first < count; ++glyphIndex)
+ {
+ GLYPHMETRICS glyphMetrics;
+ DWORD glyphSize;
+ static MAT2 matrix =
+ {
+ {0, 1}, {0, 0},
+ {0, 0}, {0, 1}
+ };
+ LPGLYPHMETRICSFLOAT glyphMetricsFloat =
+ &glyphMetricsFloatArray[glyphIndex - first];
+
+
+ /*
+ * Determine how much space is needed to store the glyph's
+ * outlines. If our glyph buffer isn't large enough,
+ * resize it.
+ */
+ glyphSize = GetGlyphOutline( hDC,
+ glyphIndex,
+ GGO_NATIVE,
+ &glyphMetrics,
+ 0,
+ NULL,
+ &matrix
+ );
+ if (glyphSize < 0)
+ return FALSE; /*WGL_STATUS_FAILURE*/
+ if (glyphSize > glyphBufSize)
+ {
+ __wglFree(glyphBuf);
+ glyphBuf = (UCHAR*) __wglMalloc(glyphBufSize = glyphSize);
+ if (!glyphBuf)
+ return FALSE; /*WGL_STATUS_NOT_ENOUGH_MEMORY*/
+ }
+
+
+ /*
+ * Get the glyph's outlines.
+ */
+ if (GetGlyphOutline( hDC,
+ glyphIndex,
+ GGO_NATIVE,
+ &glyphMetrics,
+ glyphBufSize,
+ glyphBuf,
+ &matrix
+ ) < 0)
+ {
+ __wglFree(glyphBuf);
+ return FALSE; /*WGL_STATUS_FAILURE*/
+ }
+
+ glyphMetricsFloat->gmfBlackBoxX =
+ (FLOAT) glyphMetrics.gmBlackBoxX * ScaleFactor;
+ glyphMetricsFloat->gmfBlackBoxY =
+ (FLOAT) glyphMetrics.gmBlackBoxY * ScaleFactor;
+ glyphMetricsFloat->gmfptGlyphOrigin.x =
+ (FLOAT) glyphMetrics.gmptGlyphOrigin.x * ScaleFactor;
+ glyphMetricsFloat->gmfptGlyphOrigin.y =
+ (FLOAT) glyphMetrics.gmptGlyphOrigin.y * ScaleFactor;
+ glyphMetricsFloat->gmfCellIncX =
+ (FLOAT) glyphMetrics.gmCellIncX * ScaleFactor;
+ glyphMetricsFloat->gmfCellIncY =
+ (FLOAT) glyphMetrics.gmCellIncY * ScaleFactor;
+
+ /*
+ * Turn the glyph into a display list:
+ */
+ if (!MakeDisplayListFromGlyph( (glyphIndex - first) + listBase,
+ glyphBuf,
+ glyphSize,
+ glyphMetricsFloat,
+ chordalDeviation + ScaleFactor,
+ extrusion,
+ format))
+ {
+ __wglFree(glyphBuf);
+ return FALSE; /*WGL_STATUS_FAILURE*/
+ }
+ }
+
+
+ /*
+ * Clean up temporary storage and return. If an error occurred,
+ * clear all OpenGL error flags and return FAILURE status;
+ * otherwise just return SUCCESS.
+ */
+ __wglFree(glyphBuf);
+
+ SelectObject(hDC, hOldFont);
+
+ if (_GLD_glGetError() == GL_NO_ERROR)
+ return TRUE; /*WGL_STATUS_SUCCESS*/
+ else
+ {
+ while (_GLD_glGetError() != GL_NO_ERROR)
+ ;
+ return FALSE; /*WGL_STATUS_FAILURE*/
+ }
+ }
+
+
+
+/*****************************************************************************
+ * CreateHighResolutionFont
+ *
+ * Gets metrics for the current font and creates an equivalent font
+ * scaled to the design units of the font.
+ *
+ *****************************************************************************/
+
+static HFONT
+CreateHighResolutionFont(HDC hDC)
+ {
+ UINT otmSize;
+ OUTLINETEXTMETRIC *otm;
+ LONG fontHeight, fontWidth, fontUnits;
+ LOGFONT logFont;
+
+ otmSize = GetOutlineTextMetrics(hDC, 0, NULL);
+ if (otmSize == 0)
+ return NULL;
+
+ otm = (OUTLINETEXTMETRIC *) __wglMalloc(otmSize);
+ if (otm == NULL)
+ return NULL;
+
+ otm->otmSize = otmSize;
+ if (GetOutlineTextMetrics(hDC, otmSize, otm) == 0)
+ return NULL;
+
+ fontHeight = otm->otmTextMetrics.tmHeight -
+ otm->otmTextMetrics.tmInternalLeading;
+ fontWidth = otm->otmTextMetrics.tmAveCharWidth;
+ fontUnits = (LONG) otm->otmEMSquare;
+
+ ScaleFactor = 1.0F / (FLOAT) fontUnits;
+
+ logFont.lfHeight = - ((LONG) fontUnits);
+ logFont.lfWidth = (LONG)
+ ((FLOAT) (fontWidth * fontUnits) / (FLOAT) fontHeight);
+ logFont.lfEscapement = 0;
+ logFont.lfOrientation = 0;
+ logFont.lfWeight = otm->otmTextMetrics.tmWeight;
+ logFont.lfItalic = otm->otmTextMetrics.tmItalic;
+ logFont.lfUnderline = otm->otmTextMetrics.tmUnderlined;
+ logFont.lfStrikeOut = otm->otmTextMetrics.tmStruckOut;
+ logFont.lfCharSet = otm->otmTextMetrics.tmCharSet;
+ logFont.lfOutPrecision = OUT_OUTLINE_PRECIS;
+ logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
+ logFont.lfQuality = DEFAULT_QUALITY;
+ logFont.lfPitchAndFamily =
+ otm->otmTextMetrics.tmPitchAndFamily & 0xf0;
+ strcpy(logFont.lfFaceName,
+ (char *)otm + (int)otm->otmpFaceName);
+
+ hNewFont = CreateFontIndirect(&logFont);
+ if (hNewFont == NULL)
+ return NULL;
+
+ __wglFree(otm);
+
+ return hNewFont;
+ }
+
+
+
+/*****************************************************************************
+ * MakeDisplayListFromGlyph
+ *
+ * Converts the outline of a glyph to an OpenGL display list.
+ *
+ * Return value is nonzero for success, zero for failure.
+ *
+ * Does not check for OpenGL errors, so if the caller needs to know about them,
+ * it should call glGetError().
+ *****************************************************************************/
+
+static int
+MakeDisplayListFromGlyph( IN DWORD listName,
+ IN UCHAR* glyphBuf,
+ IN DWORD glyphSize,
+ IN LPGLYPHMETRICSFLOAT glyphMetricsFloat,
+ IN FLOAT chordalDeviation,
+ IN FLOAT extrusion,
+ IN INT format)
+ {
+ int status;
+
+ _GLD_glNewList(listName, GL_COMPILE);
+ status = DrawGlyph( glyphBuf,
+ glyphSize,
+ chordalDeviation,
+ extrusion,
+ format);
+
+ _GLD_glTranslatef(glyphMetricsFloat->gmfCellIncX,
+ glyphMetricsFloat->gmfCellIncY,
+ 0.0F);
+ _GLD_glEndList();
+
+ return status;
+ }
+
+
+
+/*****************************************************************************
+ * DrawGlyph
+ *
+ * Converts the outline of a glyph to OpenGL drawing primitives, tessellating
+ * as needed, and then draws the glyph. Tessellation of the quadratic splines
+ * in the outline is controlled by "chordalDeviation", and the drawing
+ * primitives (lines or polygons) are selected by "format".
+ *
+ * Return value is nonzero for success, zero for failure.
+ *
+ * Does not check for OpenGL errors, so if the caller needs to know about them,
+ * it should call glGetError().
+ *****************************************************************************/
+
+static int
+DrawGlyph( IN UCHAR* glyphBuf,
+ IN DWORD glyphSize,
+ IN FLOAT chordalDeviation,
+ IN FLOAT extrusion,
+ IN INT format)
+ {
+ INT status = 0;
+ FLOAT* p;
+ DWORD loop;
+ DWORD point;
+ GLUtesselator* tess = NULL;
+
+
+ /*
+ * Initialize the global buffer into which we place the outlines:
+ */
+ if (!InitLineBuf())
+ goto exit;
+
+
+ /*
+ * Convert the glyph outlines to a set of polyline loops.
+ * (See MakeLinesFromGlyph() for the format of the loop data
+ * structure.)
+ */
+ if (!MakeLinesFromGlyph(glyphBuf, glyphSize, chordalDeviation))
+ goto exit;
+ p = LineBuf;
+
+
+ /*
+ * Now draw the loops in the appropriate format:
+ */
+ if (format == WGL_FONT_LINES)
+ {
+ /*
+ * This is the easy case. Just draw the outlines.
+ */
+ for (loop = (DWORD) *p++; loop; --loop)
+ {
+ _GLD_glBegin(GL_LINE_LOOP);
+ for (point = (DWORD) *p++; point; --point)
+ {
+ _GLD_glVertex2fv(p);
+ p += 2;
+ }
+ _GLD_glEnd();
+ }
+ status = 1;
+ }
+
+ else if (format == WGL_FONT_POLYGONS)
+ {
+ double v[3];
+ FLOAT *save_p = p;
+ GLfloat z_value;
+
+ /*
+ * This is the hard case. We have to set up a tessellator
+ * to convert the outlines into a set of polygonal
+ * primitives, which the tessellator passes to some
+ * auxiliary routines for drawing.
+ */
+ if (!LoadGLUTesselator())
+ goto exit;
+ if (!InitVertBuf())
+ goto exit;
+ if (!(tess = gluNewTessProc()))
+ goto exit;
+ gluTessCallbackProc(tess, GLU_BEGIN, (void(CALLBACK *)()) _GLD_glBegin);
+ gluTessCallbackProc(tess, GLU_TESS_VERTEX_DATA,
+ (void(CALLBACK *)()) TessVertexOutData);
+ gluTessCallbackProc(tess, GLU_END, (void(CALLBACK *)()) _GLD_glEnd);
+ gluTessCallbackProc(tess, GLU_ERROR, (void(CALLBACK *)()) TessError);
+ gluTessCallbackProc(tess, GLU_TESS_COMBINE, (void(CALLBACK *)()) TessCombine);
+ gluTessNormalProc(tess, 0.0F, 0.0F, 1.0F);
+
+ TessErrorOccurred = 0;
+ _GLD_glNormal3f(0.0f, 0.0f, 1.0f);
+ v[2] = 0.0;
+ z_value = 0.0f;
+
+ gluTessBeginPolygonProc(tess, (void *)*(int *)&z_value);
+ for (loop = (DWORD) *p++; loop; --loop)
+ {
+ gluTessBeginContourProc(tess);
+
+ for (point = (DWORD) *p++; point; --point)
+ {
+ v[0] = p[0];
+ v[1] = p[1];
+ gluTessVertexProc(tess, v, p);
+ p += 2;
+ }
+
+ gluTessEndContourProc(tess);
+ }
+ gluTessEndPolygonProc(tess);
+
+ status = !TessErrorOccurred;
+
+ /* Extrusion code */
+ if (extrusion) {
+ DWORD loops;
+ GLfloat thickness = (GLfloat) -extrusion;
+ FLOAT *vert, *vert2;
+ DWORD count;
+
+ p = save_p;
+ loops = (DWORD) *p++;
+
+ for (loop = 0; loop < loops; loop++) {
+ GLfloat dx, dy, len;
+ DWORD last;
+
+ count = (DWORD) *p++;
+ _GLD_glBegin(GL_QUAD_STRIP);
+
+ /* Check if the first and last vertex are identical
+ * so we don't draw the same quad twice.
+ */
+ vert = p + (count-1)*2;
+ last = (p[0] == vert[0] && p[1] == vert[1]) ? count-1 : count;
+
+ for (point = 0; point <= last; point++) {
+ vert = p + 2 * (point % last);
+ vert2 = p + 2 * ((point+1) % last);
+
+ dx = vert[0] - vert2[0];
+ dy = vert[1] - vert2[1];
+ len = (GLfloat)sqrt(dx * dx + dy * dy);
+
+ _GLD_glNormal3f(dy / len, -dx / len, 0.0f);
+ _GLD_glVertex3f((GLfloat) vert[0],
+ (GLfloat) vert[1], thickness);
+ _GLD_glVertex3f((GLfloat) vert[0],
+ (GLfloat) vert[1], 0.0f);
+ }
+
+ _GLD_glEnd();
+ p += count*2;
+ }
+
+ /* Draw the back face */
+ p = save_p;
+ v[2] = thickness;
+ _GLD_glNormal3f(0.0f, 0.0f, -1.0f);
+ gluTessNormalProc(tess, 0.0F, 0.0F, -1.0F);
+
+ gluTessBeginPolygonProc(tess, (void *)*(int *)&thickness);
+
+ for (loop = (DWORD) *p++; loop; --loop)
+ {
+ count = (DWORD) *p++;
+
+ gluTessBeginContourProc(tess);
+
+ for (point = 0; point < count; point++)
+ {
+ vert = p + ((count-point-1)<<1);
+ v[0] = vert[0];
+ v[1] = vert[1];
+ gluTessVertexProc(tess, v, vert);
+ }
+ p += count*2;
+
+ gluTessEndContourProc(tess);
+ }
+ gluTessEndPolygonProc(tess);
+ }
+
+#if DEBUG
+ if (TessErrorOccurred)
+ printf("Tessellation error %s\n",
+ gluErrorString(TessErrorOccurred));
+#endif
+ }
+
+
+exit:
+ FreeLineBuf();
+ if (tess)
+ gluDeleteTessProc(tess);
+ // UnloadGLUTesselator();
+ FreeVertBuf();
+ return status;
+ }
+
+
+
+/*****************************************************************************
+ * LoadGLUTesselator
+ *
+ * Maps the glu32.dll module and gets function pointers for the
+ * tesselator functions.
+ *****************************************************************************/
+
+static BOOL
+LoadGLUTesselator(void)
+ {
+ if (gluModuleHandle != NULL)
+ return TRUE;
+
+ {
+ extern HINSTANCE hInstanceOpenGL;
+ char *gluName = "GLU32.DLL";
+// char name[256];
+// char *ptr;
+// int len;
+
+/*
+ len = GetModuleFileName(hInstanceOpenGL, name, 255);
+ if (len != 0)
+ {
+ ptr = name+len-1;
+ while (ptr > name && *ptr != '\\')
+ ptr--;
+ if (*ptr == '\\')
+ ptr++;
+ if (!stricmp(ptr, "cosmogl.dll"))
+ {
+ gluName = "COSMOGLU.DLL";
+ }
+ else if (!stricmp(ptr, "opengl32.dll"))
+ {
+ gluName = "GLU32.DLL";
+ }
+ }
+*/
+ if ((gluModuleHandle = LoadLibrary(gluName)) == NULL)
+ return FALSE;
+ }
+
+ if ((gluNewTessProc = (gluNewTessProto)
+ GetProcAddress(gluModuleHandle, "gluNewTess")) == NULL)
+ return FALSE;
+
+ if ((gluDeleteTessProc = (gluDeleteTessProto)
+ GetProcAddress(gluModuleHandle, "gluDeleteTess")) == NULL)
+ return FALSE;
+
+ if ((gluTessBeginPolygonProc = (gluTessBeginPolygonProto)
+ GetProcAddress(gluModuleHandle, "gluTessBeginPolygon")) == NULL)
+ return FALSE;
+
+ if ((gluTessBeginContourProc = (gluTessBeginContourProto)
+ GetProcAddress(gluModuleHandle, "gluTessBeginContour")) == NULL)
+ return FALSE;
+
+ if ((gluTessVertexProc = (gluTessVertexProto)
+ GetProcAddress(gluModuleHandle, "gluTessVertex")) == NULL)
+ return FALSE;
+
+ if ((gluTessEndContourProc = (gluTessEndContourProto)
+ GetProcAddress(gluModuleHandle, "gluTessEndContour")) == NULL)
+ return FALSE;
+
+ if ((gluTessEndPolygonProc = (gluTessEndPolygonProto)
+ GetProcAddress(gluModuleHandle, "gluTessEndPolygon")) == NULL)
+ return FALSE;
+
+ if ((gluTessPropertyProc = (gluTessPropertyProto)
+ GetProcAddress(gluModuleHandle, "gluTessProperty")) == NULL)
+ return FALSE;
+
+ if ((gluTessNormalProc = (gluTessNormalProto)
+ GetProcAddress(gluModuleHandle, "gluTessNormal")) == NULL)
+ return FALSE;
+
+ if ((gluTessCallbackProc = (gluTessCallbackProto)
+ GetProcAddress(gluModuleHandle, "gluTessCallback")) == NULL)
+ return FALSE;
+
+ return TRUE;
+ }
+
+
+
+/*****************************************************************************
+ * UnloadGLUTesselator
+ *
+ * Unmaps the glu32.dll module.
+ *****************************************************************************/
+
+static BOOL
+UnloadGLUTesselator(void)
+ {
+ if (gluModuleHandle != NULL)
+ if (FreeLibrary(gluModuleHandle) == FALSE)
+ return FALSE;
+ gluModuleHandle = NULL;
+ }
+
+
+
+/*****************************************************************************
+ * TessVertexOut
+ *
+ * Used by tessellator to handle output vertexes.
+ *****************************************************************************/
+
+static void CALLBACK
+TessVertexOut(FLOAT p[3])
+ {
+ GLfloat v[2];
+
+ v[0] = p[0] * ScaleFactor;
+ v[1] = p[1] * ScaleFactor;
+ _GLD_glVertex2fv(v);
+ }
+
+static void CALLBACK
+TessVertexOutData(FLOAT p[3], GLfloat z)
+{
+ GLfloat v[3];
+
+ v[0] = (GLfloat) p[0];
+ v[1] = (GLfloat) p[1];
+ v[2] = z;
+ _GLD_glVertex3fv(v);
+}
+
+
+/*****************************************************************************
+ * TessCombine
+ *
+ * Used by tessellator to handle self-intersecting contours and degenerate
+ * geometry.
+ *****************************************************************************/
+
+static void CALLBACK
+TessCombine(double coords[3],
+ void* vertex_data[4],
+ FLOAT weight[4],
+ void** outData)
+ {
+ if (!AppendToVertBuf((FLOAT) coords[0])
+ || !AppendToVertBuf((FLOAT) coords[1])
+ || !AppendToVertBuf((FLOAT) coords[2]))
+ TessErrorOccurred = GL_OUT_OF_MEMORY;
+ *outData = VertBuf + (VertBufIndex - 3);
+ }
+
+
+
+/*****************************************************************************
+ * TessError
+ *
+ * Saves the last tessellator error code in the global TessErrorOccurred.
+ *****************************************************************************/
+
+static void CALLBACK
+TessError(GLenum error)
+ {
+ TessErrorOccurred = error;
+ }
+
+
+
+/*****************************************************************************
+ * MakeLinesFromGlyph
+ *
+ * Converts the outline of a glyph from the TTPOLYGON format to a simple
+ * array of floating-point values containing one or more loops.
+ *
+ * The first element of the output array is a count of the number of loops.
+ * The loop data follows this count. Each loop consists of a count of the
+ * number of vertices it contains, followed by the vertices. Each vertex
+ * is an X and Y coordinate. For example, a single triangle might be
+ * described by this array:
+ *
+ * 1., 3., 0., 0., 1., 0., 0., 1.
+ * ^ ^ ^ ^ ^ ^ ^ ^
+ * #loops #verts x1 y1 x2 y2 x3 y3
+ *
+ * A two-loop glyph would look like this:
+ *
+ * 2., 3., 0.,0., 1.,0., 0.,1., 3., .2,.2, .4,.2, .2,.4
+ *
+ * Line segments from the TTPOLYGON are transferred to the output array in
+ * the obvious way. Quadratic splines in the TTPOLYGON are converted to
+ * collections of line segments
+ *****************************************************************************/
+
+static int
+MakeLinesFromGlyph(IN UCHAR* glyphBuf,
+ IN DWORD glyphSize,
+ IN FLOAT chordalDeviation)
+ {
+ UCHAR* p;
+ int status = 0;
+
+
+ /*
+ * Pick up all the polygons (aka loops) that make up the glyph:
+ */
+ if (!AppendToLineBuf(0.0F)) /* loop count at LineBuf[0] */
+ goto exit;
+
+ p = glyphBuf;
+ while (p < glyphBuf + glyphSize)
+ {
+ if (!MakeLinesFromTTPolygon(&p, chordalDeviation))
+ goto exit;
+ LineBuf[0] += 1.0F; /* increment loop count */
+ }
+
+ status = 1;
+
+exit:
+ return status;
+ }
+
+
+
+/*****************************************************************************
+ * MakeLinesFromTTPolygon
+ *
+ * Converts a TTPOLYGONHEADER and its associated curve structures into a
+ * single polyline loop in the global LineBuf.
+ *****************************************************************************/
+
+static int
+MakeLinesFromTTPolygon( IN OUT UCHAR** pp,
+ IN FLOAT chordalDeviation)
+ {
+ DWORD polySize;
+ UCHAR* polyStart;
+ DWORD vertexCountIndex;
+
+ /*
+ * Record where the polygon data begins, and where the loop's
+ * vertex count resides:
+ */
+ polyStart = *pp;
+ vertexCountIndex = LineBufIndex;
+ if (!AppendToLineBuf(0.0F))
+ return 0;
+
+ /*
+ * Extract relevant data from the TTPOLYGONHEADER:
+ */
+ polySize = GetDWord(pp);
+ if (GetDWord(pp) != TT_POLYGON_TYPE) /* polygon type */
+ return 0;
+ if (!AppendToLineBuf((FLOAT) GetFixed(pp))) /* first X coord */
+ return 0;
+ if (!AppendToLineBuf((FLOAT) GetFixed(pp))) /* first Y coord */
+ return 0;
+ LineBuf[vertexCountIndex] += 1.0F;
+
+ /*
+ * Process each of the TTPOLYCURVE structures in the polygon:
+ */
+ while (*pp < polyStart + polySize)
+ if (!MakeLinesFromTTPolycurve( pp,
+ vertexCountIndex,
+ chordalDeviation))
+ return 0;
+
+ return 1;
+ }
+
+
+
+/*****************************************************************************
+ * MakeLinesFromTTPolyCurve
+ *
+ * Converts the lines and splines in a single TTPOLYCURVE structure to points
+ * in the global LineBuf.
+ *****************************************************************************/
+
+static int
+MakeLinesFromTTPolycurve( IN OUT UCHAR** pp,
+ IN DWORD vertexCountIndex,
+ IN FLOAT chordalDeviation)
+ {
+ WORD type;
+ WORD pointCount;
+
+
+ /*
+ * Pick up the relevant fields of the TTPOLYCURVE structure:
+ */
+ type = (WORD) GetWord(pp);
+ pointCount = (WORD) GetWord(pp);
+
+ /*
+ * Convert the "curve" to line segments:
+ */
+ if (type == TT_PRIM_LINE)
+ return MakeLinesFromTTLine( pp,
+ vertexCountIndex,
+ pointCount);
+ else if (type == TT_PRIM_QSPLINE)
+ return MakeLinesFromTTQSpline( pp,
+ vertexCountIndex,
+ pointCount,
+ chordalDeviation);
+ else
+ return 0;
+ }
+
+
+
+/*****************************************************************************
+ * MakeLinesFromTTLine
+ *
+ * Converts points from the polyline in a TT_PRIM_LINE structure to
+ * equivalent points in the global LineBuf.
+ *****************************************************************************/
+static int
+MakeLinesFromTTLine( IN OUT UCHAR** pp,
+ IN DWORD vertexCountIndex,
+ IN WORD pointCount)
+ {
+ /*
+ * Just copy the line segments into the line buffer (converting
+ * type as we go):
+ */
+ LineBuf[vertexCountIndex] += pointCount;
+ while (pointCount--)
+ {
+ if (!AppendToLineBuf((FLOAT) GetFixed(pp)) /* X coord */
+ || !AppendToLineBuf((FLOAT) GetFixed(pp))) /* Y coord */
+ return 0;
+ }
+
+ return 1;
+ }
+
+
+
+/*****************************************************************************
+ * MakeLinesFromTTQSpline
+ *
+ * Converts points from the poly quadratic spline in a TT_PRIM_QSPLINE
+ * structure to polyline points in the global LineBuf.
+ *****************************************************************************/
+
+static int
+MakeLinesFromTTQSpline( IN OUT UCHAR** pp,
+ IN DWORD vertexCountIndex,
+ IN WORD pointCount,
+ IN FLOAT chordalDeviation)
+ {
+ FLOAT x0, y0, x1, y1, x2, y2;
+ WORD point;
+
+ /*
+ * Process each of the non-interpolated points in the outline.
+ * To do this, we need to generate two interpolated points (the
+ * start and end of the arc) for each non-interpolated point.
+ * The first interpolated point is always the one most recently
+ * stored in LineBuf, so we just extract it from there. The
+ * second interpolated point is either the average of the next
+ * two points in the QSpline, or the last point in the QSpline
+ * if only one remains.
+ */
+ for (point = 0; point < pointCount - 1; ++point)
+ {
+ x0 = LineBuf[LineBufIndex - 2];
+ y0 = LineBuf[LineBufIndex - 1];
+
+ x1 = (FLOAT) GetFixed(pp);
+ y1 = (FLOAT) GetFixed(pp);
+
+ if (point == pointCount - 2)
+ {
+ /*
+ * This is the last arc in the QSpline. The final
+ * point is the end of the arc.
+ */
+ x2 = (FLOAT) GetFixed(pp);
+ y2 = (FLOAT) GetFixed(pp);
+ }
+ else
+ {
+ /*
+ * Peek at the next point in the input to compute
+ * the end of the arc:
+ */
+ x2 = 0.5F * (x1 + (FLOAT) GetFixed(pp));
+ y2 = 0.5F * (y1 + (FLOAT) GetFixed(pp));
+ /*
+ * Push the point back onto the input so it will
+ * be reused as the next off-curve point:
+ */
+ *pp -= 8;
+ }
+
+ if (!MakeLinesFromArc( x0, y0,
+ x1, y1,
+ x2, y2,
+ vertexCountIndex,
+ chordalDeviation * chordalDeviation))
+ return 0;
+ }
+
+ return 1;
+ }
+
+
+
+/*****************************************************************************
+ * MakeLinesFromArc
+ *
+ * Subdivides one arc of a quadratic spline until the chordal deviation
+ * tolerance requirement is met, then places the resulting set of line
+ * segments in the global LineBuf.
+ *****************************************************************************/
+
+static int
+MakeLinesFromArc( IN FLOAT x0,
+ IN FLOAT y0,
+ IN FLOAT x1,
+ IN FLOAT y1,
+ IN FLOAT x2,
+ IN FLOAT y2,
+ IN DWORD vertexCountIndex,
+ IN FLOAT chordalDeviationSquared)
+ {
+ FLOAT x01;
+ FLOAT y01;
+ FLOAT x12;
+ FLOAT y12;
+ FLOAT midPointX;
+ FLOAT midPointY;
+ FLOAT deltaX;
+ FLOAT deltaY;
+
+ /*
+ * Calculate midpoint of the curve by de Casteljau:
+ */
+ x01 = 0.5F * (x0 + x1);
+ y01 = 0.5F * (y0 + y1);
+ x12 = 0.5F * (x1 + x2);
+ y12 = 0.5F * (y1 + y2);
+ midPointX = 0.5F * (x01 + x12);
+ midPointY = 0.5F * (y01 + y12);
+
+
+ /*
+ * Estimate chordal deviation by the distance from the midpoint
+ * of the curve to its non-interpolated control point. If this
+ * distance is greater than the specified chordal deviation
+ * constraint, then subdivide. Otherwise, generate polylines
+ * from the three control points.
+ */
+ deltaX = midPointX - x1;
+ deltaY = midPointY - y1;
+ if (deltaX * deltaX + deltaY * deltaY > chordalDeviationSquared)
+ {
+ MakeLinesFromArc( x0, y0,
+ x01, y01,
+ midPointX, midPointY,
+ vertexCountIndex,
+ chordalDeviationSquared);
+
+ MakeLinesFromArc( midPointX, midPointY,
+ x12, y12,
+ x2, y2,
+ vertexCountIndex,
+ chordalDeviationSquared);
+ }
+ else
+ {
+ /*
+ * The "pen" is already at (x0, y0), so we don't need to
+ * add that point to the LineBuf.
+ */
+ if (!AppendToLineBuf(x1)
+ || !AppendToLineBuf(y1)
+ || !AppendToLineBuf(x2)
+ || !AppendToLineBuf(y2))
+ return 0;
+ LineBuf[vertexCountIndex] += 2.0F;
+ }
+
+ return 1;
+ }
+
+
+
+/*****************************************************************************
+ * InitLineBuf
+ *
+ * Initializes the global LineBuf and its associated size and current-element
+ * counters.
+ *****************************************************************************/
+
+static int
+InitLineBuf(void)
+ {
+ if (!(LineBuf = (FLOAT*)
+ __wglMalloc((LineBufSize = LINE_BUF_QUANT) * sizeof(FLOAT))))
+ return 0;
+ LineBufIndex = 0;
+ return 1;
+ }
+
+
+
+/*****************************************************************************
+ * InitVertBuf
+ *
+ * Initializes the global VertBuf and its associated size and current-element
+ * counters.
+ *****************************************************************************/
+
+static int
+InitVertBuf(void)
+ {
+ if (!(VertBuf = (FLOAT*)
+ __wglMalloc((VertBufSize = VERT_BUF_QUANT) * sizeof(FLOAT))))
+ return 0;
+ VertBufIndex = 0;
+ return 1;
+ }
+
+
+
+/*****************************************************************************
+ * AppendToLineBuf
+ *
+ * Appends one floating-point value to the global LineBuf array. Return value
+ * is non-zero for success, zero for failure.
+ *****************************************************************************/
+
+static int
+AppendToLineBuf(FLOAT value)
+ {
+ if (LineBufIndex >= LineBufSize)
+ {
+ FLOAT* f;
+
+ f = (FLOAT*) __wglRealloc(LineBuf,
+ (LineBufSize += LINE_BUF_QUANT) * sizeof(FLOAT));
+ if (!f)
+ return 0;
+ LineBuf = f;
+ }
+ LineBuf[LineBufIndex++] = value;
+ return 1;
+ }
+
+
+
+/*****************************************************************************
+ * AppendToVertBuf
+ *
+ * Appends one floating-point value to the global VertBuf array. Return value
+ * is non-zero for success, zero for failure.
+ *
+ * Note that we can't realloc this one, because the tessellator is using
+ * pointers into it.
+ *****************************************************************************/
+
+static int
+AppendToVertBuf(FLOAT value)
+ {
+ if (VertBufIndex >= VertBufSize)
+ return 0;
+ VertBuf[VertBufIndex++] = value;
+ return 1;
+ }
+
+
+
+/*****************************************************************************
+ * FreeLineBuf
+ *
+ * Cleans up vertex buffer structure.
+ *****************************************************************************/
+
+static void
+FreeLineBuf(void)
+ {
+ if (LineBuf)
+ {
+ __wglFree(LineBuf);
+ LineBuf = NULL;
+ }
+ }
+
+
+
+/*****************************************************************************
+ * FreeVertBuf
+ *
+ * Cleans up vertex buffer structure.
+ *****************************************************************************/
+
+static void
+FreeVertBuf(void)
+ {
+ if (VertBuf)
+ {
+ __wglFree(VertBuf);
+ VertBuf = NULL;
+ }
+ }
+
+
+
+/*****************************************************************************
+ * GetWord
+ *
+ * Fetch the next 16-bit word from a little-endian byte stream, and increment
+ * the stream pointer to the next unscanned byte.
+ *****************************************************************************/
+
+static long GetWord(UCHAR** p)
+ {
+ long value;
+
+ value = ((*p)[1] << 8) + (*p)[0];
+ *p += 2;
+ return value;
+ }
+
+
+
+/*****************************************************************************
+ * GetDWord
+ *
+ * Fetch the next 32-bit word from a little-endian byte stream, and increment
+ * the stream pointer to the next unscanned byte.
+ *****************************************************************************/
+
+static long GetDWord(UCHAR** p)
+ {
+ long value;
+
+ value = ((*p)[3] << 24) + ((*p)[2] << 16) + ((*p)[1] << 8) + (*p)[0];
+ *p += 4;
+ return value;
+ }
+
+
+
+
+/*****************************************************************************
+ * GetFixed
+ *
+ * Fetch the next 32-bit fixed-point value from a little-endian byte stream,
+ * convert it to floating-point, and increment the stream pointer to the next
+ * unscanned byte.
+ *****************************************************************************/
+
+static double GetFixed(
+ UCHAR** p)
+{
+ long hiBits, loBits;
+ double value;
+
+ loBits = GetWord(p);
+ hiBits = GetWord(p);
+ value = (double) ((hiBits << 16) | loBits) / 65536.0;
+
+ return value * ScaleFactor;
+}
+
+// ***********************************************************************
+
diff --git a/mesalib/src/mesa/drivers/windows/gldirect/dglwgl.h b/mesalib/src/mesa/drivers/windows/gldirect/dglwgl.h
index aac041033..1dc5c034e 100644
--- a/mesalib/src/mesa/drivers/windows/gldirect/dglwgl.h
+++ b/mesalib/src/mesa/drivers/windows/gldirect/dglwgl.h
@@ -1,127 +1,127 @@
-/****************************************************************************
-*
-* Mesa 3-D graphics library
-* Direct3D Driver Interface
-*
-* ========================================================================
-*
-* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
-*
-* Permission is hereby granted, free of charge, to any person obtaining a
-* copy of this software and associated documentation files (the "Software"),
-* to deal in the Software without restriction, including without limitation
-* the rights to use, copy, modify, merge, publish, distribute, sublicense,
-* and/or sell copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included
-* in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
-* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-* SOFTWARE.
-*
-* ======================================================================
-*
-* Language: ANSI C
-* Environment: Windows 9x (Win32)
-*
-* Description: OpenGL window functions (wgl*).
-*
-****************************************************************************/
-
-#ifndef __DGLWGL_H
-#define __DGLWGL_H
-
-// Disable compiler complaints about DLL linkage
-#pragma warning (disable:4273)
-
-// Macros to control compilation
-#define STRICT
-#define WIN32_LEAN_AND_MEAN
-
-#include <windows.h>
-#include <GL\gl.h>
-
-#include "dglcontext.h"
-#include "dglglobals.h"
-#include "dglmacros.h"
-#include "ddlog.h"
-#include "dglpf.h"
-
-/*---------------------- Macros and type definitions ----------------------*/
-
-typedef struct {
- PROC proc;
- char *name;
-} DGL_extension;
-
-#ifndef __MINGW32__
-/* XXX why is this here?
- * It should probaby be somewhere in src/mesa/drivers/windows/
- */
-#if defined(_WIN32) && !defined(_WINGDI_) && !defined(_WINGDI_H) && !defined(_GNU_H_WINDOWS32_DEFINES) && !defined(OPENSTEP) && !defined(BUILD_FOR_SNAP)
-# define WGL_FONT_LINES 0
-# define WGL_FONT_POLYGONS 1
-#ifndef _GNU_H_WINDOWS32_FUNCTIONS
-# ifdef UNICODE
-# define wglUseFontBitmaps wglUseFontBitmapsW
-# define wglUseFontOutlines wglUseFontOutlinesW
-# else
-# define wglUseFontBitmaps wglUseFontBitmapsA
-# define wglUseFontOutlines wglUseFontOutlinesA
-# endif /* !UNICODE */
-#endif /* _GNU_H_WINDOWS32_FUNCTIONS */
-typedef struct tagLAYERPLANEDESCRIPTOR LAYERPLANEDESCRIPTOR, *PLAYERPLANEDESCRIPTOR, *LPLAYERPLANEDESCRIPTOR;
-typedef struct _GLYPHMETRICSFLOAT GLYPHMETRICSFLOAT, *PGLYPHMETRICSFLOAT, *LPGLYPHMETRICSFLOAT;
-typedef struct tagPIXELFORMATDESCRIPTOR PIXELFORMATDESCRIPTOR, *PPIXELFORMATDESCRIPTOR, *LPPIXELFORMATDESCRIPTOR;
-#if !defined(GLX_USE_MESA)
-#include <GL/mesa_wgl.h>
-#endif
-#endif
-#endif /* !__MINGW32__ */
-
-/*------------------------- Function Prototypes ---------------------------*/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef _USE_GLD3_WGL
-int APIENTRY DGL_ChoosePixelFormat(HDC a, CONST PIXELFORMATDESCRIPTOR *ppfd);
-BOOL APIENTRY DGL_CopyContext(HGLRC a, HGLRC b, UINT c);
-HGLRC APIENTRY DGL_CreateContext(HDC a);
-HGLRC APIENTRY DGL_CreateLayerContext(HDC a, int b);
-BOOL APIENTRY DGL_DeleteContext(HGLRC a);
-BOOL APIENTRY DGL_DescribeLayerPlane(HDC a, int b, int c, UINT d, LPLAYERPLANEDESCRIPTOR e);
-int APIENTRY DGL_DescribePixelFormat(HDC a, int b, UINT c, LPPIXELFORMATDESCRIPTOR d);
-HGLRC APIENTRY DGL_GetCurrentContext(void);
-HDC APIENTRY DGL_GetCurrentDC(void);
-PROC APIENTRY DGL_GetDefaultProcAddress(LPCSTR a);
-int APIENTRY DGL_GetLayerPaletteEntries(HDC a, int b, int c, int d, COLORREF *e);
-int APIENTRY DGL_GetPixelFormat(HDC a);
-PROC APIENTRY DGL_GetProcAddress(LPCSTR a);
-BOOL APIENTRY DGL_MakeCurrent(HDC a, HGLRC b);
-BOOL APIENTRY DGL_RealizeLayerPalette(HDC a, int b, BOOL c);
-int APIENTRY DGL_SetLayerPaletteEntries(HDC a, int b, int c, int d, CONST COLORREF *e);
-BOOL APIENTRY DGL_SetPixelFormat(HDC a, int b, CONST PIXELFORMATDESCRIPTOR *c);
-BOOL APIENTRY DGL_ShareLists(HGLRC a, HGLRC b);
-BOOL APIENTRY DGL_SwapBuffers(HDC a);
-BOOL APIENTRY DGL_SwapLayerBuffers(HDC a, UINT b);
-BOOL APIENTRY DGL_UseFontBitmapsA(HDC a, DWORD b, DWORD c, DWORD d);
-BOOL APIENTRY DGL_UseFontBitmapsW(HDC a, DWORD b, DWORD c, DWORD d);
-BOOL APIENTRY DGL_UseFontOutlinesA(HDC a, DWORD b, DWORD c, DWORD d, FLOAT e, FLOAT f, int g, LPGLYPHMETRICSFLOAT h);
-BOOL APIENTRY DGL_UseFontOutlinesW(HDC a, DWORD b, DWORD c, DWORD d, FLOAT e, FLOAT f, int g, LPGLYPHMETRICSFLOAT h);
-#endif //_USE_GLD3_WGL
-
-BOOL dglWglResizeBuffers(GLcontext *ctx, BOOL bDefaultDriver);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x (Win32)
+*
+* Description: OpenGL window functions (wgl*).
+*
+****************************************************************************/
+
+#ifndef __DGLWGL_H
+#define __DGLWGL_H
+
+// Disable compiler complaints about DLL linkage
+#pragma warning (disable:4273)
+
+// Macros to control compilation
+#define STRICT
+#define WIN32_LEAN_AND_MEAN
+
+#include <windows.h>
+#include <GL\gl.h>
+
+#include "dglcontext.h"
+#include "dglglobals.h"
+#include "dglmacros.h"
+#include "ddlog.h"
+#include "dglpf.h"
+
+/*---------------------- Macros and type definitions ----------------------*/
+
+typedef struct {
+ PROC proc;
+ char *name;
+} DGL_extension;
+
+#ifndef __MINGW32__
+/* XXX why is this here?
+ * It should probaby be somewhere in src/mesa/drivers/windows/
+ */
+#if defined(_WIN32) && !defined(_WINGDI_) && !defined(_WINGDI_H) && !defined(_GNU_H_WINDOWS32_DEFINES) && !defined(OPENSTEP) && !defined(BUILD_FOR_SNAP)
+# define WGL_FONT_LINES 0
+# define WGL_FONT_POLYGONS 1
+#ifndef _GNU_H_WINDOWS32_FUNCTIONS
+# ifdef UNICODE
+# define wglUseFontBitmaps wglUseFontBitmapsW
+# define wglUseFontOutlines wglUseFontOutlinesW
+# else
+# define wglUseFontBitmaps wglUseFontBitmapsA
+# define wglUseFontOutlines wglUseFontOutlinesA
+# endif /* !UNICODE */
+#endif /* _GNU_H_WINDOWS32_FUNCTIONS */
+typedef struct tagLAYERPLANEDESCRIPTOR LAYERPLANEDESCRIPTOR, *PLAYERPLANEDESCRIPTOR, *LPLAYERPLANEDESCRIPTOR;
+typedef struct _GLYPHMETRICSFLOAT GLYPHMETRICSFLOAT, *PGLYPHMETRICSFLOAT, *LPGLYPHMETRICSFLOAT;
+typedef struct tagPIXELFORMATDESCRIPTOR PIXELFORMATDESCRIPTOR, *PPIXELFORMATDESCRIPTOR, *LPPIXELFORMATDESCRIPTOR;
+#if !defined(GLX_USE_MESA)
+#include <GL/mesa_wgl.h>
+#endif
+#endif
+#endif /* !__MINGW32__ */
+
+/*------------------------- Function Prototypes ---------------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _USE_GLD3_WGL
+int APIENTRY DGL_ChoosePixelFormat(HDC a, CONST PIXELFORMATDESCRIPTOR *ppfd);
+BOOL APIENTRY DGL_CopyContext(HGLRC a, HGLRC b, UINT c);
+HGLRC APIENTRY DGL_CreateContext(HDC a);
+HGLRC APIENTRY DGL_CreateLayerContext(HDC a, int b);
+BOOL APIENTRY DGL_DeleteContext(HGLRC a);
+BOOL APIENTRY DGL_DescribeLayerPlane(HDC a, int b, int c, UINT d, LPLAYERPLANEDESCRIPTOR e);
+int APIENTRY DGL_DescribePixelFormat(HDC a, int b, UINT c, LPPIXELFORMATDESCRIPTOR d);
+HGLRC APIENTRY DGL_GetCurrentContext(void);
+HDC APIENTRY DGL_GetCurrentDC(void);
+PROC APIENTRY DGL_GetDefaultProcAddress(LPCSTR a);
+int APIENTRY DGL_GetLayerPaletteEntries(HDC a, int b, int c, int d, COLORREF *e);
+int APIENTRY DGL_GetPixelFormat(HDC a);
+PROC APIENTRY DGL_GetProcAddress(LPCSTR a);
+BOOL APIENTRY DGL_MakeCurrent(HDC a, HGLRC b);
+BOOL APIENTRY DGL_RealizeLayerPalette(HDC a, int b, BOOL c);
+int APIENTRY DGL_SetLayerPaletteEntries(HDC a, int b, int c, int d, CONST COLORREF *e);
+BOOL APIENTRY DGL_SetPixelFormat(HDC a, int b, CONST PIXELFORMATDESCRIPTOR *c);
+BOOL APIENTRY DGL_ShareLists(HGLRC a, HGLRC b);
+BOOL APIENTRY DGL_SwapBuffers(HDC a);
+BOOL APIENTRY DGL_SwapLayerBuffers(HDC a, UINT b);
+BOOL APIENTRY DGL_UseFontBitmapsA(HDC a, DWORD b, DWORD c, DWORD d);
+BOOL APIENTRY DGL_UseFontBitmapsW(HDC a, DWORD b, DWORD c, DWORD d);
+BOOL APIENTRY DGL_UseFontOutlinesA(HDC a, DWORD b, DWORD c, DWORD d, FLOAT e, FLOAT f, int g, LPGLYPHMETRICSFLOAT h);
+BOOL APIENTRY DGL_UseFontOutlinesW(HDC a, DWORD b, DWORD c, DWORD d, FLOAT e, FLOAT f, int g, LPGLYPHMETRICSFLOAT h);
+#endif //_USE_GLD3_WGL
+
+BOOL dglWglResizeBuffers(struct gl_context *ctx, BOOL bDefaultDriver);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_driver_dx9.c b/mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_driver_dx9.c
new file mode 100644
index 000000000..0a508355c
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_driver_dx9.c
@@ -0,0 +1,1206 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: Driver interface code to Mesa
+*
+****************************************************************************/
+
+//#include <windows.h>
+#include "dglcontext.h"
+#include "ddlog.h"
+#include "gld_dx9.h"
+
+#include "glheader.h"
+#include "context.h"
+#include "colormac.h"
+#include "depth.h"
+#include "extensions.h"
+#include "macros.h"
+#include "matrix.h"
+// #include "mem.h"
+//#include "mmath.h"
+#include "mtypes.h"
+#include "texformat.h"
+#include "teximage.h"
+#include "texstore.h"
+#include "vbo/vbo.h"
+#include "swrast_setup/swrast_setup.h"
+#include "swrast_setup/ss_context.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+extern BOOL dglSwapBuffers(HDC hDC);
+
+// HACK: Hack the _33 member of the OpenGL perspective projection matrix
+const float _fPersp_33 = 1.6f;
+
+//---------------------------------------------------------------------------
+// Internal functions
+//---------------------------------------------------------------------------
+
+void _gld_mesa_warning(
+ __struct gl_context *gc,
+ char *str)
+{
+ // Intercept Mesa's internal warning mechanism
+ gldLogPrintf(GLDLOG_WARN, "Mesa warning: %s", str);
+}
+
+//---------------------------------------------------------------------------
+
+void _gld_mesa_fatal(
+ __struct gl_context *gc,
+ char *str)
+{
+ // Intercept Mesa's internal fatal-message mechanism
+ gldLogPrintf(GLDLOG_CRITICAL, "Mesa FATAL: %s", str);
+
+ // Mesa calls abort(0) here.
+ ddlogClose();
+ exit(0);
+}
+
+//---------------------------------------------------------------------------
+
+D3DSTENCILOP _gldConvertStencilOp(
+ GLenum StencilOp)
+{
+ // Used by Stencil: pass, fail and zfail
+
+ switch (StencilOp) {
+ case GL_KEEP:
+ return D3DSTENCILOP_KEEP;
+ case GL_ZERO:
+ return D3DSTENCILOP_ZERO;
+ case GL_REPLACE:
+ return D3DSTENCILOP_REPLACE;
+ case GL_INCR:
+ return D3DSTENCILOP_INCRSAT;
+ case GL_DECR:
+ return D3DSTENCILOP_DECRSAT;
+ case GL_INVERT:
+ return D3DSTENCILOP_INVERT;
+ case GL_INCR_WRAP_EXT: // GL_EXT_stencil_wrap
+ return D3DSTENCILOP_INCR;
+ case GL_DECR_WRAP_EXT: // GL_EXT_stencil_wrap
+ return D3DSTENCILOP_DECR;
+ }
+
+#ifdef _DEBUG
+ gldLogMessage(GLDLOG_ERROR, "_gldConvertStencilOp: Unknown StencilOp\n");
+#endif
+
+ return D3DSTENCILOP_KEEP;
+}
+
+//---------------------------------------------------------------------------
+
+D3DCMPFUNC _gldConvertCompareFunc(
+ GLenum CmpFunc)
+{
+ // Used for Alpha func, depth func and stencil func.
+
+ switch (CmpFunc) {
+ case GL_NEVER:
+ return D3DCMP_NEVER;
+ case GL_LESS:
+ return D3DCMP_LESS;
+ case GL_EQUAL:
+ return D3DCMP_EQUAL;
+ case GL_LEQUAL:
+ return D3DCMP_LESSEQUAL;
+ case GL_GREATER:
+ return D3DCMP_GREATER;
+ case GL_NOTEQUAL:
+ return D3DCMP_NOTEQUAL;
+ case GL_GEQUAL:
+ return D3DCMP_GREATEREQUAL;
+ case GL_ALWAYS:
+ return D3DCMP_ALWAYS;
+ };
+
+#ifdef _DEBUG
+ gldLogMessage(GLDLOG_ERROR, "_gldConvertCompareFunc: Unknown CompareFunc\n");
+#endif
+
+ return D3DCMP_ALWAYS;
+}
+
+//---------------------------------------------------------------------------
+
+D3DBLEND _gldConvertBlendFunc(
+ GLenum blend,
+ GLenum DefaultBlend)
+{
+ switch (blend) {
+ case GL_ZERO:
+ return D3DBLEND_ZERO;
+ case GL_ONE:
+ return D3DBLEND_ONE;
+ case GL_DST_COLOR:
+ return D3DBLEND_DESTCOLOR;
+ case GL_SRC_COLOR:
+ return D3DBLEND_SRCCOLOR;
+ case GL_ONE_MINUS_DST_COLOR:
+ return D3DBLEND_INVDESTCOLOR;
+ case GL_ONE_MINUS_SRC_COLOR:
+ return D3DBLEND_INVSRCCOLOR;
+ case GL_SRC_ALPHA:
+ return D3DBLEND_SRCALPHA;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ return D3DBLEND_INVSRCALPHA;
+ case GL_DST_ALPHA:
+ return D3DBLEND_DESTALPHA;
+ case GL_ONE_MINUS_DST_ALPHA:
+ return D3DBLEND_INVDESTALPHA;
+ case GL_SRC_ALPHA_SATURATE:
+ return D3DBLEND_SRCALPHASAT;
+ }
+
+#ifdef _DEBUG
+ gldLogMessage(GLDLOG_ERROR, "_gldConvertBlendFunc: Unknown BlendFunc\n");
+#endif
+
+ return DefaultBlend;
+}
+
+//---------------------------------------------------------------------------
+// Misc. functions
+//---------------------------------------------------------------------------
+
+void gld_Noop_DX9(
+ struct gl_context *ctx)
+{
+#ifdef _DEBUG
+ gldLogMessage(GLDLOG_ERROR, "gld_Noop called!\n");
+#endif
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Error_DX9(
+ struct gl_context *ctx)
+{
+#ifdef _DEBUG
+ // Quite useless.
+// gldLogMessage(GLDLOG_ERROR, "ctx->Driver.Error called!\n");
+#endif
+}
+
+//---------------------------------------------------------------------------
+// Required Mesa functions
+//---------------------------------------------------------------------------
+
+static GLboolean gld_set_draw_buffer_DX9(
+ struct gl_context *ctx,
+ GLenum mode)
+{
+ (void) ctx;
+ if ((mode==GL_FRONT_LEFT) || (mode == GL_BACK_LEFT)) {
+ return GL_TRUE;
+ }
+ else {
+ return GL_FALSE;
+ }
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_set_read_buffer_DX9(
+ struct gl_context *ctx,
+ struct gl_framebuffer *buffer,
+ GLenum mode)
+{
+ /* separate read buffer not supported */
+/*
+ ASSERT(buffer == ctx->DrawBuffer);
+ ASSERT(mode == GL_FRONT_LEFT);
+*/
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Clear_DX9(
+ struct gl_context *ctx,
+ GLbitfield mask,
+ GLboolean all,
+ GLint x,
+ GLint y,
+ GLint width,
+ GLint height)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ DWORD dwFlags = 0;
+ D3DCOLOR Color = 0;
+ float Z = 0.0f;
+ DWORD Stencil = 0;
+ D3DRECT d3dClearRect;
+
+ // TODO: Colourmask
+ const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask[0];
+
+ if (!gld->pDev)
+ return;
+
+ if (mask & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT)) {
+ GLubyte col[4];
+ CLAMPED_FLOAT_TO_UBYTE(col[0], ctx->Color.ClearColor[0]);
+ CLAMPED_FLOAT_TO_UBYTE(col[1], ctx->Color.ClearColor[1]);
+ CLAMPED_FLOAT_TO_UBYTE(col[2], ctx->Color.ClearColor[2]);
+ CLAMPED_FLOAT_TO_UBYTE(col[3], ctx->Color.ClearColor[3]);
+ dwFlags |= D3DCLEAR_TARGET;
+ Color = D3DCOLOR_RGBA(col[0], col[1], col[2], col[3]);
+ }
+
+ if (mask & DD_DEPTH_BIT) {
+ // D3D8 will fail the Clear call if we try and clear a
+ // depth buffer and we haven't created one.
+ // Also, some apps try and clear a depth buffer,
+ // when a depth buffer hasn't been requested by the app.
+ if (ctx->Visual.depthBits == 0) {
+ mask &= ~DD_DEPTH_BIT; // Remove depth bit from mask
+ } else {
+ dwFlags |= D3DCLEAR_ZBUFFER;
+ Z = ctx->Depth.Clear;
+ }
+ }
+
+ if (mask & DD_STENCIL_BIT) {
+ if (ctx->Visual.stencilBits == 0) {
+ // No stencil bits in depth buffer
+ mask &= ~DD_STENCIL_BIT; // Remove stencil bit from mask
+ } else {
+ dwFlags |= D3DCLEAR_STENCIL;
+ Stencil = ctx->Stencil.Clear;
+ }
+ }
+
+ // Some apps do really weird things with the rect, such as Quake3.
+ if ((x < 0) || (y < 0) || (width <= 0) || (height <= 0)) {
+ all = GL_TRUE;
+ }
+
+ if (!all) {
+ // Calculate clear subrect
+ d3dClearRect.x1 = x;
+ d3dClearRect.y1 = gldCtx->dwHeight - (y + height);
+ d3dClearRect.x2 = x + width;
+ d3dClearRect.y2 = d3dClearRect.y1 + height;
+// gldLogPrintf(GLDLOG_INFO, "Rect %d,%d %d,%d", x,y,width,height);
+ }
+
+ // dwFlags will be zero if there's nothing to clear
+ if (dwFlags) {
+ _GLD_DX9_DEV(Clear(
+ gld->pDev,
+ all ? 0 : 1,
+ all ? NULL : &d3dClearRect,
+ dwFlags,
+ Color, Z, Stencil));
+ }
+
+ if (mask & DD_ACCUM_BIT) {
+ // Clear accumulation buffer
+ }
+}
+
+//---------------------------------------------------------------------------
+
+// Mesa 5: Parameter change
+static void gld_buffer_size_DX9(
+// struct gl_context *ctx,
+ struct gl_framebuffer *fb,
+ GLuint *width,
+ GLuint *height)
+{
+// GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+
+ *width = fb->Width; // gldCtx->dwWidth;
+ *height = fb->Height; // gldCtx->dwHeight;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_Finish_DX9(
+ struct gl_context *ctx)
+{
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_Flush_DX9(
+ struct gl_context *ctx)
+{
+ GLD_context *gld = GLD_GET_CONTEXT(ctx);
+
+ // TODO: Detect apps that glFlush() then SwapBuffers() ?
+
+ if (gld->EmulateSingle) {
+ // Emulating a single-buffered context.
+ // [Direct3D doesn't allow rendering to front buffer]
+ dglSwapBuffers(gld->hDC);
+ }
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_STENCIL(
+ struct gl_context *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ // Two-sided stencil. New for Mesa 5
+ const GLuint uiFace = 0UL;
+
+ struct gl_stencil_attrib *pStencil = &ctx->Stencil;
+
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_STENCILENABLE, pStencil->Enabled ? TRUE : FALSE));
+ if (pStencil->Enabled) {
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_STENCILFUNC, _gldConvertCompareFunc(pStencil->Function[uiFace])));
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_STENCILREF, pStencil->Ref[uiFace]));
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_STENCILMASK, pStencil->ValueMask[uiFace]));
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_STENCILWRITEMASK, pStencil->WriteMask[uiFace]));
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_STENCILFAIL, _gldConvertStencilOp(pStencil->FailFunc[uiFace])));
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_STENCILZFAIL, _gldConvertStencilOp(pStencil->ZFailFunc[uiFace])));
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_STENCILPASS, _gldConvertStencilOp(pStencil->ZPassFunc[uiFace])));
+ }
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_COLOR(
+ struct gl_context *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ DWORD dwFlags = 0;
+ D3DBLEND src;
+ D3DBLEND dest;
+
+ // Alpha func
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_ALPHAFUNC, _gldConvertCompareFunc(ctx->Color.AlphaFunc)));
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_ALPHAREF, (DWORD)ctx->Color.AlphaRef));
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_ALPHATESTENABLE, ctx->Color.AlphaEnabled));
+
+ // Blend func
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_ALPHABLENDENABLE, ctx->Color.BlendEnabled));
+ src = _gldConvertBlendFunc(ctx->Color.BlendSrcRGB, GL_ONE);
+ dest = _gldConvertBlendFunc(ctx->Color.BlendDstRGB, GL_ZERO);
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_SRCBLEND, src));
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_DESTBLEND, dest));
+
+ // Color mask
+ if (ctx->Color.ColorMask[0][0]) dwFlags |= D3DCOLORWRITEENABLE_RED;
+ if (ctx->Color.ColorMask[0][1]) dwFlags |= D3DCOLORWRITEENABLE_GREEN;
+ if (ctx->Color.ColorMask[0][2]) dwFlags |= D3DCOLORWRITEENABLE_BLUE;
+ if (ctx->Color.ColorMask[0][3]) dwFlags |= D3DCOLORWRITEENABLE_ALPHA;
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_COLORWRITEENABLE, dwFlags));
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_DEPTH(
+ struct gl_context *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_ZENABLE, ctx->Depth.Test ? D3DZB_TRUE : D3DZB_FALSE));
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_ZFUNC, _gldConvertCompareFunc(ctx->Depth.Func)));
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_ZWRITEENABLE, ctx->Depth.Mask ? TRUE : FALSE));
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_POLYGON(
+ struct gl_context *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ D3DFILLMODE d3dFillMode = D3DFILL_SOLID;
+ D3DCULL d3dCullMode = D3DCULL_NONE;
+ float fOffset = 0; // Changed from int to float for DX9
+
+ // Fillmode
+ switch (ctx->Polygon.FrontMode) {
+ case GL_POINT:
+ d3dFillMode = D3DFILL_POINT;
+ break;
+ case GL_LINE:
+ d3dFillMode = D3DFILL_WIREFRAME;
+ break;
+ case GL_FILL:
+ d3dFillMode = D3DFILL_SOLID;
+ break;
+ }
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FILLMODE, d3dFillMode));
+
+ if (ctx->Polygon.CullFlag) {
+ switch (ctx->Polygon.CullFaceMode) {
+ case GL_BACK:
+ if (ctx->Polygon.FrontFace == GL_CCW)
+ d3dCullMode = D3DCULL_CW;
+ else
+ d3dCullMode = D3DCULL_CCW;
+ break;
+ case GL_FRONT:
+ if (ctx->Polygon.FrontFace == GL_CCW)
+ d3dCullMode = D3DCULL_CCW;
+ else
+ d3dCullMode = D3DCULL_CW;
+ break;
+ case GL_FRONT_AND_BACK:
+ d3dCullMode = D3DCULL_NONE;
+ break;
+ default:
+ break;
+ }
+ } else {
+ d3dCullMode = D3DCULL_NONE;
+ }
+// d3dCullMode = D3DCULL_NONE; // FOR DEBUGGING
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_CULLMODE, d3dCullMode));
+
+ // Polygon offset
+ // ZBIAS ranges from 0 to 16 and can only move towards the viewer
+ // Mesa5: ctx->Polygon._OffsetAny removed
+ if (ctx->Polygon.OffsetFill) {
+ fOffset = ctx->Polygon.OffsetUnits;
+// if (iOffset < 0.0f)
+// iOffset = -iOffset;
+// else
+// iOffset = 0.0f; // D3D can't push away
+ }
+ // NOTE: SetRenderState() required a DWORD, so need to cast
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_DEPTHBIAS, *((DWORD*)&fOffset)));
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_FOG(
+ struct gl_context *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ D3DCOLOR d3dFogColour;
+ D3DFOGMODE d3dFogMode = D3DFOG_LINEAR;
+
+ // TODO: Fog is calculated seperately in the Mesa pipeline
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGENABLE, FALSE));
+ return;
+
+ // Fog enable
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGENABLE, ctx->Fog.Enabled));
+ if (!ctx->Fog.Enabled) {
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGTABLEMODE, D3DFOG_NONE));
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGVERTEXMODE, D3DFOG_NONE));
+ return; // If disabled, don't bother setting any fog state
+ }
+
+ // Fog colour
+ d3dFogColour = D3DCOLOR_COLORVALUE( ctx->Fog.Color[0],
+ ctx->Fog.Color[1],
+ ctx->Fog.Color[2],
+ ctx->Fog.Color[3]);
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGCOLOR, d3dFogColour));
+
+ // Fog density
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGDENSITY, *((DWORD*) (&ctx->Fog.Density))));
+
+ // Fog start
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGSTART, *((DWORD*) (&ctx->Fog.Start))));
+
+ // Fog end
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGEND, *((DWORD*) (&ctx->Fog.End))));
+
+ // Fog mode
+ switch (ctx->Fog.Mode) {
+ case GL_LINEAR:
+ d3dFogMode = D3DFOG_LINEAR;
+ break;
+ case GL_EXP:
+ d3dFogMode = D3DFOG_EXP;
+ break;
+ case GL_EXP2:
+ d3dFogMode = D3DFOG_EXP2;
+ break;
+ }
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGTABLEMODE, d3dFogMode));
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGVERTEXMODE, D3DFOG_NONE));
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_LIGHT(
+ struct gl_context *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+ DWORD dwSpecularEnable;
+
+ // Shademode
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_SHADEMODE, (ctx->Light.ShadeModel == GL_SMOOTH) ? D3DSHADE_GOURAUD : D3DSHADE_FLAT));
+
+ // Separate specular colour
+ if (ctx->Light.Enabled)
+ dwSpecularEnable = (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) ? TRUE: FALSE;
+ else
+ dwSpecularEnable = FALSE;
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_SPECULARENABLE, dwSpecularEnable));
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_MODELVIEW(
+ struct gl_context *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ D3DMATRIX m;
+ //GLfloat *pM = ctx->ModelView.m;
+ // Mesa5: Model-view is now a stack
+ GLfloat *pM = ctx->ModelviewMatrixStack.Top->m;
+ m._11 = pM[0];
+ m._12 = pM[1];
+ m._13 = pM[2];
+ m._14 = pM[3];
+ m._21 = pM[4];
+ m._22 = pM[5];
+ m._23 = pM[6];
+ m._24 = pM[7];
+ m._31 = pM[8];
+ m._32 = pM[9];
+ m._33 = pM[10];
+ m._34 = pM[11];
+ m._41 = pM[12];
+ m._42 = pM[13];
+ m._43 = pM[14];
+ m._44 = pM[15];
+
+ gld->matModelView = m;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_PROJECTION(
+ struct gl_context *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ D3DMATRIX m;
+ //GLfloat *pM = ctx->ProjectionMatrix.m;
+ // Mesa 5: Now a stack
+ GLfloat *pM = ctx->ProjectionMatrixStack.Top->m;
+ m._11 = pM[0];
+ m._12 = pM[1];
+ m._13 = pM[2];
+ m._14 = pM[3];
+
+ m._21 = pM[4];
+ m._22 = pM[5];
+ m._23 = pM[6];
+ m._24 = pM[7];
+
+ m._31 = pM[8];
+ m._32 = pM[9];
+ m._33 = pM[10] / _fPersp_33; // / 1.6f;
+ m._34 = pM[11];
+
+ m._41 = pM[12];
+ m._42 = pM[13];
+ m._43 = pM[14] / 2.0f;
+ m._44 = pM[15];
+
+ gld->matProjection = m;
+}
+
+//---------------------------------------------------------------------------
+/*
+void gldFrustumHook_DX9(
+ GLdouble left,
+ GLdouble right,
+ GLdouble bottom,
+ GLdouble top,
+ GLdouble nearval,
+ GLdouble farval)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ // Pass values on to Mesa first (in case we mess with them)
+ _mesa_Frustum(left, right, bottom, top, nearval, farval);
+
+ _fPersp_33 = farval / (nearval - farval);
+
+// ddlogPrintf(GLDLOG_SYSTEM, "Frustum: %f", farval/nearval);
+}
+
+//---------------------------------------------------------------------------
+
+void gldOrthoHook_DX9(
+ GLdouble left,
+ GLdouble right,
+ GLdouble bottom,
+ GLdouble top,
+ GLdouble nearval,
+ GLdouble farval)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ // Pass values on to Mesa first (in case we mess with them)
+ _mesa_Ortho(left, right, bottom, top, nearval, farval);
+
+ _fPersp_33 = 1.6f;
+
+// ddlogPrintf(GLDLOG_SYSTEM, "Ortho: %f", farval/nearval);
+}
+*/
+//---------------------------------------------------------------------------
+
+void gld_NEW_VIEWPORT(
+ struct gl_context *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ D3DVIEWPORT9 d3dvp;
+// GLint x, y;
+// GLsizei w, h;
+
+ // Set depth range
+ _GLD_DX9_DEV(GetViewport(gld->pDev, &d3dvp));
+ // D3D can't do Quake1/Quake2 z-trick
+ if (ctx->Viewport.Near <= ctx->Viewport.Far) {
+ d3dvp.MinZ = ctx->Viewport.Near;
+ d3dvp.MaxZ = ctx->Viewport.Far;
+ } else {
+ d3dvp.MinZ = ctx->Viewport.Far;
+ d3dvp.MaxZ = ctx->Viewport.Near;
+ }
+/* x = ctx->Viewport.X;
+ y = ctx->Viewport.Y;
+ w = ctx->Viewport.Width;
+ h = ctx->Viewport.Height;
+ if (x < 0) x = 0;
+ if (y < 0) y = 0;
+ if (w > gldCtx->dwWidth) w = gldCtx->dwWidth;
+ if (h > gldCtx->dwHeight) h = gldCtx->dwHeight;
+ // Ditto for D3D viewport dimensions
+ if (w+x > gldCtx->dwWidth) w = gldCtx->dwWidth-x;
+ if (h+y > gldCtx->dwHeight) h = gldCtx->dwHeight-y;
+ d3dvp.X = x;
+ d3dvp.Y = gldCtx->dwHeight - (y + h);
+ d3dvp.Width = w;
+ d3dvp.Height = h;*/
+ _GLD_DX9_DEV(SetViewport(gld->pDev, &d3dvp));
+
+// gld->fFlipWindowY = (float)gldCtx->dwHeight;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_SCISSOR(
+ struct gl_context *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ // Bail if IHV driver cannot scissor
+ if (!gld->bCanScissor)
+ return;
+
+ // Set scissor rect
+ if (ctx->Scissor.Enabled) {
+ RECT rcRect;
+ // Keep in mind that RECT's need an extra row and column
+ rcRect.left = ctx->Scissor.X;
+ rcRect.right = ctx->Scissor.X + ctx->Scissor.Width; // + 1;
+ rcRect.top = gldCtx->dwHeight - (ctx->Scissor.Y + ctx->Scissor.Height);
+ rcRect.bottom = rcRect.top + ctx->Scissor.Height;
+ IDirect3DDevice9_SetScissorRect(gld->pDev, &rcRect);
+ }
+
+ // Enable/disable scissor as required
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_SCISSORTESTENABLE, ctx->Scissor.Enabled));
+}
+
+//---------------------------------------------------------------------------
+
+__inline BOOL _gldAnyEvalEnabled(
+ struct gl_context *ctx)
+{
+ struct gl_eval_attrib *eval = &ctx->Eval;
+
+ if ((eval->AutoNormal) ||
+ (eval->Map1Color4) ||
+ (eval->Map1Index) ||
+ (eval->Map1Normal) ||
+ (eval->Map1TextureCoord1) ||
+ (eval->Map1TextureCoord2) ||
+ (eval->Map1TextureCoord3) ||
+ (eval->Map1TextureCoord4) ||
+ (eval->Map1Vertex3) ||
+ (eval->Map1Vertex4) ||
+ (eval->Map2Color4) ||
+ (eval->Map2Index) ||
+ (eval->Map2Normal) ||
+ (eval->Map2TextureCoord1) ||
+ (eval->Map2TextureCoord2) ||
+ (eval->Map2TextureCoord3) ||
+ (eval->Map2TextureCoord4) ||
+ (eval->Map2Vertex3) ||
+ (eval->Map2Vertex4)
+ )
+ return TRUE;
+
+ return FALSE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL _gldChooseInternalPipeline(
+ struct gl_context *ctx,
+ GLD_driver_dx9 *gld)
+{
+// return TRUE; // DEBUGGING: ALWAYS USE MESA
+// return FALSE; // DEBUGGING: ALWAYS USE D3D
+
+ if ((glb.dwTnL == GLDS_TNL_MESA) || (gld->bHasHWTnL == FALSE))
+ {
+ gld->PipelineUsage.qwMesa.QuadPart++;
+ return TRUE; // Force Mesa TnL
+ }
+
+ if ((ctx->Light.Enabled) ||
+ (1) ||
+ (ctx->Texture._TexGenEnabled) ||
+ (ctx->Texture._TexMatEnabled) ||
+// (ctx->Transform._AnyClip) ||
+ (ctx->Scissor.Enabled) ||
+ _gldAnyEvalEnabled(ctx) // Put this last so we can early-out
+ )
+ {
+ gld->PipelineUsage.qwMesa.QuadPart++;
+ return TRUE;
+ }
+
+ gld->PipelineUsage.qwD3DFVF.QuadPart++;
+ return FALSE;
+
+/* // Force Mesa pipeline?
+ if (glb.dwTnL == GLDS_TNL_MESA) {
+ gld->PipelineUsage.dwMesa.QuadPart++;
+ return GLD_PIPELINE_MESA;
+ }
+
+ // Test for functionality not exposed in the D3D pathways
+ if ((ctx->Texture._GenFlags)) {
+ gld->PipelineUsage.dwMesa.QuadPart++;
+ return GLD_PIPELINE_MESA;
+ }
+
+ // Now decide if vertex shader can be used.
+ // If two sided lighting is enabled then we must either
+ // use Mesa TnL or the vertex shader
+ if (ctx->_TriangleCaps & DD_TRI_LIGHT_TWOSIDE) {
+ if (gld->VStwosidelight.hShader && !ctx->Fog.Enabled) {
+ // Use Vertex Shader
+ gld->PipelineUsage.dwD3D2SVS.QuadPart++;
+ return GLD_PIPELINE_D3D_VS_TWOSIDE;
+ } else {
+ // Use Mesa TnL
+ gld->PipelineUsage.dwMesa.QuadPart++;
+ return GLD_PIPELINE_MESA;
+ }
+ }
+
+ // Must be D3D fixed-function pipeline
+ gld->PipelineUsage.dwD3DFVF.QuadPart++;
+ return GLD_PIPELINE_D3D_FVF;
+*/
+}
+
+//---------------------------------------------------------------------------
+
+void gld_update_state_DX9(
+ struct gl_context *ctx,
+ GLuint new_state)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ GLD_pb_dx9 *gldPB;
+
+ if (!gld || !gld->pDev)
+ return;
+
+ _swsetup_InvalidateState( ctx, new_state );
+ _vbo_InvalidateState( ctx, new_state );
+ _tnl_InvalidateState( ctx, new_state );
+
+ // SetupIndex will be used in the pipelines for choosing setup function
+ if ((ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE | DD_SEPARATE_SPECULAR)) ||
+ (ctx->Fog.Enabled))
+ {
+ if (ctx->_TriangleCaps & DD_FLATSHADE)
+ gld->iSetupFunc = GLD_SI_FLAT_EXTRAS;
+ else
+ gld->iSetupFunc = GLD_SI_SMOOTH_EXTRAS;
+ } else {
+ if (ctx->_TriangleCaps & DD_FLATSHADE)
+ gld->iSetupFunc = GLD_SI_FLAT; // Setup flat shade + texture
+ else
+ gld->iSetupFunc = GLD_SI_SMOOTH; // Setup smooth shade + texture
+ }
+
+ gld->bUseMesaTnL = _gldChooseInternalPipeline(ctx, gld);
+ if (gld->bUseMesaTnL) {
+ gldPB = &gld->PB2d;
+ _GLD_DX9_DEV(SetSoftwareVertexProcessing(gld->pDev, TRUE));
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_CLIPPING, FALSE));
+ _GLD_DX9_DEV(SetVertexShader(gld->pDev, NULL));
+ _GLD_DX9_DEV(SetFVF(gld->pDev, gldPB->dwFVF));
+ } else {
+ gldPB = &gld->PB3d;
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_CLIPPING, TRUE));
+// if (gld->TnLPipeline == GLD_PIPELINE_D3D_VS_TWOSIDE) {
+// _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, !gld->VStwosidelight.bHardware));
+// _GLD_DX9_DEV(SetVertexShader(gld->pDev, gld->VStwosidelight.hShader));
+// } else {
+// _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, !gld->bHasHWTnL));
+ _GLD_DX9_DEV(SetSoftwareVertexProcessing(gld->pDev, !gld->bHasHWTnL));
+ _GLD_DX9_DEV(SetVertexShader(gld->pDev, NULL));
+ _GLD_DX9_DEV(SetFVF(gld->pDev, gldPB->dwFVF));
+// }
+ }
+
+#define _GLD_TEST_STATE(a) \
+ if (new_state & (a)) { \
+ gld##a(ctx); \
+ new_state &= ~(a); \
+ }
+
+#define _GLD_TEST_STATE_DX9(a) \
+ if (new_state & (a)) { \
+ gld##a##_DX9(ctx); \
+ new_state &= ~(a); \
+ }
+
+#define _GLD_IGNORE_STATE(a) new_state &= ~(a);
+
+// if (!gld->bUseMesaTnL) {
+ // Not required if Mesa is doing the TnL.
+ // Problem: If gld->bUseMesaTnL is TRUE when these are signaled,
+ // then we'll miss updating the D3D TnL pipeline.
+ // Therefore, don't test for gld->bUseMesaTnL
+ _GLD_TEST_STATE(_NEW_MODELVIEW);
+ _GLD_TEST_STATE(_NEW_PROJECTION);
+// }
+
+ _GLD_TEST_STATE_DX9(_NEW_TEXTURE); // extern, so guard with _DX9
+ _GLD_TEST_STATE(_NEW_COLOR);
+ _GLD_TEST_STATE(_NEW_DEPTH);
+ _GLD_TEST_STATE(_NEW_POLYGON);
+ _GLD_TEST_STATE(_NEW_STENCIL);
+ _GLD_TEST_STATE(_NEW_FOG);
+ _GLD_TEST_STATE(_NEW_LIGHT);
+ _GLD_TEST_STATE(_NEW_VIEWPORT);
+
+ _GLD_IGNORE_STATE(_NEW_TRANSFORM);
+
+ // Scissor Test: New for DX9
+ _GLD_TEST_STATE(_NEW_SCISSOR);
+
+// Stubs for future use.
+/* _GLD_TEST_STATE(_NEW_TEXTURE_MATRIX);
+ _GLD_TEST_STATE(_NEW_COLOR_MATRIX);
+ _GLD_TEST_STATE(_NEW_ACCUM);
+ _GLD_TEST_STATE(_NEW_EVAL);
+ _GLD_TEST_STATE(_NEW_HINT);
+ _GLD_TEST_STATE(_NEW_LINE);
+ _GLD_TEST_STATE(_NEW_PIXEL);
+ _GLD_TEST_STATE(_NEW_POINT);
+ _GLD_TEST_STATE(_NEW_POLYGONSTIPPLE);
+ _GLD_TEST_STATE(_NEW_PACKUNPACK);
+ _GLD_TEST_STATE(_NEW_ARRAY);
+ _GLD_TEST_STATE(_NEW_RENDERMODE);
+ _GLD_TEST_STATE(_NEW_BUFFERS);
+ _GLD_TEST_STATE(_NEW_MULTISAMPLE);
+*/
+
+// For debugging.
+#if 0
+#define _GLD_TEST_UNHANDLED_STATE(a) \
+ if (new_state & (a)) { \
+ gldLogMessage(GLDLOG_ERROR, "Unhandled " #a "\n"); \
+ }
+ _GLD_TEST_UNHANDLED_STATE(_NEW_TEXTURE_MATRIX);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_COLOR_MATRIX);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_ACCUM);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_EVAL);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_HINT);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_LINE);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_PIXEL);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_POINT);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_POLYGONSTIPPLE);
+// _GLD_TEST_UNHANDLED_STATE(_NEW_SCISSOR);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_PACKUNPACK);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_ARRAY);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_RENDERMODE);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_BUFFERS);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_MULTISAMPLE);
+#undef _GLD_UNHANDLED_STATE
+#endif
+
+#undef _GLD_TEST_STATE
+}
+
+//---------------------------------------------------------------------------
+// Viewport
+//---------------------------------------------------------------------------
+
+void gld_Viewport_DX9(
+ struct gl_context *ctx,
+ GLint x,
+ GLint y,
+ GLsizei w,
+ GLsizei h)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ D3DVIEWPORT9 d3dvp;
+
+ if (!gld || !gld->pDev)
+ return;
+
+ // This is a hack. When the app is minimized, Mesa passes
+ // w=1 and h=1 for viewport dimensions. Without this test
+ // we get a GPF in gld_wgl_resize_buffers().
+ if ((w==1) && (h==1))
+ return;
+
+ // Call ResizeBuffersMESA. This function will early-out
+ // if no resize is needed.
+ //ctx->Driver.ResizeBuffersMESA(ctx);
+ // Mesa 5: Changed parameters
+ ctx->Driver.ResizeBuffers(gldCtx->glBuffer);
+
+#if 0
+ ddlogPrintf(GLDLOG_SYSTEM, ">> Viewport x=%d y=%d w=%d h=%d", x,y,w,h);
+#endif
+
+ // ** D3D viewport must not be outside the render target surface **
+ // Sanity check the GL viewport dimensions
+ if (x < 0) x = 0;
+ if (y < 0) y = 0;
+ if (w > gldCtx->dwWidth) w = gldCtx->dwWidth;
+ if (h > gldCtx->dwHeight) h = gldCtx->dwHeight;
+ // Ditto for D3D viewport dimensions
+ if (w+x > gldCtx->dwWidth) w = gldCtx->dwWidth-x;
+ if (h+y > gldCtx->dwHeight) h = gldCtx->dwHeight-y;
+
+ d3dvp.X = x;
+ d3dvp.Y = gldCtx->dwHeight - (y + h);
+ d3dvp.Width = w;
+ d3dvp.Height = h;
+ if (ctx->Viewport.Near <= ctx->Viewport.Far) {
+ d3dvp.MinZ = ctx->Viewport.Near;
+ d3dvp.MaxZ = ctx->Viewport.Far;
+ } else {
+ d3dvp.MinZ = ctx->Viewport.Far;
+ d3dvp.MaxZ = ctx->Viewport.Near;
+ }
+
+ // TODO: DEBUGGING
+// d3dvp.MinZ = 0.0f;
+// d3dvp.MaxZ = 1.0f;
+
+ _GLD_DX9_DEV(SetViewport(gld->pDev, &d3dvp));
+
+}
+
+//---------------------------------------------------------------------------
+
+extern BOOL dglWglResizeBuffers(struct gl_context *ctx, BOOL bDefaultDriver);
+
+// Mesa 5: Parameter change
+void gldResizeBuffers_DX9(
+// struct gl_context *ctx)
+ struct gl_framebuffer *fb)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ dglWglResizeBuffers(ctx, TRUE);
+}
+
+//---------------------------------------------------------------------------
+#ifdef _DEBUG
+// This is only for debugging.
+// To use, plug into ctx->Driver.Enable pointer below.
+void gld_Enable(
+ struct gl_context *ctx,
+ GLenum e,
+ GLboolean b)
+{
+ char buf[1024];
+ sprintf(buf, "Enable: %s (%s)\n", _mesa_lookup_enum_by_nr(e), b?"TRUE":"FALSE");
+ ddlogMessage(DDLOG_SYSTEM, buf);
+}
+#endif
+//---------------------------------------------------------------------------
+// Driver pointer setup
+//---------------------------------------------------------------------------
+
+extern const GLubyte* _gldGetStringGeneric(struct gl_context*, GLenum);
+
+void gldSetupDriverPointers_DX9(
+ struct gl_context *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+ // Mandatory functions
+ ctx->Driver.GetString = _gldGetStringGeneric;
+ ctx->Driver.UpdateState = gld_update_state_DX9;
+ ctx->Driver.Clear = gld_Clear_DX9;
+ ctx->Driver.DrawBuffer = gld_set_draw_buffer_DX9;
+ ctx->Driver.GetBufferSize = gld_buffer_size_DX9;
+ ctx->Driver.Finish = gld_Finish_DX9;
+ ctx->Driver.Flush = gld_Flush_DX9;
+ ctx->Driver.Error = gld_Error_DX9;
+
+ // Hardware accumulation buffer
+ ctx->Driver.Accum = NULL; // TODO: gld_Accum;
+
+ // Bitmap functions
+ ctx->Driver.CopyPixels = gld_CopyPixels_DX9;
+ ctx->Driver.DrawPixels = gld_DrawPixels_DX9;
+ ctx->Driver.ReadPixels = gld_ReadPixels_DX9;
+ ctx->Driver.Bitmap = gld_Bitmap_DX9;
+
+ // Buffer resize
+ ctx->Driver.ResizeBuffers = gldResizeBuffers_DX9;
+
+ // Texture image functions
+ ctx->Driver.ChooseTextureFormat = gld_ChooseTextureFormat_DX9;
+ ctx->Driver.TexImage1D = gld_TexImage1D_DX9;
+ ctx->Driver.TexImage2D = gld_TexImage2D_DX9;
+ ctx->Driver.TexImage3D = _mesa_store_teximage3d;
+ ctx->Driver.TexSubImage1D = gld_TexSubImage1D_DX9;
+ ctx->Driver.TexSubImage2D = gld_TexSubImage2D_DX9;
+ ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d;
+
+ ctx->Driver.CopyTexImage1D = gldCopyTexImage1D_DX9; //NULL;
+ ctx->Driver.CopyTexImage2D = gldCopyTexImage2D_DX9; //NULL;
+ ctx->Driver.CopyTexSubImage1D = gldCopyTexSubImage1D_DX9; //NULL;
+ ctx->Driver.CopyTexSubImage2D = gldCopyTexSubImage2D_DX9; //NULL;
+ ctx->Driver.CopyTexSubImage3D = gldCopyTexSubImage3D_DX9;
+ ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage;
+
+ // Texture object functions
+ ctx->Driver.BindTexture = NULL;
+ ctx->Driver.NewTextureObject = NULL; // Not yet implemented by Mesa!;
+ ctx->Driver.DeleteTexture = gld_DeleteTexture_DX9;
+ ctx->Driver.PrioritizeTexture = NULL;
+
+ // Imaging functionality
+ ctx->Driver.CopyColorTable = NULL;
+ ctx->Driver.CopyColorSubTable = NULL;
+ ctx->Driver.CopyConvolutionFilter1D = NULL;
+ ctx->Driver.CopyConvolutionFilter2D = NULL;
+
+ // State changing functions
+ ctx->Driver.AlphaFunc = NULL; //gld_AlphaFunc;
+ ctx->Driver.BlendFuncSeparate = NULL; //gld_BlendFunc;
+ ctx->Driver.ClearColor = NULL; //gld_ClearColor;
+ ctx->Driver.ClearDepth = NULL; //gld_ClearDepth;
+ ctx->Driver.ClearStencil = NULL; //gld_ClearStencil;
+ ctx->Driver.ColorMask = NULL; //gld_ColorMask;
+ ctx->Driver.CullFace = NULL; //gld_CullFace;
+ ctx->Driver.ClipPlane = NULL; //gld_ClipPlane;
+ ctx->Driver.FrontFace = NULL; //gld_FrontFace;
+ ctx->Driver.DepthFunc = NULL; //gld_DepthFunc;
+ ctx->Driver.DepthMask = NULL; //gld_DepthMask;
+ ctx->Driver.DepthRange = NULL;
+ ctx->Driver.Enable = NULL; //gld_Enable;
+ ctx->Driver.Fogfv = NULL; //gld_Fogfv;
+ ctx->Driver.Hint = NULL; //gld_Hint;
+ ctx->Driver.Lightfv = NULL; //gld_Lightfv;
+ ctx->Driver.LightModelfv = NULL; //gld_LightModelfv;
+ ctx->Driver.LineStipple = NULL; //gld_LineStipple;
+ ctx->Driver.LineWidth = NULL; //gld_LineWidth;
+ ctx->Driver.LogicOpcode = NULL; //gld_LogicOpcode;
+ ctx->Driver.PointParameterfv = NULL; //gld_PointParameterfv;
+ ctx->Driver.PointSize = NULL; //gld_PointSize;
+ ctx->Driver.PolygonMode = NULL; //gld_PolygonMode;
+ ctx->Driver.PolygonOffset = NULL; //gld_PolygonOffset;
+ ctx->Driver.PolygonStipple = NULL; //gld_PolygonStipple;
+ ctx->Driver.RenderMode = NULL; //gld_RenderMode;
+ ctx->Driver.Scissor = NULL; //gld_Scissor;
+ ctx->Driver.ShadeModel = NULL; //gld_ShadeModel;
+ ctx->Driver.StencilFunc = NULL; //gld_StencilFunc;
+ ctx->Driver.StencilMask = NULL; //gld_StencilMask;
+ ctx->Driver.StencilOp = NULL; //gld_StencilOp;
+ ctx->Driver.TexGen = NULL; //gld_TexGen;
+ ctx->Driver.TexEnv = NULL;
+ ctx->Driver.TexParameter = NULL;
+ ctx->Driver.TextureMatrix = NULL; //gld_TextureMatrix;
+ ctx->Driver.Viewport = gld_Viewport_DX9;
+
+ _swsetup_Wakeup(ctx);
+
+ tnl->Driver.RunPipeline = _tnl_run_pipeline;
+ tnl->Driver.Render.ResetLineStipple = gld_ResetLineStipple_DX9;
+ tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon;
+ tnl->Driver.Render.ClippedLine = _tnl_RenderClippedLine;
+
+ // Hook into glFrustum() and glOrtho()
+// ctx->Exec->Frustum = gldFrustumHook_DX9;
+// ctx->Exec->Ortho = gldOrthoHook_DX9;
+
+}
+
+//---------------------------------------------------------------------------
diff --git a/mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_dx9.h b/mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_dx9.h
new file mode 100644
index 000000000..5cb36ac05
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_dx9.h
@@ -0,0 +1,327 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: GLDirect Direct3D 9.0 header file
+*
+****************************************************************************/
+
+#ifndef _GLD_DX9_H
+#define _GLD_DX9_H
+
+//---------------------------------------------------------------------------
+// Windows includes
+//---------------------------------------------------------------------------
+
+//#ifndef STRICT
+//#define STRICT
+//#endif
+
+//#define WIN32_LEAN_AND_MEAN
+//#include <windows.h>
+#include <d3d9.h>
+#include <d3dx9.h>
+
+// MS screwed up with the DX8.1 SDK - there's no compile-time
+// method of compiling for 8.0 via the 8.1 SDK unless you
+// "make sure you don't use any 8.1 interfaces".
+// We CAN use 8.1 D3DX static functions, though - just not new 8.1 interfaces.
+//
+// D3D_SDK_VERSION is 120 for 8.0 (supported by Windows 95).
+// D3D_SDK_VERSION is 220 for 8.1 (NOT supported by Windows 95).
+//
+//#define D3D_SDK_VERSION_DX9_SUPPORT_WIN95 120
+//#define D3D_SDK_VERSION_DX91 220
+
+// Typedef for obtaining function from d3d8.dll
+typedef IDirect3D9* (WINAPI *FNDIRECT3DCREATE9) (UINT);
+
+
+//---------------------------------------------------------------------------
+// Defines
+//---------------------------------------------------------------------------
+
+#ifdef _DEBUG
+#define _GLD_TEST_HRESULT(h) \
+{ \
+ HRESULT _hr = (h); \
+ if (FAILED(_hr)) { \
+ gldLogError(GLDLOG_ERROR, #h, _hr); \
+ } \
+}
+#define _GLD_DX9(func) _GLD_TEST_HRESULT(IDirect3D9_##func##)
+#define _GLD_DX9_DEV(func) _GLD_TEST_HRESULT(IDirect3DDevice9_##func##)
+#define _GLD_DX9_VB(func) _GLD_TEST_HRESULT(IDirect3DVertexBuffer9_##func##)
+#define _GLD_DX9_TEX(func) _GLD_TEST_HRESULT(IDirect3DTexture9_##func##)
+#else
+#define _GLD_DX9(func) IDirect3D9_##func
+#define _GLD_DX9_DEV(func) IDirect3DDevice9_##func
+#define _GLD_DX9_VB(func) IDirect3DVertexBuffer9_##func
+#define _GLD_DX9_TEX(func) IDirect3DTexture9_##func
+#endif
+
+#define SAFE_RELEASE(p) \
+{ \
+ if (p) { \
+ (p)->lpVtbl->Release(p); \
+ (p) = NULL; \
+ } \
+}
+
+#define SAFE_RELEASE_VB9(p) \
+{ \
+ if (p) { \
+ IDirect3DVertexBuffer9_Release((p)); \
+ (p) = NULL; \
+ } \
+}
+
+#define SAFE_RELEASE_SURFACE9(p) \
+{ \
+ if (p) { \
+ IDirect3DSurface9_Release((p)); \
+ (p) = NULL; \
+ } \
+}
+
+// Setup index.
+enum {
+ GLD_SI_FLAT = 0,
+ GLD_SI_SMOOTH = 1,
+ GLD_SI_FLAT_EXTRAS = 2,
+ GLD_SI_SMOOTH_EXTRAS = 3,
+};
+/*
+// Internal pipeline
+typedef enum {
+ GLD_PIPELINE_MESA = 0, // Mesa pipeline
+ GLD_PIPELINE_D3D_FVF = 1, // Direct3D Fixed-function pipeline
+ GLD_PIPELINE_D3D_VS_TWOSIDE = 2 // Direct3D two-sided-lighting vertex shader
+} GLD_tnl_pipeline;
+*/
+//---------------------------------------------------------------------------
+// Vertex definitions for Fixed-Function pipeline
+//---------------------------------------------------------------------------
+
+//
+// NOTE: If the number of texture units is altered then most of
+// the texture code will need to be revised.
+//
+
+#define GLD_MAX_TEXTURE_UNITS_DX9 2
+
+//
+// 2D vertex transformed by Mesa
+//
+#define GLD_FVF_2D_VERTEX ( D3DFVF_XYZRHW | \
+ D3DFVF_DIFFUSE | \
+ D3DFVF_SPECULAR | \
+ D3DFVF_TEX2)
+typedef struct {
+ FLOAT x, y; // 2D raster coords
+ FLOAT sz; // Screen Z (depth)
+ FLOAT rhw; // Reciprocal homogenous W
+ DWORD diffuse; // Diffuse colour
+ DWORD specular; // For separate-specular support
+ FLOAT t0_u, t0_v; // 1st set of texture coords
+ FLOAT t1_u, t1_v; // 2nd set of texture coords
+} GLD_2D_VERTEX;
+
+
+//
+// 3D vertex transformed by Direct3D
+//
+#define GLD_FVF_3D_VERTEX ( D3DFVF_XYZ | \
+ D3DFVF_DIFFUSE | \
+ D3DFVF_TEX2)
+
+typedef struct {
+ D3DXVECTOR3 Position; // XYZ Vector in object space
+ D3DCOLOR Diffuse; // Diffuse colour
+ D3DXVECTOR2 TexUnit0; // Texture unit 0
+ D3DXVECTOR2 TexUnit1; // Texture unit 1
+} GLD_3D_VERTEX;
+
+//---------------------------------------------------------------------------
+// Vertex Shaders
+//---------------------------------------------------------------------------
+/*
+// DX8 Vertex Shader
+typedef struct {
+ DWORD hShader; // If NULL, shader is invalid and cannot be used
+ BOOL bHardware; // If TRUE then shader was created for hardware,
+ // otherwise shader was created for software.
+} GLD_vertexShader;
+*/
+//---------------------------------------------------------------------------
+// Structs
+//---------------------------------------------------------------------------
+
+// This keeps a count of how many times we choose each individual internal
+// pathway. Useful for seeing if a certain pathway was ever used by an app, and
+// how much each pathway is biased.
+// Zero the members at context creation and dump stats at context deletion.
+typedef struct {
+ // Note: DWORD is probably too small
+ ULARGE_INTEGER qwMesa; // Mesa TnL pipeline
+ ULARGE_INTEGER qwD3DFVF; // Direct3D Fixed-Function pipeline
+// ULARGE_INTEGER dwD3D2SVS; // Direct3D Two-Sided Vertex Shader pipeline
+} GLD_pipeline_usage;
+
+// GLDirect Primitive Buffer (points, lines, triangles and quads)
+typedef struct {
+ // Data for IDirect3DDevice9::CreateVertexBuffer()
+ DWORD dwStride; // Stride of vertex
+ DWORD dwUsage; // Usage flags
+ DWORD dwFVF; // Direct3D Flexible Vertex Format
+ DWORD dwPool; // Pool flags
+
+ IDirect3DVertexBuffer9 *pVB; // Holds points, lines, tris and quads.
+
+ // Point list is assumed to be at start of buffer
+ DWORD iFirstLine; // Index of start of line list
+ DWORD iFirstTriangle; // Index of start of triangle list
+
+ BYTE *pPoints; // Pointer to next free point
+ BYTE *pLines; // Pointer to next free line
+ BYTE *pTriangles; // Pointer to next free triangle
+
+ DWORD nPoints; // Number of points ready to render
+ DWORD nLines; // Number of lines ready to render
+ DWORD nTriangles; // Number of triangles ready to render
+} GLD_pb_dx9;
+
+// GLDirect DX9 driver data
+typedef struct {
+ // GLDirect vars
+ BOOL bDoublebuffer; // Doublebuffer (otherwise single-buffered)
+ BOOL bDepthStencil; // Depth buffer needed (stencil optional)
+ D3DFORMAT RenderFormat; // Format of back/front buffer
+ D3DFORMAT DepthFormat; // Format of depth/stencil
+// float fFlipWindowY; // Value for flipping viewport Y coord
+
+ // Direct3D vars
+ D3DCAPS9 d3dCaps9;
+ BOOL bHasHWTnL; // Device has Hardware Transform/Light?
+ IDirect3D9 *pD3D; // Base Direct3D9 interface
+ IDirect3DDevice9 *pDev; // Direct3D9 Device interface
+ GLD_pb_dx9 PB2d; // Vertices transformed by Mesa
+ GLD_pb_dx9 PB3d; // Vertices transformed by Direct3D
+ D3DPRIMITIVETYPE d3dpt; // Current Direct3D primitive type
+ D3DXMATRIX matProjection; // Projection matrix for D3D TnL
+ D3DXMATRIX matModelView; // Model/View matrix for D3D TnL
+ int iSetupFunc; // Which setup functions to use
+ BOOL bUseMesaTnL; // Whether to use Mesa or D3D for TnL
+
+ // Direct3D vars for two-sided lighting
+// GLD_vertexShader VStwosidelight; // Vertex Shader for two-sided lighting
+// D3DXMATRIX matWorldViewProj;// World/View/Projection matrix for shaders
+
+
+// GLD_tnl_pipeline TnLPipeline; // Index of current internal pipeline
+ GLD_pipeline_usage PipelineUsage;
+
+ BOOL bCanScissor; // Scissor test - new for DX9
+} GLD_driver_dx9;
+
+#define GLD_GET_DX9_DRIVER(c) (GLD_driver_dx9*)(c)->glPriv
+
+//---------------------------------------------------------------------------
+// Function prototypes
+//---------------------------------------------------------------------------
+
+PROC gldGetProcAddress_DX9(LPCSTR a);
+void gldEnableExtensions_DX9(struct gl_context *ctx);
+void gldInstallPipeline_DX9(struct gl_context *ctx);
+void gldSetupDriverPointers_DX9(struct gl_context *ctx);
+//void gldResizeBuffers_DX9(struct gl_context *ctx);
+void gldResizeBuffers_DX9(struct gl_framebuffer *fb);
+
+
+// Texture functions
+
+void gldCopyTexImage1D_DX9(struct gl_context *ctx, GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border);
+void gldCopyTexImage2D_DX9(struct gl_context *ctx, GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+void gldCopyTexSubImage1D_DX9(struct gl_context *ctx, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width );
+void gldCopyTexSubImage2D_DX9(struct gl_context *ctx, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height );
+void gldCopyTexSubImage3D_DX9(struct gl_context *ctx, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height );
+
+void gld_NEW_TEXTURE_DX9(struct gl_context *ctx);
+void gld_DrawPixels_DX9(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels);
+void gld_ReadPixels_DX9(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const struct gl_pixelstore_attrib *unpack, GLvoid *dest);
+void gld_CopyPixels_DX9(struct gl_context *ctx, GLint srcx, GLint srcy, GLsizei width, GLsizei height, GLint dstx, GLint dsty, GLenum type);
+void gld_Bitmap_DX9(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei height, const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap);
+const struct gl_texture_format* gld_ChooseTextureFormat_DX9(struct gl_context *ctx, GLint internalFormat, GLenum srcFormat, GLenum srcType);
+void gld_TexImage2D_DX9(struct gl_context *ctx, GLenum target, GLint level, GLint internalFormat, GLint width, GLint height, GLint border, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *tObj, struct gl_texture_image *texImage);
+void gld_TexImage1D_DX9(struct gl_context *ctx, GLenum target, GLint level, GLint internalFormat, GLint width, GLint border, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *texObj, struct gl_texture_image *texImage );
+void gld_TexSubImage2D_DX9( struct gl_context *ctx, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *texObj, struct gl_texture_image *texImage );
+void gld_TexSubImage1D_DX9(struct gl_context *ctx, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *texObj, struct gl_texture_image *texImage);
+void gld_DeleteTexture_DX9(struct gl_context *ctx, struct gl_texture_object *tObj);
+void gld_ResetLineStipple_DX9(struct gl_context *ctx);
+
+// 2D primitive functions
+
+void gld_Points2D_DX9(struct gl_context *ctx, GLuint first, GLuint last);
+
+void gld_Line2DFlat_DX9(struct gl_context *ctx, GLuint v0, GLuint v1);
+void gld_Line2DSmooth_DX9(struct gl_context *ctx, GLuint v0, GLuint v1);
+
+void gld_Triangle2DFlat_DX9(struct gl_context *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Triangle2DSmooth_DX9(struct gl_context *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Triangle2DFlatExtras_DX9(struct gl_context *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Triangle2DSmoothExtras_DX9(struct gl_context *ctx, GLuint v0, GLuint v1, GLuint v2);
+
+void gld_Quad2DFlat_DX9(struct gl_context *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+void gld_Quad2DSmooth_DX9(struct gl_context *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+void gld_Quad2DFlatExtras_DX9(struct gl_context *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+void gld_Quad2DSmoothExtras_DX9(struct gl_context *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+
+// 3D primitive functions
+
+void gld_Points3D_DX9(struct gl_context *ctx, GLuint first, GLuint last);
+void gld_Line3DFlat_DX9(struct gl_context *ctx, GLuint v0, GLuint v1);
+void gld_Triangle3DFlat_DX9(struct gl_context *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Quad3DFlat_DX9(struct gl_context *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+void gld_Line3DSmooth_DX9(struct gl_context *ctx, GLuint v0, GLuint v1);
+void gld_Triangle3DSmooth_DX9(struct gl_context *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Quad3DSmooth_DX9(struct gl_context *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+
+// Primitive functions for Two-sided-lighting Vertex Shader
+
+void gld_Points2DTwoside_DX9(struct gl_context *ctx, GLuint first, GLuint last);
+void gld_Line2DFlatTwoside_DX9(struct gl_context *ctx, GLuint v0, GLuint v1);
+void gld_Line2DSmoothTwoside_DX9(struct gl_context *ctx, GLuint v0, GLuint v1);
+void gld_Triangle2DFlatTwoside_DX9(struct gl_context *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Triangle2DSmoothTwoside_DX9(struct gl_context *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Quad2DFlatTwoside_DX9(struct gl_context *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+void gld_Quad2DSmoothTwoside_DX9(struct gl_context *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+
+#endif
diff --git a/mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_dxerr9.h b/mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_dxerr9.h
new file mode 100644
index 000000000..7ec8c8a46
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_dxerr9.h
@@ -0,0 +1,77 @@
+/*==========================================================================;
+ *
+ *
+ * File: dxerr9.h
+ * Content: DirectX Error Library Include File
+ *
+ ****************************************************************************/
+
+#ifndef _GLD_DXERR9_H_
+#define _GLD_DXERR9_H_
+
+
+#include <d3d9.h>
+
+//
+// DXGetErrorString9
+//
+// Desc: Converts an DirectX HRESULT to a string
+//
+// Args: HRESULT hr Can be any error code from
+// DPLAY D3D8 D3DX8 DMUSIC DSOUND
+//
+// Return: Converted string
+//
+const char* __stdcall DXGetErrorString9A(HRESULT hr);
+const WCHAR* __stdcall DXGetErrorString9W(HRESULT hr);
+
+#ifdef UNICODE
+ #define DXGetErrorString9 DXGetErrorString9W
+#else
+ #define DXGetErrorString9 DXGetErrorString9A
+#endif
+
+
+//
+// DXTrace
+//
+// Desc: Outputs a formatted error message to the debug stream
+//
+// Args: CHAR* strFile The current file, typically passed in using the
+// __FILE__ macro.
+// DWORD dwLine The current line number, typically passed in using the
+// __LINE__ macro.
+// HRESULT hr An HRESULT that will be traced to the debug stream.
+// CHAR* strMsg A string that will be traced to the debug stream (may be NULL)
+// BOOL bPopMsgBox If TRUE, then a message box will popup also containing the passed info.
+//
+// Return: The hr that was passed in.
+//
+//HRESULT __stdcall DXTraceA( char* strFile, DWORD dwLine, HRESULT hr, char* strMsg, BOOL bPopMsgBox = FALSE );
+//HRESULT __stdcall DXTraceW( char* strFile, DWORD dwLine, HRESULT hr, WCHAR* strMsg, BOOL bPopMsgBox = FALSE );
+HRESULT __stdcall DXTraceA( char* strFile, DWORD dwLine, HRESULT hr, char* strMsg, BOOL bPopMsgBox);
+HRESULT __stdcall DXTraceW( char* strFile, DWORD dwLine, HRESULT hr, WCHAR* strMsg, BOOL bPopMsgBox);
+
+#ifdef UNICODE
+ #define DXTrace DXTraceW
+#else
+ #define DXTrace DXTraceA
+#endif
+
+
+//
+// Helper macros
+//
+#if defined(DEBUG) | defined(_DEBUG)
+ #define DXTRACE_MSG(str) DXTrace( __FILE__, (DWORD)__LINE__, 0, str, FALSE )
+ #define DXTRACE_ERR(str,hr) DXTrace( __FILE__, (DWORD)__LINE__, hr, str, TRUE )
+ #define DXTRACE_ERR_NOMSGBOX(str,hr) DXTrace( __FILE__, (DWORD)__LINE__, hr, str, FALSE )
+#else
+ #define DXTRACE_MSG(str) (0L)
+ #define DXTRACE_ERR(str,hr) (hr)
+ #define DXTRACE_ERR_NOMSGBOX(str,hr) (hr)
+#endif
+
+
+#endif
+
diff --git a/mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_ext_dx9.c b/mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_ext_dx9.c
new file mode 100644
index 000000000..d370ce413
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_ext_dx9.c
@@ -0,0 +1,344 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: GL extensions
+*
+****************************************************************************/
+
+//#include "../GLDirect.h"
+//#include "../gld_log.h"
+//#include "../gld_settings.h"
+
+#include <windows.h>
+#define GL_GLEXT_PROTOTYPES
+#include <GL/gl.h>
+#include <GL/glext.h>
+
+//#include "ddlog.h"
+//#include "gld_dx8.h"
+
+#include "glheader.h"
+#include "context.h"
+#include "colormac.h"
+#include "depth.h"
+#include "extensions.h"
+#include "macros.h"
+#include "matrix.h"
+// #include "mem.h"
+//#include "mmath.h"
+#include "mtypes.h"
+#include "texformat.h"
+#include "texstore.h"
+#include "vbo/vbo.h"
+#include "swrast_setup/swrast_setup.h"
+#include "swrast_setup/ss_context.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+#include "dglcontext.h"
+#include "extensions.h"
+
+// For some reason this is not defined in an above header...
+extern void _mesa_enable_imaging_extensions(struct gl_context *ctx);
+
+//---------------------------------------------------------------------------
+// Hack for the SGIS_multitexture extension that was removed from Mesa
+// NOTE: SGIS_multitexture enums also clash with GL_SGIX_async_pixel
+
+ // NOTE: Quake2 ran *slower* with this enabled, so I've
+ // disabled it for now.
+ // To enable, uncomment:
+ // _mesa_add_extension(ctx, GL_TRUE, szGL_SGIS_multitexture, 0);
+
+//---------------------------------------------------------------------------
+
+enum {
+ /* Quake2 GL_SGIS_multitexture */
+ GL_SELECTED_TEXTURE_SGIS = 0x835B,
+ GL_SELECTED_TEXTURE_COORD_SET_SGIS = 0x835C,
+ GL_MAX_TEXTURES_SGIS = 0x835D,
+ GL_TEXTURE0_SGIS = 0x835E,
+ GL_TEXTURE1_SGIS = 0x835F,
+ GL_TEXTURE2_SGIS = 0x8360,
+ GL_TEXTURE3_SGIS = 0x8361,
+ GL_TEXTURE_COORD_SET_SOURCE_SGIS = 0x8363,
+};
+
+//---------------------------------------------------------------------------
+
+void APIENTRY gldSelectTextureSGIS(
+ GLenum target)
+{
+ GLenum ARB_target = GL_TEXTURE0_ARB + (target - GL_TEXTURE0_SGIS);
+ glActiveTextureARB(ARB_target);
+}
+
+//---------------------------------------------------------------------------
+
+void APIENTRY gldMTexCoord2fSGIS(
+ GLenum target,
+ GLfloat s,
+ GLfloat t)
+{
+ GLenum ARB_target = GL_TEXTURE0_ARB + (target - GL_TEXTURE0_SGIS);
+ glMultiTexCoord2fARB(ARB_target, s, t);
+}
+
+//---------------------------------------------------------------------------
+
+void APIENTRY gldMTexCoord2fvSGIS(
+ GLenum target,
+ const GLfloat *v)
+{
+ GLenum ARB_target = GL_TEXTURE0_ARB + (target - GL_TEXTURE0_SGIS);
+ glMultiTexCoord2fvARB(ARB_target, v);
+}
+
+//---------------------------------------------------------------------------
+// Extensions
+//---------------------------------------------------------------------------
+
+typedef struct {
+ PROC proc;
+ char *name;
+} GLD_extension;
+
+GLD_extension GLD_extList[] = {
+#ifdef GL_EXT_polygon_offset
+ { (PROC)glPolygonOffsetEXT, "glPolygonOffsetEXT" },
+#endif
+ { (PROC)glBlendEquationEXT, "glBlendEquationEXT" },
+ { (PROC)glBlendColorEXT, "glBlendColorExt" },
+ { (PROC)glVertexPointerEXT, "glVertexPointerEXT" },
+ { (PROC)glNormalPointerEXT, "glNormalPointerEXT" },
+ { (PROC)glColorPointerEXT, "glColorPointerEXT" },
+ { (PROC)glIndexPointerEXT, "glIndexPointerEXT" },
+ { (PROC)glTexCoordPointerEXT, "glTexCoordPointer" },
+ { (PROC)glEdgeFlagPointerEXT, "glEdgeFlagPointerEXT" },
+ { (PROC)glGetPointervEXT, "glGetPointervEXT" },
+ { (PROC)glArrayElementEXT, "glArrayElementEXT" },
+ { (PROC)glDrawArraysEXT, "glDrawArrayEXT" },
+ { (PROC)glAreTexturesResidentEXT, "glAreTexturesResidentEXT" },
+ { (PROC)glBindTextureEXT, "glBindTextureEXT" },
+ { (PROC)glDeleteTexturesEXT, "glDeleteTexturesEXT" },
+ { (PROC)glGenTexturesEXT, "glGenTexturesEXT" },
+ { (PROC)glIsTextureEXT, "glIsTextureEXT" },
+ { (PROC)glPrioritizeTexturesEXT, "glPrioritizeTexturesEXT" },
+ { (PROC)glCopyTexSubImage3DEXT, "glCopyTexSubImage3DEXT" },
+ { (PROC)glTexImage3DEXT, "glTexImage3DEXT" },
+ { (PROC)glTexSubImage3DEXT, "glTexSubImage3DEXT" },
+ { (PROC)glPointParameterfEXT, "glPointParameterfEXT" },
+ { (PROC)glPointParameterfvEXT, "glPointParameterfvEXT" },
+
+ { (PROC)glLockArraysEXT, "glLockArraysEXT" },
+ { (PROC)glUnlockArraysEXT, "glUnlockArraysEXT" },
+ { NULL, "\0" }
+};
+
+GLD_extension GLD_multitexList[] = {
+/*
+ { (PROC)glMultiTexCoord1dSGIS, "glMTexCoord1dSGIS" },
+ { (PROC)glMultiTexCoord1dvSGIS, "glMTexCoord1dvSGIS" },
+ { (PROC)glMultiTexCoord1fSGIS, "glMTexCoord1fSGIS" },
+ { (PROC)glMultiTexCoord1fvSGIS, "glMTexCoord1fvSGIS" },
+ { (PROC)glMultiTexCoord1iSGIS, "glMTexCoord1iSGIS" },
+ { (PROC)glMultiTexCoord1ivSGIS, "glMTexCoord1ivSGIS" },
+ { (PROC)glMultiTexCoord1sSGIS, "glMTexCoord1sSGIS" },
+ { (PROC)glMultiTexCoord1svSGIS, "glMTexCoord1svSGIS" },
+ { (PROC)glMultiTexCoord2dSGIS, "glMTexCoord2dSGIS" },
+ { (PROC)glMultiTexCoord2dvSGIS, "glMTexCoord2dvSGIS" },
+ { (PROC)glMultiTexCoord2fSGIS, "glMTexCoord2fSGIS" },
+ { (PROC)glMultiTexCoord2fvSGIS, "glMTexCoord2fvSGIS" },
+ { (PROC)glMultiTexCoord2iSGIS, "glMTexCoord2iSGIS" },
+ { (PROC)glMultiTexCoord2ivSGIS, "glMTexCoord2ivSGIS" },
+ { (PROC)glMultiTexCoord2sSGIS, "glMTexCoord2sSGIS" },
+ { (PROC)glMultiTexCoord2svSGIS, "glMTexCoord2svSGIS" },
+ { (PROC)glMultiTexCoord3dSGIS, "glMTexCoord3dSGIS" },
+ { (PROC)glMultiTexCoord3dvSGIS, "glMTexCoord3dvSGIS" },
+ { (PROC)glMultiTexCoord3fSGIS, "glMTexCoord3fSGIS" },
+ { (PROC)glMultiTexCoord3fvSGIS, "glMTexCoord3fvSGIS" },
+ { (PROC)glMultiTexCoord3iSGIS, "glMTexCoord3iSGIS" },
+ { (PROC)glMultiTexCoord3ivSGIS, "glMTexCoord3ivSGIS" },
+ { (PROC)glMultiTexCoord3sSGIS, "glMTexCoord3sSGIS" },
+ { (PROC)glMultiTexCoord3svSGIS, "glMTexCoord3svSGIS" },
+ { (PROC)glMultiTexCoord4dSGIS, "glMTexCoord4dSGIS" },
+ { (PROC)glMultiTexCoord4dvSGIS, "glMTexCoord4dvSGIS" },
+ { (PROC)glMultiTexCoord4fSGIS, "glMTexCoord4fSGIS" },
+ { (PROC)glMultiTexCoord4fvSGIS, "glMTexCoord4fvSGIS" },
+ { (PROC)glMultiTexCoord4iSGIS, "glMTexCoord4iSGIS" },
+ { (PROC)glMultiTexCoord4ivSGIS, "glMTexCoord4ivSGIS" },
+ { (PROC)glMultiTexCoord4sSGIS, "glMTexCoord4sSGIS" },
+ { (PROC)glMultiTexCoord4svSGIS, "glMTexCoord4svSGIS" },
+ { (PROC)glMultiTexCoordPointerSGIS, "glMTexCoordPointerSGIS" },
+ { (PROC)glSelectTextureSGIS, "glSelectTextureSGIS" },
+ { (PROC)glSelectTextureCoordSetSGIS, "glSelectTextureCoordSetSGIS" },
+*/
+ { (PROC)glActiveTextureARB, "glActiveTextureARB" },
+ { (PROC)glClientActiveTextureARB, "glClientActiveTextureARB" },
+ { (PROC)glMultiTexCoord1dARB, "glMultiTexCoord1dARB" },
+ { (PROC)glMultiTexCoord1dvARB, "glMultiTexCoord1dvARB" },
+ { (PROC)glMultiTexCoord1fARB, "glMultiTexCoord1fARB" },
+ { (PROC)glMultiTexCoord1fvARB, "glMultiTexCoord1fvARB" },
+ { (PROC)glMultiTexCoord1iARB, "glMultiTexCoord1iARB" },
+ { (PROC)glMultiTexCoord1ivARB, "glMultiTexCoord1ivARB" },
+ { (PROC)glMultiTexCoord1sARB, "glMultiTexCoord1sARB" },
+ { (PROC)glMultiTexCoord1svARB, "glMultiTexCoord1svARB" },
+ { (PROC)glMultiTexCoord2dARB, "glMultiTexCoord2dARB" },
+ { (PROC)glMultiTexCoord2dvARB, "glMultiTexCoord2dvARB" },
+ { (PROC)glMultiTexCoord2fARB, "glMultiTexCoord2fARB" },
+ { (PROC)glMultiTexCoord2fvARB, "glMultiTexCoord2fvARB" },
+ { (PROC)glMultiTexCoord2iARB, "glMultiTexCoord2iARB" },
+ { (PROC)glMultiTexCoord2ivARB, "glMultiTexCoord2ivARB" },
+ { (PROC)glMultiTexCoord2sARB, "glMultiTexCoord2sARB" },
+ { (PROC)glMultiTexCoord2svARB, "glMultiTexCoord2svARB" },
+ { (PROC)glMultiTexCoord3dARB, "glMultiTexCoord3dARB" },
+ { (PROC)glMultiTexCoord3dvARB, "glMultiTexCoord3dvARB" },
+ { (PROC)glMultiTexCoord3fARB, "glMultiTexCoord3fARB" },
+ { (PROC)glMultiTexCoord3fvARB, "glMultiTexCoord3fvARB" },
+ { (PROC)glMultiTexCoord3iARB, "glMultiTexCoord3iARB" },
+ { (PROC)glMultiTexCoord3ivARB, "glMultiTexCoord3ivARB" },
+ { (PROC)glMultiTexCoord3sARB, "glMultiTexCoord3sARB" },
+ { (PROC)glMultiTexCoord3svARB, "glMultiTexCoord3svARB" },
+ { (PROC)glMultiTexCoord4dARB, "glMultiTexCoord4dARB" },
+ { (PROC)glMultiTexCoord4dvARB, "glMultiTexCoord4dvARB" },
+ { (PROC)glMultiTexCoord4fARB, "glMultiTexCoord4fARB" },
+ { (PROC)glMultiTexCoord4fvARB, "glMultiTexCoord4fvARB" },
+ { (PROC)glMultiTexCoord4iARB, "glMultiTexCoord4iARB" },
+ { (PROC)glMultiTexCoord4ivARB, "glMultiTexCoord4ivARB" },
+ { (PROC)glMultiTexCoord4sARB, "glMultiTexCoord4sARB" },
+ { (PROC)glMultiTexCoord4svARB, "glMultiTexCoord4svARB" },
+
+ // Descent3 doesn't use correct string, hence this hack
+ { (PROC)glMultiTexCoord4fARB, "glMultiTexCoord4f" },
+
+ // Quake2 SGIS multitexture
+ { (PROC)gldSelectTextureSGIS, "glSelectTextureSGIS" },
+ { (PROC)gldMTexCoord2fSGIS, "glMTexCoord2fSGIS" },
+ { (PROC)gldMTexCoord2fvSGIS, "glMTexCoord2fvSGIS" },
+
+ { NULL, "\0" }
+};
+
+//---------------------------------------------------------------------------
+
+PROC gldGetProcAddress_DX(
+ LPCSTR a)
+{
+ int i;
+ PROC proc = NULL;
+
+ for (i=0; GLD_extList[i].proc; i++) {
+ if (!strcmp(a, GLD_extList[i].name)) {
+ proc = GLD_extList[i].proc;
+ break;
+ }
+ }
+
+ if (glb.bMultitexture) {
+ for (i=0; GLD_multitexList[i].proc; i++) {
+ if (!strcmp(a, GLD_multitexList[i].name)) {
+ proc = GLD_multitexList[i].proc;
+ break;
+ }
+ }
+ }
+
+ gldLogPrintf(GLDLOG_INFO, "GetProcAddress: %s (%s)", a, proc ? "OK" : "Failed");
+
+ return proc;
+}
+
+//---------------------------------------------------------------------------
+
+void gldEnableExtensions_DX9(
+ struct gl_context *ctx)
+{
+ GLuint i;
+
+ // Mesa enables some extensions by default.
+ // This table decides which ones we want to switch off again.
+
+ // NOTE: GL_EXT_compiled_vertex_array appears broken.
+
+ const char *gld_disable_extensions[] = {
+// "GL_ARB_transpose_matrix",
+// "GL_EXT_compiled_vertex_array",
+// "GL_EXT_polygon_offset",
+// "GL_EXT_rescale_normal",
+ "GL_EXT_texture3D",
+// "GL_NV_texgen_reflection",
+ NULL
+ };
+
+ const char *gld_multitex_extensions[] = {
+ "GL_ARB_multitexture", // Quake 3
+ NULL
+ };
+
+ // Quake 2 engines
+ const char *szGL_SGIS_multitexture = "GL_SGIS_multitexture";
+
+ const char *gld_enable_extensions[] = {
+ "GL_EXT_texture_env_add", // Quake 3
+ "GL_ARB_texture_env_add", // Quake 3
+ NULL
+ };
+
+ for (i=0; gld_disable_extensions[i]; i++) {
+ _mesa_disable_extension(ctx, gld_disable_extensions[i]);
+ }
+
+ for (i=0; gld_enable_extensions[i]; i++) {
+ _mesa_enable_extension(ctx, gld_enable_extensions[i]);
+ }
+
+ if (glb.bMultitexture) {
+ for (i=0; gld_multitex_extensions[i]; i++) {
+ _mesa_enable_extension(ctx, gld_multitex_extensions[i]);
+ }
+
+ // GL_SGIS_multitexture
+ // NOTE: Quake2 ran *slower* with this enabled, so I've
+ // disabled it for now.
+ // Fair bit slower on GeForce256,
+ // Much slower on 3dfx Voodoo5 5500.
+// _mesa_add_extension(ctx, GL_TRUE, szGL_SGIS_multitexture, 0);
+
+ }
+
+ _mesa_enable_imaging_extensions(ctx);
+ _mesa_enable_1_3_extensions(ctx);
+ _mesa_enable_1_4_extensions(ctx);
+}
+
+//---------------------------------------------------------------------------
diff --git a/mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_pipeline_dx9.c b/mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_pipeline_dx9.c
new file mode 100644
index 000000000..6c41e567d
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_pipeline_dx9.c
@@ -0,0 +1,77 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: Mesa transformation pipeline with GLDirect fastpath
+*
+****************************************************************************/
+
+//#include "../GLDirect.h"
+
+#include "dglcontext.h"
+#include "ddlog.h"
+#include "gld_dx9.h"
+
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+//---------------------------------------------------------------------------
+
+extern struct tnl_pipeline_stage _gld_d3d_render_stage;
+extern struct tnl_pipeline_stage _gld_mesa_render_stage;
+
+static const struct tnl_pipeline_stage *gld_pipeline[] = {
+ &_gld_d3d_render_stage, // Direct3D TnL
+ &_tnl_vertex_transform_stage,
+ &_tnl_normal_transform_stage,
+ &_tnl_lighting_stage,
+ &_tnl_fog_coordinate_stage, /* TODO: Omit fog stage. ??? */
+ &_tnl_texgen_stage,
+ &_tnl_texture_transform_stage,
+ &_tnl_point_attenuation_stage,
+ &_gld_mesa_render_stage, // Mesa TnL, D3D rendering
+ 0,
+};
+
+//---------------------------------------------------------------------------
+
+void gldInstallPipeline_DX9(
+ struct gl_context *ctx)
+{
+ // Remove any existing pipeline stages,
+ // then install GLDirect pipeline stages.
+
+ _tnl_destroy_pipeline(ctx);
+ _tnl_install_pipeline(ctx, gld_pipeline);
+}
+
+//---------------------------------------------------------------------------
diff --git a/mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_primitive_dx9.c b/mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_primitive_dx9.c
new file mode 100644
index 000000000..aaed87028
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_primitive_dx9.c
@@ -0,0 +1,1446 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: Primitive (points/lines/tris/quads) rendering
+*
+****************************************************************************/
+
+//#include "../GLDirect.h"
+
+//#include "gld_dx8.h"
+
+#include "dglcontext.h"
+#include "ddlog.h"
+#include "gld_dx9.h"
+
+#include "glheader.h"
+#include "context.h"
+#include "colormac.h"
+#include "depth.h"
+#include "extensions.h"
+#include "macros.h"
+#include "matrix.h"
+// #include "mem.h"
+//#include "mmath.h"
+#include "mtypes.h"
+#include "texformat.h"
+#include "texstore.h"
+#include "vbo/vbo.h"
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "swrast_setup/ss_context.h"
+#include "swrast/s_context.h"
+#include "swrast/s_depth.h"
+#include "swrast/s_lines.h"
+#include "swrast/s_triangle.h"
+#include "swrast/s_trispan.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+// Disable compiler complaints about unreferenced local variables
+#pragma warning (disable:4101)
+
+//---------------------------------------------------------------------------
+// Helper defines for primitives
+//---------------------------------------------------------------------------
+
+//static const float ooZ = 1.0f / 65536.0f; // One over Z
+
+#define GLD_COLOUR (D3DCOLOR_RGBA(swv->color[0], swv->color[1], swv->color[2], swv->color[3]))
+#define GLD_SPECULAR (D3DCOLOR_RGBA(swv->specular[0], swv->specular[1], swv->specular[2], swv->specular[3]))
+#define GLD_FLIP_Y(y) (gldCtx->dwHeight - (y))
+
+//---------------------------------------------------------------------------
+// 2D vertex setup
+//---------------------------------------------------------------------------
+
+#define GLD_SETUP_2D_VARS_POINTS \
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); \
+ GLD_2D_VERTEX *pV = (GLD_2D_VERTEX*)gld->PB2d.pPoints; \
+ SScontext *ss = SWSETUP_CONTEXT(ctx); \
+ SWvertex *swv; \
+ DWORD dwSpecularColour; \
+ DWORD dwFlatColour
+
+#define GLD_SETUP_2D_VARS_LINES \
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); \
+ GLD_2D_VERTEX *pV = (GLD_2D_VERTEX*)gld->PB2d.pLines; \
+ SScontext *ss = SWSETUP_CONTEXT(ctx); \
+ SWvertex *swv; \
+ DWORD dwSpecularColour; \
+ DWORD dwFlatColour
+
+#define GLD_SETUP_2D_VARS_TRIANGLES \
+ BOOL bFog = ctx->Fog.Enabled; \
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); \
+ GLD_2D_VERTEX *pV = (GLD_2D_VERTEX*)gld->PB2d.pTriangles; \
+ SScontext *ss = SWSETUP_CONTEXT(ctx); \
+ SWvertex *swv; \
+ DWORD dwSpecularColour; \
+ DWORD dwFlatColour; \
+ GLuint facing = 0; \
+ struct vertex_buffer *VB; \
+ GLchan (*vbcolor)[4]; \
+ GLchan (*vbspec)[4]
+
+#define GLD_SETUP_GET_SWVERT(s) \
+ swv = &ss->verts[##s]
+
+#define GLD_SETUP_2D_VERTEX \
+ pV->x = swv->win[0]; \
+ pV->y = GLD_FLIP_Y(swv->win[1]); \
+ pV->rhw = swv->win[3]
+
+#define GLD_SETUP_SMOOTH_COLOUR \
+ pV->diffuse = GLD_COLOUR
+
+#define GLD_SETUP_GET_FLAT_COLOUR \
+ dwFlatColour = GLD_COLOUR
+#define GLD_SETUP_GET_FLAT_FOG_COLOUR \
+ dwFlatColour = _gldComputeFog(ctx, swv)
+
+#define GLD_SETUP_USE_FLAT_COLOUR \
+ pV->diffuse = dwFlatColour
+
+#define GLD_SETUP_GET_FLAT_SPECULAR \
+ dwSpecularColour= GLD_SPECULAR
+
+#define GLD_SETUP_USE_FLAT_SPECULAR \
+ pV->specular = dwSpecularColour
+
+#define GLD_SETUP_DEPTH \
+ pV->sz = swv->win[2] / ctx->DepthMaxF
+// pV->z = swv->win[2] * ooZ;
+
+#define GLD_SETUP_SPECULAR \
+ pV->specular = GLD_SPECULAR
+
+#define GLD_SETUP_FOG \
+ pV->diffuse = _gldComputeFog(ctx, swv)
+
+#define GLD_SETUP_TEX0 \
+ pV->t0_u = swv->texcoord[0][0]; \
+ pV->t0_v = swv->texcoord[0][1]
+
+#define GLD_SETUP_TEX1 \
+ pV->t1_u = swv->texcoord[1][0]; \
+ pV->t1_v = swv->texcoord[1][1]
+
+#define GLD_SETUP_LIGHTING(v) \
+ if (facing == 1) { \
+ pV->diffuse = D3DCOLOR_RGBA(vbcolor[##v][0], vbcolor[##v][1], vbcolor[##v][2], vbcolor[##v][3]); \
+ if (vbspec) { \
+ pV->specular = D3DCOLOR_RGBA(vbspec[##v][0], vbspec[##v][1], vbspec[##v][2], vbspec[##v][3]); \
+ } \
+ } else { \
+ if (bFog) \
+ GLD_SETUP_FOG; \
+ else \
+ GLD_SETUP_SMOOTH_COLOUR; \
+ GLD_SETUP_SPECULAR; \
+ }
+
+#define GLD_SETUP_GET_FLAT_LIGHTING(v) \
+ if (facing == 1) { \
+ dwFlatColour = D3DCOLOR_RGBA(vbcolor[##v][0], vbcolor[##v][1], vbcolor[##v][2], vbcolor[##v][3]); \
+ if (vbspec) { \
+ dwSpecularColour = D3DCOLOR_RGBA(vbspec[##v][0], vbspec[##v][1], vbspec[##v][2], vbspec[##v][3]); \
+ } \
+ }
+
+#define GLD_SETUP_TWOSIDED_LIGHTING \
+ /* Two-sided lighting */ \
+ if (ctx->_TriangleCaps & DD_TRI_LIGHT_TWOSIDE) { \
+ SWvertex *verts = SWSETUP_CONTEXT(ctx)->verts; \
+ SWvertex *v[3]; \
+ GLfloat ex,ey,fx,fy,cc; \
+ /* Get vars for later */ \
+ VB = &TNL_CONTEXT(ctx)->vb; \
+ vbcolor = (GLchan (*)[4])VB->BackfaceColorPtr->data; \
+ if (VB->BackfaceSecondaryColorPtr) { \
+ vbspec = (GLchan (*)[4])VB->BackfaceSecondaryColorPtr->data; \
+ } else { \
+ vbspec = NULL; \
+ } \
+ v[0] = &verts[v0]; \
+ v[1] = &verts[v1]; \
+ v[2] = &verts[v2]; \
+ ex = v[0]->win[0] - v[2]->win[0]; \
+ ey = v[0]->win[1] - v[2]->win[1]; \
+ fx = v[1]->win[0] - v[2]->win[0]; \
+ fy = v[1]->win[1] - v[2]->win[1]; \
+ cc = ex*fy - ey*fx; \
+ facing = (cc < 0.0) ^ ctx->Polygon._FrontBit; \
+ }
+
+//---------------------------------------------------------------------------
+// 3D vertex setup
+//---------------------------------------------------------------------------
+
+#define GLD_SETUP_3D_VARS_POINTS \
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); \
+ GLD_3D_VERTEX *pV = (GLD_3D_VERTEX*)gld->PB3d.pPoints; \
+ TNLcontext *tnl = TNL_CONTEXT(ctx); \
+ struct vertex_buffer *VB = &tnl->vb; \
+ GLfloat (*p4f)[4]; \
+ GLfloat (*tc)[4]; \
+ DWORD dwColor;
+
+#define GLD_SETUP_3D_VARS_LINES \
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); \
+ GLD_3D_VERTEX *pV = (GLD_3D_VERTEX*)gld->PB3d.pLines; \
+ TNLcontext *tnl = TNL_CONTEXT(ctx); \
+ struct vertex_buffer *VB = &tnl->vb; \
+ GLfloat (*p4f)[4]; \
+ GLfloat (*tc)[4]; \
+ DWORD dwColor;
+
+#define GLD_SETUP_3D_VARS_TRIANGLES \
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); \
+ GLD_3D_VERTEX *pV = (GLD_3D_VERTEX*)gld->PB3d.pTriangles; \
+ TNLcontext *tnl = TNL_CONTEXT(ctx); \
+ struct vertex_buffer *VB = &tnl->vb; \
+ GLfloat (*p4f)[4]; \
+ GLfloat (*tc)[4]; \
+ DWORD dwColor;
+
+#define GLD_SETUP_3D_VERTEX(v) \
+ p4f = VB->AttribPtr[_TNL_ATTRIB_POS]->data; \
+ pV->Position.x = p4f[##v][0]; \
+ pV->Position.y = p4f[##v][1]; \
+ pV->Position.z = p4f[##v][2];
+
+#define GLD_SETUP_SMOOTH_COLOUR_3D(v) \
+ p4f = (GLfloat (*)[4])VB->AttribPtr[_TNL_ATTRIB_COLOR0]->data; \
+ pV->Diffuse = D3DCOLOR_COLORVALUE(p4f[##v][0], p4f[##v][1], p4f[##v][2], p4f[##v][3]);
+
+
+#define GLD_SETUP_GET_FLAT_COLOUR_3D(v) \
+ p4f = (GLfloat (*)[4])VB->AttribPtr[_TNL_ATTRIB_COLOR00]->data; \
+ dwColor = D3DCOLOR_COLORVALUE(p4f[##v][0], p4f[##v][1], p4f[##v][2], p4f[##v][3]);
+
+#define GLD_SETUP_USE_FLAT_COLOUR_3D \
+ pV->Diffuse = dwColor;
+
+#define GLD_SETUP_TEX0_3D(v) \
+ if (VB->AttribPtr[_TNL_ATTRIB_TEX0]) { \
+ tc = VB->AttribPtr[_TNL_ATTRIB_TEX0]->data; \
+ pV->TexUnit0.x = tc[##v][0]; \
+ pV->TexUnit0.y = tc[##v][1]; \
+ }
+
+#define GLD_SETUP_TEX1_3D(v) \
+ if (VB->AttribPtr[_TNL_ATTRIB_TEX1]) { \
+ tc = VB->AttribPtr[_TNL_ATTRIB_TEX1]->data; \
+ pV->TexUnit1.x = tc[##v][0]; \
+ pV->TexUnit1.y = tc[##v][1]; \
+ }
+
+//---------------------------------------------------------------------------
+// Helper functions
+//---------------------------------------------------------------------------
+
+__inline DWORD _gldComputeFog(
+ struct gl_context *ctx,
+ SWvertex *swv)
+{
+ // Full fog calculation.
+ // Based on Mesa code.
+
+ GLchan rFog, gFog, bFog;
+ GLchan fR, fG, fB;
+ const GLfloat f = swv->fog;
+ const GLfloat g = 1.0 - f;
+
+ UNCLAMPED_FLOAT_TO_CHAN(rFog, ctx->Fog.Color[RCOMP]);
+ UNCLAMPED_FLOAT_TO_CHAN(gFog, ctx->Fog.Color[GCOMP]);
+ UNCLAMPED_FLOAT_TO_CHAN(bFog, ctx->Fog.Color[BCOMP]);
+ fR = f * swv->color[0] + g * rFog;
+ fG = f * swv->color[1] + g * gFog;
+ fB = f * swv->color[2] + g * bFog;
+ return D3DCOLOR_RGBA(fR, fG, fB, swv->color[3]);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_ResetLineStipple_DX9(
+ struct gl_context *ctx)
+{
+ // TODO: Fake stipple with a 32x32 texture.
+}
+
+//---------------------------------------------------------------------------
+// 2D (post-transformed) primitives
+//---------------------------------------------------------------------------
+
+void gld_Points2D_DX9(
+ struct gl_context *ctx,
+ GLuint first,
+ GLuint last)
+{
+ GLD_SETUP_2D_VARS_POINTS;
+
+ unsigned i;
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+
+ // _Size is already clamped to MaxPointSize and MinPointSize
+ IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_POINTSIZE, *((DWORD*)&ctx->Point._Size));
+
+ if (VB->Elts) {
+ for (i=first; i<last; i++, pV++) {
+ if (VB->ClipMask[VB->Elts[i]] == 0) {
+// _swrast_Point( ctx, &verts[VB->Elts[i]] );
+ GLD_SETUP_GET_SWVERT(VB->Elts[i]);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_SPECULAR;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ }
+ }
+ } else {
+ GLD_SETUP_GET_SWVERT(first);
+ for (i=first; i<last; i++, swv++, pV++) {
+ if (VB->ClipMask[i] == 0) {
+// _swrast_Point( ctx, &verts[i] );
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_SPECULAR;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ }
+ }
+ }
+
+ gld->PB2d.pPoints = (BYTE*)pV;
+ gld->PB2d.nPoints += (last-first);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Line2DFlat_DX9(
+ struct gl_context *ctx,
+ GLuint v0,
+ GLuint v1)
+{
+ GLD_SETUP_2D_VARS_LINES;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_GET_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_GET_FLAT_SPECULAR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ gld->PB2d.pLines = (BYTE*)pV;
+ gld->PB2d.nLines++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Line2DSmooth_DX9(
+ struct gl_context *ctx,
+ GLuint v0,
+ GLuint v1)
+{
+ GLD_SETUP_2D_VARS_LINES;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_SPECULAR;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_SPECULAR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ gld->PB2d.pLines = (BYTE*)pV;
+ gld->PB2d.nLines++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle2DFlat_DX9(
+ struct gl_context *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_GET_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle2DSmooth_DX9(
+ struct gl_context *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle2DFlatExtras_DX9(
+ struct gl_context *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_TWOSIDED_LIGHTING(v2);
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ if (bFog)
+ GLD_SETUP_GET_FLAT_FOG_COLOUR;
+ else
+ GLD_SETUP_GET_FLAT_COLOUR;
+ GLD_SETUP_GET_FLAT_SPECULAR;
+ GLD_SETUP_GET_FLAT_LIGHTING(v2);
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle2DSmoothExtras_DX9(
+ struct gl_context *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_TWOSIDED_LIGHTING(v0);
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v0);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v1);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v2);
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad2DFlat_DX9(
+ struct gl_context *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_GET_SWVERT(v3);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_GET_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v3);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad2DSmooth_DX9(
+ struct gl_context *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v3);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad2DFlatExtras_DX9(
+ struct gl_context *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_TWOSIDED_LIGHTING(v3);
+
+ GLD_SETUP_GET_SWVERT(v3);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ if (bFog)
+ GLD_SETUP_GET_FLAT_FOG_COLOUR;
+ else
+ GLD_SETUP_GET_FLAT_COLOUR;
+ GLD_SETUP_GET_FLAT_SPECULAR;
+ GLD_SETUP_GET_FLAT_LIGHTING(v3);
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v3);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad2DSmoothExtras_DX9(
+ struct gl_context *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_TWOSIDED_LIGHTING(v0);
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v0);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v1);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v2);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v2);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v3);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v3);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v0);
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+// 3D (pre-transformed) primitives
+//---------------------------------------------------------------------------
+
+void gld_Points3D_DX9(
+ struct gl_context *ctx,
+ GLuint first,
+ GLuint last)
+{
+ GLD_SETUP_3D_VARS_POINTS
+
+ unsigned i;
+// struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+
+ // _Size is already clamped to MaxPointSize and MinPointSize
+ IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_POINTSIZE, *((DWORD*)&ctx->Point._Size));
+
+ if (VB->Elts) {
+ for (i=first; i<last; i++, pV++) {
+ if (VB->ClipMask[VB->Elts[i]] == 0) {
+// _swrast_Point( ctx, &verts[VB->Elts[i]] );
+// GLD_SETUP_GET_SWVERT(VB->Elts[i]);
+ GLD_SETUP_3D_VERTEX(VB->Elts[i])
+ GLD_SETUP_SMOOTH_COLOUR_3D(i)
+ GLD_SETUP_TEX0_3D(i)
+ GLD_SETUP_TEX1_3D(i)
+ }
+ }
+ } else {
+// GLD_SETUP_GET_SWVERT(first);
+ for (i=first; i<last; i++, pV++) {
+ if (VB->ClipMask[i] == 0) {
+// _swrast_Point( ctx, &verts[i] );
+ GLD_SETUP_3D_VERTEX(i)
+ GLD_SETUP_SMOOTH_COLOUR_3D(i)
+ GLD_SETUP_TEX0_3D(i)
+ GLD_SETUP_TEX1_3D(i)
+ }
+ }
+ }
+/*
+ for (i=first; i<last; i++, pV++) {
+ GLD_SETUP_3D_VERTEX(i)
+ GLD_SETUP_SMOOTH_COLOUR_3D(i)
+ GLD_SETUP_TEX0_3D(i)
+ GLD_SETUP_TEX1_3D(i)
+ }
+*/
+ gld->PB3d.pPoints = (BYTE*)pV;
+ gld->PB3d.nPoints += (last-first);
+}
+
+//---------------------------------------------------------------------------
+// Line functions
+//---------------------------------------------------------------------------
+
+void gld_Line3DFlat_DX9(
+ struct gl_context *ctx,
+ GLuint v0,
+ GLuint v1)
+{
+ GLD_SETUP_3D_VARS_LINES
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_GET_FLAT_COLOUR_3D(v1)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ pV++;
+
+ gld->PB3d.pLines = (BYTE*)pV;
+ gld->PB3d.nLines++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Line3DSmooth_DX9(
+ struct gl_context *ctx,
+ GLuint v0,
+ GLuint v1)
+{
+ GLD_SETUP_3D_VARS_LINES
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v1)
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v0)
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ pV++;
+
+ gld->PB3d.pLines = (BYTE*)pV;
+ gld->PB3d.nLines++;
+}
+
+//---------------------------------------------------------------------------
+// Triangle functions
+//---------------------------------------------------------------------------
+
+void gld_Triangle3DFlat_DX9(
+ struct gl_context *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+ GLD_SETUP_3D_VARS_TRIANGLES
+
+ GLD_SETUP_3D_VERTEX(v2)
+ GLD_SETUP_TEX0_3D(v2)
+ GLD_SETUP_TEX1_3D(v2)
+ GLD_SETUP_GET_FLAT_COLOUR_3D(v2)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ pV++;
+
+ gld->PB3d.pTriangles = (BYTE*)pV;
+ gld->PB3d.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle3DSmooth_DX9(
+ struct gl_context *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+ GLD_SETUP_3D_VARS_TRIANGLES
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v0)
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v1)
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v2)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v2)
+ GLD_SETUP_TEX0_3D(v2)
+ GLD_SETUP_TEX1_3D(v2)
+ pV++;
+
+ gld->PB3d.pTriangles = (BYTE*)pV;
+ gld->PB3d.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+// Quad functions
+//---------------------------------------------------------------------------
+
+void gld_Quad3DFlat_DX9(
+ struct gl_context *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLD_SETUP_3D_VARS_TRIANGLES
+
+ GLD_SETUP_3D_VERTEX(v3)
+ GLD_SETUP_GET_FLAT_COLOUR_3D(v3)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v3)
+ GLD_SETUP_TEX1_3D(v3)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v2)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v2)
+ GLD_SETUP_TEX1_3D(v2)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v3)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v3)
+ GLD_SETUP_TEX1_3D(v3)
+ pV++;
+
+ gld->PB3d.pTriangles = (BYTE*)pV;
+ gld->PB3d.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad3DSmooth_DX9(
+ struct gl_context *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLD_SETUP_3D_VARS_TRIANGLES
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v0)
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v1)
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v2)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v2)
+ GLD_SETUP_TEX0_3D(v2)
+ GLD_SETUP_TEX1_3D(v2)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v2)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v2)
+ GLD_SETUP_TEX0_3D(v2)
+ GLD_SETUP_TEX1_3D(v2)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v3)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v3)
+ GLD_SETUP_TEX0_3D(v3)
+ GLD_SETUP_TEX1_3D(v3)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v0)
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ pV++;
+
+ gld->PB3d.pTriangles = (BYTE*)pV;
+ gld->PB3d.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+// Vertex setup for two-sided-lighting vertex shader
+//---------------------------------------------------------------------------
+
+/*
+
+void gld_Points2DTwoside_DX9(struct gl_context *ctx, GLuint first, GLuint last)
+{
+ // NOTE: Two-sided lighting does not apply to Points
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Line2DFlatTwoside_DX9(struct gl_context *ctx, GLuint v0, GLuint v1)
+{
+ // NOTE: Two-sided lighting does not apply to Lines
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Line2DSmoothTwoside_DX9(struct gl_context *ctx, GLuint v0, GLuint v1)
+{
+ // NOTE: Two-sided lighting does not apply to Lines
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle2DFlatTwoside_DX9(struct gl_context *ctx, GLuint v0, GLuint v1, GLuint v2)
+{
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle2DSmoothTwoside_DX9(struct gl_context *ctx, GLuint v0, GLuint v1, GLuint v2)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+ GLD_TWOSIDED_VERTEX *pV = (GLD_TWOSIDED_VERTEX*)gld->PBtwosidelight.pTriangles;
+ SScontext *ss = SWSETUP_CONTEXT(ctx);
+ SWvertex *swv;
+ DWORD dwSpecularColour;
+ DWORD dwFlatColour;
+ GLuint facing = 0;
+ struct vertex_buffer *VB;
+ GLchan (*vbcolor)[4];
+ GLchan (*vbspec)[4];
+
+ // Reciprocal of DepthMax
+ const float ooDepthMax = 1.0f / ctx->DepthMaxF;
+
+ // 1st vert
+ swv = &ss->verts[v0];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 2nd vert
+ swv = &ss->verts[v1];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 3rd vert
+ swv = &ss->verts[v2];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ gld->PBtwosidelight.pTriangles = (BYTE*)pV;
+ gld->PBtwosidelight.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad2DFlatTwoside_DX9(struct gl_context *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+ GLD_TWOSIDED_VERTEX *pV = (GLD_TWOSIDED_VERTEX*)gld->PBtwosidelight.pTriangles;
+ SScontext *ss = SWSETUP_CONTEXT(ctx);
+ SWvertex *swv;
+ DWORD dwSpecularColour;
+ DWORD dwFlatColour;
+ GLuint facing = 0;
+ struct vertex_buffer *VB;
+ GLchan (*vbcolor)[4];
+ GLchan (*vbspec)[4];
+
+ // Reciprocal of DepthMax
+ const float ooDepthMax = 1.0f / ctx->DepthMaxF;
+
+ // 1st vert
+ swv = &ss->verts[v0];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 2nd vert
+ swv = &ss->verts[v1];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 3rd vert
+ swv = &ss->verts[v2];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 4th vert
+ swv = &ss->verts[v2];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 5th vert
+ swv = &ss->verts[v3];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 6th vert
+ swv = &ss->verts[v0];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ gld->PBtwosidelight.pTriangles = (BYTE*)pV;
+ gld->PBtwosidelight.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad2DSmoothTwoside_DX9(struct gl_context *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+ GLD_TWOSIDED_VERTEX *pV = (GLD_TWOSIDED_VERTEX*)gld->PBtwosidelight.pTriangles;
+ SScontext *ss = SWSETUP_CONTEXT(ctx);
+ SWvertex *swv;
+ DWORD dwSpecularColour;
+ DWORD dwFlatColour;
+ GLuint facing = 0;
+ struct vertex_buffer *VB;
+ GLchan (*vbcolor)[4];
+ GLchan (*vbspec)[4];
+
+ // Reciprocal of DepthMax
+ const float ooDepthMax = 1.0f / ctx->DepthMaxF;
+
+ // 1st vert
+ swv = &ss->verts[v0];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 2nd vert
+ swv = &ss->verts[v1];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 3rd vert
+ swv = &ss->verts[v2];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 4th vert
+ swv = &ss->verts[v2];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 5th vert
+ swv = &ss->verts[v3];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 6th vert
+ swv = &ss->verts[v0];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ gld->PBtwosidelight.pTriangles = (BYTE*)pV;
+ gld->PBtwosidelight.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+
+*/
diff --git a/mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_texture_dx9.c b/mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_texture_dx9.c
new file mode 100644
index 000000000..c3ebdc3af
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_texture_dx9.c
@@ -0,0 +1,2104 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: Texture / Bitmap functions
+*
+****************************************************************************/
+
+#include "dglcontext.h"
+#include "ddlog.h"
+#include "gld_dx9.h"
+
+#include <d3dx9tex.h>
+
+#include "texformat.h"
+#include "colormac.h"
+#include "texstore.h"
+#include "image.h"
+// #include "mem.h"
+
+//---------------------------------------------------------------------------
+
+#define GLD_FLIP_HEIGHT(y,h) (gldCtx->dwHeight - (y) - (h))
+
+//---------------------------------------------------------------------------
+// 1D texture fetch
+//---------------------------------------------------------------------------
+
+#define CHAN_SRC( t, i, j, k, sz ) \
+ ((GLchan *)(t)->Data + (i) * (sz))
+#define UBYTE_SRC( t, i, j, k, sz ) \
+ ((GLubyte *)(t)->Data + (i) * (sz))
+#define USHORT_SRC( t, i, j, k ) \
+ ((GLushort *)(t)->Data + (i))
+#define FLOAT_SRC( t, i, j, k ) \
+ ((GLfloat *)(t)->Data + (i))
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_1d_texel_X8R8G8B8(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texel )
+{
+ const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 );
+ GLchan *rgba = (GLchan *)texel;
+ rgba[RCOMP] = src[2];
+ rgba[GCOMP] = src[1];
+ rgba[BCOMP] = src[0];
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_1d_texel_f_X8R8G8B8(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 );
+ texel[RCOMP] = CHAN_TO_FLOAT(src[0]);
+ texel[GCOMP] = CHAN_TO_FLOAT(src[1]);
+ texel[BCOMP] = CHAN_TO_FLOAT(src[2]);
+ texel[ACOMP] = 1.f;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_1d_texel_X1R5G5B5(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLchan *rgba = (GLchan *) texel; GLushort s = *src;
+ rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 10) & 0xf8) * 255 / 0xf8 );
+ rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 5) & 0xf8) * 255 / 0xf8 );
+ rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf8) * 255 / 0xf8 );
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_1d_texel_f_X1R5G5B5(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLushort s = *src;
+ texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 10) & 0xf8) * 255 / 0xf8 );
+ texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 5) & 0xf8) * 255 / 0xf8 );
+ texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf8) * 255 / 0xf8 );
+ texel[ACOMP] = 1.f;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_1d_texel_X4R4G4B4(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLchan *rgba = (GLchan *) texel; GLushort s = *src;
+ rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf) * 255 / 0xf );
+ rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 4) & 0xf) * 255 / 0xf );
+ rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf) * 255 / 0xf );
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_1d_texel_f_X4R4G4B4(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLushort s = *src;
+ texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 8) & 0xf) * 255 / 0xf );
+ texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 4) & 0xf) * 255 / 0xf );
+ texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf) * 255 / 0xf );
+ texel[ACOMP] = 1.f;
+}
+
+//---------------------------------------------------------------------------
+
+#undef CHAN_SRC
+#undef UBYTE_SRC
+#undef USHORT_SRC
+#undef FLOAT_SRC
+
+//---------------------------------------------------------------------------
+// 2D texture fetch
+//---------------------------------------------------------------------------
+
+#define CHAN_SRC( t, i, j, k, sz ) \
+ ((GLchan *)(t)->Data + ((t)->Width * (j) + (i)) * (sz))
+#define UBYTE_SRC( t, i, j, k, sz ) \
+ ((GLubyte *)(t)->Data + ((t)->Width * (j) + (i)) * (sz))
+#define USHORT_SRC( t, i, j, k ) \
+ ((GLushort *)(t)->Data + ((t)->Width * (j) + (i)))
+#define FLOAT_SRC( t, i, j, k ) \
+ ((GLfloat *)(t)->Data + ((t)->Width * (j) + (i)))
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_2d_texel_X8R8G8B8(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texel )
+{
+ const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 );
+ GLchan *rgba = (GLchan *)texel;
+ rgba[RCOMP] = src[2];
+ rgba[GCOMP] = src[1];
+ rgba[BCOMP] = src[0];
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_2d_texel_f_X8R8G8B8(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 );
+ texel[RCOMP] = CHAN_TO_FLOAT(src[0]);
+ texel[GCOMP] = CHAN_TO_FLOAT(src[1]);
+ texel[BCOMP] = CHAN_TO_FLOAT(src[2]);
+ texel[ACOMP] = 1.f;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_2d_texel_X1R5G5B5(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLchan *rgba = (GLchan *) texel; GLushort s = *src;
+ rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 10) & 0xf8) * 255 / 0xf8 );
+ rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 5) & 0xf8) * 255 / 0xf8 );
+ rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf8) * 255 / 0xf8 );
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_2d_texel_f_X1R5G5B5(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLushort s = *src;
+ texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 10) & 0xf8) * 255 / 0xf8 );
+ texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 5) & 0xf8) * 255 / 0xf8 );
+ texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf8) * 255 / 0xf8 );
+ texel[ACOMP] = 1.f;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_2d_texel_X4R4G4B4(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLchan *rgba = (GLchan *) texel; GLushort s = *src;
+ rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf) * 255 / 0xf );
+ rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 4) & 0xf) * 255 / 0xf );
+ rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf) * 255 / 0xf );
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_2d_texel_f_X4R4G4B4(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLushort s = *src;
+ texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 8) & 0xf) * 255 / 0xf );
+ texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 4) & 0xf) * 255 / 0xf );
+ texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf) * 255 / 0xf );
+ texel[ACOMP] = 1.f;
+}
+
+//---------------------------------------------------------------------------
+
+#undef CHAN_SRC
+#undef UBYTE_SRC
+#undef USHORT_SRC
+#undef FLOAT_SRC
+
+//---------------------------------------------------------------------------
+// 3D texture fetch
+//---------------------------------------------------------------------------
+
+#define CHAN_SRC( t, i, j, k, sz ) \
+ (GLchan *)(t)->Data + (((t)->Height * (k) + (j)) * \
+ (t)->Width + (i)) * (sz)
+#define UBYTE_SRC( t, i, j, k, sz ) \
+ ((GLubyte *)(t)->Data + (((t)->Height * (k) + (j)) * \
+ (t)->Width + (i)) * (sz))
+#define USHORT_SRC( t, i, j, k ) \
+ ((GLushort *)(t)->Data + (((t)->Height * (k) + (j)) * \
+ (t)->Width + (i)))
+#define FLOAT_SRC( t, i, j, k ) \
+ ((GLfloat *)(t)->Data + (((t)->Height * (k) + (j)) * \
+ (t)->Width + (i)))
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_3d_texel_X8R8G8B8(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texel )
+{
+ const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 );
+ GLchan *rgba = (GLchan *)texel;
+ rgba[RCOMP] = src[2];
+ rgba[GCOMP] = src[1];
+ rgba[BCOMP] = src[0];
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_3d_texel_f_X8R8G8B8(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 );
+ texel[RCOMP] = CHAN_TO_FLOAT(src[0]);
+ texel[GCOMP] = CHAN_TO_FLOAT(src[1]);
+ texel[BCOMP] = CHAN_TO_FLOAT(src[2]);
+ texel[ACOMP] = 1.f;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_3d_texel_X1R5G5B5(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLchan *rgba = (GLchan *) texel; GLushort s = *src;
+ rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 10) & 0xf8) * 255 / 0xf8 );
+ rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 5) & 0xf8) * 255 / 0xf8 );
+ rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf8) * 255 / 0xf8 );
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_3d_texel_f_X1R5G5B5(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLushort s = *src;
+ texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 10) & 0xf8) * 255 / 0xf8 );
+ texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 5) & 0xf8) * 255 / 0xf8 );
+ texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf8) * 255 / 0xf8 );
+ texel[ACOMP] = 1.f;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_3d_texel_X4R4G4B4(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLchan *rgba = (GLchan *) texel; GLushort s = *src;
+ rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf) * 255 / 0xf );
+ rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 4) & 0xf) * 255 / 0xf );
+ rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf) * 255 / 0xf );
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_3d_texel_f_X4R4G4B4(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLushort s = *src;
+ texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 8) & 0xf) * 255 / 0xf );
+ texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 4) & 0xf) * 255 / 0xf );
+ texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf) * 255 / 0xf );
+ texel[ACOMP] = 1.f;
+}
+
+//---------------------------------------------------------------------------
+
+#undef CHAN_SRC
+#undef UBYTE_SRC
+#undef USHORT_SRC
+#undef FLOAT_SRC
+
+//---------------------------------------------------------------------------
+// Direct3D texture formats that have no Mesa equivalent
+//---------------------------------------------------------------------------
+
+const struct gl_texture_format _gld_texformat_X8R8G8B8 = {
+ MESA_FORMAT_ARGB8888, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 8, /* RedBits */
+ 8, /* GreenBits */
+ 8, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 4, /* TexelBytes */
+ _mesa_texstore_argb8888, /* StoreTexImageFunc */
+ gld_fetch_1d_texel_X8R8G8B8, /* FetchTexel1D */
+ gld_fetch_2d_texel_X8R8G8B8, /* FetchTexel2D */
+ gld_fetch_3d_texel_X8R8G8B8, /* FetchTexel3D */
+ gld_fetch_1d_texel_f_X8R8G8B8, /* FetchTexel1Df */
+ gld_fetch_2d_texel_f_X8R8G8B8, /* FetchTexel2Df */
+ gld_fetch_3d_texel_f_X8R8G8B8, /* FetchTexel3Df */
+};
+
+const struct gl_texture_format _gld_texformat_X1R5G5B5 = {
+ MESA_FORMAT_ARGB1555, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 5, /* RedBits */
+ 5, /* GreenBits */
+ 5, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 2, /* TexelBytes */
+ _mesa_texstore_argb1555, /* StoreTexImageFunc */
+ gld_fetch_1d_texel_X1R5G5B5, /* FetchTexel1D */
+ gld_fetch_2d_texel_X1R5G5B5, /* FetchTexel2D */
+ gld_fetch_3d_texel_X1R5G5B5, /* FetchTexel3D */
+ gld_fetch_1d_texel_f_X1R5G5B5, /* FetchTexel1Df */
+ gld_fetch_2d_texel_f_X1R5G5B5, /* FetchTexel2Df */
+ gld_fetch_3d_texel_f_X1R5G5B5, /* FetchTexel3Df */
+};
+
+const struct gl_texture_format _gld_texformat_X4R4G4B4 = {
+ MESA_FORMAT_ARGB4444, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 4, /* RedBits */
+ 4, /* GreenBits */
+ 4, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 2, /* TexelBytes */
+ _mesa_texstore_argb4444, /* StoreTexImageFunc */
+ gld_fetch_1d_texel_X4R4G4B4, /* FetchTexel1D */
+ gld_fetch_2d_texel_X4R4G4B4, /* FetchTexel2D */
+ gld_fetch_3d_texel_X4R4G4B4, /* FetchTexel3D */
+ gld_fetch_1d_texel_f_X4R4G4B4, /* FetchTexel1Df */
+ gld_fetch_2d_texel_f_X4R4G4B4, /* FetchTexel2Df */
+ gld_fetch_3d_texel_f_X4R4G4B4, /* FetchTexel3Df */
+};
+
+//---------------------------------------------------------------------------
+// Texture unit constants
+//---------------------------------------------------------------------------
+
+// List of possible combinations of texture environments.
+// Example: GLD_TEXENV_MODULATE_RGBA means
+// GL_MODULATE, GL_RGBA base internal format.
+#define GLD_TEXENV_DECAL_RGB 0
+#define GLD_TEXENV_DECAL_RGBA 1
+#define GLD_TEXENV_DECAL_ALPHA 2
+#define GLD_TEXENV_REPLACE_RGB 3
+#define GLD_TEXENV_REPLACE_RGBA 4
+#define GLD_TEXENV_REPLACE_ALPHA 5
+#define GLD_TEXENV_MODULATE_RGB 6
+#define GLD_TEXENV_MODULATE_RGBA 7
+#define GLD_TEXENV_MODULATE_ALPHA 8
+#define GLD_TEXENV_BLEND_RGB 9
+#define GLD_TEXENV_BLEND_RGBA 10
+#define GLD_TEXENV_BLEND_ALPHA 11
+#define GLD_TEXENV_ADD_RGB 12
+#define GLD_TEXENV_ADD_RGBA 13
+#define GLD_TEXENV_ADD_ALPHA 14
+
+// Per-stage (i.e. per-unit) texture environment
+typedef struct {
+ DWORD ColorArg1; // Colour argument 1
+ D3DTEXTUREOP ColorOp; // Colour operation
+ DWORD ColorArg2; // Colour argument 2
+ DWORD AlphaArg1; // Alpha argument 1
+ D3DTEXTUREOP AlphaOp; // Alpha operation
+ DWORD AlphaArg2; // Alpha argument 2
+} GLD_texenv;
+
+// TODO: Do we really need to set ARG1 and ARG2 every time?
+// They seem to always be TEXTURE and CURRENT respectively.
+
+// C = Colour out
+// A = Alpha out
+// Ct = Colour from Texture
+// Cf = Colour from fragment (diffuse)
+// At = Alpha from Texture
+// Af = Alpha from fragment (diffuse)
+// Cc = GL_TEXTURE_ENV_COLOUR (GL_BLEND)
+const GLD_texenv gldTexEnv[] = {
+ // DECAL_RGB: C=Ct, A=Af
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+ // DECAL_RGBA: C=Cf(1-At)+CtAt, A=Af
+ {D3DTA_TEXTURE, D3DTOP_BLENDTEXTUREALPHA, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+ // DECAL_ALPHA: <undefined> use DECAL_RGB
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+
+ // REPLACE_RGB: C=Ct, A=Af
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+ // REPLACE_RGBA: C=Ct, A=At
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT},
+ // REPLACE_ALPHA: C=Cf, A=At
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT},
+
+ // MODULATE_RGB: C=CfCt, A=Af
+ {D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+ // MODULATE_RGBA: C=CfCt, A=AfAt
+ {D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT},
+ // MODULATE_ALPHA: C=Cf, A=AfAt
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT},
+
+ // BLEND_RGB: C=Cf(1-Ct)+CcCt, A=Af
+ {D3DTA_TEXTURE, D3DTOP_LERP, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+ // BLEND_RGBA: C=Cf(1-Ct)+CcCt, A=AfAt
+ {D3DTA_TEXTURE, D3DTOP_LERP, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT},
+ // BLEND_ALPHA: C=Cf, A=AfAt
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT},
+
+ // ADD_RGB: C=Cf+Ct, A=Af
+ {D3DTA_TEXTURE, D3DTOP_ADD, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+ // ADD_RGBA: C=Cf+Ct, A=AfAt
+ {D3DTA_TEXTURE, D3DTOP_ADD, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT},
+ // ADD_ALPHA: C=Cf, A=AfAt
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT},
+};
+
+//---------------------------------------------------------------------------
+
+D3DTEXTUREADDRESS _gldConvertWrap(
+ GLenum wrap)
+{
+ return (wrap == GL_CLAMP) ? D3DTADDRESS_CLAMP : D3DTADDRESS_WRAP;
+}
+
+//---------------------------------------------------------------------------
+
+D3DTEXTUREFILTERTYPE _gldConvertMagFilter(
+ GLenum magfilter)
+{
+ return (magfilter == GL_LINEAR) ? D3DTEXF_LINEAR : D3DTEXF_POINT;
+}
+
+//---------------------------------------------------------------------------
+
+void _gldConvertMinFilter(
+ GLenum minfilter,
+ D3DTEXTUREFILTERTYPE *min_filter,
+ D3DTEXTUREFILTERTYPE *mip_filter)
+{
+ switch (minfilter) {
+ case GL_NEAREST:
+ *min_filter = D3DTEXF_POINT;
+ *mip_filter = D3DTEXF_NONE;
+ break;
+ case GL_LINEAR:
+ *min_filter = D3DTEXF_LINEAR;
+ *mip_filter = D3DTEXF_NONE;
+ break;
+ case GL_NEAREST_MIPMAP_NEAREST:
+ *min_filter = D3DTEXF_POINT;
+ *mip_filter = D3DTEXF_POINT;
+ break;
+ case GL_LINEAR_MIPMAP_NEAREST:
+ *min_filter = D3DTEXF_LINEAR;
+ *mip_filter = D3DTEXF_POINT;
+ break;
+ case GL_NEAREST_MIPMAP_LINEAR:
+ *min_filter = D3DTEXF_POINT;
+ *mip_filter = D3DTEXF_LINEAR;
+ break;
+ case GL_LINEAR_MIPMAP_LINEAR:
+ *min_filter = D3DTEXF_LINEAR;
+ *mip_filter = D3DTEXF_LINEAR;
+ break;
+ }
+}
+
+//---------------------------------------------------------------------------
+
+D3DFORMAT _gldGLFormatToD3DFormat(
+ GLenum internalFormat)
+{
+ switch (internalFormat) {
+ case GL_INTENSITY:
+ case GL_INTENSITY4:
+ case GL_INTENSITY8:
+ case GL_INTENSITY12:
+ case GL_INTENSITY16:
+ // LUNIMANCE != INTENSITY, but D3D doesn't have I8 textures
+ return D3DFMT_L8;
+ case 1:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE4:
+ case GL_LUMINANCE8:
+ case GL_LUMINANCE12:
+ case GL_LUMINANCE16:
+ return D3DFMT_L8;
+ case GL_ALPHA:
+ case GL_ALPHA4:
+ case GL_ALPHA8:
+ case GL_ALPHA12:
+ case GL_ALPHA16:
+ return D3DFMT_A8;
+ case GL_COLOR_INDEX:
+ case GL_COLOR_INDEX1_EXT:
+ case GL_COLOR_INDEX2_EXT:
+ case GL_COLOR_INDEX4_EXT:
+ case GL_COLOR_INDEX8_EXT:
+ case GL_COLOR_INDEX12_EXT:
+ case GL_COLOR_INDEX16_EXT:
+ return D3DFMT_X8R8G8B8;
+ case 2:
+ case GL_LUMINANCE_ALPHA:
+ case GL_LUMINANCE4_ALPHA4:
+ case GL_LUMINANCE6_ALPHA2:
+ case GL_LUMINANCE8_ALPHA8:
+ case GL_LUMINANCE12_ALPHA4:
+ case GL_LUMINANCE12_ALPHA12:
+ case GL_LUMINANCE16_ALPHA16:
+ return D3DFMT_A8L8;
+ case GL_R3_G3_B2:
+ // TODO: Mesa does not support RGB332 internally
+ return D3DFMT_X4R4G4B4; //D3DFMT_R3G3B2;
+ case GL_RGB4:
+ return D3DFMT_X4R4G4B4;
+ case GL_RGB5:
+ return D3DFMT_X1R5G5B5;
+ case 3:
+ case GL_RGB:
+ case GL_RGB8:
+ case GL_RGB10:
+ case GL_RGB12:
+ case GL_RGB16:
+ return D3DFMT_R8G8B8;
+ case GL_RGBA4:
+ return D3DFMT_A4R4G4B4;
+ case 4:
+ case GL_RGBA:
+ case GL_RGBA2:
+ case GL_RGBA8:
+ case GL_RGB10_A2:
+ case GL_RGBA12:
+ case GL_RGBA16:
+ return D3DFMT_A8R8G8B8;
+ case GL_RGB5_A1:
+ return D3DFMT_A1R5G5B5;
+ }
+
+ // Return an acceptable default
+ return D3DFMT_A8R8G8B8;
+}
+
+//---------------------------------------------------------------------------
+
+GLenum _gldDecodeBaseFormat(
+ IDirect3DTexture9 *pTex)
+{
+ // Examine Direct3D texture and return base OpenGL internal texture format
+ // NOTE: We can't use any base format info from Mesa because D3D might have
+ // used a different texture format when we used D3DXCreateTexture().
+
+ // Base internal format is one of (Red Book p355):
+ // GL_ALPHA,
+ // GL_LUMINANCE,
+ // GL_LUMINANCE_ALPHA,
+ // GL_INTENSITY,
+ // GL_RGB,
+ // GL_RGBA
+
+ // NOTE: INTENSITY not used (not supported by Direct3D)
+ // LUMINANCE has same texture functions as RGB
+ // LUMINANCE_ALPHA has same texture functions as RGBA
+
+ // TODO: cache format instead of using GetLevelDesc()
+ D3DSURFACE_DESC desc;
+ _GLD_DX9_TEX(GetLevelDesc(pTex, 0, &desc));
+
+ switch (desc.Format) {
+ case D3DFMT_R8G8B8:
+ case D3DFMT_X8R8G8B8:
+ case D3DFMT_R5G6B5:
+ case D3DFMT_X1R5G5B5:
+ case D3DFMT_R3G3B2:
+ case D3DFMT_X4R4G4B4:
+ case D3DFMT_P8:
+ case D3DFMT_L8:
+ return GL_RGB;
+ case D3DFMT_A8R8G8B8:
+ case D3DFMT_A1R5G5B5:
+ case D3DFMT_A4R4G4B4:
+ case D3DFMT_A8R3G3B2:
+ case D3DFMT_A8P8:
+ case D3DFMT_A8L8:
+ case D3DFMT_A4L4:
+ return GL_RGBA;
+ case D3DFMT_A8:
+ return GL_ALPHA;
+ // Compressed texture formats. Need to check these...
+ case D3DFMT_DXT1:
+ return GL_RGBA;
+ case D3DFMT_DXT2:
+ return GL_RGB;
+ case D3DFMT_DXT3:
+ return GL_RGBA;
+ case D3DFMT_DXT4:
+ return GL_RGB;
+ case D3DFMT_DXT5:
+ return GL_RGBA;
+ }
+
+ // Fell through. Return arbitary default.
+ return GL_RGBA;
+}
+
+//---------------------------------------------------------------------------
+
+const struct gl_texture_format* _gldMesaFormatForD3DFormat(
+ D3DFORMAT d3dfmt)
+{
+ switch (d3dfmt) {
+ case D3DFMT_A8R8G8B8:
+ return &_mesa_texformat_argb8888;
+ case D3DFMT_R8G8B8:
+ return &_mesa_texformat_rgb888;
+ case D3DFMT_R5G6B5:
+ return &_mesa_texformat_rgb565;
+ case D3DFMT_A4R4G4B4:
+ return &_mesa_texformat_argb4444;
+ case D3DFMT_A1R5G5B5:
+ return &_mesa_texformat_argb1555;
+ case D3DFMT_A8L8:
+ return &_mesa_texformat_al88;
+ case D3DFMT_R3G3B2:
+ return &_mesa_texformat_rgb332;
+ case D3DFMT_A8:
+ return &_mesa_texformat_a8;
+ case D3DFMT_L8:
+ return &_mesa_texformat_l8;
+ case D3DFMT_X8R8G8B8:
+ return &_gld_texformat_X8R8G8B8;
+ case D3DFMT_X1R5G5B5:
+ return &_gld_texformat_X1R5G5B5;
+ case D3DFMT_X4R4G4B4:
+ return &_gld_texformat_X4R4G4B4;
+ }
+
+ // If we reach here then we've made an error somewhere else
+ // by allowing a format that is not supported.
+ assert(0);
+
+ return NULL; // Shut up compiler warning
+}
+
+//---------------------------------------------------------------------------
+// Copy* functions
+//---------------------------------------------------------------------------
+
+void gldCopyTexImage1D_DX9(
+ struct gl_context *ctx,
+ GLenum target, GLint level,
+ GLenum internalFormat,
+ GLint x, GLint y,
+ GLsizei width, GLint border )
+{
+ // TODO
+}
+
+//---------------------------------------------------------------------------
+
+void gldCopyTexImage2D_DX9(
+ struct gl_context *ctx,
+ GLenum target,
+ GLint level,
+ GLenum internalFormat,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLint border)
+{
+ // TODO
+}
+
+//---------------------------------------------------------------------------
+
+void gldCopyTexSubImage1D_DX9(
+ struct gl_context *ctx,
+ GLenum target, GLint level,
+ GLint xoffset, GLint x, GLint y, GLsizei width )
+{
+ // TODO
+}
+
+//---------------------------------------------------------------------------
+
+void gldCopyTexSubImage2D_DX9(
+ struct gl_context *ctx,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height)
+{
+ // TODO
+}
+
+//---------------------------------------------------------------------------
+
+void gldCopyTexSubImage3D_DX9(
+ struct gl_context *ctx,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height )
+{
+ // TODO ?
+}
+
+//---------------------------------------------------------------------------
+// Bitmap/Pixel functions
+//---------------------------------------------------------------------------
+
+#define GLD_FLIP_Y(y) (gldCtx->dwHeight - (y))
+
+#define _GLD_FVF_IMAGE (D3DFVF_XYZRHW | D3DFVF_TEX1)
+
+typedef struct {
+ FLOAT x, y; // 2D raster coords
+ FLOAT z; // depth value
+ FLOAT rhw; // reciprocal homogenous W (always 1.0f)
+ FLOAT tu, tv; // texture coords
+} _GLD_IMAGE_VERTEX;
+
+//---------------------------------------------------------------------------
+
+HRESULT _gldDrawPixels(
+ struct gl_context *ctx,
+ BOOL bChromakey, // Alpha test for glBitmap() images
+ GLint x, // GL x position
+ GLint y, // GL y position (needs flipping)
+ GLsizei width, // Width of input image
+ GLsizei height, // Height of input image
+ IDirect3DSurface9 *pImage)
+{
+ //
+ // Draw input image as texture implementing PixelZoom and clipping.
+ // Any fragment operations currently enabled will be used.
+ //
+
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ IDirect3DTexture9 *pTexture;
+ D3DSURFACE_DESC d3dsd;
+ IDirect3DSurface9 *pSurface;
+ _GLD_IMAGE_VERTEX v[4];
+ HRESULT hr;
+
+ float ZoomWidth, ZoomHeight;
+ float ScaleWidth, ScaleHeight;
+
+ // Create a texture to hold image
+ hr = D3DXCreateTexture(
+ gld->pDev,
+ width, height,
+ 1, // miplevels
+ 0, // usage
+ D3DFMT_A8R8G8B8, // format
+ D3DPOOL_MANAGED, // pool
+ &pTexture);
+ if (FAILED(hr))
+ return hr;
+
+ hr = IDirect3DTexture9_GetSurfaceLevel(pTexture, 0, &pSurface);
+ if (FAILED(hr)) {
+ IDirect3DTexture9_Release(pTexture);
+ return hr;
+ }
+
+ // Copy image into texture
+ hr = D3DXLoadSurfaceFromSurface(
+ pSurface, NULL, NULL, // Dest surface
+ pImage, NULL, NULL, // Src surface
+ D3DX_FILTER_NONE,
+ 0);
+ IDirect3DSurface9_Release(pSurface);
+ if (FAILED(hr)) {
+ IDirect3DTexture9_Release(pTexture);
+ return hr;
+ }
+
+ //
+ // Set up the quad like this (ascii-art ahead!)
+ //
+ // 3--2
+ // | |
+ // 0--1
+ //
+ //
+
+ // Set depth
+ v[0].z = v[1].z = v[2].z = v[3].z = ctx->Current.RasterPos[2];
+ // Set Reciprocal Homogenous W
+ v[0].rhw = v[1].rhw = v[2].rhw = v[3].rhw = 1.0f;
+
+ // Set texcoords
+ // Examine texture size - if different to input width and height
+ // then we'll need to munge the texcoords to fit.
+ IDirect3DTexture9_GetLevelDesc(pTexture, 0, &d3dsd);
+ ScaleWidth = (float)width / (float)d3dsd.Width;
+ ScaleHeight = (float)height / (float)d3dsd.Height;
+ v[0].tu = 0.0f; v[0].tv = 0.0f;
+ v[1].tu = ScaleWidth; v[1].tv = 0.0f;
+ v[2].tu = ScaleWidth; v[2].tv = ScaleHeight;
+ v[3].tu = 0.0f; v[3].tv = ScaleHeight;
+
+ // Set raster positions
+ ZoomWidth = (float)width * ctx->Pixel.ZoomX;
+ ZoomHeight = (float)height * ctx->Pixel.ZoomY;
+
+ v[0].x = x; v[0].y = GLD_FLIP_Y(y);
+ v[1].x = x+ZoomWidth; v[1].y = GLD_FLIP_Y(y);
+ v[2].x = x+ZoomWidth; v[2].y = GLD_FLIP_Y(y+ZoomHeight);
+ v[3].x = x; v[3].y = GLD_FLIP_Y(y+ZoomHeight);
+
+ // Draw image with full HW acceleration
+ // NOTE: Be nice to use a State Block for all this state...
+ IDirect3DDevice9_SetTexture(gld->pDev, 0, pTexture);
+ IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_CULLMODE, D3DCULL_NONE);
+ IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_CLIPPING, TRUE);
+
+// IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_MINFILTER, D3DTEXF_POINT);
+// IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_MIPFILTER, D3DTEXF_POINT);
+// IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_MAGFILTER, D3DTEXF_POINT);
+// IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
+// IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
+ IDirect3DDevice9_SetSamplerState(gld->pDev, 0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
+ IDirect3DDevice9_SetSamplerState(gld->pDev, 0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
+ IDirect3DDevice9_SetSamplerState(gld->pDev, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
+ IDirect3DDevice9_SetSamplerState(gld->pDev, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
+ IDirect3DDevice9_SetSamplerState(gld->pDev, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
+
+ IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
+ IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
+ IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+ IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
+ IDirect3DDevice9_SetTextureStageState(gld->pDev, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
+ IDirect3DDevice9_SetTextureStageState(gld->pDev, 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
+
+ IDirect3DDevice9_SetVertexShader(gld->pDev, NULL);
+ IDirect3DDevice9_SetFVF(gld->pDev, _GLD_FVF_IMAGE);
+
+ //
+ // Emulate Chromakey with an Alpha Test.
+ // [Alpha Test is more widely supported anyway]
+ //
+ if (bChromakey) {
+ // Switch on alpha testing
+ IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_ALPHATESTENABLE, TRUE);
+ // Fragment passes is alpha is greater than reference value
+ IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_ALPHAFUNC, D3DCMP_GREATER);
+ // Set alpha reference value between Bitmap alpha values of
+ // zero (transparent) and one (opaque).
+ IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_ALPHAREF, 0x7f);
+ }
+
+ IDirect3DDevice9_DrawPrimitiveUP(gld->pDev, D3DPT_TRIANGLEFAN, 2, &v, sizeof(_GLD_IMAGE_VERTEX));
+
+ // Release texture
+ IDirect3DDevice9_SetTexture(gld->pDev, 0, NULL);
+ IDirect3DTexture9_Release(pTexture);
+
+ // Reset state to before we messed it up
+ FLUSH_VERTICES(ctx, _NEW_ALL);
+
+ return S_OK;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_DrawPixels_DX9(
+ struct gl_context *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *pixels )
+{
+ GLD_context *gldCtx;
+ GLD_driver_dx9 *gld;
+
+ IDirect3DSurface9 *pImage;
+ HRESULT hr;
+ D3DLOCKED_RECT d3dLockedRect;
+
+ const struct gl_texture_format *MesaFormat;
+
+ MesaFormat = _mesa_choose_tex_format(ctx, format, format, type);
+
+ // Mesa does not currently handle this format.
+ if (format == GL_BGR)
+ return;
+
+ gldCtx = GLD_GET_CONTEXT(ctx);
+ gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ hr = IDirect3DDevice9_CreateOffscreenPlainSurface(
+ gld->pDev,
+ width,
+ height,
+ D3DFMT_A8R8G8B8,
+ D3DPOOL_SCRATCH,
+ &pImage,
+ NULL);
+ if (FAILED(hr)) {
+ return;
+ }
+
+ //
+ // Use Mesa to fill in image
+ //
+
+ // Lock all of surface
+ hr = IDirect3DSurface9_LockRect(pImage, &d3dLockedRect, NULL, 0);
+ if (FAILED(hr)) {
+ IDirect3DSurface9_Release(pImage);
+ return;
+ }
+
+ // unpack image, apply transfer ops and store directly in texture
+ MesaFormat->StoreImage(
+ ctx,
+ 2,
+ GL_RGBA,
+ &_mesa_texformat_argb8888,
+ d3dLockedRect.pBits,
+ width, height, 1, 0, 0, 0,
+ d3dLockedRect.Pitch,
+ 0, /* dstImageStride */
+ format, type, pixels, unpack);
+
+ IDirect3DSurface9_UnlockRect(pImage);
+
+ _gldDrawPixels(ctx, FALSE, x, y, width, height, pImage);
+
+ IDirect3DSurface9_Release(pImage);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_ReadPixels_DX9(
+ struct gl_context *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *pack,
+ GLvoid *dest)
+{
+
+ GLD_context *gldCtx;
+ GLD_driver_dx9 *gld;
+
+ IDirect3DSurface9 *pBackbuffer = NULL;
+ IDirect3DSurface9 *pNativeImage = NULL;
+ IDirect3DSurface9 *pCanonicalImage = NULL;
+
+ D3DSURFACE_DESC d3dsd;
+ RECT rcSrc; // Source rect
+ POINT ptDst; // Dest point
+ HRESULT hr;
+ D3DLOCKED_RECT d3dLockedRect;
+ struct gl_pixelstore_attrib srcPacking;
+ int i;
+ GLint DstRowStride;
+ const struct gl_texture_format *MesaFormat;
+
+ switch (format) {
+ case GL_STENCIL_INDEX:
+ case GL_DEPTH_COMPONENT:
+ return;
+ }
+
+ MesaFormat = _mesa_choose_tex_format(ctx, format, format, type);
+ DstRowStride = _mesa_image_row_stride(pack, width, format, type);
+
+ gldCtx = GLD_GET_CONTEXT(ctx);
+ gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ // Get backbuffer
+ hr = IDirect3DDevice9_GetBackBuffer(
+ gld->pDev,
+ 0, // First swapchain
+ 0, // First backbuffer
+ D3DBACKBUFFER_TYPE_MONO,
+ &pBackbuffer);
+ if (FAILED(hr))
+ return;
+
+ // Get backbuffer description
+ hr = IDirect3DSurface9_GetDesc(pBackbuffer, &d3dsd);
+ if (FAILED(hr)) {
+ goto gld_ReadPixels_DX9_return;
+ }
+
+ // Create a surface compatible with backbuffer
+ hr = IDirect3DDevice9_CreateOffscreenPlainSurface(
+ gld->pDev,
+ width,
+ height,
+ d3dsd.Format,
+ D3DPOOL_SCRATCH,
+ &pNativeImage,
+ NULL);
+ if (FAILED(hr)) {
+ goto gld_ReadPixels_DX9_return;
+ }
+
+ // Compute source rect and dest point
+ SetRect(&rcSrc, 0, 0, width, height);
+ OffsetRect(&rcSrc, x, GLD_FLIP_HEIGHT(y, height));
+ ptDst.x = ptDst.y = 0;
+
+ // Get source pixels.
+ //
+ // This intermediate surface ensure that we can use CopyRects()
+ // instead of relying on D3DXLoadSurfaceFromSurface(), which may
+ // try and lock the backbuffer. This way seems safer.
+ //
+ // CopyRects has been removed for DX9.
+ //
+/* hr = IDirect3DDevice9_CopyRects(
+ gld->pDev,
+ pBackbuffer,
+ &rcSrc,
+ 1,
+ pNativeImage,
+ &ptDst);*/
+ hr = D3DXLoadSurfaceFromSurface(
+ pNativeImage, // Dest surface
+ NULL, // Dest palette
+ &rcSrc, // Dest rect
+ pBackbuffer, // Src surface
+ NULL, // Src palette
+ &rcSrc, // Src rect
+ D3DX_FILTER_NONE, // Filter
+ 0 // Colorkey (0=no colorkey)
+ );
+ if (FAILED(hr)) {
+ goto gld_ReadPixels_DX9_return;
+ }
+
+ // Create an RGBA8888 surface
+ hr = IDirect3DDevice9_CreateOffscreenPlainSurface(
+ gld->pDev,
+ width,
+ height,
+ D3DFMT_A8R8G8B8,
+ D3DPOOL_SCRATCH,
+ &pCanonicalImage,
+ NULL);
+ if (FAILED(hr)) {
+ goto gld_ReadPixels_DX9_return;
+ }
+
+ // Convert to RGBA8888
+ hr = D3DXLoadSurfaceFromSurface(
+ pCanonicalImage, // Dest surface
+ NULL, NULL, // Dest palette, RECT
+ pNativeImage, // Src surface
+ NULL, NULL, // Src palette, RECT
+ D3DX_FILTER_NONE, // Filter
+ 0); // Colourkey
+ if (FAILED(hr)) {
+ goto gld_ReadPixels_DX9_return;
+ }
+
+ srcPacking.Alignment = 1;
+ srcPacking.ImageHeight = height;
+ srcPacking.LsbFirst = GL_FALSE;
+ srcPacking.RowLength = 0;
+ srcPacking.SkipImages = 0;
+ srcPacking.SkipPixels = 0;
+ srcPacking.SkipRows = 0;
+ srcPacking.SwapBytes = GL_FALSE;
+
+ // Lock all of image
+ hr = IDirect3DSurface9_LockRect(pCanonicalImage, &d3dLockedRect, NULL, 0);
+ if (FAILED(hr)) {
+ goto gld_ReadPixels_DX9_return;
+ }
+
+ // We need to flip the data. Yuck.
+ // Perhaps Mesa has a span packer we can use in future...
+ for (i=0; i<height; i++) {
+ BYTE *pDestRow = (BYTE*)_mesa_image_address(2,pack, dest, width, height, format, type, 0, i, 0);
+ BYTE *pSrcRow = (BYTE*)d3dLockedRect.pBits + (d3dLockedRect.Pitch * (height-i-1));
+ MesaFormat->StoreImage(
+ ctx,
+ 2,
+ GL_RGBA, // base format
+ MesaFormat, // dst format
+ pDestRow, // dest addr
+ width, 1, 1, 0, 0, 0, // src x,y,z & dst offsets x,y,z
+ DstRowStride, // dst row stride
+ 0, // dstImageStride
+ GL_BGRA, // src format
+ GL_UNSIGNED_BYTE, // src type
+ pSrcRow, // src addr
+ &srcPacking); // packing params of source image
+ }
+
+ IDirect3DSurface9_UnlockRect(pCanonicalImage);
+
+gld_ReadPixels_DX9_return:
+ SAFE_RELEASE_SURFACE9(pCanonicalImage);
+ SAFE_RELEASE_SURFACE9(pNativeImage);
+ SAFE_RELEASE_SURFACE9(pBackbuffer);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_CopyPixels_DX9(
+ struct gl_context *ctx,
+ GLint srcx,
+ GLint srcy,
+ GLsizei width,
+ GLsizei height,
+ GLint dstx,
+ GLint dsty,
+ GLenum type)
+{
+ //
+ // NOTE: Not allowed to copy vidmem to vidmem!
+ // Therefore we use an intermediate image surface.
+ //
+
+ GLD_context *gldCtx;
+ GLD_driver_dx9 *gld;
+
+ IDirect3DSurface9 *pBackbuffer;
+ D3DSURFACE_DESC d3dsd;
+ IDirect3DSurface9 *pImage;
+ RECT rcSrc; // Source rect
+ POINT ptDst; // Dest point
+ HRESULT hr;
+
+ // Only backbuffer
+ if (type != GL_COLOR)
+ return;
+
+ gldCtx = GLD_GET_CONTEXT(ctx);
+ gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ // Get backbuffer
+ hr = IDirect3DDevice9_GetBackBuffer(
+ gld->pDev,
+ 0, // First swapchain
+ 0, // First backbuffer
+ D3DBACKBUFFER_TYPE_MONO,
+ &pBackbuffer);
+ if (FAILED(hr))
+ return;
+
+ // Get backbuffer description
+ hr = IDirect3DSurface9_GetDesc(pBackbuffer, &d3dsd);
+ if (FAILED(hr)) {
+ IDirect3DSurface9_Release(pBackbuffer);
+ return;
+ }
+
+ // Create a surface compatible with backbuffer
+ hr = IDirect3DDevice9_CreateOffscreenPlainSurface(
+ gld->pDev,
+ width,
+ height,
+ d3dsd.Format,
+ D3DPOOL_SCRATCH,
+ &pImage,
+ NULL);
+ if (FAILED(hr)) {
+ IDirect3DSurface9_Release(pBackbuffer);
+ return;
+ }
+
+ // Compute source rect and dest point
+ SetRect(&rcSrc, 0, 0, width, height);
+ OffsetRect(&rcSrc, srcx, GLD_FLIP_HEIGHT(srcy, height));
+ ptDst.x = ptDst.y = 0;
+
+ // Get source pixels
+/* hr = IDirect3DDevice8_CopyRects(
+ gld->pDev,
+ pBackbuffer,
+ &rcSrc,
+ 1,
+ pImage,
+ &ptDst);*/
+ hr = D3DXLoadSurfaceFromSurface(
+ pImage, // Dest surface
+ NULL, // Dest palette
+ &rcSrc, // Dest rect
+ pBackbuffer, // Src surface
+ NULL, // Src palette
+ &rcSrc, // Src rect
+ D3DX_FILTER_NONE, // Filter
+ 0 // Colorkey (0=no colorkey)
+ );
+ IDirect3DSurface9_Release(pBackbuffer);
+ if (FAILED(hr)) {
+ IDirect3DSurface9_Release(pImage);
+ return;
+ }
+
+ _gldDrawPixels(ctx, FALSE, dstx, dsty, width, height, pImage);
+
+ IDirect3DSurface9_Release(pImage);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Bitmap_DX9(
+ struct gl_context *ctx,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLubyte *bitmap)
+{
+ GLD_context *gldCtx;
+ GLD_driver_dx9 *gld;
+
+ IDirect3DSurface9 *pImage;
+ HRESULT hr;
+ D3DLOCKED_RECT d3dLockedRect;
+ BYTE *pTempBitmap;
+ D3DCOLOR clBitmapOne, clBitmapZero;
+ D3DCOLOR *pBits;
+ const GLubyte *src;
+ int i, j, k;
+
+ gldCtx = GLD_GET_CONTEXT(ctx);
+ gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ // A NULL bitmap is valid, but merely advances the raster position
+ if ((bitmap == NULL) || (width == 0) || (height == 0))
+ return;
+
+ clBitmapZero = D3DCOLOR_RGBA(0,0,0,0); // NOTE: Alpha is Zero
+ clBitmapOne = D3DCOLOR_COLORVALUE(
+ ctx->Current.RasterColor[0],
+ ctx->Current.RasterColor[1],
+ ctx->Current.RasterColor[2],
+ 1.0f); // NOTE: Alpha is One
+
+ hr = IDirect3DDevice9_CreateOffscreenPlainSurface(
+ gld->pDev,
+ width,
+ height,
+ D3DFMT_A8R8G8B8,
+ D3DPOOL_SCRATCH,
+ &pImage,
+ NULL);
+ if (FAILED(hr)) {
+ return;
+ }
+
+ // Lock all of surface
+ hr = IDirect3DSurface9_LockRect(pImage, &d3dLockedRect, NULL, 0);
+ if (FAILED(hr)) {
+ IDirect3DSurface9_Release(pImage);
+ return;
+ }
+
+ pTempBitmap = _mesa_unpack_bitmap(width, height, bitmap, unpack);
+ if (pTempBitmap == NULL) {
+ IDirect3DSurface9_Release(pImage);
+ return;
+ }
+
+ pBits = (D3DCOLOR*)d3dLockedRect.pBits;
+
+ for (i=0; i<height; i++) {
+ GLubyte byte;
+ pBits = (D3DCOLOR*)((BYTE*)d3dLockedRect.pBits + (i*d3dLockedRect.Pitch));
+ src = (const GLubyte *) _mesa_image_address(2,
+ &ctx->DefaultPacking, pTempBitmap, width, height, GL_COLOR_INDEX, GL_BITMAP,
+ 0, i, 0);
+ for (j=0; j<(width>>3); j++) {
+ byte = *src++;
+ for (k=0; k<8; k++) {
+ *pBits++ = (byte & 128) ? clBitmapOne : clBitmapZero;
+ byte <<= 1;
+ }
+ }
+ // Fill remaining bits from bitmap
+ if (width & 7) {
+ byte = *src;
+ for (k=0; k<(width & 7); k++) {
+ *pBits++ = (byte & 128) ? clBitmapOne : clBitmapZero;
+ byte <<= 1;
+ }
+ }
+ }
+
+ FREE(pTempBitmap);
+
+/*
+ // unpack image, apply transfer ops and store directly in texture
+ texImage->TexFormat->StoreImage(
+ ctx,
+ 2,
+ GL_BITMAP,
+ &_mesa_texformat_argb8888,
+ d3dLockedRect.pBits,
+ width, height, 1, 0, 0, 0,
+ d3dLockedRect.Pitch,
+ 0, // dstImageStride
+ GL_BITMAP, GL_COLOR_INDEX, bitmap, unpack);
+*/
+ IDirect3DSurface9_UnlockRect(pImage);
+
+ _gldDrawPixels(ctx, TRUE, x, y, width, height, pImage);
+
+ IDirect3DSurface9_Release(pImage);
+}
+
+//---------------------------------------------------------------------------
+// Texture functions
+//---------------------------------------------------------------------------
+
+void _gldAllocateTexture(
+ struct gl_context *ctx,
+ struct gl_texture_object *tObj,
+ struct gl_texture_image *texImage)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ IDirect3DTexture9 *pTex;
+ D3DFORMAT d3dFormat;
+
+ if (!tObj || !texImage)
+ return;
+
+ pTex = (IDirect3DTexture9*)tObj->DriverData;
+ if (pTex) {
+ // Decide whether we can keep existing D3D texture
+ // by examining top-level surface.
+ D3DSURFACE_DESC d3dsd;
+ _GLD_DX9_TEX(GetLevelDesc(pTex, 0, &d3dsd));
+ // Release existing texture if not compatible
+ if ((d3dsd.Width == texImage->Width) ||
+ (d3dsd.Height == texImage->Height))
+ {
+ return; // Keep the existing texture
+ }
+ tObj->DriverData = NULL;
+ _GLD_DX9_TEX(Release(pTex));
+ }
+
+ d3dFormat = _gldGLFormatToD3DFormat(texImage->IntFormat);
+ D3DXCreateTexture(
+ gld->pDev,
+ texImage->Width,
+ texImage->Height,
+ // TODO: Re-evaluate mipmapping
+ (glb.bUseMipmaps) ? D3DX_DEFAULT : 1,
+ 0, // Usage
+ d3dFormat,
+ D3DPOOL_MANAGED,
+ &pTex);
+ tObj->DriverData = pTex;
+}
+
+//---------------------------------------------------------------------------
+
+const struct gl_texture_format* gld_ChooseTextureFormat_DX9(
+ struct gl_context *ctx,
+ GLint internalFormat,
+ GLenum srcFormat,
+ GLenum srcType)
+{
+ // [Based on mesa_choose_tex_format()]
+ //
+ // We will choose only texture formats that are supported
+ // by Direct3D. If the hardware doesn't support a particular
+ // texture format, then the D3DX texture calls that we use
+ // will automatically use a HW supported format.
+ //
+ // The most critical aim is to reduce copying; if we can use
+ // texture-image data directly then it will be a big performance assist.
+ //
+
+ switch (internalFormat) {
+ case GL_INTENSITY:
+ case GL_INTENSITY4:
+ case GL_INTENSITY8:
+ case GL_INTENSITY12:
+ case GL_INTENSITY16:
+ return &_mesa_texformat_l8; // D3DFMT_L8
+ case 1:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE4:
+ case GL_LUMINANCE8:
+ case GL_LUMINANCE12:
+ case GL_LUMINANCE16:
+ return &_mesa_texformat_l8; // D3DFMT_L8
+ case GL_ALPHA:
+ case GL_ALPHA4:
+ case GL_ALPHA8:
+ case GL_ALPHA12:
+ case GL_ALPHA16:
+ return &_mesa_texformat_a8; // D3DFMT_A8
+ case GL_COLOR_INDEX:
+ case GL_COLOR_INDEX1_EXT:
+ case GL_COLOR_INDEX2_EXT:
+ case GL_COLOR_INDEX4_EXT:
+ case GL_COLOR_INDEX8_EXT:
+ case GL_COLOR_INDEX12_EXT:
+ case GL_COLOR_INDEX16_EXT:
+ return &_mesa_texformat_rgb565; // D3DFMT_R5G6B5
+ // Mesa will convert this for us later...
+ // return &_mesa_texformat_ci8; // D3DFMT_R5G6B5
+ case 2:
+ case GL_LUMINANCE_ALPHA:
+ case GL_LUMINANCE4_ALPHA4:
+ case GL_LUMINANCE6_ALPHA2:
+ case GL_LUMINANCE8_ALPHA8:
+ case GL_LUMINANCE12_ALPHA4:
+ case GL_LUMINANCE12_ALPHA12:
+ case GL_LUMINANCE16_ALPHA16:
+ return &_mesa_texformat_al88; // D3DFMT_A8L8
+ case GL_R3_G3_B2:
+ return &_mesa_texformat_rgb332; // D3DFMT_R3G3B2
+ case GL_RGB4:
+ case GL_RGBA4:
+ case GL_RGBA2:
+ return &_mesa_texformat_argb4444; // D3DFMT_A4R4G4B4
+ case 3:
+ case GL_RGB:
+ case GL_RGB5:
+ case GL_RGB8:
+ case GL_RGB10:
+ case GL_RGB12:
+ case GL_RGB16:
+ return &_mesa_texformat_rgb565;
+ case 4:
+ case GL_RGBA:
+ case GL_RGBA8:
+ case GL_RGB10_A2:
+ case GL_RGBA12:
+ case GL_RGBA16:
+ return &_mesa_texformat_argb8888;
+ case GL_RGB5_A1:
+ return &_mesa_texformat_argb1555;
+ default:
+ _mesa_problem(NULL, "unexpected format in fxDDChooseTextureFormat");
+ return NULL;
+ }
+}
+
+//---------------------------------------------------------------------------
+
+/*
+// Safer(?), slower version.
+void gld_TexImage2D_DX9(
+ struct gl_context *ctx,
+ GLenum target,
+ GLint level,
+ GLint internalFormat,
+ GLint width,
+ GLint height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *tObj,
+ struct gl_texture_image *texImage)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ IDirect3DTexture9 *pTex;
+ IDirect3DSurface9 *pSurface;
+ RECT rcSrcRect;
+ HRESULT hr;
+ GLint texelBytes = 4;
+ GLvoid *tempImage;
+
+ if (!tObj || !texImage)
+ return;
+
+ if (level == 0) {
+ _gldAllocateTexture(ctx, tObj, texImage);
+ }
+
+ pTex = (IDirect3DTexture9*)tObj->DriverData;
+ if (!pTex)
+ return; // Texture has not been created
+ if (level >= IDirect3DTexture9_GetLevelCount(pTex))
+ return; // Level does not exist
+ hr = IDirect3DTexture9_GetSurfaceLevel(pTex, level, &pSurface);
+ if (FAILED(hr))
+ return; // Surface level doesn't exist (or just a plain error)
+
+ tempImage = MALLOC(width * height * texelBytes);
+ if (!tempImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
+ IDirect3DSurface9_Release(pSurface);
+ return;
+ }
+ // unpack image, apply transfer ops and store in tempImage
+ texImage->TexFormat->StoreImage(ctx, 2, texImage->Format,
+ &_mesa_texformat_argb8888, // dest format
+ tempImage,
+ width, height, 1, 0, 0, 0,
+ width * texelBytes,
+ 0, // dstImageStride
+ format, type, pixels, packing);
+
+ SetRect(&rcSrcRect, 0, 0, width, height);
+ D3DXLoadSurfaceFromMemory(
+ pSurface,
+ NULL,
+ NULL,
+ tempImage,
+ D3DFMT_A8R8G8B8,
+ width * texelBytes,
+ NULL,
+ &rcSrcRect,
+ D3DX_FILTER_NONE,
+ 0);
+
+ FREE(tempImage);
+ IDirect3DSurface9_Release(pSurface);
+}
+*/
+
+//---------------------------------------------------------------------------
+
+// Faster, more efficient version.
+// Copies subimage straight to dest texture
+void gld_TexImage2D_DX9(
+ struct gl_context *ctx,
+ GLenum target,
+ GLint level,
+ GLint internalFormat,
+ GLint width,
+ GLint height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *tObj,
+ struct gl_texture_image *texImage)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ IDirect3DTexture9 *pTex;
+ IDirect3DSurface9 *pSurface;
+ HRESULT hr;
+ D3DLOCKED_RECT d3dLockedRect;
+ D3DSURFACE_DESC d3dsd;
+
+ if (!tObj || !texImage)
+ return;
+
+ // GLQUAKE FIX
+ // Test for input alpha data with non-alpha internalformat
+ if (((internalFormat==3) || (internalFormat==GL_RGB)) && (format==GL_RGBA)) {
+ // Input format has alpha, but a non-alpha format has been requested.
+ texImage->IntFormat = GL_RGBA;
+ internalFormat = GL_RGBA;
+ }
+
+ if (level == 0) {
+ _gldAllocateTexture(ctx, tObj, texImage);
+ }
+
+ pTex = (IDirect3DTexture9*)tObj->DriverData;
+ if (!pTex)
+ return; // Texture has not been created
+ if (level >= IDirect3DTexture9_GetLevelCount(pTex))
+ return; // Level does not exist
+ hr = IDirect3DTexture9_GetSurfaceLevel(pTex, level, &pSurface);
+ if (FAILED(hr))
+ return; // Surface level doesn't exist (or just a plain error)
+
+ IDirect3DSurface9_GetDesc(pSurface, &d3dsd);
+
+ // Lock all of surface
+ hr = IDirect3DSurface9_LockRect(pSurface, &d3dLockedRect, NULL, 0);
+ if (FAILED(hr)) {
+ IDirect3DSurface9_Release(pSurface);
+ return;
+ }
+
+ // unpack image, apply transfer ops and store directly in texture
+ texImage->TexFormat->StoreImage(
+ ctx,
+ 2,
+ texImage->Format,
+ _gldMesaFormatForD3DFormat(d3dsd.Format),
+ d3dLockedRect.pBits,
+ width, height, 1, 0, 0, 0,
+ d3dLockedRect.Pitch,
+ 0, // dstImageStride
+ format, type, pixels, packing);
+
+ IDirect3DSurface9_UnlockRect(pSurface);
+ IDirect3DSurface9_Release(pSurface);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_TexImage1D_DX9(struct gl_context *ctx, GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint border,
+ GLenum format, GLenum type, const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage )
+{
+ // A 1D texture is a 2D texture with a height of zero
+ gld_TexImage2D_DX9(ctx, target, level, internalFormat, width, 1, border, format, type, pixels, packing, texObj, texImage);
+}
+
+//---------------------------------------------------------------------------
+
+/*
+void gld_TexSubImage2D( struct gl_context *ctx, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *tObj,
+ struct gl_texture_image *texImage )
+{
+ GLD_GET_CONTEXT
+ IDirect3DTexture9 *pTex;
+ IDirect3DSurface9 *pSurface;
+ D3DFORMAT d3dFormat;
+ HRESULT hr;
+ GLint texelBytes = 4;
+ GLvoid *tempImage;
+ RECT rcSrcRect;
+ RECT rcDstRect;
+
+ if (!tObj || !texImage)
+ return;
+
+ pTex = (IDirect3DTexture9*)tObj->DriverData;
+ if (!pTex)
+ return; // Texture has not been created
+ if (level >= _GLD_DX9_TEX(GetLevelCount(pTex))
+ return; // Level does not exist
+ hr = _GLD_DX9_TEX(GetSurfaceLevel(pTex, level, &pSurface);
+ if (FAILED(hr))
+ return; // Surface level doesn't exist (or just a plain error)
+
+ d3dFormat = _gldGLFormatToD3DFormat(texImage->Format);
+ tempImage = MALLOC(width * height * texelBytes);
+ if (!tempImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
+ IDirect3DSurface9_Release(pSurface);
+ return;
+ }
+
+ // unpack image, apply transfer ops and store in tempImage
+ texImage->TexFormat->StoreImage(ctx, 2, texImage->Format,
+ &_mesa_texformat_argb8888, // dest format
+ tempImage,
+ width, height, 1, 0, 0, 0,
+ width * texelBytes,
+ 0, // dstImageStride
+ format, type, pixels, packing);
+
+ // Source rectangle is whole of input image
+ SetRect(&rcSrcRect, 0, 0, width, height);
+
+ // Dest rectangle must be offset to dest image
+ SetRect(&rcDstRect, 0, 0, width, height);
+ OffsetRect(&rcDstRect, xoffset, yoffset);
+
+ D3DXLoadSurfaceFromMemory(
+ pSurface,
+ NULL,
+ &rcDstRect,
+ tempImage,
+ D3DFMT_A8R8G8B8,
+ width * texelBytes,
+ NULL,
+ &rcSrcRect,
+ D3DX_FILTER_NONE,
+ 0);
+
+ FREE(tempImage);
+ IDirect3DSurface9_Release(pSurface);
+}
+*/
+
+//---------------------------------------------------------------------------
+
+// Faster, more efficient version.
+// Copies subimage straight to dest texture
+void gld_TexSubImage2D_DX9( struct gl_context *ctx, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *tObj,
+ struct gl_texture_image *texImage )
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ IDirect3DTexture9 *pTex;
+ IDirect3DSurface9 *pSurface;
+ HRESULT hr;
+ RECT rcDstRect;
+ D3DLOCKED_RECT d3dLockedRect;
+ D3DSURFACE_DESC d3dsd;
+
+ if (!tObj || !texImage)
+ return;
+
+ pTex = (IDirect3DTexture9*)tObj->DriverData;
+ if (!pTex)
+ return; // Texture has not been created
+ if (level >= IDirect3DTexture9_GetLevelCount(pTex))
+ return; // Level does not exist
+ hr = IDirect3DTexture9_GetSurfaceLevel(pTex, level, &pSurface);
+ if (FAILED(hr))
+ return; // Surface level doesn't exist (or just a plain error)
+
+ IDirect3DSurface9_GetDesc(pSurface, &d3dsd);
+
+ // Dest rectangle must be offset to dest image
+ SetRect(&rcDstRect, 0, 0, width, height);
+ OffsetRect(&rcDstRect, xoffset, yoffset);
+
+ // Lock sub-rect of surface
+ hr = IDirect3DSurface9_LockRect(pSurface, &d3dLockedRect, &rcDstRect, 0);
+ if (FAILED(hr)) {
+ IDirect3DSurface9_Release(pSurface);
+ return;
+ }
+
+ // unpack image, apply transfer ops and store directly in texture
+ texImage->TexFormat->StoreImage(ctx, 2, texImage->Format,
+ _gldMesaFormatForD3DFormat(d3dsd.Format),
+ d3dLockedRect.pBits,
+ width, height, 1,
+ 0, 0, 0, // NOTE: d3dLockedRect.pBits is already offset!!!
+ d3dLockedRect.Pitch,
+ 0, // dstImageStride
+ format, type, pixels, packing);
+
+
+ IDirect3DSurface9_UnlockRect(pSurface);
+ IDirect3DSurface9_Release(pSurface);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_TexSubImage1D_DX9( struct gl_context *ctx, GLenum target, GLint level,
+ GLint xoffset, GLsizei width,
+ GLenum format, GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage )
+{
+ gld_TexSubImage2D_DX9(ctx, target, level, xoffset, 0, width, 1, format, type, pixels, packing, texObj, texImage);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_DeleteTexture_DX9(
+ struct gl_context *ctx,
+ struct gl_texture_object *tObj)
+{
+ GLD_context *gld = (GLD_context*)(ctx->DriverCtx);
+
+ if (tObj) {
+ IDirect3DTexture9 *pTex = (IDirect3DTexture9*)tObj->DriverData;
+ if (pTex) {
+/* // Make sure texture is not bound to a stage before releasing it
+ for (int i=0; i<MAX_TEXTURE_UNITS; i++) {
+ if (gld->CurrentTexture[i] == pTex) {
+ gld->pDev->SetTexture(i, NULL);
+ gld->CurrentTexture[i] = NULL;
+ }
+ }*/
+ _GLD_DX9_TEX(Release(pTex));
+ tObj->DriverData = NULL;
+ }
+ }
+}
+
+//---------------------------------------------------------------------------
+
+__inline void _gldSetColorOps(
+ const GLD_driver_dx9 *gld,
+ GLuint unit,
+ DWORD ColorArg1,
+ D3DTEXTUREOP ColorOp,
+ DWORD ColorArg2)
+{
+ _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLORARG1, ColorArg1));
+ _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLOROP, ColorOp));
+ _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLORARG2, ColorArg2));
+}
+
+//---------------------------------------------------------------------------
+
+__inline void _gldSetAlphaOps(
+ const GLD_driver_dx9 *gld,
+ GLuint unit,
+ DWORD AlphaArg1,
+ D3DTEXTUREOP AlphaOp,
+ DWORD AlphaArg2)
+{
+ _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ALPHAARG1, AlphaArg1));
+ _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ALPHAOP, AlphaOp));
+ _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ALPHAARG2, AlphaArg2));
+}
+
+//---------------------------------------------------------------------------
+
+void gldUpdateTextureUnit(
+ struct gl_context *ctx,
+ GLuint unit,
+ BOOL bPassThrough)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ D3DTEXTUREFILTERTYPE minfilter;
+ D3DTEXTUREFILTERTYPE mipfilter;
+ GLenum BaseFormat;
+ DWORD dwColorArg0;
+ int iTexEnv = 0;
+ GLD_texenv *pTexenv;
+
+ // NOTE: If bPassThrough is FALSE then texture stage can be
+ // disabled otherwise it must pass-through it's current fragment.
+
+ const struct gl_texture_unit *pUnit = &ctx->Texture.Unit[unit];
+ const struct gl_texture_object *tObj = pUnit->_Current;
+
+ IDirect3DTexture9 *pTex = NULL;
+ if (tObj) {
+ pTex = (IDirect3DTexture9*)tObj->DriverData;
+ }
+
+ // Enable texturing if unit is enabled and a valid D3D texture exists
+ // Mesa 5: TEXTUREn_x altered to TEXTURE_nD_BIT
+ //if (pTex && (pUnit->Enabled & (TEXTURE0_1D | TEXTURE0_2D))) {
+ if (pTex && (pUnit->_ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT))) {
+ // Enable texturing
+ _GLD_DX9_DEV(SetTexture(gld->pDev, unit, pTex));
+ } else {
+ // Disable texturing, then return
+ _GLD_DX9_DEV(SetTexture(gld->pDev, unit, NULL));
+ if (bPassThrough) {
+ _gldSetColorOps(gld, unit, D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_DIFFUSE);
+ _gldSetAlphaOps(gld, unit, D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_DIFFUSE);
+ } else {
+ _gldSetColorOps(gld, unit, D3DTA_TEXTURE, D3DTOP_DISABLE, D3DTA_DIFFUSE);
+ _gldSetAlphaOps(gld, unit, D3DTA_TEXTURE, D3DTOP_DISABLE, D3DTA_DIFFUSE);
+ }
+ return;
+ }
+
+ // Texture parameters
+ _gldConvertMinFilter(tObj->MinFilter, &minfilter, &mipfilter);
+// _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_MINFILTER, minfilter));
+// _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_MIPFILTER, mipfilter));
+// _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_MAGFILTER, _gldConvertMagFilter(tObj->MagFilter)));
+// _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ADDRESSU, _gldConvertWrap(tObj->WrapS)));
+// _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ADDRESSV, _gldConvertWrap(tObj->WrapT)));
+ _GLD_DX9_DEV(SetSamplerState(gld->pDev, unit, D3DSAMP_MINFILTER, minfilter));
+ _GLD_DX9_DEV(SetSamplerState(gld->pDev, unit, D3DSAMP_MIPFILTER, mipfilter));
+ _GLD_DX9_DEV(SetSamplerState(gld->pDev, unit, D3DSAMP_MAGFILTER, _gldConvertMagFilter(tObj->MagFilter)));
+ _GLD_DX9_DEV(SetSamplerState(gld->pDev, unit, D3DSAMP_ADDRESSU, _gldConvertWrap(tObj->WrapS)));
+ _GLD_DX9_DEV(SetSamplerState(gld->pDev, unit, D3DSAMP_ADDRESSV, _gldConvertWrap(tObj->WrapT)));
+
+ // Texture priority
+ _GLD_DX9_TEX(SetPriority(pTex, (DWORD)(tObj->Priority*65535.0f)));
+
+ // Texture environment
+ // TODO: Examine input texture for alpha and use specific alpha/non-alpha ops.
+ // See Page 355 of the Red Book.
+ BaseFormat = _gldDecodeBaseFormat(pTex);
+
+ switch (BaseFormat) {
+ case GL_RGB:
+ iTexEnv = 0;
+ break;
+ case GL_RGBA:
+ iTexEnv = 1;
+ break;
+ case GL_ALPHA:
+ iTexEnv = 2;
+ break;
+ }
+
+ switch (pUnit->EnvMode) {
+ case GL_DECAL:
+ iTexEnv += 0;
+ break;
+ case GL_REPLACE:
+ iTexEnv += 3;
+ break;
+ case GL_MODULATE:
+ iTexEnv += 6;
+ break;
+ case GL_BLEND:
+ // Set blend colour
+ dwColorArg0 = D3DCOLOR_COLORVALUE(pUnit->EnvColor[0], pUnit->EnvColor[1], pUnit->EnvColor[2], pUnit->EnvColor[3]);
+ _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLORARG0, dwColorArg0));
+ iTexEnv += 9;
+ break;
+ case GL_ADD:
+ iTexEnv += 12;
+ break;
+ }
+ pTexenv = (GLD_texenv*)&gldTexEnv[iTexEnv];
+ _gldSetColorOps(gld, unit, pTexenv->ColorArg1, pTexenv->ColorOp, pTexenv->ColorArg2);
+ _gldSetAlphaOps(gld, unit, pTexenv->AlphaArg1, pTexenv->AlphaOp, pTexenv->AlphaArg2);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_TEXTURE_DX9(
+ struct gl_context *ctx)
+{
+ // TODO: Support for three (ATI Radeon) or more (nVidia GeForce3) texture units
+
+ BOOL bUnit0Enabled;
+ BOOL bUnit1Enabled;
+
+ if (!ctx)
+ return; // Sanity check
+
+ if (ctx->Const.MaxTextureUnits == 1) {
+ gldUpdateTextureUnit(ctx, 0, TRUE);
+ return;
+ }
+
+ //
+ // NOTE: THE FOLLOWING RELATES TO TWO TEXTURE UNITS, AND TWO ONLY!!
+ //
+
+ // Mesa 5: Texture Units altered
+ //bUnit0Enabled = (ctx->Texture._ReallyEnabled & (TEXTURE0_1D | TEXTURE0_2D)) ? TRUE : FALSE;
+ //bUnit1Enabled = (ctx->Texture._ReallyEnabled & (TEXTURE1_1D | TEXTURE1_2D)) ? TRUE : FALSE;
+ bUnit0Enabled = (ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT)) ? TRUE : FALSE;
+ bUnit1Enabled = (ctx->Texture.Unit[1]._ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT)) ? TRUE : FALSE;
+
+ // If Unit0 is disabled and Unit1 is enabled then we must pass-though
+ gldUpdateTextureUnit(ctx, 0, (!bUnit0Enabled && bUnit1Enabled) ? TRUE : FALSE);
+ // We can always disable the last texture unit
+ gldUpdateTextureUnit(ctx, 1, FALSE);
+
+#ifdef _DEBUG
+#if 0
+ {
+ // Find out whether device supports current renderstates
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+// GLD_context *gld = GLD_GET_CONTEXT(ctx);
+
+ DWORD dwPasses;
+ _GLD_DX9_DEV(ValidateDevice(gld->pDev, &dwPasses));
+// if (FAILED(hr)) {
+// gldLogError(GLDLOG_ERROR, "ValidateDevice failed", hr);
+// }
+ if (dwPasses != 1) {
+ gldLogMessage(GLDLOG_ERROR, "ValidateDevice: Can't do in one pass\n");
+ }
+ }
+#endif
+#endif
+};
+
+//---------------------------------------------------------------------------
diff --git a/mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_vb_d3d_render_dx9.c b/mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_vb_d3d_render_dx9.c
new file mode 100644
index 000000000..28164a8de
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_vb_d3d_render_dx9.c
@@ -0,0 +1,263 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: GLDirect fastpath pipeline stage
+*
+****************************************************************************/
+
+//---------------------------------------------------------------------------
+
+//#include "../GLDirect.h"
+//#include "../gld_log.h"
+//#include "gld_dx8.h"
+
+#include "dglcontext.h"
+#include "ddlog.h"
+#include "gld_dx9.h"
+
+//---------------------------------------------------------------------------
+
+#include "glheader.h"
+#include "context.h"
+#include "macros.h"
+// #include "mem.h"
+#include "mtypes.h"
+//#include "mmath.h"
+
+#include "math/m_matrix.h"
+#include "math/m_xform.h"
+
+#include "tnl/t_pipeline.h"
+
+//---------------------------------------------------------------------------
+
+__inline void _gldSetVertexShaderConstants(
+ struct gl_context *ctx,
+ GLD_driver_dx9 *gld)
+{
+ D3DXMATRIX mat, matView, matProj;
+ GLfloat *pM;
+
+ // Mesa 5: Altered to a Stack
+ //pM = ctx->ModelView.m;
+ pM = ctx->ModelviewMatrixStack.Top->m;
+ matView._11 = pM[0];
+ matView._12 = pM[1];
+ matView._13 = pM[2];
+ matView._14 = pM[3];
+ matView._21 = pM[4];
+ matView._22 = pM[5];
+ matView._23 = pM[6];
+ matView._24 = pM[7];
+ matView._31 = pM[8];
+ matView._32 = pM[9];
+ matView._33 = pM[10];
+ matView._34 = pM[11];
+ matView._41 = pM[12];
+ matView._42 = pM[13];
+ matView._43 = pM[14];
+ matView._44 = pM[15];
+
+ // Mesa 5: Altered to a Stack
+ //pM = ctx->ProjectionMatrix.m;
+ pM = ctx->ProjectionMatrixStack.Top->m;
+ matProj._11 = pM[0];
+ matProj._12 = pM[1];
+ matProj._13 = pM[2];
+ matProj._14 = pM[3];
+ matProj._21 = pM[4];
+ matProj._22 = pM[5];
+ matProj._23 = pM[6];
+ matProj._24 = pM[7];
+ matProj._31 = pM[8];
+ matProj._32 = pM[9];
+ matProj._33 = pM[10];
+ matProj._34 = pM[11];
+ matProj._41 = pM[12];
+ matProj._42 = pM[13];
+ matProj._43 = pM[14];
+ matProj._44 = pM[15];
+
+ D3DXMatrixMultiply( &mat, &matView, &matProj );
+ D3DXMatrixTranspose( &mat, &mat );
+
+ _GLD_DX9_DEV(SetVertexShaderConstantF(gld->pDev, 0, (float*)&mat, 4));
+}
+
+//---------------------------------------------------------------------------
+
+static GLboolean gld_d3d_render_stage_run(
+ struct gl_context *ctx,
+ struct tnl_pipeline_stage *stage)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ TNLcontext *tnl;
+ struct vertex_buffer *VB;
+ tnl_render_func *tab;
+ GLint pass;
+ GLD_pb_dx9 *gldPB = &gld->PB3d;
+/*
+ static int count = 0;
+ count++;
+ if (count != 2)
+ return GL_FALSE;
+*/
+ // The "check" function should disable this stage,
+ // but we'll test gld->bUseMesaTnL anyway.
+ if (gld->bUseMesaTnL) {
+ // Do nothing in this stage, but continue pipeline
+ return GL_TRUE;
+ }
+
+ tnl = TNL_CONTEXT(ctx);
+ VB = &tnl->vb;
+ pass = 0;
+
+ tnl->Driver.Render.Start( ctx );
+
+#if 0
+ // For debugging: Useful to see if an app passes colour data in
+ // an unusual format.
+ switch (VB->AttribPtr[_TNL_ATTRIB_COLOR0]->Type) {
+ case GL_FLOAT:
+ ddlogMessage(GLDLOG_SYSTEM, "ColorPtr: GL_FLOAT\n");
+ break;
+ case GL_UNSIGNED_BYTE:
+ ddlogMessage(GLDLOG_SYSTEM, "ColorPtr: GL_UNSIGNED_BYTE\n");
+ break;
+ default:
+ ddlogMessage(GLDLOG_SYSTEM, "ColorPtr: *?*\n");
+ break;
+ }
+#endif
+
+ tnl->Driver.Render.Points = gld_Points3D_DX9;
+ if (ctx->_TriangleCaps & DD_FLATSHADE) {
+ tnl->Driver.Render.Line = gld_Line3DFlat_DX9;
+ tnl->Driver.Render.Triangle = gld_Triangle3DFlat_DX9;
+ tnl->Driver.Render.Quad = gld_Quad3DFlat_DX9;
+ } else {
+ tnl->Driver.Render.Line = gld_Line3DSmooth_DX9;
+ tnl->Driver.Render.Triangle = gld_Triangle3DSmooth_DX9;
+ tnl->Driver.Render.Quad = gld_Quad3DSmooth_DX9;
+ }
+
+ _GLD_DX9_VB(Lock(gldPB->pVB, 0, 0, &gldPB->pPoints, D3DLOCK_DISCARD));
+ gldPB->nPoints = gldPB->nLines = gldPB->nTriangles = 0;
+ // Allocate primitive pointers
+ // gldPB->pPoints is always first
+ gldPB->pLines = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstLine);
+ gldPB->pTriangles = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstTriangle);
+
+ ASSERT(tnl->Driver.Render.BuildVertices);
+ ASSERT(tnl->Driver.Render.PrimitiveNotify);
+ ASSERT(tnl->Driver.Render.Points);
+ ASSERT(tnl->Driver.Render.Line);
+ ASSERT(tnl->Driver.Render.Triangle);
+ ASSERT(tnl->Driver.Render.Quad);
+ ASSERT(tnl->Driver.Render.ResetLineStipple);
+ ASSERT(tnl->Driver.Render.Interp);
+ ASSERT(tnl->Driver.Render.CopyPV);
+ ASSERT(tnl->Driver.Render.ClippedLine);
+ ASSERT(tnl->Driver.Render.ClippedPolygon);
+ ASSERT(tnl->Driver.Render.Finish);
+
+ tab = (VB->Elts ? tnl->Driver.Render.PrimTabElts : tnl->Driver.Render.PrimTabVerts);
+
+ do {
+ GLuint i, length, flags = 0;
+ for (i = 0 ; !(flags & PRIM_END) ; i += length)
+ {
+ flags = VB->Primitive[i].mode;
+ length= VB->Primitive[i].count;
+ ASSERT(length || (flags & PRIM_END));
+ ASSERT((flags & PRIM_MODE_MASK) <= GL_POLYGON+1);
+ if (length)
+ tab[flags & PRIM_MODE_MASK]( ctx, i, i + length, flags );
+ }
+ } while (tnl->Driver.Render.Multipass &&
+ tnl->Driver.Render.Multipass( ctx, ++pass ));
+
+ _GLD_DX9_VB(Unlock(gldPB->pVB));
+
+ _GLD_DX9_DEV(SetStreamSource(gld->pDev, 0, gldPB->pVB, 0, gldPB->dwStride));
+
+ _GLD_DX9_DEV(SetTransform(gld->pDev, D3DTS_PROJECTION, &gld->matProjection));
+ _GLD_DX9_DEV(SetTransform(gld->pDev, D3DTS_WORLD, &gld->matModelView));
+
+ if (gldPB->nPoints) {
+ _GLD_DX9_DEV(DrawPrimitive(gld->pDev, D3DPT_POINTLIST, 0, gldPB->nPoints));
+ gldPB->nPoints = 0;
+ }
+
+ if (gldPB->nLines) {
+ _GLD_DX9_DEV(DrawPrimitive(gld->pDev, D3DPT_LINELIST, gldPB->iFirstLine, gldPB->nLines));
+ gldPB->nLines = 0;
+ }
+
+ if (gldPB->nTriangles) {
+ _GLD_DX9_DEV(DrawPrimitive(gld->pDev, D3DPT_TRIANGLELIST, gldPB->iFirstTriangle, gldPB->nTriangles));
+ gldPB->nTriangles = 0;
+ }
+
+ return GL_FALSE; /* finished the pipe */
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_d3d_render_stage_check(
+ struct gl_context *ctx,
+ struct tnl_pipeline_stage *stage)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+ // Is this thread safe?
+ stage->active = (gld->bUseMesaTnL) ? GL_FALSE : GL_TRUE;
+ return;
+}
+
+
+//---------------------------------------------------------------------------
+
+const struct tnl_pipeline_stage _gld_d3d_render_stage =
+{
+ "gld_d3d_render_stage",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ gld_d3d_render_stage_run /* run */
+};
+
+//---------------------------------------------------------------------------
diff --git a/mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_vb_mesa_render_dx9.c b/mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_vb_mesa_render_dx9.c
new file mode 100644
index 000000000..4023d547d
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_vb_mesa_render_dx9.c
@@ -0,0 +1,443 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keithw@valinux.com>
+ */
+
+
+/*
+ * Render whole vertex buffers, including projection of vertices from
+ * clip space and clipping of primitives.
+ *
+ * This file makes calls to project vertices and to the point, line
+ * and triangle rasterizers via the function pointers:
+ *
+ * context->Driver.Render.*
+ *
+ */
+
+
+//---------------------------------------------------------------------------
+
+#include "dglcontext.h"
+#include "ddlog.h"
+#include "gld_dx9.h"
+
+//---------------------------------------------------------------------------
+
+#include "glheader.h"
+#include "context.h"
+#include "macros.h"
+#include "mtypes.h"
+//#include "mmath.h"
+
+#include "math/m_matrix.h"
+#include "math/m_xform.h"
+
+#include "tnl/t_pipeline.h"
+
+/**********************************************************************/
+/* Clip single primitives */
+/**********************************************************************/
+
+
+#if defined(USE_IEEE)
+#define NEGATIVE(x) (GET_FLOAT_BITS(x) & (1<<31))
+//#define DIFFERENT_SIGNS(x,y) ((GET_FLOAT_BITS(x) ^ GET_FLOAT_BITS(y)) & (1<<31))
+#else
+#define NEGATIVE(x) (x < 0)
+//#define DIFFERENT_SIGNS(x,y) (x * y <= 0 && x - y != 0)
+/* Could just use (x*y<0) except for the flatshading requirements.
+ * Maybe there's a better way?
+ */
+#endif
+
+
+#define W(i) coord[i][3]
+#define Z(i) coord[i][2]
+#define Y(i) coord[i][1]
+#define X(i) coord[i][0]
+#define SIZE 4
+#define TAG(x) x##_4
+#include "tnl/t_vb_cliptmp.h"
+
+
+
+/**********************************************************************/
+/* Clip and render whole begin/end objects */
+/**********************************************************************/
+
+#define NEED_EDGEFLAG_SETUP (ctx->_TriangleCaps & DD_TRI_UNFILLED)
+#define EDGEFLAG_GET(idx) VB->EdgeFlag[idx]
+#define EDGEFLAG_SET(idx, val) VB->EdgeFlag[idx] = val
+
+
+/* Vertices, with the possibility of clipping.
+ */
+#define RENDER_POINTS( start, count ) \
+ tnl->Driver.Render.Points( ctx, start, count )
+
+#define RENDER_LINE( v1, v2 ) \
+do { \
+ GLubyte c1 = mask[v1], c2 = mask[v2]; \
+ GLubyte ormask = c1|c2; \
+ if (!ormask) \
+ LineFunc( ctx, v1, v2 ); \
+ else if (!(c1 & c2 & 0x3f)) \
+ clip_line_4( ctx, v1, v2, ormask ); \
+} while (0)
+
+#define RENDER_TRI( v1, v2, v3 ) \
+do { \
+ GLubyte c1 = mask[v1], c2 = mask[v2], c3 = mask[v3]; \
+ GLubyte ormask = c1|c2|c3; \
+ if (!ormask) \
+ TriangleFunc( ctx, v1, v2, v3 ); \
+ else if (!(c1 & c2 & c3 & 0x3f)) \
+ clip_tri_4( ctx, v1, v2, v3, ormask ); \
+} while (0)
+
+#define RENDER_QUAD( v1, v2, v3, v4 ) \
+do { \
+ GLubyte c1 = mask[v1], c2 = mask[v2]; \
+ GLubyte c3 = mask[v3], c4 = mask[v4]; \
+ GLubyte ormask = c1|c2|c3|c4; \
+ if (!ormask) \
+ QuadFunc( ctx, v1, v2, v3, v4 ); \
+ else if (!(c1 & c2 & c3 & c4 & 0x3f)) \
+ clip_quad_4( ctx, v1, v2, v3, v4, ormask ); \
+} while (0)
+
+
+#define LOCAL_VARS \
+ TNLcontext *tnl = TNL_CONTEXT(ctx); \
+ struct vertex_buffer *VB = &tnl->vb; \
+ const GLuint * const elt = VB->Elts; \
+ const GLubyte *mask = VB->ClipMask; \
+ const GLuint sz = VB->ClipPtr->size; \
+ const tnl_line_func LineFunc = tnl->Driver.Render.Line; \
+ const tnl_triangle_func TriangleFunc = tnl->Driver.Render.Triangle; \
+ const tnl_quad_func QuadFunc = tnl->Driver.Render.Quad; \
+ const GLboolean stipple = ctx->Line.StippleFlag; \
+ (void) (LineFunc && TriangleFunc && QuadFunc); \
+ (void) elt; (void) mask; (void) sz; (void) stipple;
+
+#define TAG(x) clip_##x##_verts
+#define INIT(x) tnl->Driver.Render.PrimitiveNotify( ctx, x )
+#define RESET_STIPPLE if (stipple) tnl->Driver.Render.ResetLineStipple( ctx )
+#define PRESERVE_VB_DEFS
+#include "tnl/t_vb_rendertmp.h"
+
+
+
+/* Elts, with the possibility of clipping.
+ */
+#undef ELT
+#undef TAG
+#define ELT(x) elt[x]
+#define TAG(x) clip_##x##_elts
+#include "tnl/t_vb_rendertmp.h"
+
+/* TODO: do this for all primitives, verts and elts:
+ */
+static void clip_elt_triangles( struct gl_context *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ tnl_render_func render_tris = tnl->Driver.Render.PrimTabElts[GL_TRIANGLES];
+ struct vertex_buffer *VB = &tnl->vb;
+ const GLuint * const elt = VB->Elts;
+ GLubyte *mask = VB->ClipMask;
+ GLuint last = count-2;
+ GLuint j;
+ (void) flags;
+
+ tnl->Driver.Render.PrimitiveNotify( ctx, GL_TRIANGLES );
+
+ for (j=start; j < last; j+=3 ) {
+ GLubyte c1 = mask[elt[j]];
+ GLubyte c2 = mask[elt[j+1]];
+ GLubyte c3 = mask[elt[j+2]];
+ GLubyte ormask = c1|c2|c3;
+ if (ormask) {
+ if (start < j)
+ render_tris( ctx, start, j, 0 );
+ if (!(c1&c2&c3&0x3f))
+ clip_tri_4( ctx, elt[j], elt[j+1], elt[j+2], ormask );
+ start = j+3;
+ }
+ }
+
+ if (start < j)
+ render_tris( ctx, start, j, 0 );
+}
+
+/**********************************************************************/
+/* Render whole begin/end objects */
+/**********************************************************************/
+
+#define NEED_EDGEFLAG_SETUP (ctx->_TriangleCaps & DD_TRI_UNFILLED)
+#define EDGEFLAG_GET(idx) VB->EdgeFlag[idx]
+#define EDGEFLAG_SET(idx, val) VB->EdgeFlag[idx] = val
+
+
+/* Vertices, no clipping.
+ */
+#define RENDER_POINTS( start, count ) \
+ tnl->Driver.Render.Points( ctx, start, count )
+
+#define RENDER_LINE( v1, v2 ) \
+ LineFunc( ctx, v1, v2 )
+
+#define RENDER_TRI( v1, v2, v3 ) \
+ TriangleFunc( ctx, v1, v2, v3 )
+
+#define RENDER_QUAD( v1, v2, v3, v4 ) \
+ QuadFunc( ctx, v1, v2, v3, v4 )
+
+#define TAG(x) _gld_tnl_##x##_verts
+
+#define LOCAL_VARS \
+ TNLcontext *tnl = TNL_CONTEXT(ctx); \
+ struct vertex_buffer *VB = &tnl->vb; \
+ const GLuint * const elt = VB->Elts; \
+ const tnl_line_func LineFunc = tnl->Driver.Render.Line; \
+ const tnl_triangle_func TriangleFunc = tnl->Driver.Render.Triangle; \
+ const tnl_quad_func QuadFunc = tnl->Driver.Render.Quad; \
+ (void) (LineFunc && TriangleFunc && QuadFunc); \
+ (void) elt;
+
+#define RESET_STIPPLE tnl->Driver.Render.ResetLineStipple( ctx )
+#define INIT(x) tnl->Driver.Render.PrimitiveNotify( ctx, x )
+#define RENDER_TAB_QUALIFIER
+#define PRESERVE_VB_DEFS
+#include "tnl/t_vb_rendertmp.h"
+
+
+/* Elts, no clipping.
+ */
+#undef ELT
+#define TAG(x) _gld_tnl_##x##_elts
+#define ELT(x) elt[x]
+#include "tnl/t_vb_rendertmp.h"
+
+
+/**********************************************************************/
+/* Helper functions for drivers */
+/**********************************************************************/
+/*
+void _tnl_RenderClippedPolygon( struct gl_context *ctx, const GLuint *elts, GLuint n )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ GLuint *tmp = VB->Elts;
+
+ VB->Elts = (GLuint *)elts;
+ tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n, PRIM_BEGIN|PRIM_END );
+ VB->Elts = tmp;
+}
+
+void _tnl_RenderClippedLine( struct gl_context *ctx, GLuint ii, GLuint jj )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ tnl->Driver.Render.Line( ctx, ii, jj );
+}
+*/
+
+
+/**********************************************************************/
+/* Clip and render whole vertex buffers */
+/**********************************************************************/
+
+tnl_points_func _gldSetupPoints[4] = {
+ gld_Points2D_DX9,
+ gld_Points2D_DX9,
+ gld_Points2D_DX9,
+ gld_Points2D_DX9
+};
+tnl_line_func _gldSetupLine[4] = {
+ gld_Line2DFlat_DX9,
+ gld_Line2DSmooth_DX9,
+ gld_Line2DFlat_DX9,
+ gld_Line2DSmooth_DX9,
+};
+tnl_triangle_func _gldSetupTriangle[4] = {
+ gld_Triangle2DFlat_DX9,
+ gld_Triangle2DSmooth_DX9,
+ gld_Triangle2DFlatExtras_DX9,
+ gld_Triangle2DSmoothExtras_DX9
+};
+tnl_quad_func _gldSetupQuad[4] = {
+ gld_Quad2DFlat_DX9,
+ gld_Quad2DSmooth_DX9,
+ gld_Quad2DFlatExtras_DX9,
+ gld_Quad2DSmoothExtras_DX9
+};
+
+//---------------------------------------------------------------------------
+
+static GLboolean _gld_mesa_render_stage_run(
+ struct gl_context *ctx,
+ struct tnl_pipeline_stage *stage)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ tnl_render_func *tab;
+ GLint pass = 0;
+ GLD_pb_dx9 *gldPB;
+
+ /* Allow the drivers to lock before projected verts are built so
+ * that window coordinates are guarenteed not to change before
+ * rendering.
+ */
+ ASSERT(tnl->Driver.Render.Start);
+
+ tnl->Driver.Render.Start( ctx );
+
+ // NOTE: Setting D3DRS_SOFTWAREVERTEXPROCESSING for a mixed-mode device resets
+ // stream, indices and shader to default values of NULL or 0.
+/* if ((ctx->_TriangleCaps & DD_TRI_LIGHT_TWOSIDE) &&
+ gld->VStwosidelight.hShader &&
+ !ctx->Fog.Enabled)
+ {
+ IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, !gld->VStwosidelight.bHardware);
+ _GLD_DX9_DEV(SetVertexShader(gld->pDev, gld->VStwosidelight.hShader));
+ gldPB = &gld->PBtwosidelight;
+ tnl->Driver.Render.Points = gld_Points2DTwoside_DX9;
+ if (ctx->_TriangleCaps & DD_FLATSHADE) {
+ tnl->Driver.Render.Line = gld_Line2DFlatTwoside_DX9;
+ tnl->Driver.Render.Triangle = gld_Triangle2DFlatTwoside_DX9;
+ tnl->Driver.Render.Quad = gld_Quad2DFlatTwoside_DX9;
+ } else {
+ tnl->Driver.Render.Line = gld_Line2DSmoothTwoside_DX9;
+ tnl->Driver.Render.Triangle = gld_Triangle2DSmoothTwoside_DX9;
+ tnl->Driver.Render.Quad = gld_Quad2DSmoothTwoside_DX9;
+ }
+ } else {*/
+// IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, TRUE);
+ IDirect3DDevice9_SetSoftwareVertexProcessing(gld->pDev, TRUE);
+ gldPB = &gld->PB2d;
+ _GLD_DX9_DEV(SetVertexShader(gld->pDev, NULL));
+ _GLD_DX9_DEV(SetFVF(gld->pDev, gldPB->dwFVF));
+ tnl->Driver.Render.Points = _gldSetupPoints[gld->iSetupFunc];
+ tnl->Driver.Render.Line = _gldSetupLine[gld->iSetupFunc];
+ tnl->Driver.Render.Triangle = _gldSetupTriangle[gld->iSetupFunc];
+ tnl->Driver.Render.Quad = _gldSetupQuad[gld->iSetupFunc];
+// }
+
+ _GLD_DX9_VB(Lock(gldPB->pVB, 0, 0, &gldPB->pPoints, D3DLOCK_DISCARD));
+ gldPB->nPoints = gldPB->nLines = gldPB->nTriangles = 0;
+ // Allocate primitive pointers
+ // gldPB->pPoints is always first
+ gldPB->pLines = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstLine);
+ gldPB->pTriangles = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstTriangle);
+
+ ASSERT(tnl->Driver.Render.BuildVertices);
+ ASSERT(tnl->Driver.Render.PrimitiveNotify);
+ ASSERT(tnl->Driver.Render.Points);
+ ASSERT(tnl->Driver.Render.Line);
+ ASSERT(tnl->Driver.Render.Triangle);
+ ASSERT(tnl->Driver.Render.Quad);
+ ASSERT(tnl->Driver.Render.ResetLineStipple);
+ ASSERT(tnl->Driver.Render.Interp);
+ ASSERT(tnl->Driver.Render.CopyPV);
+ ASSERT(tnl->Driver.Render.ClippedLine);
+ ASSERT(tnl->Driver.Render.ClippedPolygon);
+ ASSERT(tnl->Driver.Render.Finish);
+
+ tnl->Driver.Render.BuildVertices( ctx, 0, VB->Count, ~0 );
+
+ if (VB->ClipOrMask) {
+ tab = VB->Elts ? clip_render_tab_elts : clip_render_tab_verts;
+ clip_render_tab_elts[GL_TRIANGLES] = clip_elt_triangles;
+ }
+ else {
+ tab = (VB->Elts ?
+ tnl->Driver.Render.PrimTabElts :
+ tnl->Driver.Render.PrimTabVerts);
+ }
+
+ do {
+ GLuint i, length, flags = 0;
+ for (i = 0 ; !(flags & PRIM_END) ; i += length) {
+ flags = VB->Primitive[i].mode;
+ length= VB->Primitive[i].count;
+ ASSERT(length || (flags & PRIM_END));
+ ASSERT((flags & PRIM_MODE_MASK) <= GL_POLYGON+1);
+ if (length)
+ tab[flags & PRIM_MODE_MASK]( ctx, i, i + length, flags );
+ }
+ } while (tnl->Driver.Render.Multipass &&
+ tnl->Driver.Render.Multipass( ctx, ++pass ));
+
+
+// tnl->Driver.Render.Finish( ctx );
+
+ _GLD_DX9_VB(Unlock(gldPB->pVB));
+
+ _GLD_DX9_DEV(SetStreamSource(gld->pDev, 0, gldPB->pVB, 0, gldPB->dwStride));
+
+ if (gldPB->nPoints) {
+ _GLD_DX9_DEV(DrawPrimitive(gld->pDev, D3DPT_POINTLIST, 0, gldPB->nPoints));
+ gldPB->nPoints = 0;
+ }
+
+ if (gldPB->nLines) {
+ _GLD_DX9_DEV(DrawPrimitive(gld->pDev, D3DPT_LINELIST, gldPB->iFirstLine, gldPB->nLines));
+ gldPB->nLines = 0;
+ }
+
+ if (gldPB->nTriangles) {
+ _GLD_DX9_DEV(DrawPrimitive(gld->pDev, D3DPT_TRIANGLELIST, gldPB->iFirstTriangle, gldPB->nTriangles));
+ gldPB->nTriangles = 0;
+ }
+
+ return GL_FALSE; /* finished the pipe */
+}
+
+
+/**********************************************************************/
+/* Render pipeline stage */
+/**********************************************************************/
+
+
+
+
+const struct tnl_pipeline_stage _gld_mesa_render_stage =
+{
+ "gld_mesa_render_stage",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ _gld_mesa_render_stage_run /* run */
+};
+
+//---------------------------------------------------------------------------
diff --git a/mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_wgl_dx9.c b/mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_wgl_dx9.c
new file mode 100644
index 000000000..45324128a
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_wgl_dx9.c
@@ -0,0 +1,1346 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: GLDirect Direct3D 8.x WGL (WindowsGL)
+*
+****************************************************************************/
+
+#include "dglcontext.h"
+#include "gld_driver.h"
+#include "gld_dxerr9.h"
+#include "gld_dx9.h"
+
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+
+// Copied from dglcontect.c
+#define GLDERR_NONE 0
+#define GLDERR_MEM 1
+#define GLDERR_DDRAW 2
+#define GLDERR_D3D 3
+#define GLDERR_BPP 4
+#define GLDERR_DDS 5
+// This external var keeps track of any error
+extern int nContextError;
+
+#define DDLOG_CRITICAL_OR_WARN DDLOG_CRITICAL
+
+extern void _gld_mesa_warning(struct gl_context *, char *);
+extern void _gld_mesa_fatal(struct gl_context *, char *);
+
+//---------------------------------------------------------------------------
+
+static char szColorDepthWarning[] =
+"GLDirect does not support the current desktop\n\
+color depth.\n\n\
+You may need to change the display resolution to\n\
+16 bits per pixel or higher color depth using\n\
+the Windows Display Settings control panel\n\
+before running this OpenGL application.\n";
+
+// The only depth-stencil formats currently supported by Direct3D
+// Surface Format Depth Stencil Total Bits
+// D3DFMT_D32 32 - 32
+// D3DFMT_D15S1 15 1 16
+// D3DFMT_D24S8 24 8 32
+// D3DFMT_D16 16 - 16
+// D3DFMT_D24X8 24 - 32
+// D3DFMT_D24X4S4 24 4 32
+
+// This pixel format will be used as a template when compiling the list
+// of pixel formats supported by the hardware. Many fields will be
+// filled in at runtime.
+// PFD flag defaults are upgraded to match ChoosePixelFormat() -- DaveM
+static DGL_pixelFormat pfTemplateHW =
+{
+ {
+ sizeof(PIXELFORMATDESCRIPTOR), // Size of the data structure
+ 1, // Structure version - should be 1
+ // Flags:
+ PFD_DRAW_TO_WINDOW | // The buffer can draw to a window or device surface.
+ PFD_DRAW_TO_BITMAP | // The buffer can draw to a bitmap. (DaveM)
+ PFD_SUPPORT_GDI | // The buffer supports GDI drawing. (DaveM)
+ PFD_SUPPORT_OPENGL | // The buffer supports OpenGL drawing.
+ PFD_DOUBLEBUFFER | // The buffer is double-buffered.
+ 0, // Placeholder for easy commenting of above flags
+ PFD_TYPE_RGBA, // Pixel type RGBA.
+ 16, // Total colour bitplanes (excluding alpha bitplanes)
+ 5, 0, // Red bits, shift
+ 5, 0, // Green bits, shift
+ 5, 0, // Blue bits, shift
+ 0, 0, // Alpha bits, shift (destination alpha)
+ 0, // Accumulator bits (total)
+ 0, 0, 0, 0, // Accumulator bits: Red, Green, Blue, Alpha
+ 0, // Depth bits
+ 0, // Stencil bits
+ 0, // Number of auxiliary buffers
+ 0, // Layer type
+ 0, // Specifies the number of overlay and underlay planes.
+ 0, // Layer mask
+ 0, // Specifies the transparent color or index of an underlay plane.
+ 0 // Damage mask
+ },
+ D3DFMT_UNKNOWN, // No depth/stencil buffer
+};
+
+//---------------------------------------------------------------------------
+// Vertex Shaders
+//---------------------------------------------------------------------------
+/*
+// Vertex Shader Declaration
+static DWORD dwTwoSidedLightingDecl[] =
+{
+ D3DVSD_STREAM(0),
+ D3DVSD_REG(0, D3DVSDT_FLOAT3), // XYZ position
+ D3DVSD_REG(1, D3DVSDT_FLOAT3), // XYZ normal
+ D3DVSD_REG(2, D3DVSDT_D3DCOLOR), // Diffuse color
+ D3DVSD_REG(3, D3DVSDT_D3DCOLOR), // Specular color
+ D3DVSD_REG(4, D3DVSDT_FLOAT2), // 2D texture unit 0
+ D3DVSD_REG(5, D3DVSDT_FLOAT2), // 2D texture unit 1
+ D3DVSD_END()
+};
+
+// Vertex Shader for two-sided lighting
+static char *szTwoSidedLightingVS =
+// This is a test shader!
+"vs.1.0\n"
+"m4x4 oPos,v0,c0\n"
+"mov oD0,v2\n"
+"mov oD1,v3\n"
+"mov oT0,v4\n"
+"mov oT1,v5\n"
+;
+*/
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+
+typedef struct {
+ HINSTANCE hD3D9DLL; // Handle to d3d9.dll
+ FNDIRECT3DCREATE9 fnDirect3DCreate9; // Direct3DCreate9 function prototype
+ BOOL bDirect3D; // Persistant Direct3D9 exists
+ BOOL bDirect3DDevice; // Persistant Direct3DDevice9 exists
+ IDirect3D9 *pD3D; // Persistant Direct3D9
+ IDirect3DDevice9 *pDev; // Persistant Direct3DDevice9
+} GLD_dx9_globals;
+
+// These are "global" to all DX9 contexts. KeithH
+static GLD_dx9_globals dx9Globals;
+
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+
+BOOL gldGetDXErrorString_DX(
+ HRESULT hr,
+ char *buf,
+ int nBufSize)
+{
+ //
+ // Return a string describing the input HRESULT error code
+ //
+
+ const char *pStr = DXGetErrorString9(hr);
+
+ if (pStr == NULL)
+ return FALSE;
+
+ if (strlen(pStr) > nBufSize)
+ strncpy(buf, pStr, nBufSize);
+ else
+ strcpy(buf, pStr);
+
+// D3DXGetErrorString(hr, buf, nBufSize);
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+static D3DMULTISAMPLE_TYPE _gldGetDeviceMultiSampleType(
+ IDirect3D9 *pD3D9,
+ D3DFORMAT SurfaceFormat,
+ D3DDEVTYPE d3dDevType,
+ BOOL Windowed)
+{
+ int i;
+ HRESULT hr;
+
+ if (glb.dwMultisample == GLDS_MULTISAMPLE_NONE)
+ return D3DMULTISAMPLE_NONE;
+
+ if (glb.dwMultisample == GLDS_MULTISAMPLE_FASTEST) {
+ // Find fastest multisample
+ for (i=2; i<17; i++) {
+ hr = IDirect3D9_CheckDeviceMultiSampleType(
+ pD3D9,
+ glb.dwAdapter,
+ d3dDevType,
+ SurfaceFormat,
+ Windowed,
+ (D3DMULTISAMPLE_TYPE)i,
+ NULL);
+ if (SUCCEEDED(hr)) {
+ return (D3DMULTISAMPLE_TYPE)i;
+ }
+ }
+ } else {
+ // Find nicest multisample
+ for (i=16; i>1; i--) {
+ hr = IDirect3D9_CheckDeviceMultiSampleType(
+ pD3D9,
+ glb.dwAdapter,
+ d3dDevType,
+ SurfaceFormat,
+ Windowed,
+ (D3DMULTISAMPLE_TYPE)i,
+ NULL);
+ if (SUCCEEDED(hr)) {
+ return (D3DMULTISAMPLE_TYPE)i;
+ }
+ }
+ }
+
+ // Nothing found - return default
+ return D3DMULTISAMPLE_NONE;
+}
+
+//---------------------------------------------------------------------------
+
+void _gldDestroyPrimitiveBuffer(
+ GLD_pb_dx9 *gldVB)
+{
+ SAFE_RELEASE(gldVB->pVB);
+
+ // Sanity check...
+ gldVB->nLines = gldVB->nPoints = gldVB->nTriangles = 0;
+}
+
+//---------------------------------------------------------------------------
+
+HRESULT _gldCreatePrimitiveBuffer(
+ struct gl_context *ctx,
+ GLD_driver_dx9 *lpCtx,
+ GLD_pb_dx9 *gldVB)
+{
+ HRESULT hResult;
+ char *szCreateVertexBufferFailed = "CreateVertexBuffer failed";
+ DWORD dwMaxVertices; // Max number of vertices in vertex buffer
+ DWORD dwVBSize; // Total size of vertex buffer
+
+ // If CVA (Compiled Vertex Array) is used by an OpenGL app, then we
+ // will need enough vertices to cater for Mesa::Const.MaxArrayLockSize.
+ // We'll use IMM_SIZE if it's larger (which it should not be).
+ dwMaxVertices = MAX_ARRAY_LOCK_SIZE;
+
+ // Now calculate how many vertices to allow for in total
+ // 1 per point, 2 per line, 6 per quad = 9
+ dwVBSize = dwMaxVertices * 9 * gldVB->dwStride;
+
+ hResult = IDirect3DDevice9_CreateVertexBuffer(
+ lpCtx->pDev,
+ dwVBSize,
+ gldVB->dwUsage,
+ gldVB->dwFVF,
+ gldVB->dwPool,
+ &gldVB->pVB,
+ NULL);
+ if (FAILED(hResult)) {
+ ddlogMessage(DDLOG_CRITICAL_OR_WARN, szCreateVertexBufferFailed);
+ return hResult;
+ }
+
+ gldVB->nLines = gldVB->nPoints = gldVB->nTriangles = 0;
+ gldVB->pPoints = gldVB->pLines = gldVB->pTriangles = NULL;
+ gldVB->iFirstLine = dwMaxVertices; // Index of first line in VB
+ gldVB->iFirstTriangle = dwMaxVertices*3; // Index of first triangle in VB
+
+ return S_OK;
+}
+
+//---------------------------------------------------------------------------
+// Function: _gldCreateVertexShaders
+// Create DX9 Vertex Shaders.
+//---------------------------------------------------------------------------
+/*
+void _gldCreateVertexShaders(
+ GLD_driver_dx9 *gld)
+{
+ DWORD dwFlags;
+ LPD3DXBUFFER pVSOpcodeBuffer; // Vertex Shader opcode buffer
+ HRESULT hr;
+
+#ifdef _DEBUG
+ dwFlags = D3DXASM_DEBUG;
+#else
+ dwFlags = 0; // D3DXASM_SKIPVALIDATION;
+#endif
+
+ ddlogMessage(DDLOG_INFO, "Creating shaders...\n");
+
+ // Init the shader handle
+ gld->VStwosidelight.hShader = 0;
+
+ if (gld->d3dCaps8.MaxStreams == 0) {
+ // Lame DX8 driver doesn't support streams
+ // Not fatal, as defaults will be used
+ ddlogMessage(DDLOG_WARN, "Driver doesn't support Vertex Shaders (MaxStreams==0)\n");
+ return;
+ }
+
+ // ** THIS DISABLES VERTEX SHADER SUPPORT **
+// return;
+ // ** THIS DISABLES VERTEX SHADER SUPPORT **
+
+ //
+ // Two-sided lighting
+ //
+
+#if 0
+ //
+ // DEBUGGING: Load shader from a text file
+ //
+ {
+ LPD3DXBUFFER pVSErrorBuffer; // Vertex Shader error buffer
+ hr = D3DXAssembleShaderFromFile(
+ "twoside.vsh",
+ dwFlags,
+ NULL, // No constants
+ &pVSOpcodeBuffer,
+ &pVSErrorBuffer);
+ if (pVSErrorBuffer && pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer))
+ ddlogMessage(DDLOG_INFO, pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer));
+ SAFE_RELEASE(pVSErrorBuffer);
+ }
+#else
+ {
+ LPD3DXBUFFER pVSErrorBuffer; // Vertex Shader error buffer
+ // Assemble ascii shader text into shader opcodes
+ hr = D3DXAssembleShader(
+ szTwoSidedLightingVS,
+ strlen(szTwoSidedLightingVS),
+ dwFlags,
+ NULL, // No constants
+ &pVSOpcodeBuffer,
+ &pVSErrorBuffer);
+ if (pVSErrorBuffer && pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer))
+ ddlogMessage(DDLOG_INFO, pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer));
+ SAFE_RELEASE(pVSErrorBuffer);
+ }
+#endif
+ if (FAILED(hr)) {
+ ddlogError(DDLOG_WARN, "AssembleShader failed", hr);
+ SAFE_RELEASE(pVSOpcodeBuffer);
+ return;
+ }
+
+// This is for debugging. Remove to enable vertex shaders in HW
+#define _GLD_FORCE_SW_VS 0
+
+ if (_GLD_FORCE_SW_VS) {
+ // _GLD_FORCE_SW_VS should be disabled for Final Release
+ ddlogMessage(DDLOG_SYSTEM, "[Forcing shaders in SW]\n");
+ }
+
+ // Try and create shader in hardware.
+ // NOTE: The D3D Ref device appears to succeed when trying to
+ // create the device in hardware, but later complains
+ // when trying to set it with SetVertexShader(). Go figure.
+ if (_GLD_FORCE_SW_VS || glb.dwDriver == GLDS_DRIVER_REF) {
+ // Don't try and create a hardware shader with the Ref device
+ hr = E_FAIL; // COM error/fail result
+ } else {
+ gld->VStwosidelight.bHardware = TRUE;
+ hr = IDirect3DDevice8_CreateVertexShader(
+ gld->pDev,
+ dwTwoSidedLightingDecl,
+ pVSOpcodeBuffer->lpVtbl->GetBufferPointer(pVSOpcodeBuffer),
+ &gld->VStwosidelight.hShader,
+ 0);
+ }
+ if (FAILED(hr)) {
+ ddlogMessage(DDLOG_INFO, "... HW failed, trying SW...\n");
+ // Failed. Try and create shader for software processing
+ hr = IDirect3DDevice8_CreateVertexShader(
+ gld->pDev,
+ dwTwoSidedLightingDecl,
+ pVSOpcodeBuffer->lpVtbl->GetBufferPointer(pVSOpcodeBuffer),
+ &gld->VStwosidelight.hShader,
+ D3DUSAGE_SOFTWAREPROCESSING);
+ if (FAILED(hr)) {
+ gld->VStwosidelight.hShader = 0; // Sanity check
+ ddlogError(DDLOG_WARN, "CreateVertexShader failed", hr);
+ return;
+ }
+ // Succeeded, but for software processing
+ gld->VStwosidelight.bHardware = FALSE;
+ }
+
+ SAFE_RELEASE(pVSOpcodeBuffer);
+
+ ddlogMessage(DDLOG_INFO, "... OK\n");
+}
+
+//---------------------------------------------------------------------------
+
+void _gldDestroyVertexShaders(
+ GLD_driver_dx9 *gld)
+{
+ if (gld->VStwosidelight.hShader) {
+ IDirect3DDevice8_DeleteVertexShader(gld->pDev, gld->VStwosidelight.hShader);
+ gld->VStwosidelight.hShader = 0;
+ }
+}
+*/
+//---------------------------------------------------------------------------
+
+BOOL gldCreateDrawable_DX(
+ DGL_ctx *ctx,
+// BOOL bDefaultDriver,
+ BOOL bDirectDrawPersistant,
+ BOOL bPersistantBuffers)
+{
+ //
+ // bDirectDrawPersistant: applies to IDirect3D9
+ // bPersistantBuffers: applies to IDirect3DDevice9
+ //
+
+ HRESULT hResult;
+ GLD_driver_dx9 *lpCtx = NULL;
+ D3DDEVTYPE d3dDevType;
+ D3DPRESENT_PARAMETERS d3dpp;
+ D3DDISPLAYMODE d3ddm;
+ DWORD dwBehaviourFlags;
+ D3DADAPTER_IDENTIFIER9 d3dIdent;
+
+ // Error if context is NULL.
+ if (ctx == NULL)
+ return FALSE;
+
+ if (ctx->glPriv) {
+ lpCtx = ctx->glPriv;
+ // Release any existing interfaces
+ SAFE_RELEASE(lpCtx->pDev);
+ SAFE_RELEASE(lpCtx->pD3D);
+ } else {
+ lpCtx = (GLD_driver_dx9*)malloc(sizeof(GLD_driver_dx9));
+ ZeroMemory(lpCtx, sizeof(lpCtx));
+ }
+
+ d3dDevType = (glb.dwDriver == GLDS_DRIVER_HAL) ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF;
+ // TODO: Check this
+// if (bDefaultDriver)
+// d3dDevType = D3DDEVTYPE_REF;
+
+ // Use persistant interface if needed
+ if (bDirectDrawPersistant && dx9Globals.bDirect3D) {
+ lpCtx->pD3D = dx9Globals.pD3D;
+ IDirect3D9_AddRef(lpCtx->pD3D);
+ goto SkipDirectDrawCreate;
+ }
+
+ // Create Direct3D9 object
+ lpCtx->pD3D = dx9Globals.fnDirect3DCreate9(D3D_SDK_VERSION);
+ if (lpCtx->pD3D == NULL) {
+ MessageBox(NULL, "Unable to initialize Direct3D9", "GLDirect", MB_OK);
+ ddlogMessage(DDLOG_CRITICAL_OR_WARN, "Unable to create Direct3D9 interface");
+ nContextError = GLDERR_D3D;
+ goto return_with_error;
+ }
+
+ // Cache Direct3D interface for subsequent GLRCs
+ if (bDirectDrawPersistant && !dx9Globals.bDirect3D) {
+ dx9Globals.pD3D = lpCtx->pD3D;
+ IDirect3D9_AddRef(dx9Globals.pD3D);
+ dx9Globals.bDirect3D = TRUE;
+ }
+SkipDirectDrawCreate:
+
+ // Get the display mode so we can make a compatible backbuffer
+ hResult = IDirect3D9_GetAdapterDisplayMode(lpCtx->pD3D, glb.dwAdapter, &d3ddm);
+ if (FAILED(hResult)) {
+ nContextError = GLDERR_D3D;
+ goto return_with_error;
+ }
+
+ // Get device caps
+ hResult = IDirect3D9_GetDeviceCaps(lpCtx->pD3D, glb.dwAdapter, d3dDevType, &lpCtx->d3dCaps9);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "IDirect3D9_GetDeviceCaps failed", hResult);
+ nContextError = GLDERR_D3D;
+ goto return_with_error;
+ }
+
+ // Check for hardware transform & lighting
+ lpCtx->bHasHWTnL = lpCtx->d3dCaps9.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ? TRUE : FALSE;
+
+/*
+ //
+ // GONE FOR DX9?
+ //
+ // If this flag is present then we can't default to Mesa
+ // SW rendering between BeginScene() and EndScene().
+ if (lpCtx->d3dCaps9.Caps2 & D3DCAPS2_NO2DDURING3DSCENE) {
+ ddlogMessage(DDLOG_WARN,
+ "Warning : No 2D allowed during 3D scene.\n");
+ }
+*/
+
+ //
+ // Create the Direct3D context
+ //
+
+ // Re-use original IDirect3DDevice if persistant buffers exist.
+ // Note that we test for persistant IDirect3D9 as well
+ // bDirectDrawPersistant == persistant IDirect3D9 (DirectDraw9 does not exist)
+ if (bDirectDrawPersistant && bPersistantBuffers && dx9Globals.pD3D && dx9Globals.pDev) {
+ lpCtx->pDev = dx9Globals.pDev;
+ IDirect3DDevice9_AddRef(dx9Globals.pDev);
+ goto skip_direct3ddevice_create;
+ }
+
+ // Clear the presentation parameters (sets all members to zero)
+ ZeroMemory(&d3dpp, sizeof(d3dpp));
+
+ // Recommended by MS; needed for MultiSample.
+ // Be careful if altering this for FullScreenBlit
+ d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
+
+ d3dpp.BackBufferFormat = d3ddm.Format;
+ d3dpp.BackBufferCount = 2; //1;
+ d3dpp.MultiSampleType = _gldGetDeviceMultiSampleType(lpCtx->pD3D, d3ddm.Format, d3dDevType, !ctx->bFullscreen);
+ d3dpp.AutoDepthStencilFormat = ctx->lpPF->dwDriverData;
+ d3dpp.EnableAutoDepthStencil = (d3dpp.AutoDepthStencilFormat == D3DFMT_UNKNOWN) ? FALSE : TRUE;
+
+ if (ctx->bFullscreen) {
+ ddlogWarnOption(FALSE); // Don't popup any messages in fullscreen
+ d3dpp.Windowed = FALSE;
+ d3dpp.BackBufferWidth = d3ddm.Width;
+ d3dpp.BackBufferHeight = d3ddm.Height;
+ d3dpp.hDeviceWindow = ctx->hWnd;
+ d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
+
+ // Support for vertical retrace synchronisation.
+ // Set default presentation interval in case caps bits are missing
+ d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+ if (glb.bWaitForRetrace) {
+ if (lpCtx->d3dCaps9.PresentationIntervals & D3DPRESENT_INTERVAL_ONE)
+ d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
+ } else {
+ if (lpCtx->d3dCaps9.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE)
+ d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
+ }
+ } else {
+ ddlogWarnOption(glb.bMessageBoxWarnings); // OK to popup messages
+ d3dpp.Windowed = TRUE;
+ d3dpp.BackBufferWidth = ctx->dwWidth;
+ d3dpp.BackBufferHeight = ctx->dwHeight;
+ d3dpp.hDeviceWindow = ctx->hWnd;
+ d3dpp.FullScreen_RefreshRateInHz = 0;
+ // PresentationInterval Windowed mode is optional now in DX9 (DaveM)
+ d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+ if (glb.bWaitForRetrace) {
+ d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
+ } else {
+ d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
+ }
+ }
+
+ // Decide if we can use hardware TnL
+ dwBehaviourFlags = (lpCtx->bHasHWTnL) ?
+ D3DCREATE_MIXED_VERTEXPROCESSING : D3DCREATE_SOFTWARE_VERTEXPROCESSING;
+ // Add flag to tell D3D to be thread-safe
+ if (glb.bMultiThreaded)
+ dwBehaviourFlags |= D3DCREATE_MULTITHREADED;
+ // Add flag to tell D3D to be FPU-safe
+ if (!glb.bFastFPU)
+ dwBehaviourFlags |= D3DCREATE_FPU_PRESERVE;
+ hResult = IDirect3D9_CreateDevice(lpCtx->pD3D,
+ glb.dwAdapter,
+ d3dDevType,
+ ctx->hWnd,
+ dwBehaviourFlags,
+ &d3dpp,
+ &lpCtx->pDev);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "IDirect3D9_CreateDevice failed", hResult);
+ nContextError = GLDERR_D3D;
+ goto return_with_error;
+ }
+
+ if (bDirectDrawPersistant && bPersistantBuffers && dx9Globals.pD3D) {
+ dx9Globals.pDev = lpCtx->pDev;
+ dx9Globals.bDirect3DDevice = TRUE;
+ }
+
+ // Dump some useful stats
+ hResult = IDirect3D9_GetAdapterIdentifier(
+ lpCtx->pD3D,
+ glb.dwAdapter,
+ 0, // No WHQL detection (avoid few seconds delay)
+ &d3dIdent);
+ if (SUCCEEDED(hResult)) {
+ ddlogPrintf(DDLOG_INFO, "[Driver Description: %s]", &d3dIdent.Description);
+ ddlogPrintf(DDLOG_INFO, "[Driver file: %s %d.%d.%02d.%d]",
+ d3dIdent.Driver,
+ HIWORD(d3dIdent.DriverVersion.HighPart),
+ LOWORD(d3dIdent.DriverVersion.HighPart),
+ HIWORD(d3dIdent.DriverVersion.LowPart),
+ LOWORD(d3dIdent.DriverVersion.LowPart));
+ ddlogPrintf(DDLOG_INFO, "[VendorId: 0x%X, DeviceId: 0x%X, SubSysId: 0x%X, Revision: 0x%X]",
+ d3dIdent.VendorId, d3dIdent.DeviceId, d3dIdent.SubSysId, d3dIdent.Revision);
+ }
+
+ // Test to see if IHV driver exposes Scissor Test (new for DX9)
+ lpCtx->bCanScissor = lpCtx->d3dCaps9.RasterCaps & D3DPRASTERCAPS_SCISSORTEST;
+ ddlogPrintf(DDLOG_INFO, "Can Scissor: %s", lpCtx->bCanScissor ? "Yes" : "No");
+
+ // Init projection matrix for D3D TnL
+ D3DXMatrixIdentity(&lpCtx->matProjection);
+ lpCtx->matModelView = lpCtx->matProjection;
+// gld->bUseMesaProjection = TRUE;
+
+skip_direct3ddevice_create:
+
+ // Create buffers to hold primitives
+ lpCtx->PB2d.dwFVF = GLD_FVF_2D_VERTEX;
+ lpCtx->PB2d.dwPool = D3DPOOL_SYSTEMMEM;
+ lpCtx->PB2d.dwStride = sizeof(GLD_2D_VERTEX);
+ lpCtx->PB2d.dwUsage = D3DUSAGE_DONOTCLIP |
+ D3DUSAGE_DYNAMIC |
+ D3DUSAGE_SOFTWAREPROCESSING |
+ D3DUSAGE_WRITEONLY;
+ hResult = _gldCreatePrimitiveBuffer(ctx->glCtx, lpCtx, &lpCtx->PB2d);
+ if (FAILED(hResult))
+ goto return_with_error;
+
+ lpCtx->PB3d.dwFVF = GLD_FVF_3D_VERTEX;
+ lpCtx->PB3d.dwPool = D3DPOOL_DEFAULT;
+ lpCtx->PB3d.dwStride = sizeof(GLD_3D_VERTEX);
+ lpCtx->PB3d.dwUsage = D3DUSAGE_DYNAMIC |
+//DaveM D3DUSAGE_SOFTWAREPROCESSING |
+ D3DUSAGE_WRITEONLY;
+ hResult = _gldCreatePrimitiveBuffer(ctx->glCtx, lpCtx, &lpCtx->PB3d);
+ if (FAILED(hResult))
+ goto return_with_error;
+
+/* // NOTE: A FVF code of zero indicates a non-FVF vertex buffer (for vertex shaders)
+ lpCtx->PBtwosidelight.dwFVF = 0; //GLD_FVF_TWOSIDED_VERTEX;
+ lpCtx->PBtwosidelight.dwPool = D3DPOOL_DEFAULT;
+ lpCtx->PBtwosidelight.dwStride = sizeof(GLD_TWOSIDED_VERTEX);
+ lpCtx->PBtwosidelight.dwUsage = D3DUSAGE_DONOTCLIP |
+ D3DUSAGE_DYNAMIC |
+ D3DUSAGE_SOFTWAREPROCESSING |
+ D3DUSAGE_WRITEONLY;
+ hResult = _gldCreatePrimitiveBuffer(ctx->glCtx, lpCtx, &lpCtx->PBtwosidelight);
+ if (FAILED(hResult))
+ goto return_with_error;*/
+
+ // Now try and create the DX9 Vertex Shaders
+// _gldCreateVertexShaders(lpCtx);
+
+ // Zero the pipeline usage counters
+ lpCtx->PipelineUsage.qwMesa.QuadPart =
+// lpCtx->PipelineUsage.dwD3D2SVS.QuadPart =
+ lpCtx->PipelineUsage.qwD3DFVF.QuadPart = 0;
+
+ // Assign drawable to GL private
+ ctx->glPriv = lpCtx;
+ return TRUE;
+
+return_with_error:
+ // Clean up and bail
+
+// _gldDestroyVertexShaders(lpCtx);
+
+// _gldDestroyPrimitiveBuffer(&lpCtx->PBtwosidelight);
+ _gldDestroyPrimitiveBuffer(&lpCtx->PB3d);
+ _gldDestroyPrimitiveBuffer(&lpCtx->PB2d);
+
+ SAFE_RELEASE(lpCtx->pDev);
+ SAFE_RELEASE(lpCtx->pD3D);
+ return FALSE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldResizeDrawable_DX(
+ DGL_ctx *ctx,
+ BOOL bDefaultDriver,
+ BOOL bPersistantInterface,
+ BOOL bPersistantBuffers)
+{
+ GLD_driver_dx9 *gld = NULL;
+ D3DDEVTYPE d3dDevType;
+ D3DPRESENT_PARAMETERS d3dpp;
+ D3DDISPLAYMODE d3ddm;
+ HRESULT hResult;
+
+ // Error if context is NULL.
+ if (ctx == NULL)
+ return FALSE;
+
+ gld = ctx->glPriv;
+ if (gld == NULL)
+ return FALSE;
+
+ if (ctx->bSceneStarted) {
+ IDirect3DDevice9_EndScene(gld->pDev);
+ ctx->bSceneStarted = FALSE;
+ }
+
+ d3dDevType = (glb.dwDriver == GLDS_DRIVER_HAL) ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF;
+ if (!bDefaultDriver)
+ d3dDevType = D3DDEVTYPE_REF; // Force Direct3D Reference Rasterise (software)
+
+ // Get the display mode so we can make a compatible backbuffer
+ hResult = IDirect3D9_GetAdapterDisplayMode(gld->pD3D, glb.dwAdapter, &d3ddm);
+ if (FAILED(hResult)) {
+ nContextError = GLDERR_D3D;
+// goto return_with_error;
+ return FALSE;
+ }
+
+ // Destroy DX9 Vertex Shaders before Reset()
+// _gldDestroyVertexShaders(gld);
+
+ // Release POOL_DEFAULT objects before Reset()
+ if (gld->PB2d.dwPool == D3DPOOL_DEFAULT)
+ _gldDestroyPrimitiveBuffer(&gld->PB2d);
+ if (gld->PB3d.dwPool == D3DPOOL_DEFAULT)
+ _gldDestroyPrimitiveBuffer(&gld->PB3d);
+// if (gld->PBtwosidelight.dwPool == D3DPOOL_DEFAULT)
+// _gldDestroyPrimitiveBuffer(&gld->PBtwosidelight);
+
+ // Clear the presentation parameters (sets all members to zero)
+ ZeroMemory(&d3dpp, sizeof(d3dpp));
+
+ // Recommended by MS; needed for MultiSample.
+ // Be careful if altering this for FullScreenBlit
+ d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
+
+ d3dpp.BackBufferFormat = d3ddm.Format;
+ d3dpp.BackBufferCount = 1;
+ d3dpp.MultiSampleType = _gldGetDeviceMultiSampleType(gld->pD3D, d3ddm.Format, d3dDevType, !ctx->bFullscreen);
+ d3dpp.AutoDepthStencilFormat = ctx->lpPF->dwDriverData;
+ d3dpp.EnableAutoDepthStencil = (d3dpp.AutoDepthStencilFormat == D3DFMT_UNKNOWN) ? FALSE : TRUE;
+
+ // TODO: Sync to refresh
+
+ if (ctx->bFullscreen) {
+ ddlogWarnOption(FALSE); // Don't popup any messages in fullscreen
+ d3dpp.Windowed = FALSE;
+ d3dpp.BackBufferWidth = d3ddm.Width;
+ d3dpp.BackBufferHeight = d3ddm.Height;
+ d3dpp.hDeviceWindow = ctx->hWnd;
+ d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
+ d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+ // Get better benchmark results? KeithH
+// d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_UNLIMITED;
+ } else {
+ ddlogWarnOption(glb.bMessageBoxWarnings); // OK to popup messages
+ d3dpp.Windowed = TRUE;
+ d3dpp.BackBufferWidth = ctx->dwWidth;
+ d3dpp.BackBufferHeight = ctx->dwHeight;
+ d3dpp.hDeviceWindow = ctx->hWnd;
+ d3dpp.FullScreen_RefreshRateInHz = 0;
+ d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+ }
+ hResult = IDirect3DDevice9_Reset(gld->pDev, &d3dpp);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Reset failed", hResult);
+ return FALSE;
+ //goto cleanup_and_return_with_error;
+ }
+
+ //
+ // Recreate POOL_DEFAULT objects
+ //
+ if (gld->PB2d.dwPool == D3DPOOL_DEFAULT) {
+ _gldCreatePrimitiveBuffer(ctx->glCtx, gld, &gld->PB2d);
+ }
+ if (gld->PB3d.dwPool == D3DPOOL_DEFAULT) {
+ _gldCreatePrimitiveBuffer(ctx->glCtx, gld, &gld->PB3d);
+ }
+// if (gld->PBtwosidelight.dwPool == D3DPOOL_DEFAULT) {
+// _gldCreatePrimitiveBuffer(ctx->glCtx, gld, &gld->PB2d);
+// }
+
+ // Recreate DX9 Vertex Shaders
+// _gldCreateVertexShaders(gld);
+
+ // Signal a complete state update
+ ctx->glCtx->Driver.UpdateState(ctx->glCtx, _NEW_ALL);
+
+ // Begin a new scene
+ IDirect3DDevice9_BeginScene(gld->pDev);
+ ctx->bSceneStarted = TRUE;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldDestroyDrawable_DX(
+ DGL_ctx *ctx)
+{
+ GLD_driver_dx9 *lpCtx = NULL;
+
+ // Error if context is NULL.
+ if (!ctx)
+ return FALSE;
+
+ // Error if the drawable does not exist.
+ if (!ctx->glPriv)
+ return FALSE;
+
+ lpCtx = ctx->glPriv;
+
+#ifdef _DEBUG
+ // Dump out stats
+ ddlogPrintf(DDLOG_SYSTEM, "Usage: M:0x%X%X, D:0x%X%X",
+ lpCtx->PipelineUsage.qwMesa.HighPart,
+ lpCtx->PipelineUsage.qwMesa.LowPart,
+ lpCtx->PipelineUsage.qwD3DFVF.HighPart,
+ lpCtx->PipelineUsage.qwD3DFVF.LowPart);
+#endif
+
+// _gldDestroyVertexShaders(lpCtx);
+
+// _gldDestroyPrimitiveBuffer(&lpCtx->PBtwosidelight);
+ _gldDestroyPrimitiveBuffer(&lpCtx->PB3d);
+ _gldDestroyPrimitiveBuffer(&lpCtx->PB2d);
+
+ SAFE_RELEASE(lpCtx->pDev);
+ SAFE_RELEASE(lpCtx->pD3D);
+
+ // Free the private drawable data
+ free(ctx->glPriv);
+ ctx->glPriv = NULL;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldCreatePrivateGlobals_DX(void)
+{
+ ZeroMemory(&dx9Globals, sizeof(dx9Globals));
+
+ // Load d3d9.dll
+ dx9Globals.hD3D9DLL = LoadLibrary("D3D9.DLL");
+ if (dx9Globals.hD3D9DLL == NULL)
+ return FALSE;
+
+ // Now try and obtain Direct3DCreate9
+ dx9Globals.fnDirect3DCreate9 = (FNDIRECT3DCREATE9)GetProcAddress(dx9Globals.hD3D9DLL, "Direct3DCreate9");
+ if (dx9Globals.fnDirect3DCreate9 == NULL) {
+ FreeLibrary(dx9Globals.hD3D9DLL);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldDestroyPrivateGlobals_DX(void)
+{
+ if (dx9Globals.bDirect3DDevice) {
+ SAFE_RELEASE(dx9Globals.pDev);
+ dx9Globals.bDirect3DDevice = FALSE;
+ }
+ if (dx9Globals.bDirect3D) {
+ SAFE_RELEASE(dx9Globals.pD3D);
+ dx9Globals.bDirect3D = FALSE;
+ }
+
+ FreeLibrary(dx9Globals.hD3D9DLL);
+ dx9Globals.hD3D9DLL = NULL;
+ dx9Globals.fnDirect3DCreate9 = NULL;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+static void _BitsFromDisplayFormat(
+ D3DFORMAT fmt,
+ BYTE *cColorBits,
+ BYTE *cRedBits,
+ BYTE *cGreenBits,
+ BYTE *cBlueBits,
+ BYTE *cAlphaBits)
+{
+ switch (fmt) {
+ case D3DFMT_X1R5G5B5:
+ *cColorBits = 16;
+ *cRedBits = 5;
+ *cGreenBits = 5;
+ *cBlueBits = 5;
+ *cAlphaBits = 0;
+ return;
+ case D3DFMT_R5G6B5:
+ *cColorBits = 16;
+ *cRedBits = 5;
+ *cGreenBits = 6;
+ *cBlueBits = 5;
+ *cAlphaBits = 0;
+ return;
+ case D3DFMT_X8R8G8B8:
+ *cColorBits = 32;
+ *cRedBits = 8;
+ *cGreenBits = 8;
+ *cBlueBits = 8;
+ *cAlphaBits = 0;
+ return;
+ case D3DFMT_A8R8G8B8:
+ *cColorBits = 32;
+ *cRedBits = 8;
+ *cGreenBits = 8;
+ *cBlueBits = 8;
+ *cAlphaBits = 8;
+ return;
+ }
+
+ // Should not get here!
+ *cColorBits = 32;
+ *cRedBits = 8;
+ *cGreenBits = 8;
+ *cBlueBits = 8;
+ *cAlphaBits = 0;
+}
+
+//---------------------------------------------------------------------------
+
+static void _BitsFromDepthStencilFormat(
+ D3DFORMAT fmt,
+ BYTE *cDepthBits,
+ BYTE *cStencilBits)
+{
+ // NOTE: GL expects either 32 or 16 as depth bits.
+ switch (fmt) {
+ case D3DFMT_D32:
+ *cDepthBits = 32;
+ *cStencilBits = 0;
+ return;
+ case D3DFMT_D15S1:
+ *cDepthBits = 16;
+ *cStencilBits = 1;
+ return;
+ case D3DFMT_D24S8:
+ *cDepthBits = 32;
+ *cStencilBits = 8;
+ return;
+ case D3DFMT_D16:
+ *cDepthBits = 16;
+ *cStencilBits = 0;
+ return;
+ case D3DFMT_D24X8:
+ *cDepthBits = 32;
+ *cStencilBits = 0;
+ return;
+ case D3DFMT_D24X4S4:
+ *cDepthBits = 32;
+ *cStencilBits = 4;
+ return;
+ }
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldBuildPixelformatList_DX(void)
+{
+ D3DDISPLAYMODE d3ddm;
+ D3DFORMAT fmt[6];
+ IDirect3D9 *pD3D = NULL;
+ HRESULT hr;
+ int nSupportedFormats = 0;
+ int i;
+ DGL_pixelFormat *pPF;
+ BYTE cColorBits, cRedBits, cGreenBits, cBlueBits, cAlphaBits;
+// char buf[128];
+// char cat[8];
+
+ // Direct3D (SW or HW)
+ // These are arranged so that 'best' pixelformat
+ // is higher in the list (for ChoosePixelFormat).
+ const D3DFORMAT DepthStencil[6] = {
+// New order: increaing Z, then increasing stencil
+ D3DFMT_D15S1,
+ D3DFMT_D16,
+ D3DFMT_D24X4S4,
+ D3DFMT_D24X8,
+ D3DFMT_D24S8,
+ D3DFMT_D32,
+ };
+
+ // Dump DX version
+ ddlogMessage(GLDLOG_SYSTEM, "DirectX Version : 9.0\n");
+
+ // Release any existing pixelformat list
+ if (glb.lpPF) {
+ free(glb.lpPF);
+ }
+
+ glb.nPixelFormatCount = 0;
+ glb.lpPF = NULL;
+
+ //
+ // Pixelformats for Direct3D (SW or HW) rendering
+ //
+
+ // Get a Direct3D 9.0 interface
+ pD3D = dx9Globals.fnDirect3DCreate9(D3D_SDK_VERSION);
+ if (!pD3D) {
+ return FALSE;
+ }
+
+ // We will use the display mode format when finding compliant
+ // rendertarget/depth-stencil surfaces.
+ hr = IDirect3D9_GetAdapterDisplayMode(pD3D, glb.dwAdapter, &d3ddm);
+ if (FAILED(hr)) {
+ IDirect3D9_Release(pD3D);
+ return FALSE;
+ }
+
+ // Run through the possible formats and detect supported formats
+ for (i=0; i<6; i++) {
+ hr = IDirect3D9_CheckDeviceFormat(
+ pD3D,
+ glb.dwAdapter,
+ glb.dwDriver==GLDS_DRIVER_HAL ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF,
+ d3ddm.Format,
+ D3DUSAGE_DEPTHSTENCIL,
+ D3DRTYPE_SURFACE,
+ DepthStencil[i]);
+ if (FAILED(hr))
+ // A failure here is not fatal.
+ continue;
+
+ // Verify that the depth format is compatible.
+ hr = IDirect3D9_CheckDepthStencilMatch(
+ pD3D,
+ glb.dwAdapter,
+ glb.dwDriver==GLDS_DRIVER_HAL ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF,
+ d3ddm.Format,
+ d3ddm.Format,
+ DepthStencil[i]);
+ if (FAILED(hr))
+ // A failure here is not fatal, just means depth-stencil
+ // format is not compatible with this display mode.
+ continue;
+
+ fmt[nSupportedFormats++] = DepthStencil[i];
+ }
+
+ IDirect3D9_Release(pD3D);
+
+ if (nSupportedFormats == 0)
+ return FALSE; // Bail: no compliant pixelformats
+
+ // Total count of pixelformats is:
+ // (nSupportedFormats+1)*2
+ // UPDATED: nSupportedFormats*2
+ glb.lpPF = (DGL_pixelFormat *)calloc(nSupportedFormats*2, sizeof(DGL_pixelFormat));
+ glb.nPixelFormatCount = nSupportedFormats*2;
+ if (glb.lpPF == NULL) {
+ glb.nPixelFormatCount = 0;
+ return FALSE;
+ }
+
+ // Get a copy of pointer that we can alter
+ pPF = glb.lpPF;
+
+ // Cache colour bits from display format
+ _BitsFromDisplayFormat(d3ddm.Format, &cColorBits, &cRedBits, &cGreenBits, &cBlueBits, &cAlphaBits);
+
+ //
+ // Add single-buffer formats
+ //
+/*
+ // NOTE: No longer returning pixelformats that don't contain depth
+ // Single-buffer, no depth-stencil buffer
+ memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat));
+ pPF->pfd.dwFlags &= ~PFD_DOUBLEBUFFER; // Remove doublebuffer flag
+ pPF->pfd.cColorBits = cColorBits;
+ pPF->pfd.cRedBits = cRedBits;
+ pPF->pfd.cGreenBits = cGreenBits;
+ pPF->pfd.cBlueBits = cBlueBits;
+ pPF->pfd.cAlphaBits = cAlphaBits;
+ pPF->pfd.cDepthBits = 0;
+ pPF->pfd.cStencilBits = 0;
+ pPF->dwDriverData = D3DFMT_UNKNOWN;
+ pPF++;
+*/
+ for (i=0; i<nSupportedFormats; i++, pPF++) {
+ memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat));
+ pPF->pfd.dwFlags &= ~PFD_DOUBLEBUFFER; // Remove doublebuffer flag
+ pPF->pfd.cColorBits = cColorBits;
+ pPF->pfd.cRedBits = cRedBits;
+ pPF->pfd.cGreenBits = cGreenBits;
+ pPF->pfd.cBlueBits = cBlueBits;
+ pPF->pfd.cAlphaBits = cAlphaBits;
+ _BitsFromDepthStencilFormat(fmt[i], &pPF->pfd.cDepthBits, &pPF->pfd.cStencilBits);
+ pPF->dwDriverData = fmt[i];
+ }
+
+ //
+ // Add double-buffer formats
+ //
+
+ // NOTE: No longer returning pixelformats that don't contain depth
+/*
+ memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat));
+ pPF->pfd.cColorBits = cColorBits;
+ pPF->pfd.cRedBits = cRedBits;
+ pPF->pfd.cGreenBits = cGreenBits;
+ pPF->pfd.cBlueBits = cBlueBits;
+ pPF->pfd.cAlphaBits = cAlphaBits;
+ pPF->pfd.cDepthBits = 0;
+ pPF->pfd.cStencilBits = 0;
+ pPF->dwDriverData = D3DFMT_UNKNOWN;
+ pPF++;
+*/
+ for (i=0; i<nSupportedFormats; i++, pPF++) {
+ memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat));
+ pPF->pfd.cColorBits = cColorBits;
+ pPF->pfd.cRedBits = cRedBits;
+ pPF->pfd.cGreenBits = cGreenBits;
+ pPF->pfd.cBlueBits = cBlueBits;
+ pPF->pfd.cAlphaBits = cAlphaBits;
+ _BitsFromDepthStencilFormat(fmt[i], &pPF->pfd.cDepthBits, &pPF->pfd.cStencilBits);
+ pPF->dwDriverData = fmt[i];
+ }
+
+ // Popup warning message if non RGB color mode
+ {
+ // This is a hack. KeithH
+ HDC hdcDesktop = GetDC(NULL);
+ DWORD dwDisplayBitDepth = GetDeviceCaps(hdcDesktop, BITSPIXEL);
+ ReleaseDC(0, hdcDesktop);
+ if (dwDisplayBitDepth <= 8) {
+ ddlogPrintf(DDLOG_WARN, "Current Color Depth %d bpp is not supported", dwDisplayBitDepth);
+ MessageBox(NULL, szColorDepthWarning, "GLDirect", MB_OK | MB_ICONWARNING);
+ }
+ }
+
+ // Mark list as 'current'
+ glb.bPixelformatsDirty = FALSE;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldInitialiseMesa_DX(
+ DGL_ctx *lpCtx)
+{
+ GLD_driver_dx9 *gld = NULL;
+ int MaxTextureSize, TextureLevels;
+ BOOL bSoftwareTnL;
+
+ if (lpCtx == NULL)
+ return FALSE;
+
+ gld = lpCtx->glPriv;
+ if (gld == NULL)
+ return FALSE;
+
+ if (glb.bMultitexture) {
+ lpCtx->glCtx->Const.MaxTextureUnits = gld->d3dCaps9.MaxSimultaneousTextures;
+ // Only support MAX_TEXTURE_UNITS texture units.
+ // ** If this is altered then the FVF formats must be reviewed **.
+ if (lpCtx->glCtx->Const.MaxTextureUnits > GLD_MAX_TEXTURE_UNITS_DX9)
+ lpCtx->glCtx->Const.MaxTextureUnits = GLD_MAX_TEXTURE_UNITS_DX9;
+ } else {
+ // Multitexture override
+ lpCtx->glCtx->Const.MaxTextureUnits = 1;
+ }
+
+ // max texture size
+ MaxTextureSize = min(gld->d3dCaps9.MaxTextureHeight, gld->d3dCaps9.MaxTextureWidth);
+ if (MaxTextureSize == 0)
+ MaxTextureSize = 256; // Sanity check
+
+ //
+ // HACK!!
+ if (MaxTextureSize > 1024)
+ MaxTextureSize = 1024; // HACK - CLAMP TO 1024
+ // HACK!!
+ //
+
+ // Got to set MAX_TEXTURE_SIZE as max levels.
+ // Who thought this stupid idea up? ;)
+ TextureLevels = 0;
+ // Calculate power-of-two.
+ while (MaxTextureSize) {
+ TextureLevels++;
+ MaxTextureSize >>= 1;
+ }
+ lpCtx->glCtx->Const.MaxTextureLevels = (TextureLevels) ? TextureLevels : 8;
+ lpCtx->glCtx->Const.MaxDrawBuffers = 1;
+
+ IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_LIGHTING, FALSE);
+ IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_CULLMODE, D3DCULL_NONE);
+ IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_DITHERENABLE, TRUE);
+ IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
+
+ IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_ZENABLE,
+ (lpCtx->lpPF->dwDriverData!=D3DFMT_UNKNOWN) ? D3DZB_TRUE : D3DZB_FALSE);
+
+ // Set the view matrix
+ {
+ D3DXMATRIX vm;
+#if 1
+ D3DXMatrixIdentity(&vm);
+#else
+ D3DXVECTOR3 Eye(0.0f, 0.0f, 0.0f);
+ D3DXVECTOR3 At(0.0f, 0.0f, -1.0f);
+ D3DXVECTOR3 Up(0.0f, 1.0f, 0.0f);
+ D3DXMatrixLookAtRH(&vm, &Eye, &At, &Up);
+ vm._31 = -vm._31;
+ vm._32 = -vm._32;
+ vm._33 = -vm._33;
+ vm._34 = -vm._34;
+#endif
+ IDirect3DDevice9_SetTransform(gld->pDev, D3DTS_VIEW, &vm);
+ }
+
+ if (gld->bHasHWTnL) {
+ if (glb.dwTnL == GLDS_TNL_DEFAULT)
+ bSoftwareTnL = FALSE; // HW TnL
+ else {
+ bSoftwareTnL = ((glb.dwTnL == GLDS_TNL_MESA) || (glb.dwTnL == GLDS_TNL_D3DSW)) ? TRUE : FALSE;
+ }
+ } else {
+ // No HW TnL, so no choice possible
+ bSoftwareTnL = TRUE;
+ }
+// IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, bSoftwareTnL);
+ IDirect3DDevice9_SetSoftwareVertexProcessing(gld->pDev, bSoftwareTnL);
+
+// Dump this in a Release build as well, now.
+//#ifdef _DEBUG
+ ddlogPrintf(DDLOG_INFO, "HW TnL: %s",
+ gld->bHasHWTnL ? (bSoftwareTnL ? "Disabled" : "Enabled") : "Unavailable");
+//#endif
+
+ gldEnableExtensions_DX9(lpCtx->glCtx);
+ gldInstallPipeline_DX9(lpCtx->glCtx);
+ gldSetupDriverPointers_DX9(lpCtx->glCtx);
+
+ // Signal a complete state update
+ lpCtx->glCtx->Driver.UpdateState(lpCtx->glCtx, _NEW_ALL);
+
+ // Start a scene
+ IDirect3DDevice9_BeginScene(gld->pDev);
+ lpCtx->bSceneStarted = TRUE;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldSwapBuffers_DX(
+ DGL_ctx *ctx,
+ HDC hDC,
+ HWND hWnd)
+{
+ HRESULT hr;
+ GLD_driver_dx9 *gld = NULL;
+
+ if (ctx == NULL)
+ return FALSE;
+
+ gld = ctx->glPriv;
+ if (gld == NULL)
+ return FALSE;
+
+ if (ctx->bSceneStarted) {
+ IDirect3DDevice9_EndScene(gld->pDev);
+ ctx->bSceneStarted = FALSE;
+ }
+
+ // Swap the buffers. hWnd may override the hWnd used for CreateDevice()
+ hr = IDirect3DDevice9_Present(gld->pDev, NULL, NULL, hWnd, NULL);
+
+exit_swap:
+
+ IDirect3DDevice9_BeginScene(gld->pDev);
+ ctx->bSceneStarted = TRUE;
+
+// Debugging code
+#ifdef _DEBUG
+// ddlogMessage(GLDLOG_WARN, "SwapBuffers\n");
+#endif
+
+ return (FAILED(hr)) ? FALSE : TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldGetDisplayMode_DX(
+ DGL_ctx *ctx,
+ GLD_displayMode *glddm)
+{
+ D3DDISPLAYMODE d3ddm;
+ HRESULT hr;
+ GLD_driver_dx9 *lpCtx = NULL;
+ BYTE cColorBits, cRedBits, cGreenBits, cBlueBits, cAlphaBits;
+
+ if ((glddm == NULL) || (ctx == NULL))
+ return FALSE;
+
+ lpCtx = ctx->glPriv;
+ if (lpCtx == NULL)
+ return FALSE;
+
+ if (lpCtx->pD3D == NULL)
+ return FALSE;
+
+ hr = IDirect3D9_GetAdapterDisplayMode(lpCtx->pD3D, glb.dwAdapter, &d3ddm);
+ if (FAILED(hr))
+ return FALSE;
+
+ // Get info from the display format
+ _BitsFromDisplayFormat(d3ddm.Format,
+ &cColorBits, &cRedBits, &cGreenBits, &cBlueBits, &cAlphaBits);
+
+ glddm->Width = d3ddm.Width;
+ glddm->Height = d3ddm.Height;
+ glddm->BPP = cColorBits;
+ glddm->Refresh = d3ddm.RefreshRate;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
diff --git a/mesalib/src/mesa/drivers/windows/gldirect/gld_driver.c b/mesalib/src/mesa/drivers/windows/gldirect/gld_driver.c
index f7c575614..226dc5a5a 100644
--- a/mesalib/src/mesa/drivers/windows/gldirect/gld_driver.c
+++ b/mesalib/src/mesa/drivers/windows/gldirect/gld_driver.c
@@ -1,279 +1,279 @@
-/****************************************************************************
-*
-* Mesa 3-D graphics library
-* Direct3D Driver Interface
-*
-* ========================================================================
-*
-* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
-*
-* Permission is hereby granted, free of charge, to any person obtaining a
-* copy of this software and associated documentation files (the "Software"),
-* to deal in the Software without restriction, including without limitation
-* the rights to use, copy, modify, merge, publish, distribute, sublicense,
-* and/or sell copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included
-* in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
-* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-* SOFTWARE.
-*
-* ======================================================================
-*
-* Language: ANSI C
-* Environment: Windows 9x/2000/XP/XBox (Win32)
-*
-* Description: Driver functions and interfaces
-*
-****************************************************************************/
-
-#define STRICT
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-
-#include "gld_driver.h"
-#include "ddlog.h"
-#include "glheader.h"
-
-// For glGetString().
-#include "common_x86_asm.h"
-
-//---------------------------------------------------------------------------
-
-static char *szDriverError = "Driver used before initialisation!";
-
-// This holds our dynamically created OpenGL renderer string.
-// 256 chars should be plenty - remember that some apps display this.
-static char _gldRendererString[256];
-
-static char *szVendor = "SciTech Software, Inc.";
-
-//---------------------------------------------------------------------------
-
-extern BOOL gldGetDXErrorString_DX(HRESULT hr, char *buf, int nBufSize);
-
-extern BOOL gldCreateDrawable_MesaSW(DGL_ctx *ctx, BOOL bPersistantInterface, BOOL bPersistantBuffers);
-extern BOOL gldResizeDrawable_MesaSW(DGL_ctx *ctx, BOOL bDefaultDriver, BOOL bPersistantInterface, BOOL bPersistantBuffers);
-extern BOOL gldDestroyDrawable_MesaSW(DGL_ctx *ctx);
-extern BOOL gldCreatePrivateGlobals_MesaSW(void);
-extern BOOL gldDestroyPrivateGlobals_MesaSW(void);
-extern BOOL gldBuildPixelformatList_MesaSW(void);
-extern BOOL gldInitialiseMesa_MesaSW(DGL_ctx *ctx);
-extern BOOL gldSwapBuffers_MesaSW(DGL_ctx *ctx, HDC hDC, HWND hWnd);
-extern PROC gldGetProcAddress_MesaSW(LPCSTR a);
-extern BOOL gldGetDisplayMode_MesaSW(DGL_ctx *ctx, GLD_displayMode *glddm);
-
-extern BOOL gldCreateDrawable_DX(DGL_ctx *ctx, BOOL bPersistantInterface, BOOL bPersistantBuffers);
-extern BOOL gldResizeDrawable_DX(DGL_ctx *ctx, BOOL bDefaultDriver, BOOL bPersistantInterface, BOOL bPersistantBuffers);
-extern BOOL gldDestroyDrawable_DX(DGL_ctx *ctx);
-extern BOOL gldCreatePrivateGlobals_DX(void);
-extern BOOL gldDestroyPrivateGlobals_DX(void);
-extern BOOL gldBuildPixelformatList_DX(void);
-extern BOOL gldInitialiseMesa_DX(DGL_ctx *ctx);
-extern BOOL gldSwapBuffers_DX(DGL_ctx *ctx, HDC hDC, HWND hWnd);
-extern PROC gldGetProcAddress_DX(LPCSTR a);
-extern BOOL gldGetDisplayMode_DX(DGL_ctx *ctx, GLD_displayMode *glddm);
-
-//---------------------------------------------------------------------------
-// NOP functions. Called if proper driver functions are not set.
-//---------------------------------------------------------------------------
-
-static BOOL _gldDriverError(void)
-{
- ddlogMessage(DDLOG_CRITICAL, szDriverError);
- return FALSE;
-}
-
-//---------------------------------------------------------------------------
-
-static BOOL _GetDXErrorString_ERROR(
- HRESULT hr,
- char *buf,
- int nBufSize)
-{
- return _gldDriverError();
-}
-
-//---------------------------------------------------------------------------
-
-static BOOL _CreateDrawable_ERROR(
- DGL_ctx *ctx,
- BOOL bPersistantInterface,
- BOOL bPersistantBuffers)
-{
- return _gldDriverError();
-}
-
-//---------------------------------------------------------------------------
-
-static BOOL _ResizeDrawable_ERROR(
- DGL_ctx *ctx,
- BOOL bDefaultDriver,
- BOOL bPersistantInterface,
- BOOL bPersistantBuffers)
-{
- return _gldDriverError();
-}
-
-//---------------------------------------------------------------------------
-
-static BOOL _DestroyDrawable_ERROR(
- DGL_ctx *ctx)
-{
- return _gldDriverError();
-}
-
-//---------------------------------------------------------------------------
-
-static BOOL _CreatePrivateGlobals_ERROR(void)
-{
- return _gldDriverError();
-}
-
-//---------------------------------------------------------------------------
-
-static BOOL _DestroyPrivateGlobals_ERROR(void)
-{
- return _gldDriverError();
-}
-
-//---------------------------------------------------------------------------
-
-static BOOL _BuildPixelformatList_ERROR(void)
-{
- return _gldDriverError();
-}
-
-//---------------------------------------------------------------------------
-
-
-static BOOL _InitialiseMesa_ERROR(
- DGL_ctx *ctx)
-{
- return _gldDriverError();
-}
-
-//---------------------------------------------------------------------------
-
-static BOOL _SwapBuffers_ERROR(
- DGL_ctx *ctx,
- HDC hDC,
- HWND hWnd)
-{
- return _gldDriverError();
-}
-
-//---------------------------------------------------------------------------
-
-static PROC _GetProcAddress_ERROR(
- LPCSTR a)
-{
- _gldDriverError();
- return NULL;
-}
-
-//---------------------------------------------------------------------------
-
-static BOOL _GetDisplayMode_ERROR(
- DGL_ctx *ctx,
- GLD_displayMode *glddm)
-{
- return _gldDriverError();
-}
-
-//---------------------------------------------------------------------------
-// Functions useful to all drivers
-//---------------------------------------------------------------------------
-
-const GLubyte* _gldGetStringGeneric(
- GLcontext *ctx,
- GLenum name)
-{
- if (!ctx)
- return NULL;
-
- switch (name) {
- case GL_RENDERER:
- sprintf(_gldRendererString, "GLDirect 4.0 %s%s%s%s (%s %s)",
- _mesa_x86_cpu_features ? "/x86" : "",
- cpu_has_mmx ? "/MMX" : "",
- cpu_has_3dnow ? "/3DNow!" : "",
- cpu_has_xmm ? "/SSE" : "",
- __DATE__, __TIME__);
- return (const GLubyte *) _gldRendererString;
- case GL_VENDOR:
- return (const GLubyte *) szVendor;
- default:
- return NULL;
- }
-}
-
-//---------------------------------------------------------------------------
-// Global driver function pointers, initially set to functions that
-// will report an error when called.
-//---------------------------------------------------------------------------
-
-GLD_driver _gldDriver = {
- _GetDXErrorString_ERROR,
- _CreateDrawable_ERROR,
- _ResizeDrawable_ERROR,
- _DestroyDrawable_ERROR,
- _CreatePrivateGlobals_ERROR,
- _DestroyPrivateGlobals_ERROR,
- _BuildPixelformatList_ERROR,
- _InitialiseMesa_ERROR,
- _SwapBuffers_ERROR,
- _GetProcAddress_ERROR,
- _GetDisplayMode_ERROR
-};
-
-//---------------------------------------------------------------------------
-// Init function. Should be called as soon as regkeys/ini-settings are read.
-//---------------------------------------------------------------------------
-
-BOOL gldInitDriverPointers(
- DWORD dwDriver)
-{
- _gldDriver.GetDXErrorString = gldGetDXErrorString_DX;
-
- if (dwDriver == GLDS_DRIVER_MESA_SW) {
- // Mesa Software driver
- _gldDriver.CreateDrawable = gldCreateDrawable_MesaSW;
- _gldDriver.ResizeDrawable = gldResizeDrawable_MesaSW;
- _gldDriver.DestroyDrawable = gldDestroyDrawable_MesaSW;
- _gldDriver.CreatePrivateGlobals = gldCreatePrivateGlobals_MesaSW;
- _gldDriver.DestroyPrivateGlobals = gldDestroyPrivateGlobals_MesaSW;
- _gldDriver.BuildPixelformatList = gldBuildPixelformatList_MesaSW;
- _gldDriver.InitialiseMesa = gldInitialiseMesa_MesaSW;
- _gldDriver.SwapBuffers = gldSwapBuffers_MesaSW;
- _gldDriver.wglGetProcAddress = gldGetProcAddress_MesaSW;
- _gldDriver.GetDisplayMode = gldGetDisplayMode_MesaSW;
- return TRUE;
- }
-
- if ((dwDriver == GLDS_DRIVER_REF) || (dwDriver == GLDS_DRIVER_HAL)) {
- // Direct3D driver, either HW or SW
- _gldDriver.CreateDrawable = gldCreateDrawable_DX;
- _gldDriver.ResizeDrawable = gldResizeDrawable_DX;
- _gldDriver.DestroyDrawable = gldDestroyDrawable_DX;
- _gldDriver.CreatePrivateGlobals = gldCreatePrivateGlobals_DX;
- _gldDriver.DestroyPrivateGlobals = gldDestroyPrivateGlobals_DX;
- _gldDriver.BuildPixelformatList = gldBuildPixelformatList_DX;
- _gldDriver.InitialiseMesa = gldInitialiseMesa_DX;
- _gldDriver.SwapBuffers = gldSwapBuffers_DX;
- _gldDriver.wglGetProcAddress = gldGetProcAddress_DX;
- _gldDriver.GetDisplayMode = gldGetDisplayMode_DX;
- return TRUE;
- };
-
- return FALSE;
-}
-
-//---------------------------------------------------------------------------
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: Driver functions and interfaces
+*
+****************************************************************************/
+
+#define STRICT
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+#include "gld_driver.h"
+#include "ddlog.h"
+#include "glheader.h"
+
+// For glGetString().
+#include "common_x86_asm.h"
+
+//---------------------------------------------------------------------------
+
+static char *szDriverError = "Driver used before initialisation!";
+
+// This holds our dynamically created OpenGL renderer string.
+// 256 chars should be plenty - remember that some apps display this.
+static char _gldRendererString[256];
+
+static char *szVendor = "SciTech Software, Inc.";
+
+//---------------------------------------------------------------------------
+
+extern BOOL gldGetDXErrorString_DX(HRESULT hr, char *buf, int nBufSize);
+
+extern BOOL gldCreateDrawable_MesaSW(DGL_ctx *ctx, BOOL bPersistantInterface, BOOL bPersistantBuffers);
+extern BOOL gldResizeDrawable_MesaSW(DGL_ctx *ctx, BOOL bDefaultDriver, BOOL bPersistantInterface, BOOL bPersistantBuffers);
+extern BOOL gldDestroyDrawable_MesaSW(DGL_ctx *ctx);
+extern BOOL gldCreatePrivateGlobals_MesaSW(void);
+extern BOOL gldDestroyPrivateGlobals_MesaSW(void);
+extern BOOL gldBuildPixelformatList_MesaSW(void);
+extern BOOL gldInitialiseMesa_MesaSW(DGL_ctx *ctx);
+extern BOOL gldSwapBuffers_MesaSW(DGL_ctx *ctx, HDC hDC, HWND hWnd);
+extern PROC gldGetProcAddress_MesaSW(LPCSTR a);
+extern BOOL gldGetDisplayMode_MesaSW(DGL_ctx *ctx, GLD_displayMode *glddm);
+
+extern BOOL gldCreateDrawable_DX(DGL_ctx *ctx, BOOL bPersistantInterface, BOOL bPersistantBuffers);
+extern BOOL gldResizeDrawable_DX(DGL_ctx *ctx, BOOL bDefaultDriver, BOOL bPersistantInterface, BOOL bPersistantBuffers);
+extern BOOL gldDestroyDrawable_DX(DGL_ctx *ctx);
+extern BOOL gldCreatePrivateGlobals_DX(void);
+extern BOOL gldDestroyPrivateGlobals_DX(void);
+extern BOOL gldBuildPixelformatList_DX(void);
+extern BOOL gldInitialiseMesa_DX(DGL_ctx *ctx);
+extern BOOL gldSwapBuffers_DX(DGL_ctx *ctx, HDC hDC, HWND hWnd);
+extern PROC gldGetProcAddress_DX(LPCSTR a);
+extern BOOL gldGetDisplayMode_DX(DGL_ctx *ctx, GLD_displayMode *glddm);
+
+//---------------------------------------------------------------------------
+// NOP functions. Called if proper driver functions are not set.
+//---------------------------------------------------------------------------
+
+static BOOL _gldDriverError(void)
+{
+ ddlogMessage(DDLOG_CRITICAL, szDriverError);
+ return FALSE;
+}
+
+//---------------------------------------------------------------------------
+
+static BOOL _GetDXErrorString_ERROR(
+ HRESULT hr,
+ char *buf,
+ int nBufSize)
+{
+ return _gldDriverError();
+}
+
+//---------------------------------------------------------------------------
+
+static BOOL _CreateDrawable_ERROR(
+ DGL_ctx *ctx,
+ BOOL bPersistantInterface,
+ BOOL bPersistantBuffers)
+{
+ return _gldDriverError();
+}
+
+//---------------------------------------------------------------------------
+
+static BOOL _ResizeDrawable_ERROR(
+ DGL_ctx *ctx,
+ BOOL bDefaultDriver,
+ BOOL bPersistantInterface,
+ BOOL bPersistantBuffers)
+{
+ return _gldDriverError();
+}
+
+//---------------------------------------------------------------------------
+
+static BOOL _DestroyDrawable_ERROR(
+ DGL_ctx *ctx)
+{
+ return _gldDriverError();
+}
+
+//---------------------------------------------------------------------------
+
+static BOOL _CreatePrivateGlobals_ERROR(void)
+{
+ return _gldDriverError();
+}
+
+//---------------------------------------------------------------------------
+
+static BOOL _DestroyPrivateGlobals_ERROR(void)
+{
+ return _gldDriverError();
+}
+
+//---------------------------------------------------------------------------
+
+static BOOL _BuildPixelformatList_ERROR(void)
+{
+ return _gldDriverError();
+}
+
+//---------------------------------------------------------------------------
+
+
+static BOOL _InitialiseMesa_ERROR(
+ DGL_ctx *ctx)
+{
+ return _gldDriverError();
+}
+
+//---------------------------------------------------------------------------
+
+static BOOL _SwapBuffers_ERROR(
+ DGL_ctx *ctx,
+ HDC hDC,
+ HWND hWnd)
+{
+ return _gldDriverError();
+}
+
+//---------------------------------------------------------------------------
+
+static PROC _GetProcAddress_ERROR(
+ LPCSTR a)
+{
+ _gldDriverError();
+ return NULL;
+}
+
+//---------------------------------------------------------------------------
+
+static BOOL _GetDisplayMode_ERROR(
+ DGL_ctx *ctx,
+ GLD_displayMode *glddm)
+{
+ return _gldDriverError();
+}
+
+//---------------------------------------------------------------------------
+// Functions useful to all drivers
+//---------------------------------------------------------------------------
+
+const GLubyte* _gldGetStringGeneric(
+ struct gl_context *ctx,
+ GLenum name)
+{
+ if (!ctx)
+ return NULL;
+
+ switch (name) {
+ case GL_RENDERER:
+ sprintf(_gldRendererString, "GLDirect 4.0 %s%s%s%s (%s %s)",
+ _mesa_x86_cpu_features ? "/x86" : "",
+ cpu_has_mmx ? "/MMX" : "",
+ cpu_has_3dnow ? "/3DNow!" : "",
+ cpu_has_xmm ? "/SSE" : "",
+ __DATE__, __TIME__);
+ return (const GLubyte *) _gldRendererString;
+ case GL_VENDOR:
+ return (const GLubyte *) szVendor;
+ default:
+ return NULL;
+ }
+}
+
+//---------------------------------------------------------------------------
+// Global driver function pointers, initially set to functions that
+// will report an error when called.
+//---------------------------------------------------------------------------
+
+GLD_driver _gldDriver = {
+ _GetDXErrorString_ERROR,
+ _CreateDrawable_ERROR,
+ _ResizeDrawable_ERROR,
+ _DestroyDrawable_ERROR,
+ _CreatePrivateGlobals_ERROR,
+ _DestroyPrivateGlobals_ERROR,
+ _BuildPixelformatList_ERROR,
+ _InitialiseMesa_ERROR,
+ _SwapBuffers_ERROR,
+ _GetProcAddress_ERROR,
+ _GetDisplayMode_ERROR
+};
+
+//---------------------------------------------------------------------------
+// Init function. Should be called as soon as regkeys/ini-settings are read.
+//---------------------------------------------------------------------------
+
+BOOL gldInitDriverPointers(
+ DWORD dwDriver)
+{
+ _gldDriver.GetDXErrorString = gldGetDXErrorString_DX;
+
+ if (dwDriver == GLDS_DRIVER_MESA_SW) {
+ // Mesa Software driver
+ _gldDriver.CreateDrawable = gldCreateDrawable_MesaSW;
+ _gldDriver.ResizeDrawable = gldResizeDrawable_MesaSW;
+ _gldDriver.DestroyDrawable = gldDestroyDrawable_MesaSW;
+ _gldDriver.CreatePrivateGlobals = gldCreatePrivateGlobals_MesaSW;
+ _gldDriver.DestroyPrivateGlobals = gldDestroyPrivateGlobals_MesaSW;
+ _gldDriver.BuildPixelformatList = gldBuildPixelformatList_MesaSW;
+ _gldDriver.InitialiseMesa = gldInitialiseMesa_MesaSW;
+ _gldDriver.SwapBuffers = gldSwapBuffers_MesaSW;
+ _gldDriver.wglGetProcAddress = gldGetProcAddress_MesaSW;
+ _gldDriver.GetDisplayMode = gldGetDisplayMode_MesaSW;
+ return TRUE;
+ }
+
+ if ((dwDriver == GLDS_DRIVER_REF) || (dwDriver == GLDS_DRIVER_HAL)) {
+ // Direct3D driver, either HW or SW
+ _gldDriver.CreateDrawable = gldCreateDrawable_DX;
+ _gldDriver.ResizeDrawable = gldResizeDrawable_DX;
+ _gldDriver.DestroyDrawable = gldDestroyDrawable_DX;
+ _gldDriver.CreatePrivateGlobals = gldCreatePrivateGlobals_DX;
+ _gldDriver.DestroyPrivateGlobals = gldDestroyPrivateGlobals_DX;
+ _gldDriver.BuildPixelformatList = gldBuildPixelformatList_DX;
+ _gldDriver.InitialiseMesa = gldInitialiseMesa_DX;
+ _gldDriver.SwapBuffers = gldSwapBuffers_DX;
+ _gldDriver.wglGetProcAddress = gldGetProcAddress_DX;
+ _gldDriver.GetDisplayMode = gldGetDisplayMode_DX;
+ return TRUE;
+ };
+
+ return FALSE;
+}
+
+//---------------------------------------------------------------------------
diff --git a/mesalib/src/mesa/drivers/windows/gldirect/gld_driver.h b/mesalib/src/mesa/drivers/windows/gldirect/gld_driver.h
index 01a46a832..6067245b8 100644
--- a/mesalib/src/mesa/drivers/windows/gldirect/gld_driver.h
+++ b/mesalib/src/mesa/drivers/windows/gldirect/gld_driver.h
@@ -1,90 +1,90 @@
-/****************************************************************************
-*
-* Mesa 3-D graphics library
-* Direct3D Driver Interface
-*
-* ========================================================================
-*
-* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
-*
-* Permission is hereby granted, free of charge, to any person obtaining a
-* copy of this software and associated documentation files (the "Software"),
-* to deal in the Software without restriction, including without limitation
-* the rights to use, copy, modify, merge, publish, distribute, sublicense,
-* and/or sell copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included
-* in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
-* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-* SOFTWARE.
-*
-* ======================================================================
-*
-* Language: ANSI C
-* Environment: Windows 9x/2000/XP/XBox (Win32)
-*
-* Description: Driver functions and interfaces
-*
-****************************************************************************/
-
-#ifndef _GLD_DRIVER_H
-#define _GLD_DRIVER_H
-
-// This file is only useful is we're using the new GLD3 WGL code.
-#ifdef _USE_GLD3_WGL
-
-#include "dglcontext.h"
-
-// Same as DX8 D3DDISPLAYMODE
-typedef struct {
- DWORD Width;
- DWORD Height;
- DWORD Refresh;
- DWORD BPP;
-} GLD_displayMode;
-
-typedef struct {
- // Returns a string for a given HRESULT error code.
- BOOL (*GetDXErrorString)(HRESULT hr, char *buf, int nBufSize);
-
- // Driver functions for managing drawables.
- // Functions must respect persistant buffers / persistant interface.
- // NOTE: Persistant interface is: DirectDraw, pre-DX8; Direct3D, DX8 and above.
- BOOL (*CreateDrawable)(DGL_ctx *ctx, BOOL bPersistantInterface, BOOL bPersistantBuffers);
- BOOL (*ResizeDrawable)(DGL_ctx *ctx, BOOL bDefaultDriver, BOOL bPersistantInterface, BOOL bPersistantBuffers);
- BOOL (*DestroyDrawable)(DGL_ctx *ctx);
-
- // Create/Destroy private globals belonging to driver
- BOOL (*CreatePrivateGlobals)(void);
- BOOL (*DestroyPrivateGlobals)(void);
-
- // Build pixelformat list
- BOOL (*BuildPixelformatList)(void);
-
- // Initialise Mesa's driver pointers
- BOOL (*InitialiseMesa)(DGL_ctx *ctx);
-
- // Swap buffers
- BOOL (*SwapBuffers)(DGL_ctx *ctx, HDC hDC, HWND hWnd);
-
- // wglGetProcAddress()
- PROC (*wglGetProcAddress)(LPCSTR a);
-
- BOOL (*GetDisplayMode)(DGL_ctx *ctx, GLD_displayMode *glddm);
-} GLD_driver;
-
-extern GLD_driver _gldDriver;
-
-BOOL gldInitDriverPointers(DWORD dwDriver);
-const GLubyte* _gldGetStringGeneric(GLcontext *ctx, GLenum name);
-
-#endif // _USE_GLD3_WGL
-
-#endif // _GLD_DRIVER_H
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: Driver functions and interfaces
+*
+****************************************************************************/
+
+#ifndef _GLD_DRIVER_H
+#define _GLD_DRIVER_H
+
+// This file is only useful is we're using the new GLD3 WGL code.
+#ifdef _USE_GLD3_WGL
+
+#include "dglcontext.h"
+
+// Same as DX8 D3DDISPLAYMODE
+typedef struct {
+ DWORD Width;
+ DWORD Height;
+ DWORD Refresh;
+ DWORD BPP;
+} GLD_displayMode;
+
+typedef struct {
+ // Returns a string for a given HRESULT error code.
+ BOOL (*GetDXErrorString)(HRESULT hr, char *buf, int nBufSize);
+
+ // Driver functions for managing drawables.
+ // Functions must respect persistant buffers / persistant interface.
+ // NOTE: Persistant interface is: DirectDraw, pre-DX8; Direct3D, DX8 and above.
+ BOOL (*CreateDrawable)(DGL_ctx *ctx, BOOL bPersistantInterface, BOOL bPersistantBuffers);
+ BOOL (*ResizeDrawable)(DGL_ctx *ctx, BOOL bDefaultDriver, BOOL bPersistantInterface, BOOL bPersistantBuffers);
+ BOOL (*DestroyDrawable)(DGL_ctx *ctx);
+
+ // Create/Destroy private globals belonging to driver
+ BOOL (*CreatePrivateGlobals)(void);
+ BOOL (*DestroyPrivateGlobals)(void);
+
+ // Build pixelformat list
+ BOOL (*BuildPixelformatList)(void);
+
+ // Initialise Mesa's driver pointers
+ BOOL (*InitialiseMesa)(DGL_ctx *ctx);
+
+ // Swap buffers
+ BOOL (*SwapBuffers)(DGL_ctx *ctx, HDC hDC, HWND hWnd);
+
+ // wglGetProcAddress()
+ PROC (*wglGetProcAddress)(LPCSTR a);
+
+ BOOL (*GetDisplayMode)(DGL_ctx *ctx, GLD_displayMode *glddm);
+} GLD_driver;
+
+extern GLD_driver _gldDriver;
+
+BOOL gldInitDriverPointers(DWORD dwDriver);
+const GLubyte* _gldGetStringGeneric(struct gl_context *ctx, GLenum name);
+
+#endif // _USE_GLD3_WGL
+
+#endif // _GLD_DRIVER_H
diff --git a/mesalib/src/mesa/drivers/windows/gldirect/gldirect.rc b/mesalib/src/mesa/drivers/windows/gldirect/gldirect.rc
new file mode 100644
index 000000000..b0a22b281
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/gldirect/gldirect.rc
@@ -0,0 +1,43 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: Windows Resource Compiler
+* Environment: Windows 95
+*
+****************************************************************************/
+
+#ifndef WORKSHOP_INVOKED
+ #include <windows.h>
+#endif
+
+#define FILE_DESCRIPTION "SciTech GLDirect"
+#define ORIG_FILENAME "opengl32.dll"
+#define FILE_TYPE VFT_DLL
+
+#include "gldirect/gldver.ver"
diff --git a/mesalib/src/mesa/drivers/windows/gldirect/mesasw/colors.h b/mesalib/src/mesa/drivers/windows/gldirect/mesasw/colors.h
new file mode 100644
index 000000000..12b5003bf
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/gldirect/mesasw/colors.h
@@ -0,0 +1,520 @@
+/* File name : colors.h
+ * Version : 2.3
+ *
+ * Header file for display driver for Mesa 2.3 under
+ * Windows95 and WindowsNT
+ * This file defines macros and global variables needed
+ * for converting color format
+ *
+ * Copyright (C) 1996- Li Wei
+ * Address : Institute of Artificial Intelligence
+ * : & Robotics
+ * : Xi'an Jiaotong University
+ * Email : liwei@aiar.xjtu.edu.cn
+ * Web page : http://sun.aiar.xjtu.edu.cn
+ *
+ * This file and its associations are partially based on the
+ * Windows NT driver for Mesa, written by Mark Leaming
+ * (mark@rsinc.com).
+ */
+
+/*
+ * Macros for pixel format defined
+ */
+
+/*
+ * Revision 1.1 2004/04/20 11:13:11 alanh
+ * add SciTech's GLDirect driver for Windows.
+ *
+ * This code is donated to Mesa which allows the usage of
+ * a Direct3D layer (DX7, DX8, DX9 or complete software fallback).
+ *
+ * No build system exists for this code yet, that will come.....
+ *
+ * Revision 1.1.1.1 1999/08/19 00:55:42 jtg
+ * Imported sources
+ *
+ * Revision 1.2 1999/01/03 03:08:57 brianp
+ * Ted Jump's changes
+ *
+ * Revision 1.1 1999/01/03 03:08:12 brianp
+ * Initial revision
+ *
+ * Revision 2.0.2 1997/4/30 15:58:00 CST by Li Wei(liwei@aiar.xjtu.edu.cn)
+ * Add LUTs need for dithering
+ */
+
+/*
+ * Revision 1.1 2004/04/20 11:13:11 alanh
+ * add SciTech's GLDirect driver for Windows.
+ *
+ * This code is donated to Mesa which allows the usage of
+ * a Direct3D layer (DX7, DX8, DX9 or complete software fallback).
+ *
+ * No build system exists for this code yet, that will come.....
+ *
+ * Revision 1.1.1.1 1999/08/19 00:55:42 jtg
+ * Imported sources
+ *
+ * Revision 1.2 1999/01/03 03:08:57 brianp
+ * Ted Jump's changes
+ *
+ * Revision 1.1 1999/01/03 03:08:12 brianp
+ * Initial revision
+ *
+ * Revision 2.0.1 1997/4/29 15:52:00 CST by Li Wei(liwei@aiar.xjtu.edu.cn)
+ * Add BGR8 Macro
+ */
+
+/*
+ * Revision 1.1 2004/04/20 11:13:11 alanh
+ * add SciTech's GLDirect driver for Windows.
+ *
+ * This code is donated to Mesa which allows the usage of
+ * a Direct3D layer (DX7, DX8, DX9 or complete software fallback).
+ *
+ * No build system exists for this code yet, that will come.....
+ *
+ * Revision 1.1.1.1 1999/08/19 00:55:42 jtg
+ * Imported sources
+ *
+ * Revision 1.2 1999/01/03 03:08:57 brianp
+ * Ted Jump's changes
+ *
+ * Revision 1.1 1999/01/03 03:08:12 brianp
+ * Initial revision
+ *
+ * Revision 2.0 1996/11/15 10:55:00 CST by Li Wei(liwei@aiar.xjtu.edu.cn)
+ * Initial revision
+ */
+/* Values for wmesa->pixelformat: */
+
+#define PF_8A8B8G8R 3 /* 32-bit TrueColor: 8-A, 8-B, 8-G, 8-R */
+#define PF_8R8G8B 4 /* 32-bit TrueColor: 8-R, 8-G, 8-B */
+#define PF_5R6G5B 5 /* 16-bit TrueColor: 5-R, 6-G, 5-B bits */
+#define PF_DITHER8 6 /* Dithered RGB using a lookup table */
+#define PF_LOOKUP 7 /* Undithered RGB using a lookup table */
+#define PF_GRAYSCALE 10 /* Grayscale or StaticGray */
+#define PF_BADFORMAT 11
+#define PF_INDEX8 12
+
+char ColorMap16[] = {
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
+0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,
+0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,
+0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,
+0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,
+0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,
+0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,
+0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,
+0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,
+0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,
+0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,
+0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,
+0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,
+0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,
+0x1A,0x1A,0x1A,0x1A,0x1A,0x1A,0x1A,0x1A,
+0x1B,0x1B,0x1B,0x1B,0x1B,0x1B,0x1B,0x1B,
+0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,
+0x1D,0x1D,0x1D,0x1D,0x1D,0x1D,0x1D,0x1D,
+0x1E,0x1E,0x1E,0x1E,0x1E,0x1E,0x1E,0x1E,
+0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F};
+
+#define BGR8(r,g,b) (unsigned)(((BYTE)(b & 0xc0 | (g & 0xe0)>>2 | (r & 0xe0)>>5)))
+#ifdef DDRAW
+#define BGR16(r,g,b) ((WORD)(((BYTE)(ColorMap16[b]) | ((BYTE)(g&0xfc) << 3)) | (((WORD)(BYTE)(ColorMap16[r])) << 11)))
+#else
+#define BGR16(r,g,b) ((WORD)(((BYTE)(ColorMap16[b]) | ((BYTE)(ColorMap16[g]) << 5)) | (((WORD)(BYTE)(ColorMap16[r])) << 10)))
+#endif
+#define BGR24(r,g,b) (unsigned long)(((DWORD)(((BYTE)(b)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(r))<<16))) << 8)
+#define BGR32(r,g,b) (unsigned long)((DWORD)(((BYTE)(b)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(r))<<16)))
+
+
+
+/*
+ * If pixelformat==PF_8A8B8G8R:
+ */
+#define PACK_8A8B8G8R( R, G, B, A ) \
+ ( ((A) << 24) | ((B) << 16) | ((G) << 8) | (R) )
+
+
+/*
+ * If pixelformat==PF_8R8G8B:
+ */
+#define PACK_8R8G8B( R, G, B) ( ((R) << 16) | ((G) << 8) | (B) )
+
+
+/*
+ * If pixelformat==PF_5R6G5B:
+ */
+
+
+#ifdef DDRAW
+#define PACK_5R6G5B( R, G, B) ((WORD)(((BYTE)(ColorMap16[B]) | ((BYTE)(G&0xfc) << 3)) | (((WORD)(BYTE)(ColorMap16[R])) << 11)))
+#else
+#define PACK_5R6G5B( R, G, B) ((WORD)(((BYTE)(ColorMap16[B]) | ((BYTE)(ColorMap16[G]) << 5)) | (((WORD)(BYTE)(ColorMap16[R])) << 10)))
+#endif
+/*----------------------------------------------------------------------------
+
+Division lookup tables. These tables compute 0-255 divided by 51 and
+modulo 51. These tables could approximate gamma correction.
+
+*/
+
+char unsigned const aDividedBy51Rounded[256] =
+{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+};
+
+char unsigned const aDividedBy51[256] =
+{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5,
+};
+
+char unsigned const aModulo51[256] =
+{
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 0, 1, 2, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 47, 48, 49, 50, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+ 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+ 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 0, 1, 2, 3,
+ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+ 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 0,
+};
+
+/*----------------------------------------------------------------------------
+
+Multiplication LUTs. These compute 0-5 times 6 and 36.
+
+*/
+
+char unsigned const aTimes6[6] =
+{
+ 0, 6, 12, 18, 24, 30
+};
+
+char unsigned const aTimes36[6] =
+{
+ 0, 36, 72, 108, 144, 180
+};
+
+
+/*----------------------------------------------------------------------------
+
+Dither matrices for 8 bit to 2.6 bit halftones.
+
+*/
+
+char unsigned const aHalftone16x16[256] =
+{
+ 0, 44, 9, 41, 3, 46, 12, 43, 1, 44, 10, 41, 3, 46, 12, 43,
+ 34, 16, 25, 19, 37, 18, 28, 21, 35, 16, 26, 19, 37, 18, 28, 21,
+ 38, 6, 47, 3, 40, 9, 50, 6, 38, 7, 47, 4, 40, 9, 49, 6,
+ 22, 28, 13, 31, 25, 31, 15, 34, 22, 29, 13, 32, 24, 31, 15, 34,
+ 2, 46, 12, 43, 1, 45, 10, 42, 2, 45, 11, 42, 1, 45, 11, 42,
+ 37, 18, 27, 21, 35, 17, 26, 20, 36, 17, 27, 20, 36, 17, 26, 20,
+ 40, 8, 49, 5, 38, 7, 48, 4, 39, 8, 48, 5, 39, 7, 48, 4,
+ 24, 30, 15, 33, 23, 29, 13, 32, 23, 30, 14, 33, 23, 29, 14, 32,
+ 2, 46, 12, 43, 0, 44, 10, 41, 3, 47, 12, 44, 0, 44, 10, 41,
+ 37, 18, 27, 21, 35, 16, 25, 19, 37, 19, 28, 22, 35, 16, 25, 19,
+ 40, 9, 49, 5, 38, 7, 47, 4, 40, 9, 50, 6, 38, 6, 47, 3,
+ 24, 30, 15, 34, 22, 29, 13, 32, 25, 31, 15, 34, 22, 28, 13, 31,
+ 1, 45, 11, 42, 2, 46, 11, 42, 1, 45, 10, 41, 2, 46, 11, 43,
+ 36, 17, 26, 20, 36, 17, 27, 21, 35, 16, 26, 20, 36, 18, 27, 21,
+ 39, 8, 48, 4, 39, 8, 49, 5, 38, 7, 48, 4, 39, 8, 49, 5,
+ 23, 29, 14, 33, 24, 30, 14, 33, 23, 29, 13, 32, 24, 30, 14, 33,
+};
+
+char unsigned const aHalftone8x8[64] =
+{
+ 0, 38, 9, 47, 2, 40, 11, 50,
+ 25, 12, 35, 22, 27, 15, 37, 24,
+ 6, 44, 3, 41, 8, 47, 5, 43,
+ 31, 19, 28, 15, 34, 21, 31, 18,
+ 1, 39, 11, 49, 0, 39, 10, 48,
+ 27, 14, 36, 23, 26, 13, 35, 23,
+ 7, 46, 4, 43, 7, 45, 3, 42,
+ 33, 20, 30, 17, 32, 19, 29, 16,
+};
+
+char unsigned const aHalftone4x4_1[16] =
+{
+ 0, 25, 6, 31,
+ 38, 12, 44, 19,
+ 9, 35, 3, 28,
+ 47, 22, 41, 15
+};
+
+char unsigned const aHalftone4x4_2[16] =
+{
+ 41, 3, 9, 28,
+ 35, 15, 22, 47,
+ 6, 25, 38, 0,
+ 19, 44, 31, 12
+};
+
+/***************************************************************************
+ aWinGHalftoneTranslation
+
+ Translates a 2.6 bit-per-pixel halftoned representation into the
+ slightly rearranged WinG Halftone Palette.
+*/
+
+char unsigned const aWinGHalftoneTranslation[216] =
+{
+ 0,
+ 29,
+ 30,
+ 31,
+ 32,
+ 249,
+ 33,
+ 34,
+ 35,
+ 36,
+ 37,
+ 38,
+ 39,
+ 40,
+ 41,
+ 42,
+ 43,
+ 44,
+ 45,
+ 46,
+ 47,
+ 48,
+ 49,
+ 50,
+ 51,
+ 52,
+ 53,
+ 54,
+ 55,
+ 56,
+ 250,
+ 250,
+ 57,
+ 58,
+ 59,
+ 251,
+ 60,
+ 61,
+ 62,
+ 63,
+ 64,
+ 65,
+ 66,
+ 67,
+ 68,
+ 69,
+ 70,
+ 71,
+ 72,
+ 73,
+ 74,
+ 75,
+ 76,
+ 77,
+ 78,
+ 79,
+ 80,
+ 81,
+ 82,
+ 83,
+ 84,
+ 85,
+ 86,
+ 87,
+ 88,
+ 89,
+ 250,
+ 90,
+ 91,
+ 92,
+ 93,
+ 94,
+ 95,
+ 96,
+ 97,
+ 98,
+ 99,
+ 100,
+ 101,
+ 102,
+ 103,
+ 104,
+ 105,
+ 106,
+ 107,
+ 108,
+ 109,
+ 110,
+ 111,
+ 227,
+ 112,
+ 113,
+ 114,
+ 115,
+ 116,
+ 117,
+ 118,
+ 119,
+ 151,
+ 120,
+ 121,
+ 122,
+ 123,
+ 124,
+ 228,
+ 125,
+ 126,
+ 229,
+ 133,
+ 162,
+ 135,
+ 131,
+ 132,
+ 137,
+ 166,
+ 134,
+ 140,
+ 130,
+ 136,
+ 143,
+ 138,
+ 139,
+ 174,
+ 141,
+ 142,
+ 177,
+ 129,
+ 144,
+ 145,
+ 146,
+ 147,
+ 148,
+ 149,
+ 150,
+ 157,
+ 152,
+ 153,
+ 154,
+ 155,
+ 156,
+ 192,
+ 158,
+ 159,
+ 160,
+ 161,
+ 196,
+ 163,
+ 164,
+ 165,
+ 127,
+ 199,
+ 167,
+ 168,
+ 169,
+ 170,
+ 171,
+ 172,
+ 173,
+ 207,
+ 175,
+ 176,
+ 210,
+ 178,
+ 179,
+ 180,
+ 181,
+ 182,
+ 183,
+ 184,
+ 185,
+ 186,
+ 187,
+ 188,
+ 189,
+ 190,
+ 191,
+ 224,
+ 193,
+ 194,
+ 195,
+ 252,
+ 252,
+ 197,
+ 198,
+ 128,
+ 253,
+ 252,
+ 200,
+ 201,
+ 202,
+ 203,
+ 204,
+ 205,
+ 206,
+ 230,
+ 208,
+ 209,
+ 231,
+ 211,
+ 212,
+ 213,
+ 214,
+ 215,
+ 216,
+ 217,
+ 218,
+ 219,
+ 220,
+ 221,
+ 222,
+ 254,
+ 223,
+ 232,
+ 225,
+ 226,
+ 255,
+};
diff --git a/mesalib/src/mesa/drivers/windows/gldirect/mesasw/gld_wgl_mesasw.c b/mesalib/src/mesa/drivers/windows/gldirect/mesasw/gld_wgl_mesasw.c
new file mode 100644
index 000000000..36ebe9f31
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/gldirect/mesasw/gld_wgl_mesasw.c
@@ -0,0 +1,1682 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: Mesa Software WGL (WindowsGL)
+*
+****************************************************************************/
+
+#include <windows.h>
+#define GL_GLEXT_PROTOTYPES
+#include <GL/gl.h>
+#include <GL/glext.h>
+
+#include "glheader.h"
+#include "colors.h"
+#include "context.h"
+#include "colormac.h"
+#include "dd.h"
+#include "depth.h"
+#include "extensions.h"
+#include "macros.h"
+#include "matrix.h"
+// #include "mem.h"
+//#include "mmath.h"
+#include "mtypes.h"
+#include "texformat.h"
+#include "texstore.h"
+#include "teximage.h"
+#include "vbo/vbo.h"
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "swrast/s_context.h"
+#include "swrast/s_depth.h"
+#include "swrast/s_lines.h"
+#include "swrast/s_triangle.h"
+#include "swrast/s_trispan.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+#include "dglcontext.h"
+#include "gld_driver.h"
+
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+
+DGL_pixelFormat pfTemplateMesaSW =
+{
+ {
+ sizeof(PIXELFORMATDESCRIPTOR), // Size of the data structure
+ 1, // Structure version - should be 1
+ // Flags:
+ PFD_DRAW_TO_WINDOW | // The buffer can draw to a window or device surface.
+ PFD_DRAW_TO_BITMAP | // The buffer can draw to a bitmap. (DaveM)
+ PFD_SUPPORT_GDI | // The buffer supports GDI drawing. (DaveM)
+ PFD_SUPPORT_OPENGL | // The buffer supports OpenGL drawing.
+ PFD_DOUBLEBUFFER | // The buffer is double-buffered.
+ 0, // Placeholder for easy commenting of above flags
+ PFD_TYPE_RGBA, // Pixel type RGBA.
+ 32, // Total colour bitplanes (excluding alpha bitplanes)
+ 8, 0, // Red bits, shift
+ 8, 8, // Green bits, shift
+ 8, 16, // Blue bits, shift
+ 8, 24, // Alpha bits, shift (destination alpha)
+ 64, // Accumulator bits (total)
+ 16, 16, 16, 16, // Accumulator bits: Red, Green, Blue, Alpha
+ 16, // Depth bits
+ 8, // Stencil bits
+ 0, // Number of auxiliary buffers
+ 0, // Layer type
+ 0, // Specifies the number of overlay and underlay planes.
+ 0, // Layer mask
+ 0, // Specifies the transparent color or index of an underlay plane.
+ 0 // Damage mask
+ },
+ 0, // Unused
+};
+
+//---------------------------------------------------------------------------
+// Extensions
+//---------------------------------------------------------------------------
+
+typedef struct {
+ PROC proc;
+ char *name;
+} GLD_extension;
+
+static GLD_extension GLD_extList[] = {
+#ifdef GL_EXT_polygon_offset
+ { (PROC)glPolygonOffsetEXT, "glPolygonOffsetEXT" },
+#endif
+ { (PROC)glBlendEquationEXT, "glBlendEquationEXT" },
+ { (PROC)glBlendColorEXT, "glBlendColorExt" },
+ { (PROC)glVertexPointerEXT, "glVertexPointerEXT" },
+ { (PROC)glNormalPointerEXT, "glNormalPointerEXT" },
+ { (PROC)glColorPointerEXT, "glColorPointerEXT" },
+ { (PROC)glIndexPointerEXT, "glIndexPointerEXT" },
+ { (PROC)glTexCoordPointerEXT, "glTexCoordPointer" },
+ { (PROC)glEdgeFlagPointerEXT, "glEdgeFlagPointerEXT" },
+ { (PROC)glGetPointervEXT, "glGetPointervEXT" },
+ { (PROC)glArrayElementEXT, "glArrayElementEXT" },
+ { (PROC)glDrawArraysEXT, "glDrawArrayEXT" },
+ { (PROC)glAreTexturesResidentEXT, "glAreTexturesResidentEXT" },
+ { (PROC)glBindTextureEXT, "glBindTextureEXT" },
+ { (PROC)glDeleteTexturesEXT, "glDeleteTexturesEXT" },
+ { (PROC)glGenTexturesEXT, "glGenTexturesEXT" },
+ { (PROC)glIsTextureEXT, "glIsTextureEXT" },
+ { (PROC)glPrioritizeTexturesEXT, "glPrioritizeTexturesEXT" },
+ { (PROC)glCopyTexSubImage3DEXT, "glCopyTexSubImage3DEXT" },
+ { (PROC)glTexImage3DEXT, "glTexImage3DEXT" },
+ { (PROC)glTexSubImage3DEXT, "glTexSubImage3DEXT" },
+ { (PROC)glPointParameterfEXT, "glPointParameterfEXT" },
+ { (PROC)glPointParameterfvEXT, "glPointParameterfvEXT" },
+ { (PROC)glLockArraysEXT, "glLockArraysEXT" },
+ { (PROC)glUnlockArraysEXT, "glUnlockArraysEXT" },
+ { NULL, "\0" }
+};
+
+//---------------------------------------------------------------------------
+// WMesa Internal Functions
+//---------------------------------------------------------------------------
+
+#define PAGE_FILE 0xffffffff
+
+#define REDBITS 0x03
+#define REDSHIFT 0x00
+#define GREENBITS 0x03
+#define GREENSHIFT 0x03
+#define BLUEBITS 0x02
+#define BLUESHIFT 0x06
+
+typedef struct _dibSection {
+ HDC hDC;
+ HANDLE hFileMap;
+ BOOL fFlushed;
+ LPVOID base;
+} WMDIBSECTION, *PWMDIBSECTION;
+
+typedef struct wmesa_context {
+ HWND Window;
+ HDC hDC;
+ HPALETTE hPalette;
+ HPALETTE hOldPalette;
+ HPEN hPen;
+ HPEN hOldPen;
+ HCURSOR hOldCursor;
+ COLORREF crColor;
+ // 3D projection stuff
+ RECT drawRect;
+ UINT uiDIBoffset;
+ // OpenGL stuff
+ HPALETTE hGLPalette;
+ GLuint width;
+ GLuint height;
+ GLuint ScanWidth;
+ GLboolean db_flag; //* double buffered?
+ GLboolean rgb_flag; //* RGB mode?
+ GLboolean dither_flag; //* use dither when 256 color mode for RGB?
+ GLuint depth; //* bits per pixel (1, 8, 24, etc)
+ ULONG pixel; // current color index or RGBA pixel value
+ ULONG clearpixel; //* pixel for clearing the color buffers
+ PBYTE ScreenMem; // WinG memory
+ BITMAPINFO *IndexFormat;
+ HPALETTE hPal; // Current Palette
+ HPALETTE hPalHalfTone;
+
+
+ WMDIBSECTION dib;
+ BITMAPINFO bmi;
+ HBITMAP hbmDIB;
+ HBITMAP hOldBitmap;
+ HBITMAP Old_Compat_BM;
+ HBITMAP Compat_BM; // Bitmap for double buffering
+ PBYTE pbPixels;
+ int nColors;
+ BYTE cColorBits;
+ int pixelformat;
+
+ RECT rectOffScreen;
+ RECT rectSurface;
+// HWND hwnd;
+ DWORD pitch;
+ PBYTE addrOffScreen;
+
+ // We always double-buffer, for performance reasons, but
+ // we need to know which of SwapBuffers() or glFlush() to
+ // handle. If we're emulating, then we update on Flush(),
+ // otherwise we update on SwapBufers(). KeithH
+ BOOL bEmulateSingleBuffer;
+} WMesaContext, *PWMC;
+
+#define GLD_GET_WMESA_DRIVER(c) (WMesaContext*)(c)->glPriv
+
+// TODO:
+GLint stereo_flag = 0 ;
+
+/* If we are double-buffering, we want to get the DC for the
+ * off-screen DIB, otherwise the DC for the window.
+ */
+#define DD_GETDC ((Current->db_flag) ? Current->dib.hDC : Current->hDC )
+#define DD_RELEASEDC
+
+#define FLIP(Y) (Current->height-(Y)-1)
+
+struct DISPLAY_OPTIONS {
+ int stereo;
+ int fullScreen;
+ int mode;
+ int bpp;
+};
+
+struct DISPLAY_OPTIONS displayOptions;
+
+//---------------------------------------------------------------------------
+
+static unsigned char threeto8[8] = {
+ 0, 0111>>1, 0222>>1, 0333>>1, 0444>>1, 0555>>1, 0666>>1, 0377
+};
+
+static unsigned char twoto8[4] = {
+ 0, 0x55, 0xaa, 0xff
+};
+
+static unsigned char oneto8[2] = {
+ 0, 255
+};
+
+//---------------------------------------------------------------------------
+
+BYTE DITHER_RGB_2_8BIT( int red, int green, int blue, int pixel, int scanline)
+{
+ char unsigned redtemp, greentemp, bluetemp, paletteindex;
+
+ //*** now, look up each value in the halftone matrix
+ //*** using an 8x8 ordered dither.
+ redtemp = aDividedBy51[red]
+ + (aModulo51[red] > aHalftone8x8[(pixel%8)*8
+ + scanline%8]);
+ greentemp = aDividedBy51[(char unsigned)green]
+ + (aModulo51[green] > aHalftone8x8[
+ (pixel%8)*8 + scanline%8]);
+ bluetemp = aDividedBy51[(char unsigned)blue]
+ + (aModulo51[blue] > aHalftone8x8[
+ (pixel%8)*8 +scanline%8]);
+
+ //*** recombine the halftoned rgb values into a palette index
+ paletteindex =
+ redtemp + aTimes6[greentemp] + aTimes36[bluetemp];
+
+ //*** and translate through the wing halftone palette
+ //*** translation vector to give the correct value.
+ return aWinGHalftoneTranslation[paletteindex];
+}
+
+//---------------------------------------------------------------------------
+
+static unsigned char componentFromIndex(UCHAR i, UINT nbits, UINT shift)
+{
+ unsigned char val;
+
+ val = i >> shift;
+ switch (nbits) {
+
+ case 1:
+ val &= 0x1;
+ return oneto8[val];
+
+ case 2:
+ val &= 0x3;
+ return twoto8[val];
+
+ case 3:
+ val &= 0x7;
+ return threeto8[val];
+
+ default:
+ return 0;
+ }
+}
+
+//---------------------------------------------------------------------------
+
+
+void wmSetPixel(PWMC pwc, int iScanLine, int iPixel, BYTE r, BYTE g, BYTE b)
+{
+ WMesaContext *Current = pwc;
+
+ // Test for invalid scanline parameter. KeithH
+ if ((iScanLine < 0) || (iScanLine >= pwc->height))
+ return;
+
+ if (Current->db_flag) {
+ LPBYTE lpb = pwc->pbPixels;
+ UINT nBypp = pwc->cColorBits >> 3;
+ UINT nOffset = iPixel % nBypp;
+
+ lpb += pwc->ScanWidth * iScanLine;
+ lpb += iPixel * nBypp;
+
+ if(nBypp == 1){
+ if(pwc->dither_flag)
+ *lpb = DITHER_RGB_2_8BIT(r,g,b,iScanLine,iPixel);
+ else
+ *lpb = BGR8(r,g,b);
+ }
+ else if(nBypp == 2)
+ *((LPWORD)lpb) = BGR16(r,g,b);
+ else if (nBypp == 3)
+ *((LPDWORD)lpb) = BGR24(r,g,b);
+ else if (nBypp == 4)
+ *((LPDWORD)lpb) = BGR32(r,g,b);
+ }
+ else{
+ SetPixel(Current->hDC, iPixel, iScanLine, RGB(r,g,b));
+ }
+}
+
+//---------------------------------------------------------------------------
+
+void wmCreateDIBSection(
+ HDC hDC,
+ PWMC pwc, // handle of device context
+ CONST BITMAPINFO *pbmi, // bitmap size, format, and color data
+ UINT iUsage // color data type indicator: RGB values or palette indices
+ )
+{
+ DWORD dwSize = 0;
+ DWORD dwScanWidth;
+ UINT nBypp = pwc->cColorBits / 8;
+ HDC hic;
+
+ dwScanWidth = (((pwc->ScanWidth * nBypp)+ 3) & ~3);
+
+ pwc->ScanWidth =pwc->pitch = dwScanWidth;
+
+ if (stereo_flag)
+ pwc->ScanWidth = 2* pwc->pitch;
+
+ dwSize = sizeof(BITMAPINFO) + (dwScanWidth * pwc->height);
+
+ pwc->dib.hFileMap = CreateFileMapping((HANDLE)PAGE_FILE,
+ NULL,
+ PAGE_READWRITE | SEC_COMMIT,
+ 0,
+ dwSize,
+ NULL);
+
+ if (!pwc->dib.hFileMap)
+ return;
+
+ pwc->dib.base = MapViewOfFile(pwc->dib.hFileMap,
+ FILE_MAP_ALL_ACCESS,
+ 0,
+ 0,
+ 0);
+
+ if(!pwc->dib.base){
+ CloseHandle(pwc->dib.hFileMap);
+ return;
+ }
+
+
+ CopyMemory(pwc->dib.base, pbmi, sizeof(BITMAPINFO));
+
+ hic = CreateIC("display", NULL, NULL, NULL);
+ pwc->dib.hDC = CreateCompatibleDC(hic);
+
+
+ pwc->hbmDIB = CreateDIBSection(hic,
+ &(pwc->bmi),
+ (iUsage ? DIB_PAL_COLORS : DIB_RGB_COLORS),
+ &(pwc->pbPixels),
+ pwc->dib.hFileMap,
+ 0);
+ pwc->ScreenMem = pwc->addrOffScreen = pwc->pbPixels;
+ pwc->hOldBitmap = SelectObject(pwc->dib.hDC, pwc->hbmDIB);
+
+ DeleteDC(hic);
+
+ return;
+
+}
+
+//---------------------------------------------------------------------------
+
+void wmCreatePalette( PWMC pwdc )
+{
+ /* Create a compressed and re-expanded 3:3:2 palette */
+ int i;
+ LOGPALETTE *pPal;
+ BYTE rb, rs, gb, gs, bb, bs;
+
+ pwdc->nColors = 0x100;
+
+ pPal = (PLOGPALETTE)malloc(sizeof(LOGPALETTE) +
+ pwdc->nColors * sizeof(PALETTEENTRY));
+ memset( pPal, 0, sizeof(LOGPALETTE) + pwdc->nColors * sizeof(PALETTEENTRY) );
+
+ pPal->palVersion = 0x300;
+
+ rb = REDBITS;
+ rs = REDSHIFT;
+ gb = GREENBITS;
+ gs = GREENSHIFT;
+ bb = BLUEBITS;
+ bs = BLUESHIFT;
+
+ if (pwdc->db_flag) {
+
+ /* Need to make two palettes: one for the screen DC and one for the DIB. */
+ pPal->palNumEntries = pwdc->nColors;
+ for (i = 0; i < pwdc->nColors; i++) {
+ pPal->palPalEntry[i].peRed = componentFromIndex( i, rb, rs );
+ pPal->palPalEntry[i].peGreen = componentFromIndex( i, gb, gs );
+ pPal->palPalEntry[i].peBlue = componentFromIndex( i, bb, bs );
+ pPal->palPalEntry[i].peFlags = 0;
+ }
+ pwdc->hGLPalette = CreatePalette( pPal );
+ pwdc->hPalette = CreatePalette( pPal );
+ }
+
+ else {
+ pPal->palNumEntries = pwdc->nColors;
+ for (i = 0; i < pwdc->nColors; i++) {
+ pPal->palPalEntry[i].peRed = componentFromIndex( i, rb, rs );
+ pPal->palPalEntry[i].peGreen = componentFromIndex( i, gb, gs );
+ pPal->palPalEntry[i].peBlue = componentFromIndex( i, bb, bs );
+ pPal->palPalEntry[i].peFlags = 0;
+ }
+ pwdc->hGLPalette = CreatePalette( pPal );
+ }
+
+ free(pPal);
+
+}
+
+//---------------------------------------------------------------------------
+
+/* This function sets the color table of a DIB section
+ * to match that of the destination DC
+ */
+BOOL wmSetDibColors(PWMC pwc)
+{
+ RGBQUAD *pColTab, *pRGB;
+ PALETTEENTRY *pPal, *pPE;
+ int i, nColors;
+ BOOL bRet=TRUE;
+ DWORD dwErr=0;
+
+ /* Build a color table in the DIB that maps to the
+ * selected palette in the DC.
+ */
+ nColors = 1 << pwc->cColorBits;
+ pPal = (PALETTEENTRY *)malloc( nColors * sizeof(PALETTEENTRY));
+ memset( pPal, 0, nColors * sizeof(PALETTEENTRY) );
+ GetPaletteEntries( pwc->hGLPalette, 0, nColors, pPal );
+ pColTab = (RGBQUAD *)malloc( nColors * sizeof(RGBQUAD));
+ for (i = 0, pRGB = pColTab, pPE = pPal; i < nColors; i++, pRGB++, pPE++) {
+ pRGB->rgbRed = pPE->peRed;
+ pRGB->rgbGreen = pPE->peGreen;
+ pRGB->rgbBlue = pPE->peBlue;
+ }
+ if(pwc->db_flag)
+ bRet = SetDIBColorTable(pwc->dib.hDC, 0, nColors, pColTab );
+
+ if(!bRet)
+ dwErr = GetLastError();
+
+ free( pColTab );
+ free( pPal );
+
+ return bRet;
+}
+
+//---------------------------------------------------------------------------
+
+static void wmSetPixelFormat( PWMC wc, HDC hDC)
+{
+ if(wc->rgb_flag)
+ wc->cColorBits = GetDeviceCaps(hDC, BITSPIXEL);
+ else
+ wc->cColorBits = 8;
+ switch(wc->cColorBits){
+ case 8:
+ if(wc->dither_flag != GL_TRUE)
+ wc->pixelformat = PF_INDEX8;
+ else
+ wc->pixelformat = PF_DITHER8;
+ break;
+ case 16:
+ wc->pixelformat = PF_5R6G5B;
+ break;
+ case 32:
+ wc->pixelformat = PF_8R8G8B;
+ break;
+ default:
+ wc->pixelformat = PF_BADFORMAT;
+ }
+}
+
+//---------------------------------------------------------------------------
+
+/*
+ * This function creates the DIB section that is used for combined
+ * GL and GDI calls
+ */
+BOOL wmCreateBackingStore(PWMC pwc, long lxSize, long lySize)
+{
+ HDC hdc = pwc->hDC;
+ LPBITMAPINFO pbmi = &(pwc->bmi);
+ int iUsage;
+
+ pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ pbmi->bmiHeader.biWidth = lxSize;
+ pbmi->bmiHeader.biHeight= -lySize;
+ pbmi->bmiHeader.biPlanes = 1;
+ if(pwc->rgb_flag)
+ pbmi->bmiHeader.biBitCount = GetDeviceCaps(pwc->hDC, BITSPIXEL);
+ else
+ pbmi->bmiHeader.biBitCount = 8;
+ pbmi->bmiHeader.biCompression = BI_RGB;
+ pbmi->bmiHeader.biSizeImage = 0;
+ pbmi->bmiHeader.biXPelsPerMeter = 0;
+ pbmi->bmiHeader.biYPelsPerMeter = 0;
+ pbmi->bmiHeader.biClrUsed = 0;
+ pbmi->bmiHeader.biClrImportant = 0;
+
+ iUsage = (pbmi->bmiHeader.biBitCount <= 8) ? DIB_PAL_COLORS : DIB_RGB_COLORS;
+
+ pwc->cColorBits = pbmi->bmiHeader.biBitCount;
+ pwc->ScanWidth = pwc->pitch = lxSize;
+ pwc->width = lxSize;
+ pwc->height = lySize;
+
+ wmCreateDIBSection(hdc, pwc, pbmi, iUsage);
+
+ if ((iUsage == DIB_PAL_COLORS) && !(pwc->hGLPalette)) {
+ wmCreatePalette( pwc );
+ wmSetDibColors( pwc );
+ }
+ wmSetPixelFormat(pwc, pwc->hDC);
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+/*
+ * Free up the dib section that was created
+ */
+BOOL wmDeleteBackingStore(PWMC pwc)
+{
+ SelectObject(pwc->dib.hDC, pwc->hOldBitmap);
+ DeleteDC(pwc->dib.hDC);
+ DeleteObject(pwc->hbmDIB);
+ UnmapViewOfFile(pwc->dib.base);
+ CloseHandle(pwc->dib.hFileMap);
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+/*
+ * Blit memory DC to screen DC
+ */
+BOOL wmFlush(PWMC pwc, HDC hDC)
+{
+ BOOL bRet = 0;
+ DWORD dwErr = 0;
+
+// Now using bEmulateSingleBuffer in the calling function. KeithH
+
+// if(pwc->db_flag){
+ bRet = BitBlt(hDC, 0, 0, pwc->width, pwc->height,
+ pwc->dib.hDC, 0, 0, SRCCOPY);
+// }
+
+ return bRet;
+
+}
+
+//---------------------------------------------------------------------------
+// Support Functions
+//---------------------------------------------------------------------------
+
+static void flush(struct gl_context* ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+/*
+ if((Current->rgb_flag &&!(Current->db_flag))
+ ||(!Current->rgb_flag))
+ {
+ wmFlush(Current, Current->hDC);
+ }
+*/
+ // Only flush if we're not in double-buffer mode. KeithH
+ // The demo fractal.c calls glutSwapBuffers() then glFlush()!
+ if (Current->bEmulateSingleBuffer) {
+ wmFlush(Current, Current->hDC);
+ }
+}
+
+
+//---------------------------------------------------------------------------
+
+/*
+ * Set the color used to clear the color buffer.
+ */
+//static void clear_color( struct gl_context* ctx, const GLchan color[4] )
+// Changed for Mesa 5.x. KeithH
+static void clear_color(
+ struct gl_context* ctx,
+ const GLfloat color[4])
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ GLubyte col[4];
+ CLAMPED_FLOAT_TO_UBYTE(col[0], color[0]);
+ CLAMPED_FLOAT_TO_UBYTE(col[1], color[1]);
+ CLAMPED_FLOAT_TO_UBYTE(col[2], color[2]);
+ Current->clearpixel = RGB(col[0], col[1], col[2]);
+}
+
+
+//---------------------------------------------------------------------------
+
+
+/*
+ * Clear the specified region of the color buffer using the clear color
+ * or index as specified by one of the two functions above.
+ *
+ * This procedure clears either the front and/or the back COLOR buffers.
+ * Only the "left" buffer is cleared since we are not stereo.
+ * Clearing of the other non-color buffers is left to the swrast.
+ * We also only clear the color buffers if the color masks are all 1's.
+ * Otherwise, we let swrast do it.
+ */
+
+static clear(struct gl_context* ctx, GLbitfield mask,
+ GLboolean all, GLint x, GLint y, GLint width, GLint height)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ DWORD dwColor;
+ WORD wColor;
+ BYTE bColor;
+ LPDWORD lpdw = (LPDWORD)Current->pbPixels;
+ LPWORD lpw = (LPWORD)Current->pbPixels;
+ LPBYTE lpb = Current->pbPixels;
+ int lines;
+ const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask;
+
+ if (all){
+ x=y=0;
+ width=Current->width;
+ height=Current->height;
+ }
+
+
+ /* sanity check - can't have right(stereo) buffers */
+ assert((mask & (DD_FRONT_RIGHT_BIT | DD_BACK_RIGHT_BIT)) == 0);
+
+ /* clear alpha */
+ if ((mask & (DD_FRONT_LEFT_BIT | DD_BACK_RIGHT_BIT)) &&
+ ctx->DrawBuffer->UseSoftwareAlphaBuffers &&
+ ctx->Color.ColorMask[ACOMP]) {
+ _swrast_clear_alpha_buffers( ctx );
+ }
+
+ if (*colorMask == 0xffffffff && ctx->Color.IndexMask == 0xffffffff) {
+ if (mask & DD_BACK_LEFT_BIT) {
+ /* Double-buffering - clear back buffer */
+ UINT nBypp = Current->cColorBits / 8;
+ int i = 0;
+ int iSize = 0;
+
+ assert(Current->db_flag==GL_TRUE); /* we'd better be double buffer */
+ if(nBypp ==1 ){
+ iSize = Current->width/4;
+ bColor = BGR8(GetRValue(Current->clearpixel),
+ GetGValue(Current->clearpixel),
+ GetBValue(Current->clearpixel));
+ wColor = MAKEWORD(bColor,bColor);
+ dwColor = MAKELONG(wColor, wColor);
+ }
+ if(nBypp == 2){
+ iSize = Current->width / 2;
+ wColor = BGR16(GetRValue(Current->clearpixel),
+ GetGValue(Current->clearpixel),
+ GetBValue(Current->clearpixel));
+ dwColor = MAKELONG(wColor, wColor);
+ }
+ else if(nBypp == 4){
+ iSize = Current->width;
+ dwColor = BGR32(GetRValue(Current->clearpixel),
+ GetGValue(Current->clearpixel),
+ GetBValue(Current->clearpixel));
+ }
+
+ /* clear a line */
+ while(i < iSize){
+ *lpdw = dwColor;
+ lpdw++;
+ i++;
+ }
+
+ /* This is the 24bit case */
+ if (nBypp == 3) {
+ iSize = Current->width *3/4;
+ dwColor = BGR24(GetRValue(Current->clearpixel),
+ GetGValue(Current->clearpixel),
+ GetBValue(Current->clearpixel));
+ while(i < iSize){
+ *lpdw = dwColor;
+ lpb += nBypp;
+ lpdw = (LPDWORD)lpb;
+ i++;
+ }
+ }
+
+ i = 0;
+ if (stereo_flag)
+ lines = height /2;
+ else
+ lines = height;
+ /* copy cleared line to other lines in buffer */
+ do {
+ memcpy(lpb, Current->pbPixels, iSize*4);
+ lpb += Current->ScanWidth;
+ i++;
+ }
+ while (i<lines-1);
+ mask &= ~DD_BACK_LEFT_BIT;
+ } /* double-buffer */
+
+ if (mask & DD_FRONT_LEFT_BIT) {
+ /* single-buffer */
+ HDC DC=DD_GETDC;
+ HPEN Pen=CreatePen(PS_SOLID,1,Current->clearpixel);
+ HBRUSH Brush=CreateSolidBrush(Current->clearpixel);
+ HPEN Old_Pen=SelectObject(DC,Pen);
+ HBRUSH Old_Brush=SelectObject(DC,Brush);
+ Rectangle(DC,x,y,x+width,y+height);
+ SelectObject(DC,Old_Pen);
+ SelectObject(DC,Old_Brush);
+ DeleteObject(Pen);
+ DeleteObject(Brush);
+ DD_RELEASEDC;
+ mask &= ~DD_FRONT_LEFT_BIT;
+ } /* single-buffer */
+ } /* if masks are all 1's */
+
+ /* Call swrast if there is anything left to clear (like DEPTH) */
+ if (mask)
+ _swrast_Clear( ctx, mask, all, x, y, width, height );
+}
+
+
+//---------------------------------------------------------------------------
+
+
+static void enable( struct gl_context* ctx, GLenum pname, GLboolean enable )
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+
+ if (!Current)
+ return;
+
+ if (pname == GL_DITHER) {
+ if(enable == GL_FALSE){
+ Current->dither_flag = GL_FALSE;
+ if(Current->cColorBits == 8)
+ Current->pixelformat = PF_INDEX8;
+ }
+ else{
+ if (Current->rgb_flag && Current->cColorBits == 8){
+ Current->pixelformat = PF_DITHER8;
+ Current->dither_flag = GL_TRUE;
+ }
+ else
+ Current->dither_flag = GL_FALSE;
+ }
+ }
+}
+
+//---------------------------------------------------------------------------
+
+static GLboolean set_draw_buffer( struct gl_context* ctx, GLenum mode )
+{
+ /* TODO: this could be better */
+ if (mode==GL_FRONT_LEFT || mode==GL_BACK_LEFT) {
+ return GL_TRUE;
+ }
+ else {
+ return GL_FALSE;
+ }
+}
+
+//---------------------------------------------------------------------------
+
+
+static void set_read_buffer(struct gl_context *ctx, struct gl_framebuffer *colorBuffer,
+ GLenum buffer )
+{
+ /* XXX todo */
+ return;
+}
+
+
+//---------------------------------------------------------------------------
+
+
+/* Return characteristics of the output buffer. */
+//static void buffer_size( struct gl_context* ctx, GLuint *width, GLuint *height )
+// Altered for Mesa 5.x. KeithH
+static void buffer_size(
+ struct gl_framebuffer *buffer,
+ GLuint *width,
+ GLuint *height)
+{
+ // For some reason the context is not passed into this function.
+ // Therefore we have to explicitly retrieve it.
+ GET_CURRENT_CONTEXT(ctx);
+
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ int New_Size;
+ RECT CR;
+
+ GetClientRect(Current->Window,&CR);
+
+ *width=CR.right;
+ *height=CR.bottom;
+
+ New_Size=((*width)!=Current->width) || ((*height)!=Current->height);
+
+ if (New_Size){
+ Current->width=*width;
+ Current->height=*height;
+ Current->ScanWidth=Current->width;
+ if ((Current->ScanWidth%sizeof(long))!=0)
+ Current->ScanWidth+=(sizeof(long)-(Current->ScanWidth%sizeof(long)));
+
+ if (Current->db_flag){
+ if (Current->rgb_flag==GL_TRUE && Current->dither_flag!=GL_TRUE){
+ wmDeleteBackingStore(Current);
+ wmCreateBackingStore(Current, Current->width, Current->height);
+ }
+ }
+
+ }
+}
+
+
+
+/**********************************************************************/
+/***** Accelerated point, line, polygon rendering *****/
+/**********************************************************************/
+
+/* Accelerated routines are not implemented in 4.0. See OSMesa for ideas. */
+
+static void fast_rgb_points( struct gl_context* ctx, GLuint first, GLuint last )
+{
+}
+
+//---------------------------------------------------------------------------
+
+/* Return pointer to accelerated points function */
+extern tnl_points_func choose_points_function( struct gl_context* ctx )
+{
+ return NULL;
+}
+
+//---------------------------------------------------------------------------
+
+static void fast_flat_rgb_line( struct gl_context* ctx, GLuint v0,
+ GLuint v1, GLuint pv )
+{
+}
+
+//---------------------------------------------------------------------------
+
+static tnl_line_func choose_line_function( struct gl_context* ctx )
+{
+}
+
+
+/**********************************************************************/
+/***** Span-based pixel drawing *****/
+/**********************************************************************/
+
+
+/* Write a horizontal span of 32-bit color-index pixels with a boolean mask. */
+static void write_ci32_span( const struct gl_context* ctx,
+ GLuint n, GLint x, GLint y,
+ const GLuint index[],
+ const GLubyte mask[] )
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ GLuint i;
+ PBYTE Mem=Current->ScreenMem+FLIP(y)*Current->ScanWidth+x;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++)
+ if (mask[i])
+ Mem[i]=index[i];
+}
+
+
+//---------------------------------------------------------------------------
+
+/* Write a horizontal span of 8-bit color-index pixels with a boolean mask. */
+static void write_ci8_span( const struct gl_context* ctx,
+ GLuint n, GLint x, GLint y,
+ const GLubyte index[],
+ const GLubyte mask[] )
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ GLuint i;
+ PBYTE Mem=Current->ScreenMem+FLIP(y)*Current->ScanWidth+x;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++)
+ if (mask[i])
+ Mem[i]=index[i];
+}
+
+
+//---------------------------------------------------------------------------
+
+
+/*
+ * Write a horizontal span of pixels with a boolean mask. The current
+ * color index is used for all pixels.
+ */
+static void write_mono_ci_span(const struct gl_context* ctx,
+ GLuint n,GLint x,GLint y,
+ GLuint colorIndex, const GLubyte mask[])
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ GLuint i;
+ BYTE *Mem=Current->ScreenMem+FLIP(y)*Current->ScanWidth+x;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++)
+ if (mask[i])
+ Mem[i]=colorIndex;
+}
+
+//---------------------------------------------------------------------------
+
+/*
+ * To improve the performance of this routine, frob the data into an actual
+ * scanline and call bitblt on the complete scan line instead of SetPixel.
+ */
+
+/* Write a horizontal span of RGBA color pixels with a boolean mask. */
+static void write_rgba_span( const struct gl_context* ctx, GLuint n, GLint x, GLint y,
+ const GLubyte rgba[][4], const GLubyte mask[] )
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ PWMC pwc = Current;
+
+ if (pwc->rgb_flag==GL_TRUE)
+ {
+ GLuint i;
+ HDC DC=DD_GETDC;
+ y=FLIP(y);
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ wmSetPixel(pwc, y, x + i,
+ rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
+ }
+ else {
+ for (i=0; i<n; i++)
+ wmSetPixel(pwc, y, x + i,
+ rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+ }
+ DD_RELEASEDC;
+ }
+ else
+ {
+ GLuint i;
+ BYTE *Mem=Current->ScreenMem+y*Current->ScanWidth+x;
+ y = FLIP(y);
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ Mem[i] = GetNearestPaletteIndex(Current->hPal,
+ RGB(rgba[i][RCOMP],
+ rgba[i][GCOMP],
+ rgba[i][BCOMP]));
+ }
+ else {
+ for (i=0; i<n; i++)
+ Mem[i] = GetNearestPaletteIndex(Current->hPal,
+ RGB(rgba[i][RCOMP],
+ rgba[i][GCOMP],
+ rgba[i][BCOMP]));
+ }
+ }
+}
+
+//---------------------------------------------------------------------------
+
+/* Write a horizontal span of RGB color pixels with a boolean mask. */
+static void write_rgb_span( const struct gl_context* ctx,
+ GLuint n, GLint x, GLint y,
+ const GLubyte rgb[][3], const GLubyte mask[] )
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ PWMC pwc = Current;
+
+ if (pwc->rgb_flag==GL_TRUE)
+ {
+ GLuint i;
+ HDC DC=DD_GETDC;
+ y=FLIP(y);
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ wmSetPixel(pwc, y, x + i,
+ rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]);
+ }
+ else {
+ for (i=0; i<n; i++)
+ wmSetPixel(pwc, y, x + i,
+ rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] );
+ }
+ DD_RELEASEDC;
+ }
+ else
+ {
+ GLuint i;
+ BYTE *Mem=Current->ScreenMem+y*Current->ScanWidth+x;
+ y = FLIP(y);
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ Mem[i] = GetNearestPaletteIndex(Current->hPal,
+ RGB(rgb[i][RCOMP],
+ rgb[i][GCOMP],
+ rgb[i][BCOMP]));
+ }
+ else {
+ for (i=0; i<n; i++)
+ Mem[i] = GetNearestPaletteIndex(Current->hPal,
+ RGB(rgb[i][RCOMP],
+ rgb[i][GCOMP],
+ rgb[i][BCOMP]));
+ }
+ }
+}
+
+//---------------------------------------------------------------------------
+
+/*
+ * Write a horizontal span of pixels with a boolean mask. The current color
+ * is used for all pixels.
+ */
+static void write_mono_rgba_span( const struct gl_context* ctx,
+ GLuint n, GLint x, GLint y,
+ const GLchan color[4], const GLubyte mask[])
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ ULONG pixel = RGB( color[RCOMP], color[GCOMP], color[BCOMP] );
+ GLuint i;
+ HDC DC=DD_GETDC;
+ PWMC pwc = Current;
+ assert(Current->rgb_flag==GL_TRUE);
+ y=FLIP(y);
+ if(Current->rgb_flag==GL_TRUE){
+ for (i=0; i<n; i++)
+ if (mask[i])
+ wmSetPixel(pwc,y,x+i,color[RCOMP], color[GCOMP], color[BCOMP]);
+ }
+ else {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ SetPixel(DC, y, x+i, pixel);
+ }
+ DD_RELEASEDC;
+}
+
+
+
+/**********************************************************************/
+/***** Array-based pixel drawing *****/
+/**********************************************************************/
+
+
+/* Write an array of 32-bit index pixels with a boolean mask. */
+static void write_ci32_pixels( const struct gl_context* ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLuint index[], const GLubyte mask[] )
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ GLuint i;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ BYTE *Mem=Current->ScreenMem+FLIP(y[i])*Current->ScanWidth+x[i];
+ *Mem = index[i];
+ }
+ }
+}
+
+
+//---------------------------------------------------------------------------
+
+
+/*
+ * Write an array of pixels with a boolean mask. The current color
+ * index is used for all pixels.
+ */
+static void write_mono_ci_pixels( const struct gl_context* ctx,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ GLuint colorIndex, const GLubyte mask[] )
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ GLuint i;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ BYTE *Mem=Current->ScreenMem+FLIP(y[i])*Current->ScanWidth+x[i];
+ *Mem = colorIndex;
+ }
+ }
+}
+
+
+//---------------------------------------------------------------------------
+
+
+/* Write an array of RGBA pixels with a boolean mask. */
+static void write_rgba_pixels( const struct gl_context* ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLubyte rgba[][4], const GLubyte mask[] )
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ GLuint i;
+ PWMC pwc = Current;
+ HDC DC=DD_GETDC;
+ assert(Current->rgb_flag==GL_TRUE);
+ for (i=0; i<n; i++)
+ if (mask[i])
+ wmSetPixel(pwc, FLIP(y[i]), x[i],
+ rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
+ DD_RELEASEDC;
+}
+
+
+//---------------------------------------------------------------------------
+
+
+/*
+ * Write an array of pixels with a boolean mask. The current color
+ * is used for all pixels.
+ */
+static void write_mono_rgba_pixels( const struct gl_context* ctx,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ const GLchan color[4],
+ const GLubyte mask[] )
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ GLuint i;
+ PWMC pwc = Current;
+ HDC DC=DD_GETDC;
+ assert(Current->rgb_flag==GL_TRUE);
+ for (i=0; i<n; i++)
+ if (mask[i])
+ wmSetPixel(pwc, FLIP(y[i]),x[i],color[RCOMP],
+ color[GCOMP], color[BCOMP]);
+ DD_RELEASEDC;
+}
+
+/**********************************************************************/
+/***** Read spans/arrays of pixels *****/
+/**********************************************************************/
+
+/* Read a horizontal span of color-index pixels. */
+static void read_ci32_span( const struct gl_context* ctx, GLuint n, GLint x, GLint y,
+ GLuint index[])
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ GLuint i;
+ BYTE *Mem=Current->ScreenMem+FLIP(y)*Current->ScanWidth+x;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++)
+ index[i]=Mem[i];
+}
+
+//---------------------------------------------------------------------------
+
+/* Read an array of color index pixels. */
+static void read_ci32_pixels( const struct gl_context* ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLuint indx[], const GLubyte mask[] )
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ GLuint i;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ indx[i]=*(Current->ScreenMem+FLIP(y[i])*Current->ScanWidth+x[i]);
+ }
+ }
+}
+
+//---------------------------------------------------------------------------
+
+/* Read a horizontal span of color pixels. */
+static void read_rgba_span( const struct gl_context* ctx,
+ GLuint n, GLint x, GLint y,
+ GLubyte rgba[][4] )
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ UINT i;
+ COLORREF Color;
+ HDC DC=DD_GETDC;
+ assert(Current->rgb_flag==GL_TRUE);
+ y = Current->height - y - 1;
+ for (i=0; i<n; i++) {
+ Color=GetPixel(DC,x+i,y);
+ rgba[i][RCOMP] = GetRValue(Color);
+ rgba[i][GCOMP] = GetGValue(Color);
+ rgba[i][BCOMP] = GetBValue(Color);
+ rgba[i][ACOMP] = 255;
+ }
+ DD_RELEASEDC;
+}
+
+//---------------------------------------------------------------------------
+
+/* Read an array of color pixels. */
+static void read_rgba_pixels( const struct gl_context* ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte rgba[][4], const GLubyte mask[] )
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ GLuint i;
+ COLORREF Color;
+ HDC DC=DD_GETDC;
+ assert(Current->rgb_flag==GL_TRUE);
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ GLint y2 = Current->height - y[i] - 1;
+ Color=GetPixel(DC,x[i],y2);
+ rgba[i][RCOMP] = GetRValue(Color);
+ rgba[i][GCOMP] = GetGValue(Color);
+ rgba[i][BCOMP] = GetBValue(Color);
+ rgba[i][ACOMP] = 255;
+ }
+ }
+ DD_RELEASEDC;
+}
+
+//---------------------------------------------------------------------------
+
+static void wmesa_update_state(
+ struct gl_context *ctx,
+ GLuint new_state)
+{
+ _swrast_InvalidateState( ctx, new_state );
+ _swsetup_InvalidateState( ctx, new_state );
+ _vbo_InvalidateState( ctx, new_state );
+ _tnl_InvalidateState( ctx, new_state );
+}
+
+//---------------------------------------------------------------------------
+
+static void wmesa_viewport(
+ struct gl_context *ctx,
+ GLint x,
+ GLint y,
+ GLsizei w,
+ GLsizei h)
+{
+// ctx->Driver.ResizeBuffersMESA(ctx);
+}
+
+//---------------------------------------------------------------------------
+
+static void wmesa_update_state_first_time(
+ struct gl_context *ctx,
+ GLuint new_state)
+{
+ struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference( ctx );
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+ _mesa_init_driver_functions(&ctx->Driver);
+
+ /*
+ * XXX these function pointers could be initialized just once during
+ * context creation since they don't depend on any state changes.
+ * kws - This is true - this function gets called a lot and it
+ * would be good to minimize setting all this when not needed.
+ */
+ // Good idea, so I'll do it. KeithH. :-)
+
+ ctx->Driver.GetString = _gldGetStringGeneric;
+ ctx->Driver.UpdateState = wmesa_update_state;
+ ctx->Driver.DrawBuffer = set_draw_buffer;
+ ctx->Driver.ResizeBuffers = _swrast_alloc_buffers;
+ ctx->Driver.GetBufferSize = buffer_size;
+
+ ctx->Driver.Viewport = wmesa_viewport;
+
+ ctx->Driver.Clear = clear;
+
+ ctx->Driver.Flush = flush;
+ ctx->Driver.ClearColor = clear_color;
+ ctx->Driver.Enable = enable;
+
+
+ // Does not apply for Mesa 5.x
+ //ctx->Driver.BaseCompressedTexFormat = _mesa_base_compressed_texformat;
+ //ctx->Driver.CompressedTextureSize = _mesa_compressed_texture_size;
+ //ctx->Driver.GetCompressedTexImage = _mesa_get_compressed_teximage;
+
+ swdd->SetBuffer = set_read_buffer;
+
+
+ /* Pixel/span writing functions: */
+ swdd->WriteRGBASpan = write_rgba_span;
+ swdd->WriteRGBSpan = write_rgb_span;
+ swdd->WriteMonoRGBASpan = write_mono_rgba_span;
+ swdd->WriteRGBAPixels = write_rgba_pixels;
+ swdd->WriteMonoRGBAPixels = write_mono_rgba_pixels;
+ swdd->WriteCI32Span = write_ci32_span;
+ swdd->WriteCI8Span = write_ci8_span;
+ swdd->WriteMonoCISpan = write_mono_ci_span;
+ swdd->WriteCI32Pixels = write_ci32_pixels;
+ swdd->WriteMonoCIPixels = write_mono_ci_pixels;
+
+ swdd->ReadCI32Span = read_ci32_span;
+ swdd->ReadRGBASpan = read_rgba_span;
+ swdd->ReadCI32Pixels = read_ci32_pixels;
+ swdd->ReadRGBAPixels = read_rgba_pixels;
+
+
+ tnl->Driver.RunPipeline = _tnl_run_pipeline;
+
+ wmesa_update_state(ctx, new_state);
+}
+
+//---------------------------------------------------------------------------
+// Driver interface functions
+//---------------------------------------------------------------------------
+
+BOOL gldCreateDrawable_MesaSW(
+ DGL_ctx *pCtx,
+ BOOL bPersistantInterface,
+ BOOL bPersistantBuffers)
+{
+ WMesaContext *c;
+ GLboolean true_color_flag;
+ GLboolean rgb_flag = GL_TRUE;
+ GLboolean db_flag = GL_TRUE;
+
+ if (pCtx == NULL)
+ return FALSE;
+
+ c = (struct wmesa_context * ) calloc(1,sizeof(struct wmesa_context));
+ if (!c)
+ return FALSE;
+
+ pCtx->glPriv = c;
+
+ c->hDC = pCtx->hDC;
+ c->Window = pCtx->hWnd;
+
+ true_color_flag = GetDeviceCaps(pCtx->hDC, BITSPIXEL) > 8;
+
+
+#ifdef DITHER
+ if ((true_color_flag==GL_FALSE) && (rgb_flag == GL_TRUE)){
+ c->dither_flag = GL_TRUE;
+ c->hPalHalfTone = WinGCreateHalftonePalette();
+ }
+ else
+ c->dither_flag = GL_FALSE;
+#else
+ c->dither_flag = GL_FALSE;
+#endif
+
+
+ if (rgb_flag==GL_FALSE)
+ {
+ c->rgb_flag = GL_FALSE;
+#if 0
+ /* Old WinG stuff???? */
+ c->db_flag = db_flag =GL_TRUE; /* WinG requires double buffering */
+ printf("Single buffer is not supported in color index mode, ",
+ "setting to double buffer.\n");
+#endif
+ }
+ else
+ {
+ c->rgb_flag = GL_TRUE;
+ }
+
+// db_flag = pCtx->lpPF->pfd.dwFlags & PFD_DOUBLEBUFFER ? GL_TRUE : GL_FALSE;
+ db_flag = GL_TRUE; // Force double-buffer
+ if (db_flag) {
+ c->db_flag = 1;
+ /* Double buffered */
+ {
+ wmCreateBackingStore(c, pCtx->dwWidth, pCtx->dwHeight);
+
+ }
+ } else {
+ /* Single Buffered */
+ if (c->rgb_flag)
+ c->db_flag = 0;
+ }
+
+ c->bEmulateSingleBuffer = (pCtx->lpPF->pfd.dwFlags & PFD_DOUBLEBUFFER)
+ ? FALSE : TRUE;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldResizeDrawable_MesaSW(
+ DGL_ctx *ctx,
+ BOOL bDefaultDriver,
+ BOOL bPersistantInterface,
+ BOOL bPersistantBuffers)
+{
+ WMesaContext *c;
+
+ if (ctx == NULL)
+ return FALSE;
+
+ c = ctx->glPriv;
+ if (c == NULL)
+ return FALSE;
+
+ c->hDC = ctx->hDC;
+ c->Window = ctx->hWnd;
+// c->width = ctx->dwWidth;
+// c->height = ctx->dwHeight;
+
+ if (c->db_flag) {
+ wmDeleteBackingStore(c);
+ wmCreateBackingStore(c, ctx->dwWidth, ctx->dwHeight);
+ }
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldDestroyDrawable_MesaSW(
+ DGL_ctx *ctx)
+{
+ WMesaContext *c;
+
+ if (ctx == NULL)
+ return FALSE;
+
+ c = ctx->glPriv;
+ if (c == NULL)
+ return FALSE;
+
+ if (c->hPalHalfTone != NULL)
+ DeleteObject(c->hPalHalfTone);
+
+ if (c->db_flag)
+ wmDeleteBackingStore(c);
+
+ free(c);
+
+ ctx->glPriv = NULL;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldCreatePrivateGlobals_MesaSW(void)
+{
+ // Mesa Software driver needs no private globals
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldDestroyPrivateGlobals_MesaSW(void)
+{
+ // Mesa Software driver needs no private globals
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldBuildPixelformatList_MesaSW(void)
+{
+ // Release any existing pixelformat list
+ if (glb.lpPF) {
+ free(glb.lpPF);
+ }
+
+ glb.nPixelFormatCount = 0;
+ glb.lpPF = NULL;
+
+ glb.lpPF = (DGL_pixelFormat *)calloc(2, sizeof(DGL_pixelFormat));
+ if (glb.lpPF == NULL)
+ return FALSE;
+ // Single-buffered
+ memcpy(&glb.lpPF[0], &pfTemplateMesaSW, sizeof(DGL_pixelFormat));
+ glb.lpPF[0].pfd.dwFlags &= ~PFD_DOUBLEBUFFER; // Remove doublebuffer flag
+ // Double-buffered
+ memcpy(&glb.lpPF[1], &pfTemplateMesaSW, sizeof(DGL_pixelFormat));
+ glb.nPixelFormatCount = 2;
+
+ // Mark list as 'current'
+ glb.bPixelformatsDirty = FALSE;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldInitialiseMesa_MesaSW(
+ DGL_ctx *gld)
+{
+ struct gl_context *ctx;
+
+ if (gld == NULL)
+ return FALSE;
+
+ ctx = gld->glCtx;
+
+ // Set max texture size to 256
+ ctx->Const.MaxTextureLevels = 8;
+
+ // Multitexture enable/disable
+ ctx->Const.MaxTextureUnits = (glb.bMultitexture) ? MAX_TEXTURE_UNITS : 1;
+
+ /* Initialize the software rasterizer and helper modules.*/
+
+ // Added this to force max texture diminsion to 256. KeithH
+ ctx->Const.MaxTextureLevels = 8;
+ ctx->Const.MaxDrawBuffers = 1;
+
+ _mesa_enable_sw_extensions(ctx);
+ _mesa_enable_imaging_extensions(ctx);
+ _mesa_enable_1_3_extensions(ctx);
+
+// _swrast_CreateContext( ctx );
+// _vbo_CreateContext( ctx );
+// _tnl_CreateContext( ctx );
+// _swsetup_CreateContext( ctx );
+
+ _swsetup_Wakeup( ctx );
+
+ wmesa_update_state_first_time(ctx, ~0);
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldSwapBuffers_MesaSW(
+ DGL_ctx *ctx,
+ HDC hDC,
+ HWND hWnd)
+{
+ WMesaContext *c;
+
+ if (ctx == NULL)
+ return FALSE;
+
+ c = ctx->glPriv;
+ if (c == NULL)
+ return FALSE;
+
+ /* If we're swapping the buffer associated with the current context
+ * we have to flush any pending rendering commands first.
+ */
+
+ // Altered to respect bEmulateSingleBuffer. KeithH
+// if (c->db_flag)
+ if (!c->bEmulateSingleBuffer)
+ wmFlush(c, hDC);
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+PROC gldGetProcAddress_MesaSW(
+ LPCSTR a)
+{
+ int i;
+ PROC proc = NULL;
+
+ for (i=0; GLD_extList[i].proc; i++) {
+ if (!strcmp(a, GLD_extList[i].name)) {
+ proc = GLD_extList[i].proc;
+ break;
+ }
+ }
+
+ gldLogPrintf(GLDLOG_INFO, "GetProcAddress: %s (%s)", a, proc ? "OK" : "Failed");
+
+ return proc;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldGetDisplayMode_MesaSW(
+ DGL_ctx *ctx,
+ GLD_displayMode *glddm)
+{
+ HDC hdcDesktop;
+
+ if (glddm == NULL)
+ return FALSE;
+
+ //
+ // A bit hacky... KeithH
+ //
+
+ hdcDesktop = GetDC(NULL);
+ glddm->Width = GetDeviceCaps(hdcDesktop, HORZRES);
+ glddm->Height = GetDeviceCaps(hdcDesktop, VERTRES);
+ glddm->BPP = GetDeviceCaps(hdcDesktop, BITSPIXEL);
+ glddm->Refresh = 0;
+ ReleaseDC(0, hdcDesktop);
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
diff --git a/mesalib/src/mesa/drivers/windows/gldirect/opengl32.ref b/mesalib/src/mesa/drivers/windows/gldirect/opengl32.ref
new file mode 100644
index 000000000..3a4933e54
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/gldirect/opengl32.ref
@@ -0,0 +1,495 @@
+;****************************************************************************
+;*
+;* Mesa 3-D graphics library
+;* Direct3D Driver Interface
+;*
+;* ========================================================================
+;*
+;* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+;*
+;* Permission is hereby granted, free of charge, to any person obtaining a
+;* copy of this software and associated documentation files (the "Software"),
+;* to deal in the Software without restriction, including without limitation
+;* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+;* and/or sell copies of the Software, and to permit persons to whom the
+;* Software is furnished to do so, subject to the following conditions:
+;*
+;* The above copyright notice and this permission notice shall be included
+;* in all copies or substantial portions of the Software.
+;*
+;* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+;* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+;* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+;* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+;* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+;* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+;* SOFTWARE.
+;*
+;* ======================================================================
+;*
+;* Language: ANSI C
+;* Environment: Windows 9x/2000/XP/XBox (Win32)
+;*
+;* Description: DLL Module definition file
+;*
+;****************************************************************************/
+
+DESCRIPTION 'GLDirect'
+
+VERSION 3.0
+
+EXPORTS
+ glAccum
+ glAlphaFunc
+ glAreTexturesResident
+ glArrayElement
+ glBegin
+ glBindTexture
+ glBitmap
+ glBlendFunc
+ glCallList
+ glCallLists
+ glClear
+ glClearAccum
+ glClearIndex
+ glClearColor
+ glClearDepth
+ glClearStencil
+ glClipPlane
+ glColor3b
+ glColor3d
+ glColor3f
+ glColor3i
+ glColor3s
+ glColor3ub
+ glColor3ui
+ glColor3us
+ glColor4b
+ glColor4d
+ glColor4f
+ glColor4i
+ glColor4s
+ glColor4ub
+ glColor4ui
+ glColor4us
+ glColor3bv
+ glColor3dv
+ glColor3fv
+ glColor3iv
+ glColor3sv
+ glColor3ubv
+ glColor3uiv
+ glColor3usv
+ glColor4bv
+ glColor4dv
+ glColor4fv
+ glColor4iv
+ glColor4sv
+ glColor4ubv
+ glColor4uiv
+ glColor4usv
+ glColorMask
+ glColorMaterial
+ glColorPointer
+ glColorTableEXT
+ glColorSubTableEXT
+ glCopyPixels
+ glCopyTexImage1D
+ glCopyTexImage2D
+ glCopyTexSubImage1D
+ glCopyTexSubImage2D
+ glCullFace
+ glDepthFunc
+ glDepthMask
+ glDepthRange
+ glDeleteLists
+ glDeleteTextures
+ glDisable
+ glDisableClientState
+ glDrawArrays
+ glDrawBuffer
+ glDrawElements
+ glDrawPixels
+ glEnable
+ glEnableClientState
+ glEnd
+ glEndList
+ glEvalCoord1d
+ glEvalCoord1f
+ glEvalCoord1dv
+ glEvalCoord1fv
+ glEvalCoord2d
+ glEvalCoord2f
+ glEvalCoord2dv
+ glEvalCoord2fv
+ glEvalPoint1
+ glEvalPoint2
+ glEvalMesh1
+ glEdgeFlag
+ glEdgeFlagv
+ glEdgeFlagPointer
+ glEvalMesh2
+ glFeedbackBuffer
+ glFinish
+ glFlush
+ glFogf
+ glFogi
+ glFogfv
+ glFogiv
+ glFrontFace
+ glFrustum
+ glGenLists
+ glGenTextures
+ glGetBooleanv
+ glGetClipPlane
+ glGetColorTableEXT
+ glGetColorTableParameterivEXT
+ glGetColorTableParameterfvEXT
+ glGetDoublev
+ glGetError
+ glGetFloatv
+ glGetIntegerv
+ glGetLightfv
+ glGetLightiv
+ glGetMapdv
+ glGetMapfv
+ glGetMapiv
+ glGetMaterialfv
+ glGetMaterialiv
+ glGetPixelMapfv
+ glGetPixelMapuiv
+ glGetPixelMapusv
+ glGetPointerv
+ glGetPolygonStipple
+ glGetString
+ glGetTexEnvfv
+ glGetTexEnviv
+ glGetTexGeniv
+ glGetTexGendv
+ glGetTexGenfv
+ glGetTexImage
+ glGetTexLevelParameterfv
+ glGetTexLevelParameteriv
+ glGetTexParameterfv
+ glGetTexParameteriv
+ glHint
+ glIndexd
+ glIndexf
+ glIndexi
+ glIndexs
+ glIndexub
+ glIndexdv
+ glIndexfv
+ glIndexiv
+ glIndexsv
+ glIndexubv
+ glIndexMask
+ glIndexPointer
+ glInterleavedArrays
+ glInitNames
+ glIsList
+ glIsTexture
+ glLightf
+ glLighti
+ glLightfv
+ glLightiv
+ glLightModelf
+ glLightModeli
+ glLightModelfv
+ glLightModeliv
+ glLineWidth
+ glLineStipple
+ glListBase
+ glLoadIdentity
+ glLoadMatrixd
+ glLoadMatrixf
+ glLoadName
+ glLogicOp
+ glMap1d
+ glMap1f
+ glMap2d
+ glMap2f
+ glMapGrid1d
+ glMapGrid1f
+ glMapGrid2d
+ glMapGrid2f
+ glMaterialf
+ glMateriali
+ glMaterialfv
+ glMaterialiv
+ glMatrixMode
+ glMultMatrixd
+ glMultMatrixf
+ glNewList
+ glNormal3b
+ glNormal3d
+ glNormal3f
+ glNormal3i
+ glNormal3s
+ glNormal3bv
+ glNormal3dv
+ glNormal3fv
+ glNormal3iv
+ glNormal3sv
+ glNormalPointer
+ glOrtho
+ glPassThrough
+ glPixelMapfv
+ glPixelMapuiv
+ glPixelMapusv
+ glPixelStoref
+ glPixelStorei
+ glPixelTransferf
+ glPixelTransferi
+ glPixelZoom
+ glPointSize
+ glPolygonMode
+ glPolygonOffset
+ glPolygonOffsetEXT
+ glPolygonStipple
+ glPopAttrib
+ glPopClientAttrib
+ glPopMatrix
+ glPopName
+ glPrioritizeTextures
+ glPushMatrix
+ glRasterPos2d
+ glRasterPos2f
+ glRasterPos2i
+ glRasterPos2s
+ glRasterPos3d
+ glRasterPos3f
+ glRasterPos3i
+ glRasterPos3s
+ glRasterPos4d
+ glRasterPos4f
+ glRasterPos4i
+ glRasterPos4s
+ glRasterPos2dv
+ glRasterPos2fv
+ glRasterPos2iv
+ glRasterPos2sv
+ glRasterPos3dv
+ glRasterPos3fv
+ glRasterPos3iv
+ glRasterPos3sv
+ glRasterPos4dv
+ glRasterPos4fv
+ glRasterPos4iv
+ glRasterPos4sv
+ glReadBuffer
+ glReadPixels
+ glRectd
+ glRectf
+ glRecti
+ glRects
+ glRectdv
+ glRectfv
+ glRectiv
+ glRectsv
+ glScissor
+ glIsEnabled
+ glPushAttrib
+ glPushClientAttrib
+ glPushName
+ glRenderMode
+ glRotated
+ glRotatef
+ glSelectBuffer
+ glScaled
+ glScalef
+ glShadeModel
+ glStencilFunc
+ glStencilMask
+ glStencilOp
+ glTexCoord1d
+ glTexCoord1f
+ glTexCoord1i
+ glTexCoord1s
+ glTexCoord2d
+ glTexCoord2f
+ glTexCoord2i
+ glTexCoord2s
+ glTexCoord3d
+ glTexCoord3f
+ glTexCoord3i
+ glTexCoord3s
+ glTexCoord4d
+ glTexCoord4f
+ glTexCoord4i
+ glTexCoord4s
+ glTexCoord1dv
+ glTexCoord1fv
+ glTexCoord1iv
+ glTexCoord1sv
+ glTexCoord2dv
+ glTexCoord2fv
+ glTexCoord2iv
+ glTexCoord2sv
+ glTexCoord3dv
+ glTexCoord3fv
+ glTexCoord3iv
+ glTexCoord3sv
+ glTexCoord4dv
+ glTexCoord4fv
+ glTexCoord4iv
+ glTexCoord4sv
+ glTexCoordPointer
+ glTexGend
+ glTexGenf
+ glTexGeni
+ glTexGendv
+ glTexGeniv
+ glTexGenfv
+ glTexEnvf
+ glTexEnvi
+ glTexEnvfv
+ glTexEnviv
+ glTexImage1D
+ glTexImage2D
+ glTexParameterf
+ glTexParameteri
+ glTexParameterfv
+ glTexParameteriv
+ glTexSubImage1D
+ glTexSubImage2D
+ glTranslated
+ glTranslatef
+ glVertex2d
+ glVertex2f
+ glVertex2i
+ glVertex2s
+ glVertex3d
+ glVertex3f
+ glVertex3i
+ glVertex3s
+ glVertex4d
+ glVertex4f
+ glVertex4i
+ glVertex4s
+ glVertex2dv
+ glVertex2fv
+ glVertex2iv
+ glVertex2sv
+ glVertex3dv
+ glVertex3fv
+ glVertex3iv
+ glVertex3sv
+ glVertex4dv
+ glVertex4fv
+ glVertex4iv
+ glVertex4sv
+ glVertexPointer
+ glViewport
+
+ glBlendEquationEXT
+ glBlendColorEXT
+ glVertexPointerEXT
+ glNormalPointerEXT
+ glColorPointerEXT
+ glIndexPointerEXT
+ glTexCoordPointerEXT
+ glEdgeFlagPointerEXT
+ glGetPointervEXT
+ glArrayElementEXT
+ glDrawArraysEXT
+ glBindTextureEXT
+ glDeleteTexturesEXT
+ glGenTexturesEXT
+ glPrioritizeTexturesEXT
+ glCopyTexSubImage3DEXT
+ glTexImage3DEXT
+ glTexSubImage3DEXT
+
+ glWindowPos4fMESA
+ glWindowPos2iMESA
+ glWindowPos2sMESA
+ glWindowPos2fMESA
+ glWindowPos2dMESA
+ glWindowPos2ivMESA
+ glWindowPos2svMESA
+ glWindowPos2fvMESA
+ glWindowPos2dvMESA
+ glWindowPos3iMESA
+ glWindowPos3sMESA
+ glWindowPos3fMESA
+ glWindowPos3dMESA
+ glWindowPos3ivMESA
+ glWindowPos3svMESA
+ glWindowPos3fvMESA
+ glWindowPos3dvMESA
+ glWindowPos4iMESA
+ glWindowPos4sMESA
+ glWindowPos4dMESA
+ glWindowPos4ivMESA
+ glWindowPos4svMESA
+ glWindowPos4fvMESA
+ glWindowPos4dvMESA
+ glResizeBuffersMESA
+
+ wglCopyContext
+ wglCreateContext
+ wglCreateLayerContext
+ wglDeleteContext
+ wglDescribeLayerPlane
+ wglGetCurrentContext
+ wglGetCurrentDC
+ wglGetLayerPaletteEntries
+ wglGetProcAddress
+ wglMakeCurrent
+ wglRealizeLayerPalette
+ wglSetLayerPaletteEntries
+ wglShareLists
+ wglSwapLayerBuffers
+ wglUseFontBitmapsA
+ wglUseFontBitmapsW
+ wglUseFontOutlinesA
+ wglUseFontOutlinesW
+
+;These functions are identical and therefore share the same addresses
+ ChoosePixelFormat = wglChoosePixelFormat
+ DescribePixelFormat = wglDescribePixelFormat
+ GetPixelFormat = wglGetPixelFormat
+ SetPixelFormat = wglSetPixelFormat
+ SwapBuffers = wglSwapBuffers
+
+ wglChoosePixelFormat
+ wglDescribePixelFormat
+ wglGetPixelFormat
+ wglSetPixelFormat
+ wglSwapBuffers
+
+ glActiveTextureARB
+ glClientActiveTextureARB
+ glMultiTexCoord1dARB
+ glMultiTexCoord1dvARB
+ glMultiTexCoord1fARB
+ glMultiTexCoord1fvARB
+ glMultiTexCoord1iARB
+ glMultiTexCoord1ivARB
+ glMultiTexCoord1sARB
+ glMultiTexCoord1svARB
+ glMultiTexCoord2dARB
+ glMultiTexCoord2dvARB
+ glMultiTexCoord2fARB
+ glMultiTexCoord2fvARB
+ glMultiTexCoord2iARB
+ glMultiTexCoord2ivARB
+ glMultiTexCoord2sARB
+ glMultiTexCoord2svARB
+ glMultiTexCoord3dARB
+ glMultiTexCoord3dvARB
+ glMultiTexCoord3fARB
+ glMultiTexCoord3fvARB
+ glMultiTexCoord3iARB
+ glMultiTexCoord3ivARB
+ glMultiTexCoord3sARB
+ glMultiTexCoord3svARB
+ glMultiTexCoord4dARB
+ glMultiTexCoord4dvARB
+ glMultiTexCoord4fARB
+ glMultiTexCoord4fvARB
+ glMultiTexCoord4iARB
+ glMultiTexCoord4ivARB
+ glMultiTexCoord4sARB
+ glMultiTexCoord4svARB