mesa: Delete libmesa_classic
We no longer have any classic drivers, so we no longer need libmesa_classic Reviewed-by: Emma Anholt <emma@anholt.net> Acked-by: Jason Ekstrand <jason@jlekstrand.net> Acked-by: Kenneth Graunke <kenneth@whitecape.org> Reviewed-by: Adam Jackson <ajax@redhat.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10153>
This commit is contained in:
parent
bc2d3e7b5f
commit
e030d5ba8a
|
@ -1,312 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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/accum.h"
|
||||
#include "main/arrayobj.h"
|
||||
#include "main/context.h"
|
||||
#include "main/draw.h"
|
||||
#include "main/formatquery.h"
|
||||
#include "main/framebuffer.h"
|
||||
#include "main/mipmap.h"
|
||||
#include "main/queryobj.h"
|
||||
#include "main/readpix.h"
|
||||
#include "main/rastpos.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/texstorage.h"
|
||||
#include "main/texstore.h"
|
||||
#include "main/bufferobj.h"
|
||||
#include "main/fbobject.h"
|
||||
#include "main/samplerobj.h"
|
||||
#include "main/syncobj.h"
|
||||
#include "main/barrier.h"
|
||||
#include "main/transformfeedback.h"
|
||||
#include "main/externalobjects.h"
|
||||
|
||||
#include "program/program.h"
|
||||
#include "tnl/tnl.h"
|
||||
#include "swrast/swrast.h"
|
||||
#include "swrast/s_renderbuffer.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->Finish = NULL;
|
||||
driver->Flush = NULL;
|
||||
|
||||
/* framebuffer/image functions */
|
||||
driver->Clear = _swrast_Clear;
|
||||
driver->RasterPos = _mesa_RasterPos;
|
||||
driver->DrawPixels = _swrast_DrawPixels;
|
||||
driver->ReadPixels = _mesa_readpixels;
|
||||
driver->CopyPixels = _swrast_CopyPixels;
|
||||
driver->Bitmap = _swrast_Bitmap;
|
||||
|
||||
/* Texture functions */
|
||||
driver->ChooseTextureFormat = _mesa_choose_tex_format;
|
||||
driver->QueryInternalFormat = _mesa_query_internal_format_default;
|
||||
driver->TexImage = _mesa_store_teximage;
|
||||
driver->TexSubImage = _mesa_store_texsubimage;
|
||||
driver->GetTexSubImage = _mesa_meta_GetTexSubImage;
|
||||
driver->ClearTexSubImage = _mesa_meta_ClearTexSubImage;
|
||||
driver->CopyTexSubImage = _mesa_meta_CopyTexSubImage;
|
||||
driver->GenerateMipmap = _mesa_meta_GenerateMipmap;
|
||||
driver->TestProxyTexImage = _mesa_test_proxy_teximage;
|
||||
driver->CompressedTexImage = _mesa_store_compressed_teximage;
|
||||
driver->CompressedTexSubImage = _mesa_store_compressed_texsubimage;
|
||||
driver->BindTexture = NULL;
|
||||
driver->NewTextureObject = _mesa_new_texture_object;
|
||||
driver->DeleteTexture = _mesa_delete_texture_object;
|
||||
driver->NewTextureImage = _swrast_new_texture_image;
|
||||
driver->DeleteTextureImage = _swrast_delete_texture_image;
|
||||
driver->AllocTextureImageBuffer = _swrast_alloc_texture_image_buffer;
|
||||
driver->FreeTextureImageBuffer = _swrast_free_texture_image_buffer;
|
||||
driver->MapTextureImage = _swrast_map_teximage;
|
||||
driver->UnmapTextureImage = _swrast_unmap_teximage;
|
||||
driver->DrawTex = _mesa_meta_DrawTex;
|
||||
|
||||
/* Vertex/fragment programs */
|
||||
driver->NewProgram = _mesa_new_program;
|
||||
driver->DeleteProgram = _mesa_delete_program;
|
||||
|
||||
/* ATI_fragment_shader */
|
||||
driver->NewATIfs = NULL;
|
||||
|
||||
/* Draw functions */
|
||||
driver->Draw = NULL;
|
||||
driver->DrawGallium = _mesa_draw_gallium_fallback;
|
||||
driver->DrawGalliumMultiMode = _mesa_draw_gallium_multimode_fallback;
|
||||
driver->DrawIndirect = NULL;
|
||||
driver->DrawTransformFeedback = NULL;
|
||||
|
||||
/* simple state commands */
|
||||
driver->AlphaFunc = NULL;
|
||||
driver->BlendColor = NULL;
|
||||
driver->BlendEquationSeparate = NULL;
|
||||
driver->BlendFuncSeparate = NULL;
|
||||
driver->ClipPlane = NULL;
|
||||
driver->ColorMask = NULL;
|
||||
driver->ColorMaterial = NULL;
|
||||
driver->CullFace = NULL;
|
||||
driver->DrawBuffer = NULL;
|
||||
driver->FrontFace = NULL;
|
||||
driver->DepthFunc = NULL;
|
||||
driver->DepthMask = NULL;
|
||||
driver->DepthRange = NULL;
|
||||
driver->Enable = NULL;
|
||||
driver->Fogfv = 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);
|
||||
|
||||
/* memory objects */
|
||||
_mesa_init_memory_object_functions(driver);
|
||||
|
||||
driver->NewFramebuffer = _mesa_new_framebuffer;
|
||||
driver->NewRenderbuffer = _swrast_new_soft_renderbuffer;
|
||||
driver->MapRenderbuffer = _swrast_map_soft_renderbuffer;
|
||||
driver->UnmapRenderbuffer = _swrast_unmap_soft_renderbuffer;
|
||||
driver->RenderTexture = _swrast_render_texture;
|
||||
driver->FinishRenderTexture = _swrast_finish_render_texture;
|
||||
driver->FramebufferRenderbuffer = _mesa_FramebufferRenderbuffer_sw;
|
||||
driver->ValidateFramebuffer = _mesa_validate_framebuffer;
|
||||
|
||||
driver->BlitFramebuffer = _swrast_BlitFramebuffer;
|
||||
driver->DiscardFramebuffer = NULL;
|
||||
|
||||
_mesa_init_barrier_functions(driver);
|
||||
_mesa_init_shader_object_functions(driver);
|
||||
_mesa_init_transform_feedback_functions(driver);
|
||||
_mesa_init_sampler_object_functions(driver);
|
||||
|
||||
/* T&L stuff */
|
||||
driver->CurrentExecPrimitive = 0;
|
||||
driver->CurrentSavePrimitive = 0;
|
||||
driver->NeedFlush = 0;
|
||||
driver->SaveNeedFlush = 0;
|
||||
|
||||
driver->ProgramStringNotify = _tnl_program_string;
|
||||
driver->LightingSpaceChange = NULL;
|
||||
|
||||
/* GL_ARB_texture_storage */
|
||||
driver->AllocTextureStorage = _mesa_AllocTextureStorage_sw;
|
||||
|
||||
/* GL_ARB_texture_view */
|
||||
driver->TextureView = NULL;
|
||||
|
||||
/* GL_ARB_texture_multisample */
|
||||
driver->GetSamplePosition = NULL;
|
||||
|
||||
/* Multithreading */
|
||||
driver->SetBackgroundContext = 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.Blend[0].EquationRGB,
|
||||
ctx->Color.Blend[0].EquationA);
|
||||
|
||||
ctx->Driver.BlendFuncSeparate(ctx,
|
||||
ctx->Color.Blend[0].SrcRGB,
|
||||
ctx->Color.Blend[0].DstRGB,
|
||||
ctx->Color.Blend[0].SrcA,
|
||||
ctx->Color.Blend[0].DstA);
|
||||
|
||||
ctx->Driver.ColorMask(ctx,
|
||||
GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 0),
|
||||
GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 1),
|
||||
GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 2),
|
||||
GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 3));
|
||||
|
||||
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.EnableFlags);
|
||||
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);
|
||||
{
|
||||
GLfloat mode = (GLfloat) ctx->Fog.Mode;
|
||||
ctx->Driver.Fogfv(ctx, GL_FOG_MODE, &mode);
|
||||
}
|
||||
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->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);
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern void
|
||||
_mesa_init_driver_functions(struct dd_function_table *driver);
|
||||
|
||||
|
||||
extern void
|
||||
_mesa_init_driver_state(struct gl_context *ctx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -1,573 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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
|
||||
|
||||
#include "main/mtypes.h"
|
||||
|
||||
/**
|
||||
* \name Flags for meta operations
|
||||
* \{
|
||||
*
|
||||
* These flags are passed to _mesa_meta_begin().
|
||||
*/
|
||||
#define MESA_META_ALL ~0x0
|
||||
#define MESA_META_ALPHA_TEST 0x1
|
||||
#define MESA_META_BLEND 0x2 /**< includes logicop */
|
||||
#define MESA_META_COLOR_MASK 0x4
|
||||
#define MESA_META_DEPTH_TEST 0x8
|
||||
#define MESA_META_FOG 0x10
|
||||
#define MESA_META_PIXEL_STORE 0x20
|
||||
#define MESA_META_PIXEL_TRANSFER 0x40
|
||||
#define MESA_META_RASTERIZATION 0x80
|
||||
#define MESA_META_SCISSOR 0x100
|
||||
#define MESA_META_SHADER 0x200
|
||||
#define MESA_META_STENCIL_TEST 0x400
|
||||
#define MESA_META_TRANSFORM 0x800 /**< modelview/projection matrix state */
|
||||
#define MESA_META_TEXTURE 0x1000
|
||||
#define MESA_META_VERTEX 0x2000
|
||||
#define MESA_META_VIEWPORT 0x4000
|
||||
#define MESA_META_CLAMP_FRAGMENT_COLOR 0x8000
|
||||
#define MESA_META_CLAMP_VERTEX_COLOR 0x10000
|
||||
#define MESA_META_CONDITIONAL_RENDER 0x20000
|
||||
#define MESA_META_CLIP 0x40000
|
||||
#define MESA_META_SELECT_FEEDBACK 0x80000
|
||||
#define MESA_META_MULTISAMPLE 0x100000
|
||||
#define MESA_META_FRAMEBUFFER_SRGB 0x200000
|
||||
#define MESA_META_OCCLUSION_QUERY 0x400000
|
||||
#define MESA_META_DRAW_BUFFERS 0x800000
|
||||
#define MESA_META_DITHER 0x1000000
|
||||
/**\}*/
|
||||
|
||||
/**
|
||||
* State which we may save/restore across meta ops.
|
||||
* XXX this may be incomplete...
|
||||
*/
|
||||
struct save_state
|
||||
{
|
||||
GLbitfield SavedState; /**< bitmask of MESA_META_* flags */
|
||||
|
||||
/* Always saved/restored with meta. */
|
||||
gl_api API;
|
||||
uint8_t ExtensionsVersion;
|
||||
|
||||
/** MESA_META_CLEAR (and others?) */
|
||||
struct gl_query_object *CurrentOcclusionObject;
|
||||
|
||||
/** MESA_META_ALPHA_TEST */
|
||||
GLboolean AlphaEnabled;
|
||||
GLenum AlphaFunc;
|
||||
GLclampf AlphaRef;
|
||||
|
||||
/** MESA_META_BLEND */
|
||||
GLbitfield BlendEnabled;
|
||||
GLboolean ColorLogicOpEnabled;
|
||||
|
||||
/** MESA_META_DITHER */
|
||||
GLboolean DitherFlag;
|
||||
|
||||
/** MESA_META_COLOR_MASK */
|
||||
GLbitfield ColorMask;
|
||||
|
||||
/** MESA_META_DEPTH_TEST */
|
||||
struct gl_depthbuffer_attrib Depth;
|
||||
|
||||
/** MESA_META_FOG */
|
||||
GLboolean Fog;
|
||||
|
||||
/** MESA_META_PIXEL_STORE */
|
||||
struct gl_pixelstore_attrib Pack, Unpack;
|
||||
|
||||
/** MESA_META_PIXEL_TRANSFER */
|
||||
GLfloat RedBias, RedScale;
|
||||
GLfloat GreenBias, GreenScale;
|
||||
GLfloat BlueBias, BlueScale;
|
||||
GLfloat AlphaBias, AlphaScale;
|
||||
GLfloat DepthBias, DepthScale;
|
||||
GLboolean MapColorFlag;
|
||||
|
||||
/** MESA_META_RASTERIZATION */
|
||||
GLenum FrontPolygonMode, BackPolygonMode;
|
||||
GLboolean PolygonOffset;
|
||||
GLboolean PolygonSmooth;
|
||||
GLboolean PolygonStipple;
|
||||
GLboolean PolygonCull;
|
||||
|
||||
/** MESA_META_SCISSOR */
|
||||
struct gl_scissor_attrib Scissor;
|
||||
|
||||
/** MESA_META_SHADER */
|
||||
GLboolean VertexProgramEnabled;
|
||||
struct gl_program *VertexProgram;
|
||||
GLboolean FragmentProgramEnabled;
|
||||
struct gl_program *FragmentProgram;
|
||||
GLboolean ATIFragmentShaderEnabled;
|
||||
struct gl_program *Program[MESA_SHADER_STAGES];
|
||||
struct gl_shader_program *ActiveShader;
|
||||
struct gl_pipeline_object *Pipeline;
|
||||
|
||||
/** MESA_META_STENCIL_TEST */
|
||||
struct gl_stencil_attrib Stencil;
|
||||
|
||||
/** MESA_META_TRANSFORM */
|
||||
GLfloat ModelviewMatrix[16];
|
||||
GLfloat ProjectionMatrix[16];
|
||||
GLfloat TextureMatrix[16];
|
||||
/** GL_ARB_clip_control */
|
||||
GLenum ClipOrigin; /**< GL_LOWER_LEFT or GL_UPPER_LEFT */
|
||||
GLenum ClipDepthMode; /**< GL_NEGATIVE_ONE_TO_ONE or GL_ZERO_TO_ONE */
|
||||
|
||||
/** MESA_META_CLIP */
|
||||
GLbitfield ClipPlanesEnabled;
|
||||
|
||||
/** MESA_META_TEXTURE */
|
||||
GLuint ActiveUnit;
|
||||
/** 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 */
|
||||
|
||||
/** MESA_META_VERTEX */
|
||||
struct gl_vertex_array_object *VAO;
|
||||
|
||||
/** MESA_META_VIEWPORT */
|
||||
GLfloat ViewportX, ViewportY, ViewportW, ViewportH;
|
||||
GLclampf DepthNear, DepthFar;
|
||||
|
||||
/** MESA_META_CLAMP_FRAGMENT_COLOR */
|
||||
GLenum ClampFragmentColor;
|
||||
|
||||
/** MESA_META_CLAMP_VERTEX_COLOR */
|
||||
GLenum ClampVertexColor;
|
||||
|
||||
/** MESA_META_CONDITIONAL_RENDER */
|
||||
struct gl_query_object *CondRenderQuery;
|
||||
GLenum CondRenderMode;
|
||||
|
||||
/** MESA_META_SELECT_FEEDBACK */
|
||||
GLenum RenderMode;
|
||||
struct gl_selection Select;
|
||||
struct gl_feedback Feedback;
|
||||
|
||||
/** MESA_META_MULTISAMPLE */
|
||||
struct gl_multisample_attrib Multisample;
|
||||
|
||||
/** MESA_META_FRAMEBUFFER_SRGB */
|
||||
GLboolean sRGBEnabled;
|
||||
|
||||
/** Miscellaneous (always disabled) */
|
||||
GLboolean Lighting;
|
||||
GLboolean RasterDiscard;
|
||||
GLboolean TransformFeedbackNeedsResume;
|
||||
|
||||
struct gl_framebuffer *DrawBuffer;
|
||||
struct gl_framebuffer *ReadBuffer;
|
||||
|
||||
/** MESA_META_DRAW_BUFFERS */
|
||||
GLenum16 ColorDrawBuffers[MAX_DRAW_BUFFERS];
|
||||
};
|
||||
|
||||
/**
|
||||
* 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
|
||||
{
|
||||
struct gl_texture_object *tex_obj;
|
||||
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 GLSL texture sampler which is used to generate fragment
|
||||
* shader in _mesa_meta_generate_mipmap().
|
||||
*/
|
||||
struct blit_shader {
|
||||
const char *type;
|
||||
const char *func;
|
||||
const char *texcoords;
|
||||
struct gl_shader_program *shader_prog;
|
||||
};
|
||||
|
||||
/**
|
||||
* Table of all sampler types and shaders for accessing them.
|
||||
*/
|
||||
struct blit_shader_table {
|
||||
struct blit_shader sampler_1d;
|
||||
struct blit_shader sampler_2d;
|
||||
struct blit_shader sampler_3d;
|
||||
struct blit_shader sampler_rect;
|
||||
struct blit_shader sampler_cubemap;
|
||||
struct blit_shader sampler_1d_array;
|
||||
struct blit_shader sampler_2d_array;
|
||||
struct blit_shader sampler_cubemap_array;
|
||||
};
|
||||
|
||||
/**
|
||||
* State for glBlitFramebufer()
|
||||
*/
|
||||
struct blit_state
|
||||
{
|
||||
GLuint VAO;
|
||||
struct gl_buffer_object *buf_obj;
|
||||
struct blit_shader_table shaders_with_depth;
|
||||
struct blit_shader_table shaders_without_depth;
|
||||
struct temp_texture depthTex;
|
||||
bool no_ctsi_fallback;
|
||||
};
|
||||
|
||||
struct fb_tex_blit_state
|
||||
{
|
||||
GLint baseLevelSave, maxLevelSave;
|
||||
struct gl_sampler_object *samp_obj;
|
||||
struct gl_sampler_object *samp_obj_save;
|
||||
struct gl_texture_object *tex_obj;
|
||||
struct gl_texture_object *temp_tex_obj;
|
||||
GLuint stencilSamplingSave;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* State for glClear()
|
||||
*/
|
||||
struct clear_state
|
||||
{
|
||||
GLuint VAO;
|
||||
struct gl_buffer_object *buf_obj;
|
||||
struct gl_shader_program *ShaderProg;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* State for glCopyPixels()
|
||||
*/
|
||||
struct copypix_state
|
||||
{
|
||||
GLuint VAO;
|
||||
struct gl_buffer_object *buf_obj;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* State for glDrawPixels()
|
||||
*/
|
||||
struct drawpix_state
|
||||
{
|
||||
GLuint VAO;
|
||||
struct gl_buffer_object *buf_obj;
|
||||
|
||||
GLuint StencilFP; /**< Fragment program for drawing stencil images */
|
||||
GLuint DepthFP; /**< Fragment program for drawing depth images */
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* State for glBitmap()
|
||||
*/
|
||||
struct bitmap_state
|
||||
{
|
||||
GLuint VAO;
|
||||
struct gl_buffer_object *buf_obj;
|
||||
struct temp_texture Tex; /**< separate texture from other meta ops */
|
||||
};
|
||||
|
||||
/**
|
||||
* State for _mesa_meta_generate_mipmap()
|
||||
*/
|
||||
struct gen_mipmap_state
|
||||
{
|
||||
GLuint VAO;
|
||||
struct gl_buffer_object *buf_obj;
|
||||
struct gl_framebuffer *fb;
|
||||
struct gl_sampler_object *samp_obj;
|
||||
|
||||
struct blit_shader_table shaders;
|
||||
};
|
||||
|
||||
/**
|
||||
* One of the FBO states for decompress_state. There will be one for each
|
||||
* required renderbuffer format.
|
||||
*/
|
||||
struct decompress_fbo_state
|
||||
{
|
||||
struct gl_renderbuffer *rb;
|
||||
struct gl_framebuffer *fb;
|
||||
GLint Width, Height;
|
||||
};
|
||||
|
||||
/**
|
||||
* State for texture decompression
|
||||
*/
|
||||
struct decompress_state
|
||||
{
|
||||
GLuint VAO;
|
||||
struct decompress_fbo_state byteFBO, floatFBO;
|
||||
struct gl_buffer_object *buf_obj;
|
||||
struct gl_sampler_object *samp_obj;
|
||||
|
||||
struct blit_shader_table shaders;
|
||||
};
|
||||
|
||||
/**
|
||||
* State for glDrawTex()
|
||||
*/
|
||||
struct drawtex_state
|
||||
{
|
||||
GLuint VAO;
|
||||
struct gl_buffer_object *buf_obj;
|
||||
};
|
||||
|
||||
#define MAX_META_OPS_DEPTH 8
|
||||
/**
|
||||
* 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() */
|
||||
struct decompress_state Decompress; /**< For texture decompression */
|
||||
struct drawtex_state DrawTex; /**< For _mesa_meta_DrawTex() */
|
||||
};
|
||||
|
||||
struct vertex {
|
||||
GLfloat x, y, z, tex[4];
|
||||
GLfloat r, g, b, a;
|
||||
};
|
||||
|
||||
extern void
|
||||
_mesa_meta_init(struct gl_context *ctx);
|
||||
|
||||
extern void
|
||||
_mesa_meta_free(struct gl_context *ctx);
|
||||
|
||||
extern void
|
||||
_mesa_meta_begin(struct gl_context *ctx, GLbitfield state);
|
||||
|
||||
extern void
|
||||
_mesa_meta_end(struct gl_context *ctx);
|
||||
|
||||
static inline bool
|
||||
_mesa_meta_in_progress(struct gl_context *ctx)
|
||||
{
|
||||
return ctx->Meta->SaveStackDepth != 0;
|
||||
}
|
||||
|
||||
extern void
|
||||
_mesa_meta_fb_tex_blit_begin(struct gl_context *ctx,
|
||||
struct fb_tex_blit_state *blit);
|
||||
|
||||
extern void
|
||||
_mesa_meta_fb_tex_blit_end(struct gl_context *ctx, GLenum target,
|
||||
struct fb_tex_blit_state *blit);
|
||||
|
||||
extern GLbitfield
|
||||
_mesa_meta_BlitFramebuffer(struct gl_context *ctx,
|
||||
const struct gl_framebuffer *readFb,
|
||||
const struct gl_framebuffer *drawFb,
|
||||
GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
|
||||
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
|
||||
GLbitfield mask, GLenum filter);
|
||||
|
||||
extern void
|
||||
_mesa_meta_and_swrast_BlitFramebuffer(struct gl_context *ctx,
|
||||
struct gl_framebuffer *readFb,
|
||||
struct gl_framebuffer *drawFb,
|
||||
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_glsl_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 void
|
||||
_mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target,
|
||||
struct gl_texture_object *texObj);
|
||||
|
||||
extern void
|
||||
_mesa_meta_CopyTexSubImage(struct gl_context *ctx, GLuint dims,
|
||||
struct gl_texture_image *texImage,
|
||||
GLint xoffset, GLint yoffset, GLint slice,
|
||||
struct gl_renderbuffer *rb,
|
||||
GLint x, GLint y,
|
||||
GLsizei width, GLsizei height);
|
||||
|
||||
extern void
|
||||
_mesa_meta_ClearTexSubImage(struct gl_context *ctx,
|
||||
struct gl_texture_image *texImage,
|
||||
GLint xoffset, GLint yoffset, GLint zoffset,
|
||||
GLsizei width, GLsizei height, GLsizei depth,
|
||||
const GLvoid *clearValue);
|
||||
|
||||
extern void
|
||||
_mesa_meta_GetTexSubImage(struct gl_context *ctx,
|
||||
GLint xoffset, GLint yoffset, GLint zoffset,
|
||||
GLsizei width, GLsizei height, GLsizei depth,
|
||||
GLenum format, GLenum type, GLvoid *pixels,
|
||||
struct gl_texture_image *texImage);
|
||||
|
||||
extern void
|
||||
_mesa_meta_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z,
|
||||
GLfloat width, GLfloat height);
|
||||
|
||||
/* meta-internal functions */
|
||||
void
|
||||
_mesa_meta_drawbuffers_from_bitfield(GLbitfield bits);
|
||||
|
||||
void
|
||||
_mesa_meta_link_program_with_debug(struct gl_context *ctx,
|
||||
struct gl_shader_program *sh_prog);
|
||||
|
||||
void
|
||||
_mesa_meta_compile_and_link_program(struct gl_context *ctx,
|
||||
const char *vs_source,
|
||||
const char *fs_source,
|
||||
const char *name,
|
||||
struct gl_shader_program **sh_prog_ptr);
|
||||
|
||||
extern void
|
||||
_mesa_meta_use_program(struct gl_context *ctx,
|
||||
struct gl_shader_program *sh_prog);
|
||||
|
||||
GLboolean
|
||||
_mesa_meta_alloc_texture(struct temp_texture *tex,
|
||||
GLsizei width, GLsizei height, GLenum intFormat);
|
||||
|
||||
void
|
||||
_mesa_meta_setup_texture_coords(GLenum faceTarget,
|
||||
GLint slice,
|
||||
GLint xoffset,
|
||||
GLint yoffset,
|
||||
GLint width,
|
||||
GLint height,
|
||||
GLint total_width,
|
||||
GLint total_height,
|
||||
GLint total_depth,
|
||||
GLfloat coords0[4],
|
||||
GLfloat coords1[4],
|
||||
GLfloat coords2[4],
|
||||
GLfloat coords3[4]);
|
||||
|
||||
struct temp_texture *
|
||||
_mesa_meta_get_temp_texture(struct gl_context *ctx);
|
||||
|
||||
struct temp_texture *
|
||||
_mesa_meta_get_temp_depth_texture(struct gl_context *ctx);
|
||||
|
||||
void
|
||||
_mesa_meta_setup_vertex_objects(struct gl_context *ctx,
|
||||
GLuint *VAO, struct gl_buffer_object **buf_obj,
|
||||
bool use_generic_attributes,
|
||||
unsigned vertex_size, unsigned texcoord_size,
|
||||
unsigned color_size);
|
||||
|
||||
void
|
||||
_mesa_meta_setup_ff_tnl_for_blit(struct gl_context *ctx,
|
||||
GLuint *VAO, struct gl_buffer_object **buf_obj,
|
||||
unsigned texcoord_size);
|
||||
|
||||
void
|
||||
_mesa_meta_setup_drawpix_texture(struct gl_context *ctx,
|
||||
struct temp_texture *tex,
|
||||
GLboolean newTex,
|
||||
GLsizei width, GLsizei height,
|
||||
GLenum format, GLenum type,
|
||||
const GLvoid *pixels);
|
||||
|
||||
void
|
||||
_mesa_meta_setup_copypix_texture(struct gl_context *ctx,
|
||||
struct temp_texture *tex,
|
||||
GLint srcX, GLint srcY,
|
||||
GLsizei width, GLsizei height,
|
||||
GLenum intFormat,
|
||||
GLenum filter);
|
||||
|
||||
void
|
||||
_mesa_meta_setup_blit_shader(struct gl_context *ctx,
|
||||
GLenum target,
|
||||
bool do_depth,
|
||||
struct blit_shader_table *table);
|
||||
|
||||
void
|
||||
_mesa_meta_glsl_blit_cleanup(struct gl_context *ctx, struct blit_state *blit);
|
||||
|
||||
void
|
||||
_mesa_meta_blit_shader_table_cleanup(struct gl_context *ctx,
|
||||
struct blit_shader_table *table);
|
||||
|
||||
void
|
||||
_mesa_meta_glsl_generate_mipmap_cleanup(struct gl_context *ctx,
|
||||
struct gen_mipmap_state *mipmap);
|
||||
|
||||
void
|
||||
_mesa_meta_framebuffer_texture_image(struct gl_context *ctx,
|
||||
struct gl_framebuffer *fb,
|
||||
GLenum attachment,
|
||||
struct gl_texture_image *texImage,
|
||||
GLuint layer);
|
||||
|
||||
#endif /* META_H */
|
|
@ -1,543 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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/mtypes.h"
|
||||
#include "main/arbprogram.h"
|
||||
#include "main/arrayobj.h"
|
||||
#include "main/blend.h"
|
||||
#include "main/depth.h"
|
||||
#include "main/enable.h"
|
||||
#include "main/enums.h"
|
||||
#include "main/fbobject.h"
|
||||
#include "main/image.h"
|
||||
#include "main/macros.h"
|
||||
#include "main/matrix.h"
|
||||
#include "main/readpix.h"
|
||||
#include "main/scissor.h"
|
||||
#include "main/shaderapi.h"
|
||||
#include "main/texobj.h"
|
||||
#include "main/texenv.h"
|
||||
#include "main/teximage.h"
|
||||
#include "main/texparam.h"
|
||||
#include "main/uniforms.h"
|
||||
#include "main/varray.h"
|
||||
#include "main/viewport.h"
|
||||
#include "swrast/swrast.h"
|
||||
#include "drivers/common/meta.h"
|
||||
|
||||
static struct gl_texture_object *
|
||||
texture_object_from_renderbuffer(struct gl_context *, struct gl_renderbuffer *);
|
||||
|
||||
static struct gl_sampler_object *
|
||||
setup_sampler(struct gl_context *, struct gl_texture_object *, GLenum target,
|
||||
GLenum filter, GLuint srcLevel);
|
||||
|
||||
/** Return offset in bytes of the field within a vertex struct */
|
||||
#define OFFSET(FIELD) ((void *) offsetof(struct vertex, FIELD))
|
||||
|
||||
static void
|
||||
setup_glsl_blit_framebuffer(struct gl_context *ctx,
|
||||
struct blit_state *blit,
|
||||
const struct gl_framebuffer *drawFb,
|
||||
struct gl_renderbuffer *src_rb,
|
||||
GLenum target,
|
||||
bool do_depth)
|
||||
{
|
||||
const unsigned texcoord_size = 2 + (src_rb->Depth > 1 ? 1 : 0);
|
||||
|
||||
/* target = GL_TEXTURE_RECTANGLE is not supported in GLES 3.0 */
|
||||
assert(_mesa_is_desktop_gl(ctx) || target == GL_TEXTURE_2D);
|
||||
|
||||
|
||||
_mesa_meta_setup_vertex_objects(ctx, &blit->VAO, &blit->buf_obj, true,
|
||||
2, texcoord_size, 0);
|
||||
|
||||
_mesa_meta_setup_blit_shader(ctx, target, do_depth,
|
||||
do_depth ? &blit->shaders_with_depth
|
||||
: &blit->shaders_without_depth);
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to do a color or depth glBlitFramebuffer using texturing.
|
||||
*
|
||||
* We can do this when the src renderbuffer is actually a texture, or when the
|
||||
* driver exposes BindRenderbufferTexImage().
|
||||
*/
|
||||
static bool
|
||||
blitframebuffer_texture(struct gl_context *ctx,
|
||||
const struct gl_framebuffer *readFb,
|
||||
const struct gl_framebuffer *drawFb,
|
||||
GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
|
||||
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
|
||||
GLenum filter, GLint flipX, GLint flipY,
|
||||
GLboolean glsl_version, GLboolean do_depth)
|
||||
{
|
||||
int att_index = do_depth ? BUFFER_DEPTH : readFb->_ColorReadBufferIndex;
|
||||
const struct gl_renderbuffer_attachment *readAtt =
|
||||
&readFb->Attachment[att_index];
|
||||
struct blit_state *blit = &ctx->Meta->Blit;
|
||||
struct fb_tex_blit_state fb_tex_blit;
|
||||
const GLint dstX = MIN2(dstX0, dstX1);
|
||||
const GLint dstY = MIN2(dstY0, dstY1);
|
||||
const GLint dstW = abs(dstX1 - dstX0);
|
||||
const GLint dstH = abs(dstY1 - dstY0);
|
||||
const int srcW = abs(srcX1 - srcX0);
|
||||
const int srcH = abs(srcY1 - srcY0);
|
||||
struct gl_texture_object *texObj;
|
||||
GLuint srcLevel;
|
||||
GLenum target;
|
||||
struct gl_renderbuffer *rb = readAtt->Renderbuffer;
|
||||
struct temp_texture *meta_temp_texture;
|
||||
|
||||
assert(rb->NumSamples == 0);
|
||||
|
||||
_mesa_meta_fb_tex_blit_begin(ctx, &fb_tex_blit);
|
||||
|
||||
if (readAtt->Texture &&
|
||||
(readAtt->Texture->Target == GL_TEXTURE_2D ||
|
||||
readAtt->Texture->Target == GL_TEXTURE_RECTANGLE)) {
|
||||
/* If there's a texture attached of a type we can handle, then just use
|
||||
* it directly.
|
||||
*/
|
||||
srcLevel = readAtt->TextureLevel;
|
||||
texObj = readAtt->Texture;
|
||||
} else if (!readAtt->Texture && ctx->Driver.BindRenderbufferTexImage) {
|
||||
texObj = texture_object_from_renderbuffer(ctx, rb);
|
||||
if (texObj == NULL)
|
||||
return false;
|
||||
|
||||
fb_tex_blit.temp_tex_obj = texObj;
|
||||
|
||||
srcLevel = 0;
|
||||
if (_mesa_is_winsys_fbo(readFb)) {
|
||||
GLint temp = srcY0;
|
||||
srcY0 = rb->Height - srcY1;
|
||||
srcY1 = rb->Height - temp;
|
||||
flipY = -flipY;
|
||||
}
|
||||
} else {
|
||||
GLenum tex_base_format;
|
||||
/* Fall back to doing a CopyTexSubImage to get the destination
|
||||
* renderbuffer into a texture.
|
||||
*/
|
||||
if (ctx->Meta->Blit.no_ctsi_fallback)
|
||||
return false;
|
||||
|
||||
if (do_depth) {
|
||||
meta_temp_texture = _mesa_meta_get_temp_depth_texture(ctx);
|
||||
tex_base_format = GL_DEPTH_COMPONENT;
|
||||
} else {
|
||||
meta_temp_texture = _mesa_meta_get_temp_texture(ctx);
|
||||
tex_base_format =
|
||||
_mesa_base_tex_format(ctx, rb->InternalFormat);
|
||||
}
|
||||
|
||||
srcLevel = 0;
|
||||
texObj = meta_temp_texture->tex_obj;
|
||||
if (texObj == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_mesa_meta_setup_copypix_texture(ctx, meta_temp_texture,
|
||||
srcX0, srcY0,
|
||||
srcW, srcH,
|
||||
tex_base_format,
|
||||
filter);
|
||||
|
||||
assert(texObj->Target == meta_temp_texture->Target);
|
||||
|
||||
srcX0 = 0;
|
||||
srcY0 = 0;
|
||||
srcX1 = srcW;
|
||||
srcY1 = srcH;
|
||||
}
|
||||
|
||||
target = texObj->Target;
|
||||
fb_tex_blit.tex_obj = texObj;
|
||||
fb_tex_blit.baseLevelSave = texObj->Attrib.BaseLevel;
|
||||
fb_tex_blit.maxLevelSave = texObj->Attrib.MaxLevel;
|
||||
fb_tex_blit.stencilSamplingSave = texObj->StencilSampling;
|
||||
|
||||
if (glsl_version) {
|
||||
setup_glsl_blit_framebuffer(ctx, blit, drawFb, rb, target, do_depth);
|
||||
}
|
||||
else {
|
||||
_mesa_meta_setup_ff_tnl_for_blit(ctx,
|
||||
&ctx->Meta->Blit.VAO,
|
||||
&ctx->Meta->Blit.buf_obj,
|
||||
2);
|
||||
}
|
||||
|
||||
/*
|
||||
printf("Blit from texture!\n");
|
||||
printf(" srcAtt %p dstAtt %p\n", readAtt, drawAtt);
|
||||
printf(" srcTex %p dstText %p\n", texObj, drawAtt->Texture);
|
||||
*/
|
||||
|
||||
fb_tex_blit.samp_obj = setup_sampler(ctx, texObj, target, filter, srcLevel);
|
||||
|
||||
if (ctx->Extensions.EXT_texture_sRGB_decode) {
|
||||
/* The GL 4.4 spec, section 18.3.1 ("Blitting Pixel Rectangles") says:
|
||||
*
|
||||
* "When values are taken from the read buffer, if FRAMEBUFFER_SRGB
|
||||
* is enabled and the value of FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING
|
||||
* for the framebuffer attachment corresponding to the read buffer
|
||||
* is SRGB (see section 9.2.3), the red, green, and blue components
|
||||
* are converted from the non-linear sRGB color space according to
|
||||
* equation 3.24.
|
||||
*
|
||||
* When values are written to the draw buffers, blit operations
|
||||
* bypass most of the fragment pipeline. The only fragment
|
||||
* operations which affect a blit are the pixel ownership test,
|
||||
* the scissor test, and sRGB conversion (see section 17.3.9)."
|
||||
*
|
||||
* ES 3.0 contains nearly the exact same text, but omits the part
|
||||
* about GL_FRAMEBUFFER_SRGB as that doesn't exist in ES. Mesa
|
||||
* defaults it to on for ES contexts, so we can safely check it.
|
||||
*/
|
||||
const bool decode =
|
||||
ctx->Color.sRGBEnabled && _mesa_is_format_srgb(rb->Format);
|
||||
|
||||
_mesa_set_sampler_srgb_decode(ctx, fb_tex_blit.samp_obj,
|
||||
decode ? GL_DECODE_EXT
|
||||
: GL_SKIP_DECODE_EXT);
|
||||
}
|
||||
|
||||
if (!glsl_version) {
|
||||
_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 verts[4];
|
||||
GLfloat s0, t0, s1, t1;
|
||||
|
||||
if (target == GL_TEXTURE_2D) {
|
||||
const struct gl_texture_image *texImage
|
||||
= _mesa_select_tex_image(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 = (float) srcX0;
|
||||
s1 = (float) srcX1;
|
||||
t0 = (float) srcY0;
|
||||
t1 = (float) srcY1;
|
||||
}
|
||||
|
||||
/* Silence valgrind warnings about reading uninitialized stack. */
|
||||
memset(verts, 0, sizeof(verts));
|
||||
|
||||
/* setup vertex positions */
|
||||
verts[0].x = -1.0F * flipX;
|
||||
verts[0].y = -1.0F * flipY;
|
||||
verts[1].x = 1.0F * flipX;
|
||||
verts[1].y = -1.0F * flipY;
|
||||
verts[2].x = 1.0F * flipX;
|
||||
verts[2].y = 1.0F * flipY;
|
||||
verts[3].x = -1.0F * flipX;
|
||||
verts[3].y = 1.0F * flipY;
|
||||
|
||||
verts[0].tex[0] = s0;
|
||||
verts[0].tex[1] = t0;
|
||||
verts[0].tex[2] = readAtt->Zoffset;
|
||||
verts[1].tex[0] = s1;
|
||||
verts[1].tex[1] = t0;
|
||||
verts[1].tex[2] = readAtt->Zoffset;
|
||||
verts[2].tex[0] = s1;
|
||||
verts[2].tex[1] = t1;
|
||||
verts[2].tex[2] = readAtt->Zoffset;
|
||||
verts[3].tex[0] = s0;
|
||||
verts[3].tex[1] = t1;
|
||||
verts[3].tex[2] = readAtt->Zoffset;
|
||||
|
||||
_mesa_buffer_sub_data(ctx, blit->buf_obj, 0, sizeof(verts), verts);
|
||||
}
|
||||
|
||||
/* setup viewport */
|
||||
_mesa_set_viewport(ctx, 0, dstX, dstY, dstW, dstH);
|
||||
_mesa_ColorMask(!do_depth, !do_depth, !do_depth, !do_depth);
|
||||
_mesa_set_enable(ctx, GL_DEPTH_TEST, do_depth);
|
||||
_mesa_DepthMask(do_depth);
|
||||
_mesa_DepthFunc(GL_ALWAYS);
|
||||
|
||||
_mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
_mesa_meta_fb_tex_blit_end(ctx, target, &fb_tex_blit);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
_mesa_meta_fb_tex_blit_begin(struct gl_context *ctx,
|
||||
struct fb_tex_blit_state *blit)
|
||||
{
|
||||
/* None of the existing callers preinitialize fb_tex_blit_state to zeros,
|
||||
* and both use stack variables. If samp_obj_save is not NULL,
|
||||
* _mesa_reference_sampler_object will try to dereference it. Leaving
|
||||
* random garbage in samp_obj_save can only lead to crashes.
|
||||
*
|
||||
* Since the state isn't persistent across calls, we won't catch ref
|
||||
* counting problems.
|
||||
*/
|
||||
blit->samp_obj_save = NULL;
|
||||
_mesa_reference_sampler_object(ctx, &blit->samp_obj_save,
|
||||
ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler);
|
||||
blit->temp_tex_obj = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
_mesa_meta_fb_tex_blit_end(struct gl_context *ctx, GLenum target,
|
||||
struct fb_tex_blit_state *blit)
|
||||
{
|
||||
struct gl_texture_object *const texObj =
|
||||
_mesa_get_current_tex_object(ctx, target);
|
||||
|
||||
/* Either there is no temporary texture or the temporary texture is bound. */
|
||||
assert(blit->temp_tex_obj == NULL || blit->temp_tex_obj == texObj);
|
||||
|
||||
/* Restore texture object state, the texture binding will be restored by
|
||||
* _mesa_meta_end(). If the texture is the temporary texture that is about
|
||||
* to be destroyed, don't bother restoring its state.
|
||||
*/
|
||||
if (blit->temp_tex_obj == NULL) {
|
||||
/* If the target restricts values for base level or max level, we assume
|
||||
* that the original values were valid.
|
||||
*/
|
||||
if (blit->baseLevelSave != texObj->Attrib.BaseLevel)
|
||||
_mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_BASE_LEVEL,
|
||||
&blit->baseLevelSave, false);
|
||||
|
||||
if (blit->maxLevelSave != texObj->Attrib.MaxLevel)
|
||||
_mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_MAX_LEVEL,
|
||||
&blit->maxLevelSave, false);
|
||||
|
||||
/* If ARB_stencil_texturing is not supported, the mode won't have changed. */
|
||||
if (texObj->StencilSampling != blit->stencilSamplingSave) {
|
||||
/* GLint so the compiler won't complain about type signedness mismatch
|
||||
* in the call to _mesa_texture_parameteriv below.
|
||||
*/
|
||||
const GLint param = blit->stencilSamplingSave ?
|
||||
GL_STENCIL_INDEX : GL_DEPTH_COMPONENT;
|
||||
|
||||
_mesa_texture_parameteriv(ctx, texObj, GL_DEPTH_STENCIL_TEXTURE_MODE,
|
||||
¶m, false);
|
||||
}
|
||||
}
|
||||
|
||||
_mesa_bind_sampler(ctx, ctx->Texture.CurrentUnit, blit->samp_obj_save);
|
||||
_mesa_reference_sampler_object(ctx, &blit->samp_obj_save, NULL);
|
||||
_mesa_reference_sampler_object(ctx, &blit->samp_obj, NULL);
|
||||
_mesa_delete_nameless_texture(ctx, blit->temp_tex_obj);
|
||||
}
|
||||
|
||||
static struct gl_texture_object *
|
||||
texture_object_from_renderbuffer(struct gl_context *ctx,
|
||||
struct gl_renderbuffer *rb)
|
||||
{
|
||||
struct gl_texture_image *texImage;
|
||||
struct gl_texture_object *texObj;
|
||||
const GLenum target = GL_TEXTURE_2D;
|
||||
|
||||
texObj = ctx->Driver.NewTextureObject(ctx, 0xDEADBEEF, target);
|
||||
texImage = _mesa_get_tex_image(ctx, texObj, target, 0);
|
||||
|
||||
if (!ctx->Driver.BindRenderbufferTexImage(ctx, rb, texImage)) {
|
||||
_mesa_delete_nameless_texture(ctx, texObj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (ctx->Driver.FinishRenderTexture && !rb->NeedsFinishRenderTexture) {
|
||||
rb->NeedsFinishRenderTexture = true;
|
||||
ctx->Driver.FinishRenderTexture(ctx, rb);
|
||||
}
|
||||
|
||||
return texObj;
|
||||
}
|
||||
|
||||
static struct gl_sampler_object *
|
||||
setup_sampler(struct gl_context *ctx, struct gl_texture_object *texObj,
|
||||
GLenum target, GLenum filter, GLuint srcLevel)
|
||||
{
|
||||
struct gl_sampler_object *samp_obj =
|
||||
ctx->Driver.NewSamplerObject(ctx, 0xDEADBEEF);
|
||||
|
||||
if (samp_obj == NULL)
|
||||
return NULL;
|
||||
|
||||
_mesa_bind_sampler(ctx, ctx->Texture.CurrentUnit, samp_obj);
|
||||
_mesa_set_sampler_filters(ctx, samp_obj, filter, filter);
|
||||
_mesa_set_sampler_wrap(ctx, samp_obj, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE,
|
||||
samp_obj->Attrib.WrapR);
|
||||
|
||||
/* Prepare src texture state */
|
||||
_mesa_bind_texture(ctx, target, texObj);
|
||||
if (target != GL_TEXTURE_RECTANGLE_ARB) {
|
||||
_mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_BASE_LEVEL,
|
||||
(GLint *) &srcLevel, false);
|
||||
_mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_MAX_LEVEL,
|
||||
(GLint *) &srcLevel, false);
|
||||
}
|
||||
|
||||
return samp_obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Meta implementation of ctx->Driver.BlitFramebuffer() in terms
|
||||
* of texture mapping and polygon rendering.
|
||||
*/
|
||||
GLbitfield
|
||||
_mesa_meta_BlitFramebuffer(struct gl_context *ctx,
|
||||
const struct gl_framebuffer *readFb,
|
||||
const struct gl_framebuffer *drawFb,
|
||||
GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
|
||||
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
|
||||
GLbitfield mask, GLenum filter)
|
||||
{
|
||||
const GLint dstW = abs(dstX1 - dstX0);
|
||||
const GLint dstH = abs(dstY1 - dstY0);
|
||||
const GLint dstFlipX = (dstX1 - dstX0) / dstW;
|
||||
const GLint dstFlipY = (dstY1 - dstY0) / dstH;
|
||||
|
||||
struct {
|
||||
GLint srcX0, srcY0, srcX1, srcY1;
|
||||
GLint dstX0, dstY0, dstX1, dstY1;
|
||||
} clip = {
|
||||
srcX0, srcY0, srcX1, srcY1,
|
||||
dstX0, dstY0, dstX1, dstY1
|
||||
};
|
||||
|
||||
const GLboolean use_glsl_version = ctx->Extensions.ARB_vertex_shader &&
|
||||
ctx->Extensions.ARB_fragment_shader;
|
||||
|
||||
/* Multisample blit is not supported. */
|
||||
if (readFb->Visual.samples > 0)
|
||||
return mask;
|
||||
|
||||
/* Clip a copy of the blit coordinates. If these differ from the input
|
||||
* coordinates, then we'll set the scissor.
|
||||
*/
|
||||
if (!_mesa_clip_blit(ctx, readFb, drawFb,
|
||||
&clip.srcX0, &clip.srcY0, &clip.srcX1, &clip.srcY1,
|
||||
&clip.dstX0, &clip.dstY0, &clip.dstX1, &clip.dstY1)) {
|
||||
/* clipped/scissored everything away */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Only scissor and FRAMEBUFFER_SRGB affect blit. Leave sRGB alone, but
|
||||
* save restore scissor as we'll set a custom scissor if necessary.
|
||||
*/
|
||||
_mesa_meta_begin(ctx, MESA_META_ALL &
|
||||
~(MESA_META_DRAW_BUFFERS |
|
||||
MESA_META_FRAMEBUFFER_SRGB));
|
||||
|
||||
/* Dithering shouldn't be performed for glBlitFramebuffer */
|
||||
_mesa_set_enable(ctx, GL_DITHER, GL_FALSE);
|
||||
|
||||
/* If the clipping earlier changed the destination rect at all, then
|
||||
* enable the scissor to clip to it.
|
||||
*/
|
||||
if (clip.dstX0 != dstX0 || clip.dstY0 != dstY0 ||
|
||||
clip.dstX1 != dstX1 || clip.dstY1 != dstY1) {
|
||||
_mesa_set_enable(ctx, GL_SCISSOR_TEST, GL_TRUE);
|
||||
_mesa_Scissor(MIN2(clip.dstX0, clip.dstX1),
|
||||
MIN2(clip.dstY0, clip.dstY1),
|
||||
abs(clip.dstX0 - clip.dstX1),
|
||||
abs(clip.dstY0 - clip.dstY1));
|
||||
}
|
||||
|
||||
/* Try faster, direct texture approach first */
|
||||
if (mask & GL_COLOR_BUFFER_BIT) {
|
||||
if (blitframebuffer_texture(ctx, readFb, drawFb,
|
||||
srcX0, srcY0, srcX1, srcY1,
|
||||
dstX0, dstY0, dstX1, dstY1,
|
||||
filter, dstFlipX, dstFlipY,
|
||||
use_glsl_version, false)) {
|
||||
mask &= ~GL_COLOR_BUFFER_BIT;
|
||||
}
|
||||
}
|
||||
|
||||
if (mask & GL_DEPTH_BUFFER_BIT && use_glsl_version) {
|
||||
if (blitframebuffer_texture(ctx, readFb, drawFb,
|
||||
srcX0, srcY0, srcX1, srcY1,
|
||||
dstX0, dstY0, dstX1, dstY1,
|
||||
filter, dstFlipX, dstFlipY,
|
||||
use_glsl_version, true)) {
|
||||
mask &= ~GL_DEPTH_BUFFER_BIT;
|
||||
}
|
||||
}
|
||||
|
||||
if (mask & GL_STENCIL_BUFFER_BIT) {
|
||||
/* XXX can't easily do stencil */
|
||||
}
|
||||
|
||||
_mesa_meta_end(ctx);
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
void
|
||||
_mesa_meta_glsl_blit_cleanup(struct gl_context *ctx, struct blit_state *blit)
|
||||
{
|
||||
if (blit->VAO) {
|
||||
_mesa_DeleteVertexArrays(1, &blit->VAO);
|
||||
blit->VAO = 0;
|
||||
_mesa_reference_buffer_object(ctx, &blit->buf_obj, NULL);
|
||||
}
|
||||
|
||||
_mesa_meta_blit_shader_table_cleanup(ctx, &blit->shaders_with_depth);
|
||||
_mesa_meta_blit_shader_table_cleanup(ctx, &blit->shaders_without_depth);
|
||||
|
||||
if (blit->depthTex.tex_obj != NULL) {
|
||||
_mesa_delete_nameless_texture(ctx, blit->depthTex.tex_obj);
|
||||
blit->depthTex.tex_obj = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_mesa_meta_and_swrast_BlitFramebuffer(struct gl_context *ctx,
|
||||
struct gl_framebuffer *readFb,
|
||||
struct gl_framebuffer *drawFb,
|
||||
GLint srcX0, GLint srcY0,
|
||||
GLint srcX1, GLint srcY1,
|
||||
GLint dstX0, GLint dstY0,
|
||||
GLint dstX1, GLint dstY1,
|
||||
GLbitfield mask, GLenum filter)
|
||||
{
|
||||
mask = _mesa_meta_BlitFramebuffer(ctx, readFb, drawFb,
|
||||
srcX0, srcY0, srcX1, srcY1,
|
||||
dstX0, dstY0, dstX1, dstY1,
|
||||
mask, filter);
|
||||
if (mask == 0x0)
|
||||
return;
|
||||
|
||||
_swrast_BlitFramebuffer(ctx, readFb, drawFb,
|
||||
srcX0, srcY0, srcX1, srcY1,
|
||||
dstX0, dstY0, dstX1, dstY1,
|
||||
mask, filter);
|
||||
}
|
|
@ -1,379 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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/arrayobj.h"
|
||||
#include "main/blend.h"
|
||||
#include "main/buffers.h"
|
||||
#include "main/enums.h"
|
||||
#include "main/enable.h"
|
||||
#include "main/fbobject.h"
|
||||
#include "main/framebuffer.h"
|
||||
#include "main/macros.h"
|
||||
#include "main/mipmap.h"
|
||||
#include "main/teximage.h"
|
||||
#include "main/texobj.h"
|
||||
#include "main/texparam.h"
|
||||
#include "main/varray.h"
|
||||
#include "main/viewport.h"
|
||||
#include "drivers/common/meta.h"
|
||||
#include "program/prog_instruction.h"
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
static bool
|
||||
fallback_required(struct gl_context *ctx, GLenum target,
|
||||
struct gl_texture_object *texObj)
|
||||
{
|
||||
struct gen_mipmap_state *mipmap = &ctx->Meta->Mipmap;
|
||||
struct gl_texture_image *baseImage;
|
||||
GLuint srcLevel;
|
||||
GLenum status;
|
||||
|
||||
/* check for fallbacks */
|
||||
if (target == GL_TEXTURE_3D) {
|
||||
_mesa_perf_debug(ctx, MESA_DEBUG_SEVERITY_HIGH,
|
||||
"glGenerateMipmap() to %s target\n",
|
||||
_mesa_enum_to_string(target));
|
||||
return true;
|
||||
}
|
||||
|
||||
srcLevel = texObj->Attrib.BaseLevel;
|
||||
baseImage = _mesa_select_tex_image(texObj, target, srcLevel);
|
||||
if (!baseImage) {
|
||||
_mesa_perf_debug(ctx, MESA_DEBUG_SEVERITY_HIGH,
|
||||
"glGenerateMipmap() couldn't find base teximage\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_mesa_is_format_compressed(baseImage->TexFormat)) {
|
||||
_mesa_perf_debug(ctx, MESA_DEBUG_SEVERITY_HIGH,
|
||||
"glGenerateMipmap() with %s format\n",
|
||||
_mesa_get_format_name(baseImage->TexFormat));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_mesa_is_format_srgb(baseImage->TexFormat) &&
|
||||
!ctx->Extensions.EXT_texture_sRGB_decode) {
|
||||
/* The texture format is sRGB but we can't turn off sRGB->linear
|
||||
* texture sample conversion. So we won't be able to generate the
|
||||
* right colors when rendering. Need to use a fallback.
|
||||
*/
|
||||
_mesa_perf_debug(ctx, MESA_DEBUG_SEVERITY_HIGH,
|
||||
"glGenerateMipmap() of sRGB texture without "
|
||||
"sRGB decode\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test that we can actually render in the texture's format.
|
||||
*/
|
||||
if (mipmap->fb == NULL) {
|
||||
mipmap->fb = ctx->Driver.NewFramebuffer(ctx, 0xDEADBEEF);
|
||||
if (mipmap->fb == NULL) {
|
||||
_mesa_perf_debug(ctx, MESA_DEBUG_SEVERITY_HIGH,
|
||||
"glGenerateMipmap() ran out of memory\n");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
_mesa_meta_framebuffer_texture_image(ctx, mipmap->fb,
|
||||
GL_COLOR_ATTACHMENT0, baseImage, 0);
|
||||
|
||||
status = _mesa_check_framebuffer_status(ctx, mipmap->fb);
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
|
||||
_mesa_perf_debug(ctx, MESA_DEBUG_SEVERITY_HIGH,
|
||||
"glGenerateMipmap() got incomplete FBO\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
_mesa_meta_glsl_generate_mipmap_cleanup(struct gl_context *ctx,
|
||||
struct gen_mipmap_state *mipmap)
|
||||
{
|
||||
if (mipmap->VAO == 0)
|
||||
return;
|
||||
_mesa_DeleteVertexArrays(1, &mipmap->VAO);
|
||||
mipmap->VAO = 0;
|
||||
_mesa_reference_buffer_object(ctx, &mipmap->buf_obj, NULL);
|
||||
_mesa_reference_sampler_object(ctx, &mipmap->samp_obj, NULL);
|
||||
_mesa_reference_framebuffer(&mipmap->fb, NULL);
|
||||
|
||||
_mesa_meta_blit_shader_table_cleanup(ctx, &mipmap->shaders);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called via ctx->Driver.GenerateMipmap()
|
||||
* Note: We don't yet support 3D textures, or texture borders.
|
||||
*/
|
||||
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 verts[4];
|
||||
const GLuint baseLevel = texObj->Attrib.BaseLevel;
|
||||
const GLuint maxLevel = texObj->Attrib.MaxLevel;
|
||||
const GLint maxLevelSave = texObj->Attrib.MaxLevel;
|
||||
const GLboolean genMipmapSave = texObj->Attrib.GenerateMipmap;
|
||||
const GLboolean use_glsl_version = ctx->Extensions.ARB_vertex_shader &&
|
||||
ctx->Extensions.ARB_fragment_shader;
|
||||
GLenum faceTarget;
|
||||
GLuint dstLevel;
|
||||
struct gl_sampler_object *samp_obj_save = NULL;
|
||||
GLint swizzle[4];
|
||||
GLboolean swizzleSaved = GL_FALSE;
|
||||
|
||||
/* GLint so the compiler won't complain about type signedness mismatch in
|
||||
* the calls to _mesa_texture_parameteriv below.
|
||||
*/
|
||||
static const GLint always_false = GL_FALSE;
|
||||
static const GLint always_true = GL_TRUE;
|
||||
|
||||
if (fallback_required(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, MESA_META_ALL & ~MESA_META_DRAW_BUFFERS);
|
||||
_mesa_ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||
_mesa_Disable(GL_DITHER);
|
||||
|
||||
/* Choose between glsl version and fixed function version of
|
||||
* GenerateMipmap function.
|
||||
*/
|
||||
if (use_glsl_version) {
|
||||
_mesa_meta_setup_vertex_objects(ctx, &mipmap->VAO, &mipmap->buf_obj, true,
|
||||
2, 4, 0);
|
||||
_mesa_meta_setup_blit_shader(ctx, target, false, &mipmap->shaders);
|
||||
} else {
|
||||
_mesa_meta_setup_ff_tnl_for_blit(ctx, &mipmap->VAO, &mipmap->buf_obj, 3);
|
||||
_mesa_set_enable(ctx, target, GL_TRUE);
|
||||
}
|
||||
|
||||
_mesa_reference_sampler_object(ctx, &samp_obj_save,
|
||||
ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler);
|
||||
|
||||
/* We may have been called from glGenerateTextureMipmap with CurrentUnit
|
||||
* still set to 0, so we don't know when we can skip binding the texture.
|
||||
* Assume that _mesa_bind_texture will be fast if we're rebinding the same
|
||||
* texture.
|
||||
*/
|
||||
_mesa_bind_texture(ctx, target, texObj);
|
||||
|
||||
if (mipmap->samp_obj == NULL) {
|
||||
mipmap->samp_obj = ctx->Driver.NewSamplerObject(ctx, 0xDEADBEEF);
|
||||
if (mipmap->samp_obj == NULL) {
|
||||
/* This is a bit lazy. Flag out of memory, and then don't bother to
|
||||
* clean up. Once out of memory is flagged, the only realistic next
|
||||
* move is to destroy the context. That will trigger all the right
|
||||
* clean up.
|
||||
*/
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenerateMipmap");
|
||||
return;
|
||||
}
|
||||
|
||||
_mesa_set_sampler_filters(ctx, mipmap->samp_obj, GL_LINEAR_MIPMAP_LINEAR,
|
||||
GL_LINEAR);
|
||||
_mesa_set_sampler_wrap(ctx, mipmap->samp_obj, GL_CLAMP_TO_EDGE,
|
||||
GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
|
||||
}
|
||||
|
||||
if (ctx->Extensions.EXT_texture_sRGB_decode) {
|
||||
const struct gl_texture_image *baseImage =
|
||||
_mesa_select_tex_image(texObj, target, texObj->Attrib.BaseLevel);
|
||||
const bool srgb = _mesa_is_format_srgb(baseImage->TexFormat);
|
||||
|
||||
_mesa_set_sampler_srgb_decode(ctx, mipmap->samp_obj,
|
||||
srgb ? GL_DECODE_EXT : GL_SKIP_DECODE_EXT);
|
||||
_mesa_set_framebuffer_srgb(ctx, srgb);
|
||||
}
|
||||
|
||||
_mesa_bind_sampler(ctx, ctx->Texture.CurrentUnit, mipmap->samp_obj);
|
||||
|
||||
assert(mipmap->fb != NULL);
|
||||
_mesa_bind_framebuffers(ctx, mipmap->fb, mipmap->fb);
|
||||
|
||||
_mesa_texture_parameteriv(ctx, texObj, GL_GENERATE_MIPMAP, &always_false, false);
|
||||
|
||||
if (texObj->Attrib._Swizzle != SWIZZLE_NOOP) {
|
||||
static const GLint swizzleNoop[4] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
|
||||
memcpy(swizzle, texObj->Attrib.Swizzle, sizeof(swizzle));
|
||||
swizzleSaved = GL_TRUE;
|
||||
_mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_SWIZZLE_RGBA,
|
||||
swizzleNoop, false);
|
||||
}
|
||||
|
||||
/* Silence valgrind warnings about reading uninitialized stack. */
|
||||
memset(verts, 0, sizeof(verts));
|
||||
|
||||
/* setup vertex positions */
|
||||
verts[0].x = -1.0F;
|
||||
verts[0].y = -1.0F;
|
||||
verts[1].x = 1.0F;
|
||||
verts[1].y = -1.0F;
|
||||
verts[2].x = 1.0F;
|
||||
verts[2].y = 1.0F;
|
||||
verts[3].x = -1.0F;
|
||||
verts[3].y = 1.0F;
|
||||
|
||||
/* texture is already locked, unlock now */
|
||||
_mesa_unlock_texture(ctx, texObj);
|
||||
|
||||
_mesa_prepare_mipmap_levels(ctx, texObj, baseLevel, maxLevel);
|
||||
|
||||
for (dstLevel = baseLevel + 1; dstLevel <= maxLevel; dstLevel++) {
|
||||
const struct gl_texture_image *srcImage;
|
||||
struct gl_texture_image *dstImage;
|
||||
const GLuint srcLevel = dstLevel - 1;
|
||||
GLuint layer;
|
||||
GLsizei srcWidth, srcHeight, srcDepth;
|
||||
GLsizei dstWidth, dstHeight, dstDepth;
|
||||
|
||||
srcImage = _mesa_select_tex_image(texObj, faceTarget, srcLevel);
|
||||
assert(srcImage->Border == 0);
|
||||
|
||||
/* src size */
|
||||
srcWidth = srcImage->Width;
|
||||
if (target == GL_TEXTURE_1D_ARRAY) {
|
||||
srcHeight = 1;
|
||||
srcDepth = srcImage->Height;
|
||||
} else {
|
||||
srcHeight = srcImage->Height;
|
||||
srcDepth = srcImage->Depth;
|
||||
}
|
||||
|
||||
/* new dst size */
|
||||
dstWidth = minify(srcWidth, 1);
|
||||
dstHeight = minify(srcHeight, 1);
|
||||
dstDepth = target == GL_TEXTURE_3D ? minify(srcDepth, 1) : srcDepth;
|
||||
|
||||
if (dstWidth == srcWidth &&
|
||||
dstHeight == srcHeight &&
|
||||
dstDepth == srcDepth) {
|
||||
/* all done */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Allocate storage for the destination mipmap image(s) */
|
||||
|
||||
/* Set MaxLevel large enough to hold the new level when we allocate it */
|
||||
_mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_MAX_LEVEL,
|
||||
(GLint *) &dstLevel, false);
|
||||
|
||||
dstImage = _mesa_select_tex_image(texObj, faceTarget, dstLevel);
|
||||
|
||||
/* All done. We either ran out of memory or we would go beyond the last
|
||||
* valid level of an immutable texture if we continued.
|
||||
*/
|
||||
if (dstImage == NULL)
|
||||
break;
|
||||
|
||||
/* limit minification to src level */
|
||||
_mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_MAX_LEVEL,
|
||||
(GLint *) &srcLevel, false);
|
||||
|
||||
/* setup viewport */
|
||||
_mesa_set_viewport(ctx, 0, 0, 0, dstWidth, dstHeight);
|
||||
_mesa_DrawBuffer(GL_COLOR_ATTACHMENT0);
|
||||
|
||||
for (layer = 0; layer < dstDepth; ++layer) {
|
||||
/* Setup texture coordinates */
|
||||
_mesa_meta_setup_texture_coords(faceTarget,
|
||||
layer,
|
||||
0, 0, /* xoffset, yoffset */
|
||||
srcWidth, srcHeight, /* img size */
|
||||
srcWidth, srcHeight, srcDepth,
|
||||
verts[0].tex,
|
||||
verts[1].tex,
|
||||
verts[2].tex,
|
||||
verts[3].tex);
|
||||
|
||||
/* upload vertex data */
|
||||
_mesa_buffer_data(ctx, mipmap->buf_obj, GL_NONE, sizeof(verts), verts,
|
||||
GL_DYNAMIC_DRAW, __func__);
|
||||
|
||||
_mesa_meta_framebuffer_texture_image(ctx, ctx->DrawBuffer,
|
||||
GL_COLOR_ATTACHMENT0, dstImage,
|
||||
layer);
|
||||
|
||||
/* sanity check */
|
||||
if (_mesa_check_framebuffer_status(ctx, ctx->DrawBuffer) !=
|
||||
GL_FRAMEBUFFER_COMPLETE) {
|
||||
_mesa_problem(ctx, "Unexpected incomplete framebuffer in "
|
||||
"_mesa_meta_GenerateMipmap()");
|
||||
break;
|
||||
}
|
||||
|
||||
assert(dstWidth == ctx->DrawBuffer->Width);
|
||||
if (target == GL_TEXTURE_1D_ARRAY) {
|
||||
assert(dstHeight == 1);
|
||||
} else {
|
||||
assert(dstHeight == ctx->DrawBuffer->Height);
|
||||
}
|
||||
|
||||
_mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
}
|
||||
}
|
||||
|
||||
_mesa_lock_texture(ctx, texObj); /* relock */
|
||||
|
||||
_mesa_bind_sampler(ctx, ctx->Texture.CurrentUnit, samp_obj_save);
|
||||
_mesa_reference_sampler_object(ctx, &samp_obj_save, NULL);
|
||||
|
||||
_mesa_meta_end(ctx);
|
||||
|
||||
_mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_MAX_LEVEL, &maxLevelSave,
|
||||
false);
|
||||
if (genMipmapSave)
|
||||
_mesa_texture_parameteriv(ctx, texObj, GL_GENERATE_MIPMAP, &always_true,
|
||||
false);
|
||||
if (swizzleSaved)
|
||||
_mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_SWIZZLE_RGBA, swizzle,
|
||||
false);
|
||||
}
|
|
@ -1,257 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* Copyright (C) 1999-2004 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* New (3.1) transformation code written by Keith Whitwell.
|
||||
*/
|
||||
|
||||
|
||||
/* KW: a clever asm implementation would nestle integer versions
|
||||
* of the outcode calculation underneath the division. Gcc won't
|
||||
* do this, strangely enough, so I only do the divide in
|
||||
* the case where the cliptest passes. This isn't essential,
|
||||
* and an asm implementation needn't replicate that behaviour.
|
||||
*
|
||||
* \param clip_vec vector of incoming clip-space coords
|
||||
* \param proj_vec vector of resultant NDC-space projected coords
|
||||
* \param clipMask resulting array of clip flags
|
||||
* \param orMask bitwise-OR of clipMask values
|
||||
* \param andMask bitwise-AND of clipMask values
|
||||
* \return proj_vec pointer
|
||||
*/
|
||||
static GLvector4f * TAG(cliptest_points4)( GLvector4f *clip_vec,
|
||||
GLvector4f *proj_vec,
|
||||
GLubyte clipMask[],
|
||||
GLubyte *orMask,
|
||||
GLubyte *andMask,
|
||||
GLboolean viewport_z_clip )
|
||||
{
|
||||
const GLuint stride = clip_vec->stride;
|
||||
const GLfloat *from = (GLfloat *)clip_vec->start;
|
||||
const GLuint count = clip_vec->count;
|
||||
GLuint c = 0;
|
||||
GLfloat (*vProj)[4] = (GLfloat (*)[4])proj_vec->start;
|
||||
GLubyte tmpAndMask = *andMask;
|
||||
GLubyte tmpOrMask = *orMask;
|
||||
GLuint i;
|
||||
STRIDE_LOOP {
|
||||
const GLfloat cx = from[0];
|
||||
const GLfloat cy = from[1];
|
||||
const GLfloat cz = from[2];
|
||||
const GLfloat cw = from[3];
|
||||
#if defined(__powerpc__)
|
||||
/* on powerpc cliptest is 17% faster in this way. */
|
||||
GLuint mask;
|
||||
mask = (((cw < cx) << CLIP_RIGHT_SHIFT));
|
||||
mask |= (((cw < -cx) << CLIP_LEFT_SHIFT));
|
||||
mask |= (((cw < cy) << CLIP_TOP_SHIFT));
|
||||
mask |= (((cw < -cy) << CLIP_BOTTOM_SHIFT));
|
||||
if (viewport_z_clip) {
|
||||
mask |= (((cw < cz) << CLIP_FAR_SHIFT));
|
||||
mask |= (((cw < -cz) << CLIP_NEAR_SHIFT));
|
||||
}
|
||||
#else
|
||||
GLubyte mask = 0;
|
||||
if (-cx + cw < 0) mask |= CLIP_RIGHT_BIT;
|
||||
if ( cx + cw < 0) mask |= CLIP_LEFT_BIT;
|
||||
if (-cy + cw < 0) mask |= CLIP_TOP_BIT;
|
||||
if ( cy + cw < 0) mask |= CLIP_BOTTOM_BIT;
|
||||
if (viewport_z_clip) {
|
||||
if (-cz + cw < 0) mask |= CLIP_FAR_BIT;
|
||||
if ( cz + cw < 0) mask |= CLIP_NEAR_BIT;
|
||||
}
|
||||
#endif
|
||||
|
||||
clipMask[i] = mask;
|
||||
if (mask) {
|
||||
c++;
|
||||
tmpAndMask &= mask;
|
||||
tmpOrMask |= mask;
|
||||
vProj[i][0] = 0;
|
||||
vProj[i][1] = 0;
|
||||
vProj[i][2] = 0;
|
||||
vProj[i][3] = 1;
|
||||
} else {
|
||||
GLfloat oow = 1.0F / cw;
|
||||
vProj[i][0] = cx * oow;
|
||||
vProj[i][1] = cy * oow;
|
||||
vProj[i][2] = cz * oow;
|
||||
vProj[i][3] = oow;
|
||||
}
|
||||
}
|
||||
|
||||
*orMask = tmpOrMask;
|
||||
*andMask = (GLubyte) (c < count ? 0 : tmpAndMask);
|
||||
|
||||
proj_vec->flags |= VEC_SIZE_4;
|
||||
proj_vec->size = 4;
|
||||
proj_vec->count = clip_vec->count;
|
||||
return proj_vec;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* \param clip_vec vector of incoming clip-space coords
|
||||
* \param proj_vec vector of resultant NDC-space projected coords
|
||||
* \param clipMask resulting array of clip flags
|
||||
* \param orMask bitwise-OR of clipMask values
|
||||
* \param andMask bitwise-AND of clipMask values
|
||||
* \return clip_vec pointer
|
||||
*/
|
||||
static GLvector4f * TAG(cliptest_np_points4)( GLvector4f *clip_vec,
|
||||
GLvector4f *proj_vec,
|
||||
GLubyte clipMask[],
|
||||
GLubyte *orMask,
|
||||
GLubyte *andMask,
|
||||
GLboolean viewport_z_clip )
|
||||
{
|
||||
const GLuint stride = clip_vec->stride;
|
||||
const GLuint count = clip_vec->count;
|
||||
const GLfloat *from = (GLfloat *)clip_vec->start;
|
||||
GLuint c = 0;
|
||||
GLubyte tmpAndMask = *andMask;
|
||||
GLubyte tmpOrMask = *orMask;
|
||||
GLuint i;
|
||||
(void) proj_vec;
|
||||
STRIDE_LOOP {
|
||||
const GLfloat cx = from[0];
|
||||
const GLfloat cy = from[1];
|
||||
const GLfloat cz = from[2];
|
||||
const GLfloat cw = from[3];
|
||||
#if defined(__powerpc__)
|
||||
/* on powerpc cliptest is 17% faster in this way. */
|
||||
GLuint mask;
|
||||
mask = (((cw < cx) << CLIP_RIGHT_SHIFT));
|
||||
mask |= (((cw < -cx) << CLIP_LEFT_SHIFT));
|
||||
mask |= (((cw < cy) << CLIP_TOP_SHIFT));
|
||||
mask |= (((cw < -cy) << CLIP_BOTTOM_SHIFT));
|
||||
if (viewport_z_clip) {
|
||||
mask |= (((cw < cz) << CLIP_FAR_SHIFT));
|
||||
mask |= (((cw < -cz) << CLIP_NEAR_SHIFT));
|
||||
}
|
||||
#else
|
||||
GLubyte mask = 0;
|
||||
if (-cx + cw < 0) mask |= CLIP_RIGHT_BIT;
|
||||
if ( cx + cw < 0) mask |= CLIP_LEFT_BIT;
|
||||
if (-cy + cw < 0) mask |= CLIP_TOP_BIT;
|
||||
if ( cy + cw < 0) mask |= CLIP_BOTTOM_BIT;
|
||||
if (viewport_z_clip) {
|
||||
if (-cz + cw < 0) mask |= CLIP_FAR_BIT;
|
||||
if ( cz + cw < 0) mask |= CLIP_NEAR_BIT;
|
||||
}
|
||||
#endif
|
||||
|
||||
clipMask[i] = mask;
|
||||
if (mask) {
|
||||
c++;
|
||||
tmpAndMask &= mask;
|
||||
tmpOrMask |= mask;
|
||||
}
|
||||
}
|
||||
|
||||
*orMask = tmpOrMask;
|
||||
*andMask = (GLubyte) (c < count ? 0 : tmpAndMask);
|
||||
return clip_vec;
|
||||
}
|
||||
|
||||
|
||||
static GLvector4f * TAG(cliptest_points3)( GLvector4f *clip_vec,
|
||||
GLvector4f *proj_vec,
|
||||
GLubyte clipMask[],
|
||||
GLubyte *orMask,
|
||||
GLubyte *andMask,
|
||||
GLboolean viewport_z_clip )
|
||||
{
|
||||
const GLuint stride = clip_vec->stride;
|
||||
const GLuint count = clip_vec->count;
|
||||
const GLfloat *from = (GLfloat *)clip_vec->start;
|
||||
GLubyte tmpOrMask = *orMask;
|
||||
GLubyte tmpAndMask = *andMask;
|
||||
GLuint i;
|
||||
(void) proj_vec;
|
||||
STRIDE_LOOP {
|
||||
const GLfloat cx = from[0], cy = from[1], cz = from[2];
|
||||
GLubyte mask = 0;
|
||||
if (cx > 1.0F) mask |= CLIP_RIGHT_BIT;
|
||||
else if (cx < -1.0F) mask |= CLIP_LEFT_BIT;
|
||||
if (cy > 1.0F) mask |= CLIP_TOP_BIT;
|
||||
else if (cy < -1.0F) mask |= CLIP_BOTTOM_BIT;
|
||||
if (viewport_z_clip) {
|
||||
if (cz > 1.0F) mask |= CLIP_FAR_BIT;
|
||||
else if (cz < -1.0F) mask |= CLIP_NEAR_BIT;
|
||||
}
|
||||
clipMask[i] = mask;
|
||||
tmpOrMask |= mask;
|
||||
tmpAndMask &= mask;
|
||||
}
|
||||
|
||||
*orMask = tmpOrMask;
|
||||
*andMask = tmpAndMask;
|
||||
return clip_vec;
|
||||
}
|
||||
|
||||
|
||||
static GLvector4f * TAG(cliptest_points2)( GLvector4f *clip_vec,
|
||||
GLvector4f *proj_vec,
|
||||
GLubyte clipMask[],
|
||||
GLubyte *orMask,
|
||||
GLubyte *andMask,
|
||||
GLboolean viewport_z_clip )
|
||||
{
|
||||
const GLuint stride = clip_vec->stride;
|
||||
const GLuint count = clip_vec->count;
|
||||
const GLfloat *from = (GLfloat *)clip_vec->start;
|
||||
GLubyte tmpOrMask = *orMask;
|
||||
GLubyte tmpAndMask = *andMask;
|
||||
GLuint i;
|
||||
(void) proj_vec;
|
||||
STRIDE_LOOP {
|
||||
const GLfloat cx = from[0], cy = from[1];
|
||||
GLubyte mask = 0;
|
||||
if (cx > 1.0F) mask |= CLIP_RIGHT_BIT;
|
||||
else if (cx < -1.0F) mask |= CLIP_LEFT_BIT;
|
||||
if (cy > 1.0F) mask |= CLIP_TOP_BIT;
|
||||
else if (cy < -1.0F) mask |= CLIP_BOTTOM_BIT;
|
||||
clipMask[i] = mask;
|
||||
tmpOrMask |= mask;
|
||||
tmpAndMask &= mask;
|
||||
}
|
||||
|
||||
*orMask = tmpOrMask;
|
||||
*andMask = tmpAndMask;
|
||||
return clip_vec;
|
||||
}
|
||||
|
||||
|
||||
void TAG(init_c_cliptest)( void )
|
||||
{
|
||||
_mesa_clip_tab[4] = TAG(cliptest_points4);
|
||||
_mesa_clip_tab[3] = TAG(cliptest_points3);
|
||||
_mesa_clip_tab[2] = TAG(cliptest_points2);
|
||||
|
||||
_mesa_clip_np_tab[4] = TAG(cliptest_np_points4);
|
||||
_mesa_clip_np_tab[3] = TAG(cliptest_points3);
|
||||
_mesa_clip_np_tab[2] = TAG(cliptest_points2);
|
||||
}
|
|
@ -1,86 +0,0 @@
|
|||
|
||||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* New (3.1) transformation code written by Keith Whitwell.
|
||||
*/
|
||||
|
||||
|
||||
#define COPY_FUNC( BITS ) \
|
||||
static void TAG2(copy, BITS)( GLvector4f *to, const GLvector4f *f ) \
|
||||
{ \
|
||||
GLfloat (*t)[4] = (GLfloat (*)[4])to->start; \
|
||||
GLfloat *from = f->start; \
|
||||
GLuint stride = f->stride; \
|
||||
GLuint count = to->count; \
|
||||
GLuint i; \
|
||||
\
|
||||
if (BITS) \
|
||||
STRIDE_LOOP { \
|
||||
if (BITS&1) t[i][0] = from[0]; \
|
||||
if (BITS&2) t[i][1] = from[1]; \
|
||||
if (BITS&4) t[i][2] = from[2]; \
|
||||
if (BITS&8) t[i][3] = from[3]; \
|
||||
} \
|
||||
}
|
||||
|
||||
/* We got them all here:
|
||||
*/
|
||||
COPY_FUNC( 0x0 ) /* noop */
|
||||
COPY_FUNC( 0x1 )
|
||||
COPY_FUNC( 0x2 )
|
||||
COPY_FUNC( 0x3 )
|
||||
COPY_FUNC( 0x4 )
|
||||
COPY_FUNC( 0x5 )
|
||||
COPY_FUNC( 0x6 )
|
||||
COPY_FUNC( 0x7 )
|
||||
COPY_FUNC( 0x8 )
|
||||
COPY_FUNC( 0x9 )
|
||||
COPY_FUNC( 0xa )
|
||||
COPY_FUNC( 0xb )
|
||||
COPY_FUNC( 0xc )
|
||||
COPY_FUNC( 0xd )
|
||||
COPY_FUNC( 0xe )
|
||||
COPY_FUNC( 0xf )
|
||||
|
||||
static void TAG2(init_copy, 0)( void )
|
||||
{
|
||||
_mesa_copy_tab[0x0] = TAG2(copy, 0x0);
|
||||
_mesa_copy_tab[0x1] = TAG2(copy, 0x1);
|
||||
_mesa_copy_tab[0x2] = TAG2(copy, 0x2);
|
||||
_mesa_copy_tab[0x3] = TAG2(copy, 0x3);
|
||||
_mesa_copy_tab[0x4] = TAG2(copy, 0x4);
|
||||
_mesa_copy_tab[0x5] = TAG2(copy, 0x5);
|
||||
_mesa_copy_tab[0x6] = TAG2(copy, 0x6);
|
||||
_mesa_copy_tab[0x7] = TAG2(copy, 0x7);
|
||||
_mesa_copy_tab[0x8] = TAG2(copy, 0x8);
|
||||
_mesa_copy_tab[0x9] = TAG2(copy, 0x9);
|
||||
_mesa_copy_tab[0xa] = TAG2(copy, 0xa);
|
||||
_mesa_copy_tab[0xb] = TAG2(copy, 0xb);
|
||||
_mesa_copy_tab[0xc] = TAG2(copy, 0xc);
|
||||
_mesa_copy_tab[0xd] = TAG2(copy, 0xd);
|
||||
_mesa_copy_tab[0xe] = TAG2(copy, 0xe);
|
||||
_mesa_copy_tab[0xf] = TAG2(copy, 0xf);
|
||||
}
|
|
@ -1,102 +0,0 @@
|
|||
|
||||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* New (3.1) transformation code written by Keith Whitwell.
|
||||
*/
|
||||
|
||||
|
||||
/* Note - respects the stride of the output vector.
|
||||
*/
|
||||
static void TAG(dotprod_vec2)( GLfloat *out,
|
||||
GLuint outstride,
|
||||
const GLvector4f *coord_vec,
|
||||
const GLfloat plane[4] )
|
||||
{
|
||||
GLuint stride = coord_vec->stride;
|
||||
GLfloat *coord = coord_vec->start;
|
||||
GLuint count = coord_vec->count;
|
||||
|
||||
GLuint i;
|
||||
|
||||
const GLfloat plane0 = plane[0], plane1 = plane[1], plane3 = plane[3];
|
||||
|
||||
for (i=0;i<count;i++,STRIDE_F(coord,stride),STRIDE_F(out,outstride)) {
|
||||
*out = (coord[0] * plane0 +
|
||||
coord[1] * plane1 +
|
||||
plane3);
|
||||
}
|
||||
}
|
||||
|
||||
static void TAG(dotprod_vec3)( GLfloat *out,
|
||||
GLuint outstride,
|
||||
const GLvector4f *coord_vec,
|
||||
const GLfloat plane[4] )
|
||||
{
|
||||
GLuint stride = coord_vec->stride;
|
||||
GLfloat *coord = coord_vec->start;
|
||||
GLuint count = coord_vec->count;
|
||||
|
||||
GLuint i;
|
||||
|
||||
const GLfloat plane0 = plane[0], plane1 = plane[1], plane2 = plane[2];
|
||||
const GLfloat plane3 = plane[3];
|
||||
|
||||
for (i=0;i<count;i++,STRIDE_F(coord,stride),STRIDE_F(out,outstride)) {
|
||||
*out = (coord[0] * plane0 +
|
||||
coord[1] * plane1 +
|
||||
coord[2] * plane2 +
|
||||
plane3);
|
||||
}
|
||||
}
|
||||
|
||||
static void TAG(dotprod_vec4)( GLfloat *out,
|
||||
GLuint outstride,
|
||||
const GLvector4f *coord_vec,
|
||||
const GLfloat plane[4] )
|
||||
{
|
||||
GLuint stride = coord_vec->stride;
|
||||
GLfloat *coord = coord_vec->start;
|
||||
GLuint count = coord_vec->count;
|
||||
GLuint i;
|
||||
|
||||
const GLfloat plane0 = plane[0], plane1 = plane[1], plane2 = plane[2];
|
||||
const GLfloat plane3 = plane[3];
|
||||
|
||||
for (i=0;i<count;i++,STRIDE_F(coord,stride),STRIDE_F(out,outstride)) {
|
||||
*out = (coord[0] * plane0 +
|
||||
coord[1] * plane1 +
|
||||
coord[2] * plane2 +
|
||||
coord[3] * plane3);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void TAG(init_dotprod)( void )
|
||||
{
|
||||
_mesa_dotprod_tab[2] = TAG(dotprod_vec2);
|
||||
_mesa_dotprod_tab[3] = TAG(dotprod_vec3);
|
||||
_mesa_dotprod_tab[4] = TAG(dotprod_vec4);
|
||||
}
|
|
@ -1,390 +0,0 @@
|
|||
|
||||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* Copyright (C) 1999-2003 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* New (3.1) transformation code written by Keith Whitwell.
|
||||
*/
|
||||
|
||||
/* Functions to tranform a vector of normals. This includes applying
|
||||
* the transformation matrix, rescaling and normalization.
|
||||
*/
|
||||
|
||||
/*
|
||||
* mat - the 4x4 transformation matrix
|
||||
* scale - uniform scale factor of the transformation matrix (not always used)
|
||||
* in - the source vector of normals
|
||||
* lengths - length of each incoming normal (may be NULL) (a display list
|
||||
* optimization)
|
||||
* dest - the destination vector of normals
|
||||
*/
|
||||
static void
|
||||
TAG(transform_normalize_normals)( const GLmatrix *mat,
|
||||
GLfloat scale,
|
||||
const GLvector4f *in,
|
||||
const GLfloat *lengths,
|
||||
GLvector4f *dest )
|
||||
{
|
||||
GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
|
||||
const GLfloat *from = in->start;
|
||||
const GLuint stride = in->stride;
|
||||
const GLuint count = in->count;
|
||||
const GLfloat *m = mat->inv;
|
||||
GLfloat m0 = m[0], m4 = m[4], m8 = m[8];
|
||||
GLfloat m1 = m[1], m5 = m[5], m9 = m[9];
|
||||
GLfloat m2 = m[2], m6 = m[6], m10 = m[10];
|
||||
GLuint i;
|
||||
|
||||
if (!lengths) {
|
||||
STRIDE_LOOP {
|
||||
GLfloat tx, ty, tz;
|
||||
{
|
||||
const GLfloat ux = from[0], uy = from[1], uz = from[2];
|
||||
tx = ux * m0 + uy * m1 + uz * m2;
|
||||
ty = ux * m4 + uy * m5 + uz * m6;
|
||||
tz = ux * m8 + uy * m9 + uz * m10;
|
||||
}
|
||||
{
|
||||
GLdouble len = tx*tx + ty*ty + tz*tz;
|
||||
if (len > 1e-20) {
|
||||
GLfloat scale = 1.0f / sqrtf(len);
|
||||
out[i][0] = tx * scale;
|
||||
out[i][1] = ty * scale;
|
||||
out[i][2] = tz * scale;
|
||||
}
|
||||
else {
|
||||
out[i][0] = out[i][1] = out[i][2] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (scale != 1.0f) {
|
||||
m0 *= scale, m4 *= scale, m8 *= scale;
|
||||
m1 *= scale, m5 *= scale, m9 *= scale;
|
||||
m2 *= scale, m6 *= scale, m10 *= scale;
|
||||
}
|
||||
|
||||
STRIDE_LOOP {
|
||||
GLfloat tx, ty, tz;
|
||||
{
|
||||
const GLfloat ux = from[0], uy = from[1], uz = from[2];
|
||||
tx = ux * m0 + uy * m1 + uz * m2;
|
||||
ty = ux * m4 + uy * m5 + uz * m6;
|
||||
tz = ux * m8 + uy * m9 + uz * m10;
|
||||
}
|
||||
{
|
||||
GLfloat len = lengths[i];
|
||||
out[i][0] = tx * len;
|
||||
out[i][1] = ty * len;
|
||||
out[i][2] = tz * len;
|
||||
}
|
||||
}
|
||||
}
|
||||
dest->count = in->count;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
TAG(transform_normalize_normals_no_rot)( const GLmatrix *mat,
|
||||
GLfloat scale,
|
||||
const GLvector4f *in,
|
||||
const GLfloat *lengths,
|
||||
GLvector4f *dest )
|
||||
{
|
||||
GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
|
||||
const GLfloat *from = in->start;
|
||||
const GLuint stride = in->stride;
|
||||
const GLuint count = in->count;
|
||||
const GLfloat *m = mat->inv;
|
||||
GLfloat m0 = m[0];
|
||||
GLfloat m5 = m[5];
|
||||
GLfloat m10 = m[10];
|
||||
GLuint i;
|
||||
|
||||
if (!lengths) {
|
||||
STRIDE_LOOP {
|
||||
GLfloat tx, ty, tz;
|
||||
{
|
||||
const GLfloat ux = from[0], uy = from[1], uz = from[2];
|
||||
tx = ux * m0 ;
|
||||
ty = uy * m5 ;
|
||||
tz = uz * m10;
|
||||
}
|
||||
{
|
||||
GLdouble len = tx*tx + ty*ty + tz*tz;
|
||||
if (len > 1e-20) {
|
||||
GLfloat scale = 1.0f / sqrtf(len);
|
||||
out[i][0] = tx * scale;
|
||||
out[i][1] = ty * scale;
|
||||
out[i][2] = tz * scale;
|
||||
}
|
||||
else {
|
||||
out[i][0] = out[i][1] = out[i][2] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
m0 *= scale;
|
||||
m5 *= scale;
|
||||
m10 *= scale;
|
||||
|
||||
STRIDE_LOOP {
|
||||
GLfloat tx, ty, tz;
|
||||
{
|
||||
const GLfloat ux = from[0], uy = from[1], uz = from[2];
|
||||
tx = ux * m0 ;
|
||||
ty = uy * m5 ;
|
||||
tz = uz * m10;
|
||||
}
|
||||
{
|
||||
GLfloat len = lengths[i];
|
||||
out[i][0] = tx * len;
|
||||
out[i][1] = ty * len;
|
||||
out[i][2] = tz * len;
|
||||
}
|
||||
}
|
||||
}
|
||||
dest->count = in->count;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
TAG(transform_rescale_normals_no_rot)( const GLmatrix *mat,
|
||||
GLfloat scale,
|
||||
const GLvector4f *in,
|
||||
const GLfloat *lengths,
|
||||
GLvector4f *dest )
|
||||
{
|
||||
GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
|
||||
const GLfloat *from = in->start;
|
||||
const GLuint stride = in->stride;
|
||||
const GLuint count = in->count;
|
||||
const GLfloat *m = mat->inv;
|
||||
const GLfloat m0 = scale*m[0];
|
||||
const GLfloat m5 = scale*m[5];
|
||||
const GLfloat m10 = scale*m[10];
|
||||
GLuint i;
|
||||
|
||||
(void) lengths;
|
||||
|
||||
STRIDE_LOOP {
|
||||
GLfloat ux = from[0], uy = from[1], uz = from[2];
|
||||
out[i][0] = ux * m0;
|
||||
out[i][1] = uy * m5;
|
||||
out[i][2] = uz * m10;
|
||||
}
|
||||
dest->count = in->count;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
TAG(transform_rescale_normals)( const GLmatrix *mat,
|
||||
GLfloat scale,
|
||||
const GLvector4f *in,
|
||||
const GLfloat *lengths,
|
||||
GLvector4f *dest )
|
||||
{
|
||||
GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
|
||||
const GLfloat *from = in->start;
|
||||
const GLuint stride = in->stride;
|
||||
const GLuint count = in->count;
|
||||
/* Since we are unlikely to have < 3 vertices in the buffer,
|
||||
* it makes sense to pre-multiply by scale.
|
||||
*/
|
||||
const GLfloat *m = mat->inv;
|
||||
const GLfloat m0 = scale*m[0], m4 = scale*m[4], m8 = scale*m[8];
|
||||
const GLfloat m1 = scale*m[1], m5 = scale*m[5], m9 = scale*m[9];
|
||||
const GLfloat m2 = scale*m[2], m6 = scale*m[6], m10 = scale*m[10];
|
||||
GLuint i;
|
||||
|
||||
(void) lengths;
|
||||
|
||||
STRIDE_LOOP {
|
||||
GLfloat ux = from[0], uy = from[1], uz = from[2];
|
||||
out[i][0] = ux * m0 + uy * m1 + uz * m2;
|
||||
out[i][1] = ux * m4 + uy * m5 + uz * m6;
|
||||
out[i][2] = ux * m8 + uy * m9 + uz * m10;
|
||||
}
|
||||
dest->count = in->count;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
TAG(transform_normals_no_rot)( const GLmatrix *mat,
|
||||
GLfloat scale,
|
||||
const GLvector4f *in,
|
||||
const GLfloat *lengths,
|
||||
GLvector4f *dest )
|
||||
{
|
||||
GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
|
||||
const GLfloat *from = in->start;
|
||||
const GLuint stride = in->stride;
|
||||
const GLuint count = in->count;
|
||||
const GLfloat *m = mat->inv;
|
||||
const GLfloat m0 = m[0];
|
||||
const GLfloat m5 = m[5];
|
||||
const GLfloat m10 = m[10];
|
||||
GLuint i;
|
||||
|
||||
(void) scale;
|
||||
(void) lengths;
|
||||
|
||||
STRIDE_LOOP {
|
||||
GLfloat ux = from[0], uy = from[1], uz = from[2];
|
||||
out[i][0] = ux * m0;
|
||||
out[i][1] = uy * m5;
|
||||
out[i][2] = uz * m10;
|
||||
}
|
||||
dest->count = in->count;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
TAG(transform_normals)( const GLmatrix *mat,
|
||||
GLfloat scale,
|
||||
const GLvector4f *in,
|
||||
const GLfloat *lengths,
|
||||
GLvector4f *dest )
|
||||
{
|
||||
GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
|
||||
const GLfloat *from = in->start;
|
||||
const GLuint stride = in->stride;
|
||||
const GLuint count = in->count;
|
||||
const GLfloat *m = mat->inv;
|
||||
const GLfloat m0 = m[0], m4 = m[4], m8 = m[8];
|
||||
const GLfloat m1 = m[1], m5 = m[5], m9 = m[9];
|
||||
const GLfloat m2 = m[2], m6 = m[6], m10 = m[10];
|
||||
GLuint i;
|
||||
|
||||
(void) scale;
|
||||
(void) lengths;
|
||||
|
||||
STRIDE_LOOP {
|
||||
GLfloat ux = from[0], uy = from[1], uz = from[2];
|
||||
out[i][0] = ux * m0 + uy * m1 + uz * m2;
|
||||
out[i][1] = ux * m4 + uy * m5 + uz * m6;
|
||||
out[i][2] = ux * m8 + uy * m9 + uz * m10;
|
||||
}
|
||||
dest->count = in->count;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
TAG(normalize_normals)( const GLmatrix *mat,
|
||||
GLfloat scale,
|
||||
const GLvector4f *in,
|
||||
const GLfloat *lengths,
|
||||
GLvector4f *dest )
|
||||
{
|
||||
GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
|
||||
const GLfloat *from = in->start;
|
||||
const GLuint stride = in->stride;
|
||||
const GLuint count = in->count;
|
||||
GLuint i;
|
||||
|
||||
(void) mat;
|
||||
(void) scale;
|
||||
|
||||
if (lengths) {
|
||||
STRIDE_LOOP {
|
||||
const GLfloat x = from[0], y = from[1], z = from[2];
|
||||
GLfloat invlen = lengths[i];
|
||||
out[i][0] = x * invlen;
|
||||
out[i][1] = y * invlen;
|
||||
out[i][2] = z * invlen;
|
||||
}
|
||||
}
|
||||
else {
|
||||
STRIDE_LOOP {
|
||||
const GLfloat x = from[0], y = from[1], z = from[2];
|
||||
GLdouble len = x * x + y * y + z * z;
|
||||
if (len > 1e-50) {
|
||||
len = 1.0f / sqrtf(len);
|
||||
out[i][0] = (GLfloat)(x * len);
|
||||
out[i][1] = (GLfloat)(y * len);
|
||||
out[i][2] = (GLfloat)(z * len);
|
||||
}
|
||||
else {
|
||||
out[i][0] = x;
|
||||
out[i][1] = y;
|
||||
out[i][2] = z;
|
||||
}
|
||||
}
|
||||
}
|
||||
dest->count = in->count;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
TAG(rescale_normals)( const GLmatrix *mat,
|
||||
GLfloat scale,
|
||||
const GLvector4f *in,
|
||||
const GLfloat *lengths,
|
||||
GLvector4f *dest )
|
||||
{
|
||||
GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
|
||||
const GLfloat *from = in->start;
|
||||
const GLuint stride = in->stride;
|
||||
const GLuint count = in->count;
|
||||
GLuint i;
|
||||
|
||||
(void) mat;
|
||||
(void) lengths;
|
||||
|
||||
STRIDE_LOOP {
|
||||
SCALE_SCALAR_3V( out[i], scale, from );
|
||||
}
|
||||
dest->count = in->count;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
TAG(init_c_norm_transform)( void )
|
||||
{
|
||||
_mesa_normal_tab[NORM_TRANSFORM_NO_ROT] =
|
||||
TAG(transform_normals_no_rot);
|
||||
|
||||
_mesa_normal_tab[NORM_TRANSFORM_NO_ROT | NORM_RESCALE] =
|
||||
TAG(transform_rescale_normals_no_rot);
|
||||
|
||||
_mesa_normal_tab[NORM_TRANSFORM_NO_ROT | NORM_NORMALIZE] =
|
||||
TAG(transform_normalize_normals_no_rot);
|
||||
|
||||
_mesa_normal_tab[NORM_TRANSFORM] =
|
||||
TAG(transform_normals);
|
||||
|
||||
_mesa_normal_tab[NORM_TRANSFORM | NORM_RESCALE] =
|
||||
TAG(transform_rescale_normals);
|
||||
|
||||
_mesa_normal_tab[NORM_TRANSFORM | NORM_NORMALIZE] =
|
||||
TAG(transform_normalize_normals);
|
||||
|
||||
_mesa_normal_tab[NORM_RESCALE] =
|
||||
TAG(rescale_normals);
|
||||
|
||||
_mesa_normal_tab[NORM_NORMALIZE] =
|
||||
TAG(normalize_normals);
|
||||
}
|
|
@ -1,123 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* Copyright (C) 1999-2003 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Matrix/vertex/vector transformation stuff
|
||||
*
|
||||
*
|
||||
* NOTES:
|
||||
* 1. 4x4 transformation matrices are stored in memory in column major order.
|
||||
* 2. Points/vertices are to be thought of as column vectors.
|
||||
* 3. Transformation of a point p by a matrix M is: p' = M * p
|
||||
*/
|
||||
|
||||
#include "c99_math.h"
|
||||
#include "main/glheader.h"
|
||||
#include "main/macros.h"
|
||||
|
||||
#include "m_eval.h"
|
||||
#include "m_matrix.h"
|
||||
#include "m_translate.h"
|
||||
#include "m_xform.h"
|
||||
|
||||
|
||||
#ifdef DEBUG_MATH
|
||||
#include "m_debug.h"
|
||||
#endif
|
||||
|
||||
#ifdef USE_X86_ASM
|
||||
#include "x86/common_x86_asm.h"
|
||||
#endif
|
||||
|
||||
#ifdef USE_X86_64_ASM
|
||||
#include "x86-64/x86-64.h"
|
||||
#endif
|
||||
|
||||
#ifdef USE_SPARC_ASM
|
||||
#include "sparc/sparc.h"
|
||||
#endif
|
||||
|
||||
clip_func _mesa_clip_tab[5];
|
||||
clip_func _mesa_clip_np_tab[5];
|
||||
dotprod_func _mesa_dotprod_tab[5];
|
||||
vec_copy_func _mesa_copy_tab[0x10];
|
||||
normal_func _mesa_normal_tab[0xf];
|
||||
transform_func *_mesa_transform_tab[5];
|
||||
|
||||
|
||||
/* Raw data format used for:
|
||||
* - Object-to-eye transform prior to culling, although this too
|
||||
* could be culled under some circumstances.
|
||||
* - Eye-to-clip transform (via the function above).
|
||||
* - Cliptesting
|
||||
* - And everything else too, if culling happens to be disabled.
|
||||
*
|
||||
* GH: It's used for everything now, as clipping/culling is done
|
||||
* elsewhere (most often by the driver itself).
|
||||
*/
|
||||
#define TAG(x) x
|
||||
#define TAG2(x,y) x##y
|
||||
#define STRIDE_LOOP for ( i = 0 ; i < count ; i++, STRIDE_F(from, stride) )
|
||||
#define LOOP for ( i = 0 ; i < n ; i++ )
|
||||
#define ARGS
|
||||
#include "m_xform_tmp.h"
|
||||
#include "m_clip_tmp.h"
|
||||
#include "m_norm_tmp.h"
|
||||
#include "m_dotprod_tmp.h"
|
||||
#include "m_copy_tmp.h"
|
||||
#undef TAG
|
||||
#undef TAG2
|
||||
#undef LOOP
|
||||
#undef ARGS
|
||||
|
||||
|
||||
/*
|
||||
* This is called only once. It initializes several tables with pointers
|
||||
* to optimized transformation functions. This is where we can test for
|
||||
* AMD 3Dnow! capability, Intel SSE, etc. and hook in the right code.
|
||||
*/
|
||||
void
|
||||
_math_init_transformation( void )
|
||||
{
|
||||
init_c_transformations();
|
||||
init_c_norm_transform();
|
||||
init_c_cliptest();
|
||||
init_copy0();
|
||||
init_dotprod();
|
||||
|
||||
#ifdef DEBUG_MATH
|
||||
_math_test_all_transform_functions( "default" );
|
||||
_math_test_all_normal_transform_functions( "default" );
|
||||
_math_test_all_cliptest_functions( "default" );
|
||||
#endif
|
||||
|
||||
#ifdef USE_X86_ASM
|
||||
_mesa_init_all_x86_transform_asm();
|
||||
#elif defined( USE_SPARC_ASM )
|
||||
_mesa_init_all_sparc_transform_asm();
|
||||
#elif defined( USE_X86_64_ASM )
|
||||
_mesa_init_all_x86_64_transform_asm();
|
||||
#endif
|
||||
}
|
|
@ -1,810 +0,0 @@
|
|||
|
||||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* New (3.1) transformation code written by Keith Whitwell.
|
||||
*/
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
* Begin Keith's new code
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* KW: Fixed stride, now measured in bytes as is the OpenGL array stride.
|
||||
*/
|
||||
|
||||
/* KW: These are now parameterized to produce two versions, one
|
||||
* which transforms all incoming points, and a second which
|
||||
* takes notice of a cullmask array, and only transforms
|
||||
* unculled vertices.
|
||||
*/
|
||||
|
||||
/* KW: 1-vectors can sneak into the texture pipeline via the array
|
||||
* interface. These functions are here because I want consistant
|
||||
* treatment of the vertex sizes and a lazy strategy for
|
||||
* cleaning unused parts of the vector, and so as not to exclude
|
||||
* them from the vertex array interface.
|
||||
*
|
||||
* Under our current analysis of matrices, there is no way that
|
||||
* the product of a matrix and a 1-vector can remain a 1-vector,
|
||||
* with the exception of the identity transform.
|
||||
*/
|
||||
|
||||
/* KW: No longer zero-pad outgoing vectors. Now that external
|
||||
* vectors can get into the pipeline we cannot ever assume
|
||||
* that there is more to a vector than indicated by its
|
||||
* size.
|
||||
*/
|
||||
|
||||
/* KW: Now uses clipmask and a flag to allow us to skip both/either
|
||||
* cliped and/or culled vertices.
|
||||
*/
|
||||
|
||||
/* GH: Not any more -- it's easier (and faster) to just process the
|
||||
* entire vector. Clipping and culling are handled further down
|
||||
* the pipe, most often during or after the conversion to some
|
||||
* driver-specific vertex format.
|
||||
*/
|
||||
|
||||
static void
|
||||
TAG(transform_points1_general)( GLvector4f *to_vec,
|
||||
const GLfloat m[16],
|
||||
const GLvector4f *from_vec )
|
||||
{
|
||||
const GLuint stride = from_vec->stride;
|
||||
GLfloat *from = from_vec->start;
|
||||
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
|
||||
GLuint count = from_vec->count;
|
||||
const GLfloat m0 = m[0], m12 = m[12];
|
||||
const GLfloat m1 = m[1], m13 = m[13];
|
||||
const GLfloat m2 = m[2], m14 = m[14];
|
||||
const GLfloat m3 = m[3], m15 = m[15];
|
||||
GLuint i;
|
||||
STRIDE_LOOP {
|
||||
const GLfloat ox = from[0];
|
||||
to[i][0] = m0 * ox + m12;
|
||||
to[i][1] = m1 * ox + m13;
|
||||
to[i][2] = m2 * ox + m14;
|
||||
to[i][3] = m3 * ox + m15;
|
||||
}
|
||||
to_vec->size = 4;
|
||||
to_vec->flags |= VEC_SIZE_4;
|
||||
to_vec->count = from_vec->count;
|
||||
}
|
||||
|
||||
static void
|
||||
TAG(transform_points1_identity)( GLvector4f *to_vec,
|
||||
const GLfloat m[16],
|
||||
const GLvector4f *from_vec )
|
||||
{
|
||||
const GLuint stride = from_vec->stride;
|
||||
GLfloat *from = from_vec->start;
|
||||
GLuint count = from_vec->count;
|
||||
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
|
||||
GLuint i;
|
||||
(void) m;
|
||||
if (to_vec == from_vec) return;
|
||||
STRIDE_LOOP {
|
||||
to[i][0] = from[0];
|
||||
}
|
||||
to_vec->size = 1;
|
||||
to_vec->flags |= VEC_SIZE_1;
|
||||
to_vec->count = from_vec->count;
|
||||
}
|
||||
|
||||
static void
|
||||
TAG(transform_points1_2d)( GLvector4f *to_vec,
|
||||
const GLfloat m[16],
|
||||
const GLvector4f *from_vec )
|
||||
{
|
||||
const GLuint stride = from_vec->stride;
|
||||
GLfloat *from = from_vec->start;
|
||||
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
|
||||
GLuint count = from_vec->count;
|
||||
const GLfloat m0 = m[0], m1 = m[1];
|
||||
const GLfloat m12 = m[12], m13 = m[13];
|
||||
GLuint i;
|
||||
STRIDE_LOOP {
|
||||
const GLfloat ox = from[0];
|
||||
to[i][0] = m0 * ox + m12;
|
||||
to[i][1] = m1 * ox + m13;
|
||||
}
|
||||
to_vec->size = 2;
|
||||
to_vec->flags |= VEC_SIZE_2;
|
||||
to_vec->count = from_vec->count;
|
||||
}
|
||||
|
||||
static void
|
||||
TAG(transform_points1_2d_no_rot)( GLvector4f *to_vec,
|
||||
const GLfloat m[16],
|
||||
const GLvector4f *from_vec )
|
||||
{
|
||||
const GLuint stride = from_vec->stride;
|
||||
GLfloat *from = from_vec->start;
|
||||
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
|
||||
GLuint count = from_vec->count;
|
||||
const GLfloat m0 = m[0], m12 = m[12], m13 = m[13];
|
||||
GLuint i;
|
||||
STRIDE_LOOP {
|
||||
const GLfloat ox = from[0];
|
||||
to[i][0] = m0 * ox + m12;
|
||||
to[i][1] = m13;
|
||||
}
|
||||
to_vec->size = 2;
|
||||
to_vec->flags |= VEC_SIZE_2;
|
||||
to_vec->count = from_vec->count;
|
||||
}
|
||||
|
||||
static void
|
||||
TAG(transform_points1_3d)( GLvector4f *to_vec,
|
||||
const GLfloat m[16],
|
||||
const GLvector4f *from_vec )
|
||||
{
|
||||
const GLuint stride = from_vec->stride;
|
||||
GLfloat *from = from_vec->start;
|
||||
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
|
||||
GLuint count = from_vec->count;
|
||||
const GLfloat m0 = m[0], m1 = m[1], m2 = m[2];
|
||||
const GLfloat m12 = m[12], m13 = m[13], m14 = m[14];
|
||||
GLuint i;
|
||||
STRIDE_LOOP {
|
||||
const GLfloat ox = from[0];
|
||||
to[i][0] = m0 * ox + m12;
|
||||
to[i][1] = m1 * ox + m13;
|
||||
to[i][2] = m2 * ox + m14;
|
||||
}
|
||||
to_vec->size = 3;
|
||||
to_vec->flags |= VEC_SIZE_3;
|
||||
to_vec->count = from_vec->count;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
TAG(transform_points1_3d_no_rot)( GLvector4f *to_vec,
|
||||
const GLfloat m[16],
|
||||
const GLvector4f *from_vec )
|
||||
{
|
||||
const GLuint stride = from_vec->stride;
|
||||
GLfloat *from = from_vec->start;
|
||||
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
|
||||
GLuint count = from_vec->count;
|
||||
const GLfloat m0 = m[0];
|
||||
const GLfloat m12 = m[12], m13 = m[13], m14 = m[14];
|
||||
GLuint i;
|
||||
STRIDE_LOOP {
|
||||
const GLfloat ox = from[0];
|
||||
to[i][0] = m0 * ox + m12;
|
||||
to[i][1] = m13;
|
||||
to[i][2] = m14;
|
||||
}
|
||||
to_vec->size = 3;
|
||||
to_vec->flags |= VEC_SIZE_3;
|
||||
to_vec->count = from_vec->count;
|
||||
}
|
||||
|
||||
static void
|
||||
TAG(transform_points1_perspective)( GLvector4f *to_vec,
|
||||
const GLfloat m[16],
|
||||
const GLvector4f *from_vec )
|
||||
{
|
||||
const GLuint stride = from_vec->stride;
|
||||
GLfloat *from = from_vec->start;
|
||||
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
|
||||
GLuint count = from_vec->count;
|
||||
const GLfloat m0 = m[0], m14 = m[14];
|
||||
GLuint i;
|
||||
STRIDE_LOOP {
|
||||
const GLfloat ox = from[0];
|
||||
to[i][0] = m0 * ox ;
|
||||
to[i][1] = 0 ;
|
||||
to[i][2] = m14;
|
||||
to[i][3] = 0;
|
||||
}
|
||||
to_vec->size = 4;
|
||||
to_vec->flags |= VEC_SIZE_4;
|
||||
to_vec->count = from_vec->count;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* 2-vectors, which are a lot more relevant than 1-vectors, are
|
||||
* present early in the geometry pipeline and throughout the
|
||||
* texture pipeline.
|
||||
*/
|
||||
static void
|
||||
TAG(transform_points2_general)( GLvector4f *to_vec,
|
||||
const GLfloat m[16],
|
||||
const GLvector4f *from_vec )
|
||||
{
|
||||
const GLuint stride = from_vec->stride;
|
||||
GLfloat *from = from_vec->start;
|
||||
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
|
||||
GLuint count = from_vec->count;
|
||||
const GLfloat m0 = m[0], m4 = m[4], m12 = m[12];
|
||||
const GLfloat m1 = m[1], m5 = m[5], m13 = m[13];
|
||||
const GLfloat m2 = m[2], m6 = m[6], m14 = m[14];
|
||||
const GLfloat m3 = m[3], m7 = m[7], m15 = m[15];
|
||||
GLuint i;
|
||||
STRIDE_LOOP {
|
||||
const GLfloat ox = from[0], oy = from[1];
|
||||
to[i][0] = m0 * ox + m4 * oy + m12;
|
||||
to[i][1] = m1 * ox + m5 * oy + m13;
|
||||
to[i][2] = m2 * ox + m6 * oy + m14;
|
||||
to[i][3] = m3 * ox + m7 * oy + m15;
|
||||
}
|
||||
to_vec->size = 4;
|
||||
to_vec->flags |= VEC_SIZE_4;
|
||||
to_vec->count = from_vec->count;
|
||||
}
|
||||
|
||||
static void
|
||||
TAG(transform_points2_identity)( GLvector4f *to_vec,
|
||||
const GLfloat m[16],
|
||||
const GLvector4f *from_vec )
|
||||
{
|
||||
const GLuint stride = from_vec->stride;
|
||||
GLfloat *from = from_vec->start;
|
||||
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
|
||||
GLuint count = from_vec->count;
|
||||
GLuint i;
|
||||
(void) m;
|
||||
if (to_vec == from_vec) return;
|
||||
STRIDE_LOOP {
|
||||
to[i][0] = from[0];
|
||||
to[i][1] = from[1];
|
||||
}
|
||||
to_vec->size = 2;
|
||||
to_vec->flags |= VEC_SIZE_2;
|
||||
to_vec->count = from_vec->count;
|
||||
}
|
||||
|
||||
static void
|
||||
TAG(transform_points2_2d)( GLvector4f *to_vec,
|
||||
const GLfloat m[16],
|
||||
const GLvector4f *from_vec )
|
||||
{
|
||||
const GLuint stride = from_vec->stride;
|
||||
GLfloat *from = from_vec->start;
|
||||
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
|
||||
GLuint count = from_vec->count;
|
||||
const GLfloat m0 = m[0], m1 = m[1], m4 = m[4], m5 = m[5];
|
||||
const GLfloat m12 = m[12], m13 = m[13];
|
||||
GLuint i;
|
||||
STRIDE_LOOP {
|
||||
const GLfloat ox = from[0], oy = from[1];
|
||||
to[i][0] = m0 * ox + m4 * oy + m12;
|
||||
to[i][1] = m1 * ox + m5 * oy + m13;
|
||||
}
|
||||
to_vec->size = 2;
|
||||
to_vec->flags |= VEC_SIZE_2;
|
||||
to_vec->count = from_vec->count;
|
||||
}
|
||||
|
||||
static void
|
||||
TAG(transform_points2_2d_no_rot)( GLvector4f *to_vec,
|
||||
const GLfloat m[16],
|
||||
const GLvector4f *from_vec )
|
||||
{
|
||||
const GLuint stride = from_vec->stride;
|
||||
GLfloat *from = from_vec->start;
|
||||
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
|
||||
GLuint count = from_vec->count;
|
||||
const GLfloat m0 = m[0], m5 = m[5], m12 = m[12], m13 = m[13];
|
||||
GLuint i;
|
||||
STRIDE_LOOP {
|
||||
const GLfloat ox = from[0], oy = from[1];
|
||||
to[i][0] = m0 * ox + m12;
|
||||
to[i][1] = m5 * oy + m13;
|
||||
}
|
||||
to_vec->size = 2;
|
||||
to_vec->flags |= VEC_SIZE_2;
|
||||
to_vec->count = from_vec->count;
|
||||
}
|
||||
|
||||
static void
|
||||
TAG(transform_points2_3d)( GLvector4f *to_vec,
|
||||
const GLfloat m[16],
|
||||
const GLvector4f *from_vec )
|
||||
{
|
||||
const GLuint stride = from_vec->stride;
|
||||
GLfloat *from = from_vec->start;
|
||||
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
|
||||
GLuint count = from_vec->count;
|
||||
const GLfloat m0 = m[0], m1 = m[1], m2 = m[2], m4 = m[4], m5 = m[5];
|
||||
const GLfloat m6 = m[6], m12 = m[12], m13 = m[13], m14 = m[14];
|
||||
GLuint i;
|
||||
STRIDE_LOOP {
|
||||
const GLfloat ox = from[0], oy = from[1];
|
||||
to[i][0] = m0 * ox + m4 * oy + m12;
|
||||
to[i][1] = m1 * ox + m5 * oy + m13;
|
||||
to[i][2] = m2 * ox + m6 * oy + m14;
|
||||
}
|
||||
to_vec->size = 3;
|
||||
to_vec->flags |= VEC_SIZE_3;
|
||||
to_vec->count = from_vec->count;
|
||||
}
|
||||
|
||||
|
||||
/* I would actually say this was a fairly important function, from
|
||||
* a texture transformation point of view.
|
||||
*/
|
||||
static void
|
||||
TAG(transform_points2_3d_no_rot)( GLvector4f *to_vec,
|
||||
const GLfloat m[16],
|
||||
const GLvector4f *from_vec )
|
||||
{
|
||||
const GLuint stride = from_vec->stride;
|
||||
GLfloat *from = from_vec->start;
|
||||
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
|
||||
GLuint count = from_vec->count;
|
||||
const GLfloat m0 = m[0], m5 = m[5];
|
||||
const GLfloat m12 = m[12], m13 = m[13], m14 = m[14];
|
||||
GLuint i;
|
||||
STRIDE_LOOP {
|
||||
const GLfloat ox = from[0], oy = from[1];
|
||||
to[i][0] = m0 * ox + m12;
|
||||
to[i][1] = m5 * oy + m13;
|
||||
to[i][2] = m14;
|
||||
}
|
||||
if (m14 == 0) {
|
||||
to_vec->size = 2;
|
||||
to_vec->flags |= VEC_SIZE_2;
|
||||
} else {
|
||||
to_vec->size = 3;
|
||||
to_vec->flags |= VEC_SIZE_3;
|
||||
}
|
||||
to_vec->count = from_vec->count;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
TAG(transform_points2_perspective)( GLvector4f *to_vec,
|
||||
const GLfloat m[16],
|
||||
const GLvector4f *from_vec )
|
||||
{
|
||||
const GLuint stride = from_vec->stride;
|
||||
GLfloat *from = from_vec->start;
|
||||
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
|
||||
GLuint count = from_vec->count;
|
||||
const GLfloat m0 = m[0], m5 = m[5], m14 = m[14];
|
||||
GLuint i;
|
||||
STRIDE_LOOP {
|
||||
const GLfloat ox = from[0], oy = from[1];
|
||||
to[i][0] = m0 * ox ;
|
||||
to[i][1] = m5 * oy ;
|
||||
to[i][2] = m14;
|
||||
to[i][3] = 0;
|
||||
}
|
||||
to_vec->size = 4;
|
||||
to_vec->flags |= VEC_SIZE_4;
|
||||
to_vec->count = from_vec->count;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
TAG(transform_points3_general)( GLvector4f *to_vec,
|
||||
const GLfloat m[16],
|
||||
const GLvector4f *from_vec )
|
||||
{
|
||||
const GLuint stride = from_vec->stride;
|
||||
GLfloat *from = from_vec->start;
|
||||
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
|
||||
GLuint count = from_vec->count;
|
||||
const GLfloat m0 = m[0], m4 = m[4], m8 = m[8], m12 = m[12];
|
||||
const GLfloat m1 = m[1], m5 = m[5], m9 = m[9], m13 = m[13];
|
||||
const GLfloat m2 = m[2], m6 = m[6], m10 = m[10], m14 = m[14];
|
||||
const GLfloat m3 = m[3], m7 = m[7], m11 = m[11], m15 = m[15];
|
||||
GLuint i;
|
||||
STRIDE_LOOP {
|
||||
const GLfloat ox = from[0], oy = from[1], oz = from[2];
|
||||
to[i][0] = m0 * ox + m4 * oy + m8 * oz + m12;
|
||||
to[i][1] = m1 * ox + m5 * oy + m9 * oz + m13;
|
||||
to[i][2] = m2 * ox + m6 * oy + m10 * oz + m14;
|
||||
to[i][3] = m3 * ox + m7 * oy + m11 * oz + m15;
|
||||
}
|
||||
to_vec->size = 4;
|
||||
to_vec->flags |= VEC_SIZE_4;
|
||||
to_vec->count = from_vec->count;
|
||||
}
|
||||
|
||||
static void
|
||||
TAG(transform_points3_identity)( GLvector4f *to_vec,
|
||||
const GLfloat m[16],
|
||||
const GLvector4f *from_vec )
|
||||
{
|
||||
const GLuint stride = from_vec->stride;
|
||||
GLfloat *from = from_vec->start;
|
||||
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
|
||||
GLuint count = from_vec->count;
|
||||
GLuint i;
|
||||
(void) m;
|
||||
if (to_vec == from_vec) return;
|
||||
STRIDE_LOOP {
|
||||
to[i][0] = from[0];
|
||||
to[i][1] = from[1];
|
||||
to[i][2] = from[2];
|
||||
}
|
||||
to_vec->size = 3;
|
||||
to_vec->flags |= VEC_SIZE_3;
|
||||
to_vec->count = from_vec->count;
|
||||
}
|
||||
|
||||
static void
|
||||
TAG(transform_points3_2d)( GLvector4f *to_vec,
|
||||
const GLfloat m[16],
|
||||
const GLvector4f *from_vec )
|
||||
{
|
||||
const GLuint stride = from_vec->stride;
|
||||
GLfloat *from = from_vec->start;
|
||||
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
|
||||
GLuint count = from_vec->count;
|
||||
const GLfloat m0 = m[0], m1 = m[1], m4 = m[4], m5 = m[5];
|
||||
const GLfloat m12 = m[12], m13 = m[13];
|
||||
GLuint i;
|
||||
STRIDE_LOOP {
|
||||
const GLfloat ox = from[0], oy = from[1], oz = from[2];
|
||||
to[i][0] = m0 * ox + m4 * oy + m12 ;
|
||||
to[i][1] = m1 * ox + m5 * oy + m13 ;
|
||||
to[i][2] = + oz ;
|
||||
}
|
||||
to_vec->size = 3;
|
||||
to_vec->flags |= VEC_SIZE_3;
|
||||
to_vec->count = from_vec->count;
|
||||
}
|
||||
|
||||
static void
|
||||
TAG(transform_points3_2d_no_rot)( GLvector4f *to_vec,
|
||||
const GLfloat m[16],
|
||||
const GLvector4f *from_vec )
|
||||
{
|
||||
const GLuint stride = from_vec->stride;
|
||||
GLfloat *from = from_vec->start;
|
||||
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
|
||||
GLuint count = from_vec->count;
|
||||
const GLfloat m0 = m[0], m5 = m[5], m12 = m[12], m13 = m[13];
|
||||
GLuint i;
|
||||
STRIDE_LOOP {
|
||||
const GLfloat ox = from[0], oy = from[1], oz = from[2];
|
||||
to[i][0] = m0 * ox + m12 ;
|
||||
to[i][1] = m5 * oy + m13 ;
|
||||
to[i][2] = + oz ;
|
||||
}
|
||||
to_vec->size = 3;
|
||||
to_vec->flags |= VEC_SIZE_3;
|
||||
to_vec->count = from_vec->count;
|
||||
}
|
||||
|
||||
static void
|
||||
TAG(transform_points3_3d)( GLvector4f *to_vec,
|
||||
const GLfloat m[16],
|
||||
const GLvector4f *from_vec )
|
||||
{
|
||||
const GLuint stride = from_vec->stride;
|
||||
GLfloat *from = from_vec->start;
|
||||
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
|
||||
GLuint count = from_vec->count;
|
||||
const GLfloat m0 = m[0], m1 = m[1], m2 = m[2], m4 = m[4], m5 = m[5];
|
||||
const GLfloat m6 = m[6], m8 = m[8], m9 = m[9], m10 = m[10];
|
||||
const GLfloat m12 = m[12], m13 = m[13], m14 = m[14];
|
||||
GLuint i;
|
||||
STRIDE_LOOP {
|
||||
const GLfloat ox = from[0], oy = from[1], oz = from[2];
|
||||
to[i][0] = m0 * ox + m4 * oy + m8 * oz + m12 ;
|
||||
to[i][1] = m1 * ox + m5 * oy + m9 * oz + m13 ;
|
||||
to[i][2] = m2 * ox + m6 * oy + m10 * oz + m14 ;
|
||||
}
|
||||
to_vec->size = 3;
|
||||
to_vec->flags |= VEC_SIZE_3;
|
||||
to_vec->count = from_vec->count;
|
||||
}
|
||||
|
||||
/* previously known as ortho...
|
||||
*/
|
||||
static void
|
||||
TAG(transform_points3_3d_no_rot)( GLvector4f *to_vec,
|
||||
const GLfloat m[16],
|
||||
const GLvector4f *from_vec )
|
||||
{
|
||||
const GLuint stride = from_vec->stride;
|
||||
GLfloat *from = from_vec->start;
|
||||
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
|
||||
GLuint count = from_vec->count;
|
||||
const GLfloat m0 = m[0], m5 = m[5];
|
||||
const GLfloat m10 = m[10], m12 = m[12], m13 = m[13], m14 = m[14];
|
||||
GLuint i;
|
||||
STRIDE_LOOP {
|
||||
const GLfloat ox = from[0], oy = from[1], oz = from[2];
|
||||
to[i][0] = m0 * ox + m12 ;
|
||||
to[i][1] = m5 * oy + m13 ;
|
||||
to[i][2] = m10 * oz + m14 ;
|
||||
}
|
||||
to_vec->size = 3;
|
||||
to_vec->flags |= VEC_SIZE_3;
|
||||
to_vec->count = from_vec->count;
|
||||
}
|
||||
|
||||
static void
|
||||
TAG(transform_points3_perspective)( GLvector4f *to_vec,
|
||||
const GLfloat m[16],
|
||||
const GLvector4f *from_vec )
|
||||
{
|
||||
const GLuint stride = from_vec->stride;
|
||||
GLfloat *from = from_vec->start;
|
||||
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
|
||||
GLuint count = from_vec->count;
|
||||
const GLfloat m0 = m[0], m5 = m[5], m8 = m[8], m9 = m[9];
|
||||
const GLfloat m10 = m[10], m14 = m[14];
|
||||
GLuint i;
|
||||
STRIDE_LOOP {
|
||||
const GLfloat ox = from[0], oy = from[1], oz = from[2];
|
||||
to[i][0] = m0 * ox + m8 * oz ;
|
||||
to[i][1] = m5 * oy + m9 * oz ;
|
||||
to[i][2] = m10 * oz + m14 ;
|
||||
to[i][3] = -oz ;
|
||||
}
|
||||
to_vec->size = 4;
|
||||
to_vec->flags |= VEC_SIZE_4;
|
||||
to_vec->count = from_vec->count;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
TAG(transform_points4_general)( GLvector4f *to_vec,
|
||||
const GLfloat m[16],
|
||||
const GLvector4f *from_vec )
|
||||
{
|
||||
const GLuint stride = from_vec->stride;
|
||||
GLfloat *from = from_vec->start;
|
||||
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
|
||||
GLuint count = from_vec->count;
|
||||
const GLfloat m0 = m[0], m4 = m[4], m8 = m[8], m12 = m[12];
|
||||
const GLfloat m1 = m[1], m5 = m[5], m9 = m[9], m13 = m[13];
|
||||
const GLfloat m2 = m[2], m6 = m[6], m10 = m[10], m14 = m[14];
|
||||
const GLfloat m3 = m[3], m7 = m[7], m11 = m[11], m15 = m[15];
|
||||
GLuint i;
|
||||
STRIDE_LOOP {
|
||||
const GLfloat ox = from[0], oy = from[1], oz = from[2], ow = from[3];
|
||||
to[i][0] = m0 * ox + m4 * oy + m8 * oz + m12 * ow;
|
||||
to[i][1] = m1 * ox + m5 * oy + m9 * oz + m13 * ow;
|
||||
to[i][2] = m2 * ox + m6 * oy + m10 * oz + m14 * ow;
|
||||
to[i][3] = m3 * ox + m7 * oy + m11 * oz + m15 * ow;
|
||||
}
|
||||
to_vec->size = 4;
|
||||
to_vec->flags |= VEC_SIZE_4;
|
||||
to_vec->count = from_vec->count;
|
||||
}
|
||||
|
||||
static void
|
||||
TAG(transform_points4_identity)( GLvector4f *to_vec,
|
||||
const GLfloat m[16],
|
||||
const GLvector4f *from_vec )
|
||||
{
|
||||
const GLuint stride = from_vec->stride;
|
||||
GLfloat *from = from_vec->start;
|
||||
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
|
||||
GLuint count = from_vec->count;
|
||||
GLuint i;
|
||||
(void) m;
|
||||
if (to_vec == from_vec) return;
|
||||
STRIDE_LOOP {
|
||||
to[i][0] = from[0];
|
||||
to[i][1] = from[1];
|
||||
to[i][2] = from[2];
|
||||
to[i][3] = from[3];
|
||||
}
|
||||
to_vec->size = 4;
|
||||
to_vec->flags |= VEC_SIZE_4;
|
||||
to_vec->count = from_vec->count;
|
||||
}
|
||||
|
||||
static void
|
||||
TAG(transform_points4_2d)( GLvector4f *to_vec,
|
||||
const GLfloat m[16],
|
||||
const GLvector4f *from_vec )
|
||||
{
|
||||
const GLuint stride = from_vec->stride;
|
||||
GLfloat *from = from_vec->start;
|
||||
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
|
||||
GLuint count = from_vec->count;
|
||||
const GLfloat m0 = m[0], m1 = m[1], m4 = m[4], m5 = m[5];
|
||||
const GLfloat m12 = m[12], m13 = m[13];
|
||||
GLuint i;
|
||||
STRIDE_LOOP {
|
||||
const GLfloat ox = from[0], oy = from[1], oz = from[2], ow = from[3];
|
||||
to[i][0] = m0 * ox + m4 * oy + m12 * ow;
|
||||
to[i][1] = m1 * ox + m5 * oy + m13 * ow;
|
||||
to[i][2] = + oz ;
|
||||
to[i][3] = ow;
|
||||
}
|
||||
to_vec->size = 4;
|
||||
to_vec->flags |= VEC_SIZE_4;
|
||||
to_vec->count = from_vec->count;
|
||||
}
|
||||
|
||||
static void
|
||||
TAG(transform_points4_2d_no_rot)( GLvector4f *to_vec,
|
||||
const GLfloat m[16],
|
||||
const GLvector4f *from_vec )
|
||||
{
|
||||
const GLuint stride = from_vec->stride;
|
||||
GLfloat *from = from_vec->start;
|
||||
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
|
||||
GLuint count = from_vec->count;
|
||||
const GLfloat m0 = m[0], m5 = m[5], m12 = m[12], m13 = m[13];
|
||||
GLuint i;
|
||||
STRIDE_LOOP {
|
||||
const GLfloat ox = from[0], oy = from[1], oz = from[2], ow = from[3];
|
||||
to[i][0] = m0 * ox + m12 * ow;
|
||||
to[i][1] = m5 * oy + m13 * ow;
|
||||
to[i][2] = + oz ;
|
||||
to[i][3] = ow;
|
||||
}
|
||||
to_vec->size = 4;
|
||||
to_vec->flags |= VEC_SIZE_4;
|
||||
to_vec->count = from_vec->count;
|
||||
}
|
||||
|
||||
static void
|
||||
TAG(transform_points4_3d)( GLvector4f *to_vec,
|
||||
const GLfloat m[16],
|
||||
const GLvector4f *from_vec )
|
||||
{
|
||||
const GLuint stride = from_vec->stride;
|
||||
GLfloat *from = from_vec->start;
|
||||
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
|
||||
GLuint count = from_vec->count;
|
||||
const GLfloat m0 = m[0], m1 = m[1], m2 = m[2], m4 = m[4], m5 = m[5];
|
||||
const GLfloat m6 = m[6], m8 = m[8], m9 = m[9], m10 = m[10];
|
||||
const GLfloat m12 = m[12], m13 = m[13], m14 = m[14];
|
||||
GLuint i;
|
||||
STRIDE_LOOP {
|
||||
const GLfloat ox = from[0], oy = from[1], oz = from[2], ow = from[3];
|
||||
to[i][0] = m0 * ox + m4 * oy + m8 * oz + m12 * ow;
|
||||
to[i][1] = m1 * ox + m5 * oy + m9 * oz + m13 * ow;
|
||||
to[i][2] = m2 * ox + m6 * oy + m10 * oz + m14 * ow;
|
||||
to[i][3] = ow;
|
||||
}
|
||||
to_vec->size = 4;
|
||||
to_vec->flags |= VEC_SIZE_4;
|
||||
to_vec->count = from_vec->count;
|
||||
}
|
||||
|
||||
static void
|
||||
TAG(transform_points4_3d_no_rot)( GLvector4f *to_vec,
|
||||
const GLfloat m[16],
|
||||
const GLvector4f *from_vec )
|
||||
{
|
||||
const GLuint stride = from_vec->stride;
|
||||
GLfloat *from = from_vec->start;
|
||||
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
|
||||
GLuint count = from_vec->count;
|
||||
const GLfloat m0 = m[0], m5 = m[5];
|
||||
const GLfloat m10 = m[10], m12 = m[12], m13 = m[13], m14 = m[14];
|
||||
GLuint i;
|
||||
STRIDE_LOOP {
|
||||
const GLfloat ox = from[0], oy = from[1], oz = from[2], ow = from[3];
|
||||
to[i][0] = m0 * ox + m12 * ow;
|
||||
to[i][1] = m5 * oy + m13 * ow;
|
||||
to[i][2] = m10 * oz + m14 * ow;
|
||||
to[i][3] = ow;
|
||||
}
|
||||
to_vec->size = 4;
|
||||
to_vec->flags |= VEC_SIZE_4;
|
||||
to_vec->count = from_vec->count;
|
||||
}
|
||||
|
||||
static void
|
||||
TAG(transform_points4_perspective)( GLvector4f *to_vec,
|
||||
const GLfloat m[16],
|
||||
const GLvector4f *from_vec )
|
||||
{
|
||||
const GLuint stride = from_vec->stride;
|
||||
GLfloat *from = from_vec->start;
|
||||
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
|
||||
GLuint count = from_vec->count;
|
||||
const GLfloat m0 = m[0], m5 = m[5], m8 = m[8], m9 = m[9];
|
||||
const GLfloat m10 = m[10], m14 = m[14];
|
||||
GLuint i;
|
||||
STRIDE_LOOP {
|
||||
const GLfloat ox = from[0], oy = from[1], oz = from[2], ow = from[3];
|
||||
to[i][0] = m0 * ox + m8 * oz ;
|
||||
to[i][1] = m5 * oy + m9 * oz ;
|
||||
to[i][2] = m10 * oz + m14 * ow ;
|
||||
to[i][3] = -oz ;
|
||||
}
|
||||
to_vec->size = 4;
|
||||
to_vec->flags |= VEC_SIZE_4;
|
||||
to_vec->count = from_vec->count;
|
||||
}
|
||||
|
||||
static transform_func TAG(transform_tab_1)[7];
|
||||
static transform_func TAG(transform_tab_2)[7];
|
||||
static transform_func TAG(transform_tab_3)[7];
|
||||
static transform_func TAG(transform_tab_4)[7];
|
||||
|
||||
/* Similar functions could be called several times, with more highly
|
||||
* optimized routines overwriting the arrays. This only occurs during
|
||||
* startup.
|
||||
*/
|
||||
static void TAG(init_c_transformations)( void )
|
||||
{
|
||||
#define TAG_TAB _mesa_transform_tab
|
||||
#define TAG_TAB_1 TAG(transform_tab_1)
|
||||
#define TAG_TAB_2 TAG(transform_tab_2)
|
||||
#define TAG_TAB_3 TAG(transform_tab_3)
|
||||
#define TAG_TAB_4 TAG(transform_tab_4)
|
||||
|
||||
TAG_TAB[1] = TAG_TAB_1;
|
||||
TAG_TAB[2] = TAG_TAB_2;
|
||||
TAG_TAB[3] = TAG_TAB_3;
|
||||
TAG_TAB[4] = TAG_TAB_4;
|
||||
|
||||
/* 1-D points (ie texcoords) */
|
||||
TAG_TAB_1[MATRIX_GENERAL] = TAG(transform_points1_general);
|
||||
TAG_TAB_1[MATRIX_IDENTITY] = TAG(transform_points1_identity);
|
||||
TAG_TAB_1[MATRIX_3D_NO_ROT] = TAG(transform_points1_3d_no_rot);
|
||||
TAG_TAB_1[MATRIX_PERSPECTIVE] = TAG(transform_points1_perspective);
|
||||
TAG_TAB_1[MATRIX_2D] = TAG(transform_points1_2d);
|
||||
TAG_TAB_1[MATRIX_2D_NO_ROT] = TAG(transform_points1_2d_no_rot);
|
||||
TAG_TAB_1[MATRIX_3D] = TAG(transform_points1_3d);
|
||||
|
||||
/* 2-D points */
|
||||
TAG_TAB_2[MATRIX_GENERAL] = TAG(transform_points2_general);
|
||||
TAG_TAB_2[MATRIX_IDENTITY] = TAG(transform_points2_identity);
|
||||
TAG_TAB_2[MATRIX_3D_NO_ROT] = TAG(transform_points2_3d_no_rot);
|
||||
TAG_TAB_2[MATRIX_PERSPECTIVE] = TAG(transform_points2_perspective);
|
||||
TAG_TAB_2[MATRIX_2D] = TAG(transform_points2_2d);
|
||||
TAG_TAB_2[MATRIX_2D_NO_ROT] = TAG(transform_points2_2d_no_rot);
|
||||
TAG_TAB_2[MATRIX_3D] = TAG(transform_points2_3d);
|
||||
|
||||
/* 3-D points */
|
||||
TAG_TAB_3[MATRIX_GENERAL] = TAG(transform_points3_general);
|
||||
TAG_TAB_3[MATRIX_IDENTITY] = TAG(transform_points3_identity);
|
||||
TAG_TAB_3[MATRIX_3D_NO_ROT] = TAG(transform_points3_3d_no_rot);
|
||||
TAG_TAB_3[MATRIX_PERSPECTIVE] = TAG(transform_points3_perspective);
|
||||
TAG_TAB_3[MATRIX_2D] = TAG(transform_points3_2d);
|
||||
TAG_TAB_3[MATRIX_2D_NO_ROT] = TAG(transform_points3_2d_no_rot);
|
||||
TAG_TAB_3[MATRIX_3D] = TAG(transform_points3_3d);
|
||||
|
||||
/* 4-D points */
|
||||
TAG_TAB_4[MATRIX_GENERAL] = TAG(transform_points4_general);
|
||||
TAG_TAB_4[MATRIX_IDENTITY] = TAG(transform_points4_identity);
|
||||
TAG_TAB_4[MATRIX_3D_NO_ROT] = TAG(transform_points4_3d_no_rot);
|
||||
TAG_TAB_4[MATRIX_PERSPECTIVE] = TAG(transform_points4_perspective);
|
||||
TAG_TAB_4[MATRIX_2D] = TAG(transform_points4_2d);
|
||||
TAG_TAB_4[MATRIX_2D_NO_ROT] = TAG(transform_points4_2d_no_rot);
|
||||
TAG_TAB_4[MATRIX_3D] = TAG(transform_points4_3d);
|
||||
|
||||
#undef TAG_TAB
|
||||
#undef TAG_TAB_1
|
||||
#undef TAG_TAB_2
|
||||
#undef TAG_TAB_3
|
||||
#undef TAG_TAB_4
|
||||
}
|
|
@ -351,124 +351,6 @@ files_libmesa_common = files(
|
|||
'x86/common_x86.c',
|
||||
)
|
||||
|
||||
# mesa files
|
||||
files_libmesa_classic = files(
|
||||
'math/m_clip_tmp.h',
|
||||
'math/m_copy_tmp.h',
|
||||
'math/m_dotprod_tmp.h',
|
||||
'math/m_norm_tmp.h',
|
||||
'math/m_xform.c',
|
||||
'math/m_xform.h',
|
||||
'math/m_xform_tmp.h',
|
||||
'tnl/t_context.c',
|
||||
'tnl/t_context.h',
|
||||
'tnl/t_draw.c',
|
||||
'tnl/tnl.h',
|
||||
'tnl/t_pipeline.c',
|
||||
'tnl/t_pipeline.h',
|
||||
'tnl/t_rebase.c',
|
||||
'tnl/t_split.c',
|
||||
'tnl/t_split_copy.c',
|
||||
'tnl/t_split.h',
|
||||
'tnl/t_split_inplace.c',
|
||||
'tnl/t_vb_cliptmp.h',
|
||||
'tnl/t_vb_fog.c',
|
||||
'tnl/t_vb_light.c',
|
||||
'tnl/t_vb_lighttmp.h',
|
||||
'tnl/t_vb_normals.c',
|
||||
'tnl/t_vb_points.c',
|
||||
'tnl/t_vb_program.c',
|
||||
'tnl/t_vb_render.c',
|
||||
'tnl/t_vb_rendertmp.h',
|
||||
'tnl/t_vb_texgen.c',
|
||||
'tnl/t_vb_texmat.c',
|
||||
'tnl/t_vb_vertex.c',
|
||||
'tnl/t_vertex.c',
|
||||
'tnl/t_vertex_generic.c',
|
||||
'tnl/t_vertex.h',
|
||||
'tnl/t_vertex_sse.c',
|
||||
'tnl/t_vp_build.c',
|
||||
'tnl/t_vp_build.h',
|
||||
'swrast/s_aaline.c',
|
||||
'swrast/s_aaline.h',
|
||||
'swrast/s_aalinetemp.h',
|
||||
'swrast/s_aatriangle.c',
|
||||
'swrast/s_aatriangle.h',
|
||||
'swrast/s_aatritemp.h',
|
||||
'swrast/s_alpha.c',
|
||||
'swrast/s_alpha.h',
|
||||
'swrast/s_atifragshader.c',
|
||||
'swrast/s_atifragshader.h',
|
||||
'swrast/s_bitmap.c',
|
||||
'swrast/s_blend.c',
|
||||
'swrast/s_blend.h',
|
||||
'swrast/s_blit.c',
|
||||
'swrast/s_chan.h',
|
||||
'swrast/s_clear.c',
|
||||
'swrast/s_context.c',
|
||||
'swrast/s_context.h',
|
||||
'swrast/s_copypix.c',
|
||||
'swrast/s_depth.c',
|
||||
'swrast/s_depth.h',
|
||||
'swrast/s_drawpix.c',
|
||||
'swrast_setup/ss_tritmp.h',
|
||||
'swrast_setup/ss_vb.h',
|
||||
'swrast_setup/swrast_setup.h',
|
||||
'swrast/s_feedback.c',
|
||||
'swrast/s_feedback.h',
|
||||
'swrast/s_fog.c',
|
||||
'swrast/s_fog.h',
|
||||
'swrast/s_fragprog.c',
|
||||
'swrast/s_fragprog.h',
|
||||
'swrast/s_lines.c',
|
||||
'swrast/s_lines.h',
|
||||
'swrast/s_linetemp.h',
|
||||
'swrast/s_logic.c',
|
||||
'swrast/s_logic.h',
|
||||
'swrast/s_masking.c',
|
||||
'swrast/s_masking.h',
|
||||
'swrast/s_points.c',
|
||||
'swrast/s_points.h',
|
||||
'swrast/s_renderbuffer.c',
|
||||
'swrast/s_renderbuffer.h',
|
||||
'swrast/s_span.c',
|
||||
'swrast/s_span.h',
|
||||
'swrast/s_stencil.c',
|
||||
'swrast/s_stencil.h',
|
||||
'swrast/s_texcombine.c',
|
||||
'swrast/s_texcombine.h',
|
||||
'swrast/s_texfetch.c',
|
||||
'swrast/s_texfetch.h',
|
||||
'swrast/s_texfetch_tmp.h',
|
||||
'swrast/s_texfilter.c',
|
||||
'swrast/s_texfilter.h',
|
||||
'swrast/s_texrender.c',
|
||||
'swrast/s_texture.c',
|
||||
'swrast/s_triangle.c',
|
||||
'swrast/s_triangle.h',
|
||||
'swrast/s_tritemp.h',
|
||||
'swrast/swrast.h',
|
||||
'swrast/s_zoom.c',
|
||||
'swrast/s_zoom.h',
|
||||
'swrast_setup/ss_context.c',
|
||||
'swrast_setup/ss_context.h',
|
||||
'swrast_setup/ss_triangle.c',
|
||||
'swrast_setup/ss_triangle.h',
|
||||
'drivers/common/driverfuncs.c',
|
||||
'drivers/common/driverfuncs.h',
|
||||
'drivers/common/meta_blit.c',
|
||||
'drivers/common/meta_generate_mipmap.c',
|
||||
'drivers/common/meta.c',
|
||||
'drivers/common/meta.h',
|
||||
'x86/x86_xform.c',
|
||||
'x86/3dnow.c',
|
||||
'x86/sse.c',
|
||||
'x86/rtasm/x86sse.c',
|
||||
'x86/rtasm/x86sse.h',
|
||||
'sparc/sparc.c',
|
||||
'x86-64/x86-64.c',
|
||||
)
|
||||
|
||||
files_libmesa_gallium = files(
|
||||
'state_tracker/st_atifs_to_nir.c',
|
||||
'state_tracker/st_atifs_to_nir.h',
|
||||
|
@ -612,44 +494,15 @@ inc_libmesa_asm = []
|
|||
if with_asm_arch == 'x86'
|
||||
files_libmesa_common += files(
|
||||
'x86/assyntax.h',
|
||||
'x86/clip_args.h',
|
||||
'x86/norm_args.h',
|
||||
'x86/xform_args.h',
|
||||
'x86/common_x86_asm.S',
|
||||
'x86/common_x86_asm.h',
|
||||
'x86/common_x86_features.h',
|
||||
'x86/x86_xform.h',
|
||||
'x86/x86_xform2.S',
|
||||
'x86/x86_xform3.S',
|
||||
'x86/x86_xform4.S',
|
||||
'x86/x86_cliptest.S',
|
||||
'x86/mmx.h',
|
||||
'x86/mmx_blend.S',
|
||||
'x86/mmx_blendtmp.h',
|
||||
'x86/3dnow.h',
|
||||
'x86/3dnow_xform1.S',
|
||||
'x86/3dnow_xform2.S',
|
||||
'x86/3dnow_xform3.S',
|
||||
'x86/3dnow_xform4.S',
|
||||
'x86/sse.h',
|
||||
'x86/sse_xform1.S',
|
||||
'x86/sse_xform2.S',
|
||||
'x86/sse_xform3.S',
|
||||
'x86/sse_xform4.S',
|
||||
'x86/sse_normal.S',
|
||||
'x86/read_rgba_span_x86.S',
|
||||
)
|
||||
inc_libmesa_asm = include_directories('x86')
|
||||
elif with_asm_arch == 'x86_64'
|
||||
files_libmesa_common += files('x86-64/x86-64.h', 'x86-64/xform4.S')
|
||||
inc_libmesa_asm = include_directories('x86-64')
|
||||
elif with_asm_arch == 'sparc'
|
||||
files_libmesa_common += files(
|
||||
'sparc/sparc_clip.S',
|
||||
'sparc/norm.S',
|
||||
'sparc/xform.S',
|
||||
)
|
||||
inc_libmesa_asm = include_directories('sparc')
|
||||
endif
|
||||
|
||||
format_fallback_c = custom_target(
|
||||
|
@ -733,18 +586,6 @@ libmesa_common = static_library(
|
|||
build_by_default : false,
|
||||
)
|
||||
|
||||
libmesa_classic = static_library(
|
||||
'mesa_classic',
|
||||
files_libmesa_classic,
|
||||
c_args : [c_msvc_compat_args],
|
||||
cpp_args : [cpp_msvc_compat_args],
|
||||
gnu_symbol_visibility : 'hidden',
|
||||
include_directories : [inc_include, inc_src, inc_mapi, inc_mesa, inc_gallium, inc_gallium_aux, inc_libmesa_asm, include_directories('main')],
|
||||
link_with : [libmesa_common, libglsl, libmesa_sse41],
|
||||
dependencies : [idep_nir_headers, idep_mesautil],
|
||||
build_by_default : false,
|
||||
)
|
||||
|
||||
libmesa_gallium = static_library(
|
||||
'mesa_gallium',
|
||||
files_libmesa_gallium,
|
||||
|
|
|
@ -1,605 +0,0 @@
|
|||
|
||||
#include "sparc_matrix.h"
|
||||
|
||||
.register %g2, #scratch
|
||||
.register %g3, #scratch
|
||||
|
||||
.text
|
||||
|
||||
#ifdef __arch64__
|
||||
#define STACK_VAR_OFF (2047 + (8 * 16))
|
||||
#else
|
||||
#define STACK_VAR_OFF (4 * 16)
|
||||
#endif
|
||||
|
||||
/* Newton-Raphson approximation turns out to be slower
|
||||
* (and less accurate) than direct fsqrts/fdivs.
|
||||
*/
|
||||
#define ONE_DOT_ZERO 0x3f800000
|
||||
|
||||
.globl _mesa_sparc_transform_normalize_normals
|
||||
_mesa_sparc_transform_normalize_normals:
|
||||
/* o0=mat o1=scale o2=in o3=lengths o4=dest */
|
||||
|
||||
sethi %hi(ONE_DOT_ZERO), %g2
|
||||
sub %sp, 16, %sp
|
||||
st %g2, [%sp + STACK_VAR_OFF+0x0]
|
||||
st %o1, [%sp + STACK_VAR_OFF+0x4]
|
||||
ld [%sp + STACK_VAR_OFF+0x0], %f12 ! f12 = 1.0f
|
||||
ld [%sp + STACK_VAR_OFF+0x4], %f15 ! f15 = scale
|
||||
add %sp, 16, %sp
|
||||
|
||||
add %o0, MATRIX_INV, %o0 ! o0 = mat->inv
|
||||
LDPTR [%o2 + V4F_START], %o5 ! o5 = 'from' in->start
|
||||
ld [%o2 + V4F_COUNT], %g1 ! g1 = in->count
|
||||
ld [%o2 + V4F_STRIDE], %g2 ! g2 = in->stride
|
||||
LDPTR [%o4 + V4F_START], %g3 ! g3 = 'out' dest->start
|
||||
|
||||
LDMATRIX_0_1_2_4_5_6_8_9_10(%o0)
|
||||
|
||||
/* dest->count = in->count */
|
||||
st %g1, [%o4 + V4F_COUNT]
|
||||
|
||||
cmp %g1, 1
|
||||
bl 7f
|
||||
cmp %o3, 0
|
||||
bne 4f
|
||||
clr %o4 ! 'i' for STRIDE_LOOP
|
||||
|
||||
1: /* LENGTHS == NULL */
|
||||
ld [%o5 + 0x00], %f0 ! ux = from[0]
|
||||
ld [%o5 + 0x04], %f1 ! uy = from[1]
|
||||
ld [%o5 + 0x08], %f2 ! uz = from[2]
|
||||
add %o5, %g2, %o5 ! STRIDE_F(from, stride)
|
||||
add %o4, 1, %o4 ! i++
|
||||
|
||||
/* tx (f3) = (ux * m0) + (uy * m1) + (uz * m2)
|
||||
* ty (f5) = (ux * m4) + (uy * m5) + (uz * m6)
|
||||
* tz (f7) = (ux * m8) + (uy * m9) + (uz * m10)
|
||||
*/
|
||||
fmuls %f0, M0, %f3 ! FGM Group
|
||||
fmuls %f1, M1, %f4 ! FGM Group
|
||||
fmuls %f0, M4, %f5 ! FGM Group
|
||||
fmuls %f1, M5, %f6 ! FGM Group
|
||||
fmuls %f0, M8, %f7 ! FGM Group f3 available
|
||||
fmuls %f1, M9, %f8 ! FGM Group f4 available
|
||||
fadds %f3, %f4, %f3 ! FGA
|
||||
fmuls %f2, M2, %f10 ! FGM Group f5 available
|
||||
fmuls %f2, M6, %f0 ! FGM Group f6 available
|
||||
fadds %f5, %f6, %f5 ! FGA
|
||||
fmuls %f2, M10, %f4 ! FGM Group f7 available
|
||||
fadds %f7, %f8, %f7 ! FGA Group f8,f3 available
|
||||
fadds %f3, %f10, %f3 ! FGA Group f10 available
|
||||
fadds %f5, %f0, %f5 ! FGA Group stall f0,f5 available
|
||||
fadds %f7, %f4, %f7 ! FGA Group stall f4,f7 available
|
||||
|
||||
/* f3=tx, f5=ty, f7=tz */
|
||||
|
||||
/* len (f6) = (tx * tx) + (ty * ty) + (tz * tz) */
|
||||
fmuls %f3, %f3, %f6 ! FGM Group f3 available
|
||||
fmuls %f5, %f5, %f8 ! FGM Group f5 available
|
||||
fmuls %f7, %f7, %f10 ! FGM Group f7 available
|
||||
fadds %f6, %f8, %f6 ! FGA Group 2cyc stall f6,f8 available
|
||||
fadds %f6, %f10, %f6 ! FGA Group 4cyc stall f6,f10 available
|
||||
|
||||
/* scale (f6) = 1.0 / sqrt(len) */
|
||||
fsqrts %f6, %f6 ! FDIV 20 cycles
|
||||
fdivs %f12, %f6, %f6 ! FDIV 14 cycles
|
||||
|
||||
fmuls %f3, %f6, %f3
|
||||
st %f3, [%g3 + 0x00] ! out[i][0] = tx * scale
|
||||
fmuls %f5, %f6, %f5
|
||||
st %f5, [%g3 + 0x04] ! out[i][1] = ty * scale
|
||||
fmuls %f7, %f6, %f7
|
||||
st %f7, [%g3 + 0x08] ! out[i][2] = tz * scale
|
||||
|
||||
cmp %o4, %g1 ! continue if (i < count)
|
||||
bl 1b
|
||||
add %g3, 0x10, %g3 ! advance out vector pointer
|
||||
|
||||
ba 7f
|
||||
nop
|
||||
|
||||
4: /* LENGTHS != NULL */
|
||||
fmuls M0, %f15, M0
|
||||
fmuls M1, %f15, M1
|
||||
fmuls M2, %f15, M2
|
||||
fmuls M4, %f15, M4
|
||||
fmuls M5, %f15, M5
|
||||
fmuls M6, %f15, M6
|
||||
fmuls M8, %f15, M8
|
||||
fmuls M9, %f15, M9
|
||||
fmuls M10, %f15, M10
|
||||
|
||||
5:
|
||||
ld [%o5 + 0x00], %f0 ! ux = from[0]
|
||||
ld [%o5 + 0x04], %f1 ! uy = from[1]
|
||||
ld [%o5 + 0x08], %f2 ! uz = from[2]
|
||||
add %o5, %g2, %o5 ! STRIDE_F(from, stride)
|
||||
add %o4, 1, %o4 ! i++
|
||||
|
||||
/* tx (f3) = (ux * m0) + (uy * m1) + (uz * m2)
|
||||
* ty (f5) = (ux * m4) + (uy * m5) + (uz * m6)
|
||||
* tz (f7) = (ux * m8) + (uy * m9) + (uz * m10)
|
||||
*/
|
||||
fmuls %f0, M0, %f3 ! FGM Group
|
||||
fmuls %f1, M1, %f4 ! FGM Group
|
||||
fmuls %f0, M4, %f5 ! FGM Group
|
||||
fmuls %f1, M5, %f6 ! FGM Group
|
||||
fmuls %f0, M8, %f7 ! FGM Group f3 available
|
||||
fmuls %f1, M9, %f8 ! FGM Group f4 available
|
||||
fadds %f3, %f4, %f3 ! FGA
|
||||
fmuls %f2, M2, %f10 ! FGM Group f5 available
|
||||
fmuls %f2, M6, %f0 ! FGM Group f6 available
|
||||
fadds %f5, %f6, %f5 ! FGA
|
||||
fmuls %f2, M10, %f4 ! FGM Group f7 available
|
||||
fadds %f7, %f8, %f7 ! FGA Group f8,f3 available
|
||||
fadds %f3, %f10, %f3 ! FGA Group f10 available
|
||||
ld [%o3], %f13 ! LSU
|
||||
fadds %f5, %f0, %f5 ! FGA Group stall f0,f5 available
|
||||
add %o3, 4, %o3 ! IEU0
|
||||
fadds %f7, %f4, %f7 ! FGA Group stall f4,f7 available
|
||||
|
||||
/* f3=tx, f5=ty, f7=tz, f13=lengths[i] */
|
||||
|
||||
fmuls %f3, %f13, %f3
|
||||
st %f3, [%g3 + 0x00] ! out[i][0] = tx * len
|
||||
fmuls %f5, %f13, %f5
|
||||
st %f5, [%g3 + 0x04] ! out[i][1] = ty * len
|
||||
fmuls %f7, %f13, %f7
|
||||
st %f7, [%g3 + 0x08] ! out[i][2] = tz * len
|
||||
|
||||
cmp %o4, %g1 ! continue if (i < count)
|
||||
bl 5b
|
||||
add %g3, 0x10, %g3 ! advance out vector pointer
|
||||
|
||||
7: retl
|
||||
nop
|
||||
|
||||
.globl _mesa_sparc_transform_normalize_normals_no_rot
|
||||
_mesa_sparc_transform_normalize_normals_no_rot:
|
||||
/* o0=mat o1=scale o2=in o3=lengths o4=dest */
|
||||
|
||||
sethi %hi(ONE_DOT_ZERO), %g2
|
||||
sub %sp, 16, %sp
|
||||
st %g2, [%sp + STACK_VAR_OFF+0x0]
|
||||
st %o1, [%sp + STACK_VAR_OFF+0x4]
|
||||
ld [%sp + STACK_VAR_OFF+0x0], %f12 ! f12 = 1.0f
|
||||
ld [%sp + STACK_VAR_OFF+0x4], %f15 ! f15 = scale
|
||||
add %sp, 16, %sp
|
||||
|
||||
add %o0, MATRIX_INV, %o0 ! o0 = mat->inv
|
||||
LDPTR [%o2 + V4F_START], %o5 ! o5 = 'from' in->start
|
||||
ld [%o2 + V4F_COUNT], %g1 ! g1 = in->count
|
||||
ld [%o2 + V4F_STRIDE], %g2 ! g2 = in->stride
|
||||
LDPTR [%o4 + V4F_START], %g3 ! g3 = 'out' dest->start
|
||||
|
||||
LDMATRIX_0_5_10(%o0)
|
||||
|
||||
/* dest->count = in->count */
|
||||
st %g1, [%o4 + V4F_COUNT]
|
||||
|
||||
cmp %g1, 1
|
||||
bl 7f
|
||||
cmp %o3, 0
|
||||
bne 4f
|
||||
clr %o4 ! 'i' for STRIDE_LOOP
|
||||
|
||||
1: /* LENGTHS == NULL */
|
||||
ld [%o5 + 0x00], %f0 ! ux = from[0]
|
||||
ld [%o5 + 0x04], %f1 ! uy = from[1]
|
||||
ld [%o5 + 0x08], %f2 ! uz = from[2]
|
||||
add %o5, %g2, %o5 ! STRIDE_F(from, stride)
|
||||
add %o4, 1, %o4 ! i++
|
||||
|
||||
/* tx (f3) = (ux * m0)
|
||||
* ty (f5) = (uy * m5)
|
||||
* tz (f7) = (uz * m10)
|
||||
*/
|
||||
fmuls %f0, M0, %f3 ! FGM Group
|
||||
fmuls %f1, M5, %f5 ! FGM Group
|
||||
fmuls %f2, M10, %f7 ! FGM Group
|
||||
|
||||
/* f3=tx, f5=ty, f7=tz */
|
||||
|
||||
/* len (f6) = (tx * tx) + (ty * ty) + (tz * tz) */
|
||||
fmuls %f3, %f3, %f6 ! FGM Group stall, f3 available
|
||||
fmuls %f5, %f5, %f8 ! FGM Group f5 available
|
||||
fmuls %f7, %f7, %f10 ! FGM Group f7 available
|
||||
fadds %f6, %f8, %f6 ! FGA Group 2cyc stall f6,f8 available
|
||||
fadds %f6, %f10, %f6 ! FGA Group 4cyc stall f6,f10 available
|
||||
|
||||
/* scale (f6) = 1.0 / sqrt(len) */
|
||||
fsqrts %f6, %f6 ! FDIV 20 cycles
|
||||
fdivs %f12, %f6, %f6 ! FDIV 14 cycles
|
||||
|
||||
fmuls %f3, %f6, %f3
|
||||
st %f3, [%g3 + 0x00] ! out[i][0] = tx * scale
|
||||
fmuls %f5, %f6, %f5
|
||||
st %f5, [%g3 + 0x04] ! out[i][1] = ty * scale
|
||||
fmuls %f7, %f6, %f7
|
||||
st %f7, [%g3 + 0x08] ! out[i][2] = tz * scale
|
||||
|
||||
cmp %o4, %g1 ! continue if (i < count)
|
||||
bl 1b
|
||||
add %g3, 0x10, %g3 ! advance out vector pointer
|
||||
|
||||
ba 7f
|
||||
nop
|
||||
|
||||
4: /* LENGTHS != NULL */
|
||||
fmuls M0, %f15, M0
|
||||
fmuls M5, %f15, M5
|
||||
fmuls M10, %f15, M10
|
||||
|
||||
5:
|
||||
ld [%o5 + 0x00], %f0 ! ux = from[0]
|
||||
ld [%o5 + 0x04], %f1 ! uy = from[1]
|
||||
ld [%o5 + 0x08], %f2 ! uz = from[2]
|
||||
add %o5, %g2, %o5 ! STRIDE_F(from, stride)
|
||||
add %o4, 1, %o4 ! i++
|
||||
|
||||
/* tx (f3) = (ux * m0)
|
||||
* ty (f5) = (uy * m5)
|
||||
* tz (f7) = (uz * m10)
|
||||
*/
|
||||
fmuls %f0, M0, %f3 ! FGM Group
|
||||
ld [%o3], %f13 ! LSU
|
||||
fmuls %f1, M5, %f5 ! FGM Group
|
||||
add %o3, 4, %o3 ! IEU0
|
||||
fmuls %f2, M10, %f7 ! FGM Group
|
||||
|
||||
/* f3=tx, f5=ty, f7=tz, f13=lengths[i] */
|
||||
|
||||
fmuls %f3, %f13, %f3
|
||||
st %f3, [%g3 + 0x00] ! out[i][0] = tx * len
|
||||
fmuls %f5, %f13, %f5
|
||||
st %f5, [%g3 + 0x04] ! out[i][1] = ty * len
|
||||
fmuls %f7, %f13, %f7
|
||||
st %f7, [%g3 + 0x08] ! out[i][2] = tz * len
|
||||
|
||||
cmp %o4, %g1 ! continue if (i < count)
|
||||
bl 5b
|
||||
add %g3, 0x10, %g3 ! advance out vector pointer
|
||||
|
||||
7: retl
|
||||
nop
|
||||
|
||||
.globl _mesa_sparc_transform_rescale_normals_no_rot
|
||||
_mesa_sparc_transform_rescale_normals_no_rot:
|
||||
/* o0=mat o1=scale o2=in o3=lengths o4=dest */
|
||||
sub %sp, 16, %sp
|
||||
st %o1, [%sp + STACK_VAR_OFF+0x0]
|
||||
ld [%sp + STACK_VAR_OFF+0x0], %f15 ! f15 = scale
|
||||
add %sp, 16, %sp
|
||||
|
||||
add %o0, MATRIX_INV, %o0 ! o0 = mat->inv
|
||||
LDPTR [%o2 + V4F_START], %o5 ! o5 = 'from' in->start
|
||||
ld [%o2 + V4F_COUNT], %g1 ! g1 = in->count
|
||||
ld [%o2 + V4F_STRIDE], %g2 ! g2 = in->stride
|
||||
LDPTR [%o4 + V4F_START], %g3 ! g3 = 'out' dest->start
|
||||
|
||||
LDMATRIX_0_5_10(%o0)
|
||||
|
||||
/* dest->count = in->count */
|
||||
st %g1, [%o4 + V4F_COUNT]
|
||||
|
||||
cmp %g1, 1
|
||||
bl 7f
|
||||
clr %o4 ! 'i' for STRIDE_LOOP
|
||||
|
||||
fmuls M0, %f15, M0
|
||||
fmuls M5, %f15, M5
|
||||
fmuls M10, %f15, M10
|
||||
|
||||
1: ld [%o5 + 0x00], %f0 ! ux = from[0]
|
||||
ld [%o5 + 0x04], %f1 ! uy = from[1]
|
||||
ld [%o5 + 0x08], %f2 ! uz = from[2]
|
||||
add %o5, %g2, %o5 ! STRIDE_F(from, stride)
|
||||
add %o4, 1, %o4 ! i++
|
||||
|
||||
/* tx (f3) = (ux * m0)
|
||||
* ty (f5) = (uy * m5)
|
||||
* tz (f7) = (uz * m10)
|
||||
*/
|
||||
fmuls %f0, M0, %f3 ! FGM Group
|
||||
st %f3, [%g3 + 0x00] ! LSU
|
||||
fmuls %f1, M5, %f5 ! FGM Group
|
||||
st %f5, [%g3 + 0x04] ! LSU
|
||||
fmuls %f2, M10, %f7 ! FGM Group
|
||||
st %f7, [%g3 + 0x08] ! LSU
|
||||
|
||||
cmp %o4, %g1 ! continue if (i < count)
|
||||
bl 1b
|
||||
add %g3, 0x10, %g3 ! advance out vector pointer
|
||||
|
||||
7: retl
|
||||
nop
|
||||
|
||||
.globl _mesa_sparc_transform_rescale_normals
|
||||
_mesa_sparc_transform_rescale_normals:
|
||||
/* o0=mat o1=scale o2=in o3=lengths o4=dest */
|
||||
sub %sp, 16, %sp
|
||||
st %o1, [%sp + STACK_VAR_OFF+0x0]
|
||||
ld [%sp + STACK_VAR_OFF+0x0], %f15 ! f15 = scale
|
||||
add %sp, 16, %sp
|
||||
|
||||
add %o0, MATRIX_INV, %o0 ! o0 = mat->inv
|
||||
LDPTR [%o2 + V4F_START], %o5 ! o5 = 'from' in->start
|
||||
ld [%o2 + V4F_COUNT], %g1 ! g1 = in->count
|
||||
ld [%o2 + V4F_STRIDE], %g2 ! g2 = in->stride
|
||||
LDPTR [%o4 + V4F_START], %g3 ! g3 = 'out' dest->start
|
||||
|
||||
LDMATRIX_0_1_2_4_5_6_8_9_10(%o0)
|
||||
|
||||
/* dest->count = in->count */
|
||||
st %g1, [%o4 + V4F_COUNT]
|
||||
|
||||
cmp %g1, 1
|
||||
bl 7f
|
||||
clr %o4 ! 'i' for STRIDE_LOOP
|
||||
|
||||
fmuls M0, %f15, M0
|
||||
fmuls M1, %f15, M1
|
||||
fmuls M2, %f15, M2
|
||||
fmuls M4, %f15, M4
|
||||
fmuls M5, %f15, M5
|
||||
fmuls M6, %f15, M6
|
||||
fmuls M8, %f15, M8
|
||||
fmuls M9, %f15, M9
|
||||
fmuls M10, %f15, M10
|
||||
|
||||
1: ld [%o5 + 0x00], %f0 ! ux = from[0]
|
||||
ld [%o5 + 0x04], %f1 ! uy = from[1]
|
||||
ld [%o5 + 0x08], %f2 ! uz = from[2]
|
||||
add %o5, %g2, %o5 ! STRIDE_F(from, stride)
|
||||
add %o4, 1, %o4 ! i++
|
||||
|
||||
fmuls %f0, M0, %f3 ! FGM Group
|
||||
fmuls %f1, M1, %f4 ! FGM Group
|
||||
fmuls %f0, M4, %f5 ! FGM Group
|
||||
fmuls %f1, M5, %f6 ! FGM Group
|
||||
fmuls %f0, M8, %f7 ! FGM Group f3 available
|
||||
fmuls %f1, M9, %f8 ! FGM Group f4 available
|
||||
fadds %f3, %f4, %f3 ! FGA
|
||||
fmuls %f2, M2, %f10 ! FGM Group f5 available
|
||||
fmuls %f2, M6, %f0 ! FGM Group f6 available
|
||||
fadds %f5, %f6, %f5 ! FGA
|
||||
fmuls %f2, M10, %f4 ! FGM Group f7 available
|
||||
fadds %f7, %f8, %f7 ! FGA Group f8,f3 available
|
||||
fadds %f3, %f10, %f3 ! FGA Group f10 available
|
||||
st %f3, [%g3 + 0x00] ! LSU
|
||||
fadds %f5, %f0, %f5 ! FGA Group stall f0,f5 available
|
||||
st %f5, [%g3 + 0x04] ! LSU
|
||||
fadds %f7, %f4, %f7 ! FGA Group stall f4,f7 available
|
||||
st %f7, [%g3 + 0x08] ! LSU
|
||||
|
||||
cmp %o4, %g1 ! continue if (i < count)
|
||||
bl 1b
|
||||
add %g3, 0x10, %g3 ! advance out vector pointer
|
||||
|
||||
7: retl
|
||||
nop
|
||||
|
||||
.globl _mesa_sparc_transform_normals_no_rot
|
||||
_mesa_sparc_transform_normals_no_rot:
|
||||
/* o0=mat o1=scale o2=in o3=lengths o4=dest */
|
||||
add %o0, MATRIX_INV, %o0 ! o0 = mat->inv
|
||||
LDPTR [%o2 + V4F_START], %o5 ! o5 = 'from' in->start
|
||||
ld [%o2 + V4F_COUNT], %g1 ! g1 = in->count
|
||||
ld [%o2 + V4F_STRIDE], %g2 ! g2 = in->stride
|
||||
LDPTR [%o4 + V4F_START], %g3 ! g3 = 'out' dest->start
|
||||
|
||||
LDMATRIX_0_5_10(%o0)
|
||||
|
||||
/* dest->count = in->count */
|
||||
st %g1, [%o4 + V4F_COUNT]
|
||||
|
||||
cmp %g1, 1
|
||||
bl 7f
|
||||
clr %o4 ! 'i' for STRIDE_LOOP
|
||||
|
||||
1: ld [%o5 + 0x00], %f0 ! ux = from[0]
|
||||
ld [%o5 + 0x04], %f1 ! uy = from[1]
|
||||
ld [%o5 + 0x08], %f2 ! uz = from[2]
|
||||
add %o5, %g2, %o5 ! STRIDE_F(from, stride)
|
||||
add %o4, 1, %o4 ! i++
|
||||
|
||||
/* tx (f3) = (ux * m0)
|
||||
* ty (f5) = (uy * m5)
|
||||
* tz (f7) = (uz * m10)
|
||||
*/
|
||||
fmuls %f0, M0, %f3 ! FGM Group
|
||||
st %f3, [%g3 + 0x00] ! LSU
|
||||
fmuls %f1, M5, %f5 ! FGM Group
|
||||
st %f5, [%g3 + 0x04] ! LSU
|
||||
fmuls %f2, M10, %f7 ! FGM Group
|
||||
st %f7, [%g3 + 0x08] ! LSU
|
||||
|
||||
cmp %o4, %g1 ! continue if (i < count)
|
||||
bl 1b
|
||||
add %g3, 0x10, %g3 ! advance out vector pointer
|
||||
|
||||
7: retl
|
||||
nop
|
||||
|
||||
.globl _mesa_sparc_transform_normals
|
||||
_mesa_sparc_transform_normals:
|
||||
/* o0=mat o1=scale o2=in o3=lengths o4=dest */
|
||||
add %o0, MATRIX_INV, %o0 ! o0 = mat->inv
|
||||
LDPTR [%o2 + V4F_START], %o5 ! o5 = 'from' in->start
|
||||
ld [%o2 + V4F_COUNT], %g1 ! g1 = in->count
|
||||
ld [%o2 + V4F_STRIDE], %g2 ! g2 = in->stride
|
||||
LDPTR [%o4 + V4F_START], %g3 ! g3 = 'out' dest->start
|
||||
|
||||
LDMATRIX_0_1_2_4_5_6_8_9_10(%o0)
|
||||
|
||||
/* dest->count = in->count */
|
||||
st %g1, [%o4 + V4F_COUNT]
|
||||
|
||||
cmp %g1, 1
|
||||
bl 7f
|
||||
clr %o4 ! 'i' for STRIDE_LOOP
|
||||
|
||||
1: ld [%o5 + 0x00], %f0 ! ux = from[0]
|
||||
ld [%o5 + 0x04], %f1 ! uy = from[1]
|
||||
ld [%o5 + 0x08], %f2 ! uz = from[2]
|
||||
add %o5, %g2, %o5 ! STRIDE_F(from, stride)
|
||||
add %o4, 1, %o4 ! i++
|
||||
|
||||
fmuls %f0, M0, %f3 ! FGM Group
|
||||
fmuls %f1, M1, %f4 ! FGM Group
|
||||
fmuls %f0, M4, %f5 ! FGM Group
|
||||
fmuls %f1, M5, %f6 ! FGM Group
|
||||
fmuls %f0, M8, %f7 ! FGM Group f3 available
|
||||
fmuls %f1, M9, %f8 ! FGM Group f4 available
|
||||
fadds %f3, %f4, %f3 ! FGA
|
||||
fmuls %f2, M2, %f10 ! FGM Group f5 available
|
||||
fmuls %f2, M6, %f0 ! FGM Group f6 available
|
||||
fadds %f5, %f6, %f5 ! FGA
|
||||
fmuls %f2, M10, %f4 ! FGM Group f7 available
|
||||
fadds %f7, %f8, %f7 ! FGA Group f8,f3 available
|
||||
fadds %f3, %f10, %f3 ! FGA Group f10 available
|
||||
st %f3, [%g3 + 0x00] ! LSU
|
||||
fadds %f5, %f0, %f5 ! FGA Group stall f0,f5 available
|
||||
st %f5, [%g3 + 0x04] ! LSU
|
||||
fadds %f7, %f4, %f7 ! FGA Group stall f4,f7 available
|
||||
st %f7, [%g3 + 0x08] ! LSU
|
||||
|
||||
cmp %o4, %g1 ! continue if (i < count)
|
||||
bl 1b
|
||||
add %g3, 0x10, %g3 ! advance out vector pointer
|
||||
|
||||
7: retl
|
||||
nop
|
||||
|
||||
.globl _mesa_sparc_normalize_normals
|
||||
_mesa_sparc_normalize_normals:
|
||||
/* o0=mat o1=scale o2=in o3=lengths o4=dest */
|
||||
|
||||
sethi %hi(ONE_DOT_ZERO), %g2
|
||||
sub %sp, 16, %sp
|
||||
st %g2, [%sp + STACK_VAR_OFF+0x0]
|
||||
ld [%sp + STACK_VAR_OFF+0x0], %f12 ! f12 = 1.0f
|
||||
add %sp, 16, %sp
|
||||
|
||||
LDPTR [%o2 + V4F_START], %o5 ! o5 = 'from' in->start
|
||||
ld [%o2 + V4F_COUNT], %g1 ! g1 = in->count
|
||||
ld [%o2 + V4F_STRIDE], %g2 ! g2 = in->stride
|
||||
LDPTR [%o4 + V4F_START], %g3 ! g3 = 'out' dest->start
|
||||
|
||||
/* dest->count = in->count */
|
||||
st %g1, [%o4 + V4F_COUNT]
|
||||
|
||||
cmp %g1, 1
|
||||
bl 7f
|
||||
cmp %o3, 0
|
||||
bne 4f
|
||||
clr %o4 ! 'i' for STRIDE_LOOP
|
||||
|
||||
1: /* LENGTHS == NULL */
|
||||
ld [%o5 + 0x00], %f3 ! ux = from[0]
|
||||
ld [%o5 + 0x04], %f5 ! uy = from[1]
|
||||
ld [%o5 + 0x08], %f7 ! uz = from[2]
|
||||
add %o5, %g2, %o5 ! STRIDE_F(from, stride)
|
||||
add %o4, 1, %o4 ! i++
|
||||
|
||||
/* f3=tx, f5=ty, f7=tz */
|
||||
|
||||
/* len (f6) = (tx * tx) + (ty * ty) + (tz * tz) */
|
||||
fmuls %f3, %f3, %f6 ! FGM Group f3 available
|
||||
fmuls %f5, %f5, %f8 ! FGM Group f5 available
|
||||
fmuls %f7, %f7, %f10 ! FGM Group f7 available
|
||||
fadds %f6, %f8, %f6 ! FGA Group 2cyc stall f6,f8 available
|
||||
fadds %f6, %f10, %f6 ! FGA Group 4cyc stall f6,f10 available
|
||||
|
||||
/* scale (f6) = 1.0 / sqrt(len) */
|
||||
fsqrts %f6, %f6 ! FDIV 20 cycles
|
||||
fdivs %f12, %f6, %f6 ! FDIV 14 cycles
|
||||
|
||||
fmuls %f3, %f6, %f3
|
||||
st %f3, [%g3 + 0x00] ! out[i][0] = tx * scale
|
||||
fmuls %f5, %f6, %f5
|
||||
st %f5, [%g3 + 0x04] ! out[i][1] = ty * scale
|
||||
fmuls %f7, %f6, %f7
|
||||
st %f7, [%g3 + 0x08] ! out[i][2] = tz * scale
|
||||
|
||||
cmp %o4, %g1 ! continue if (i < count)
|
||||
bl 1b
|
||||
add %g3, 0x10, %g3 ! advance out vector pointer
|
||||
|
||||
ba 7f
|
||||
nop
|
||||
|
||||
4: /* LENGTHS != NULL */
|
||||
|
||||
5:
|
||||
ld [%o5 + 0x00], %f3 ! ux = from[0]
|
||||
ld [%o5 + 0x04], %f5 ! uy = from[1]
|
||||
ld [%o5 + 0x08], %f7 ! uz = from[2]
|
||||
add %o5, %g2, %o5 ! STRIDE_F(from, stride)
|
||||
add %o4, 1, %o4 ! i++
|
||||
|
||||
ld [%o3], %f13 ! LSU
|
||||
add %o3, 4, %o3 ! IEU0
|
||||
|
||||
/* f3=tx, f5=ty, f7=tz, f13=lengths[i] */
|
||||
|
||||
fmuls %f3, %f13, %f3
|
||||
st %f3, [%g3 + 0x00] ! out[i][0] = tx * len
|
||||
fmuls %f5, %f13, %f5
|
||||
st %f5, [%g3 + 0x04] ! out[i][1] = ty * len
|
||||
fmuls %f7, %f13, %f7
|
||||
st %f7, [%g3 + 0x08] ! out[i][2] = tz * len
|
||||
|
||||
cmp %o4, %g1 ! continue if (i < count)
|
||||
bl 5b
|
||||
add %g3, 0x10, %g3 ! advance out vector pointer
|
||||
|
||||
7: retl
|
||||
nop
|
||||
|
||||
.globl _mesa_sparc_rescale_normals
|
||||
_mesa_sparc_rescale_normals:
|
||||
/* o0=mat o1=scale o2=in o3=lengths o4=dest */
|
||||
|
||||
sethi %hi(ONE_DOT_ZERO), %g2
|
||||
sub %sp, 16, %sp
|
||||
st %o1, [%sp + STACK_VAR_OFF+0x0]
|
||||
ld [%sp + STACK_VAR_OFF+0x0], %f15 ! f15 = scale
|
||||
add %sp, 16, %sp
|
||||
|
||||
LDPTR [%o2 + V4F_START], %o5 ! o5 = 'from' in->start
|
||||
ld [%o2 + V4F_COUNT], %g1 ! g1 = in->count
|
||||
ld [%o2 + V4F_STRIDE], %g2 ! g2 = in->stride
|
||||
LDPTR [%o4 + V4F_START], %g3 ! g3 = 'out' dest->start
|
||||
|
||||
/* dest->count = in->count */
|
||||
st %g1, [%o4 + V4F_COUNT]
|
||||
|
||||
cmp %g1, 1
|
||||
bl 7f
|
||||
clr %o4 ! 'i' for STRIDE_LOOP
|
||||
|
||||
1:
|
||||
ld [%o5 + 0x00], %f3 ! ux = from[0]
|
||||
ld [%o5 + 0x04], %f5 ! uy = from[1]
|
||||
ld [%o5 + 0x08], %f7 ! uz = from[2]
|
||||
add %o5, %g2, %o5 ! STRIDE_F(from, stride)
|
||||
add %o4, 1, %o4 ! i++
|
||||
|
||||
/* f3=tx, f5=ty, f7=tz */
|
||||
|
||||
fmuls %f3, %f15, %f3
|
||||
st %f3, [%g3 + 0x00] ! out[i][0] = tx * scale
|
||||
fmuls %f5, %f15, %f5
|
||||
st %f5, [%g3 + 0x04] ! out[i][1] = ty * scale
|
||||
fmuls %f7, %f15, %f7
|
||||
st %f7, [%g3 + 0x08] ! out[i][2] = tz * scale
|
||||
|
||||
cmp %o4, %g1 ! continue if (i < count)
|
||||
bl 1b
|
||||
add %g3, 0x10, %g3 ! advance out vector pointer
|
||||
|
||||
7: retl
|
||||
nop
|
|
@ -1,142 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* Copyright (C) 1999-2003 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Sparc assembly code by David S. Miller
|
||||
*/
|
||||
|
||||
|
||||
#include "sparc.h"
|
||||
|
||||
#ifdef USE_SPARC_ASM
|
||||
|
||||
#include "main/context.h"
|
||||
#include "math/m_xform.h"
|
||||
#include "tnl/t_context.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#include "math/m_debug.h"
|
||||
#endif
|
||||
|
||||
#define XFORM_ARGS GLvector4f *to_vec, \
|
||||
const GLfloat m[16], \
|
||||
const GLvector4f *from_vec
|
||||
|
||||
#define DECLARE_XFORM_GROUP(pfx, sz) \
|
||||
extern void _mesa_##pfx##_transform_points##sz##_general(XFORM_ARGS); \
|
||||
extern void _mesa_##pfx##_transform_points##sz##_identity(XFORM_ARGS); \
|
||||
extern void _mesa_##pfx##_transform_points##sz##_3d_no_rot(XFORM_ARGS); \
|
||||
extern void _mesa_##pfx##_transform_points##sz##_perspective(XFORM_ARGS); \
|
||||
extern void _mesa_##pfx##_transform_points##sz##_2d(XFORM_ARGS); \
|
||||
extern void _mesa_##pfx##_transform_points##sz##_2d_no_rot(XFORM_ARGS); \
|
||||
extern void _mesa_##pfx##_transform_points##sz##_3d(XFORM_ARGS);
|
||||
|
||||
#define ASSIGN_XFORM_GROUP(pfx, sz) \
|
||||
_mesa_transform_tab[sz][MATRIX_GENERAL] = \
|
||||
_mesa_##pfx##_transform_points##sz##_general; \
|
||||
_mesa_transform_tab[sz][MATRIX_IDENTITY] = \
|
||||
_mesa_##pfx##_transform_points##sz##_identity; \
|
||||
_mesa_transform_tab[sz][MATRIX_3D_NO_ROT] = \
|
||||
_mesa_##pfx##_transform_points##sz##_3d_no_rot; \
|
||||
_mesa_transform_tab[sz][MATRIX_PERSPECTIVE] = \
|
||||
_mesa_##pfx##_transform_points##sz##_perspective; \
|
||||
_mesa_transform_tab[sz][MATRIX_2D] = \
|
||||
_mesa_##pfx##_transform_points##sz##_2d; \
|
||||
_mesa_transform_tab[sz][MATRIX_2D_NO_ROT] = \
|
||||
_mesa_##pfx##_transform_points##sz##_2d_no_rot; \
|
||||
_mesa_transform_tab[sz][MATRIX_3D] = \
|
||||
_mesa_##pfx##_transform_points##sz##_3d;
|
||||
|
||||
|
||||
DECLARE_XFORM_GROUP(sparc, 1)
|
||||
DECLARE_XFORM_GROUP(sparc, 2)
|
||||
DECLARE_XFORM_GROUP(sparc, 3)
|
||||
DECLARE_XFORM_GROUP(sparc, 4)
|
||||
|
||||
extern GLvector4f *_mesa_sparc_cliptest_points4(GLvector4f *clip_vec,
|
||||
GLvector4f *proj_vec,
|
||||
GLubyte clipMask[],
|
||||
GLubyte *orMask,
|
||||
GLubyte *andMask,
|
||||
GLboolean viewport_z_clip);
|
||||
|
||||
extern GLvector4f *_mesa_sparc_cliptest_points4_np(GLvector4f *clip_vec,
|
||||
GLvector4f *proj_vec,
|
||||
GLubyte clipMask[],
|
||||
GLubyte *orMask,
|
||||
GLubyte *andMask,
|
||||
GLboolean viewport_z_clip);
|
||||
|
||||
#define NORM_ARGS const GLmatrix *mat, \
|
||||
GLfloat scale, \
|
||||
const GLvector4f *in, \
|
||||
const GLfloat *lengths, \
|
||||
GLvector4f *dest
|
||||
|
||||
extern void _mesa_sparc_transform_normalize_normals(NORM_ARGS);
|
||||
extern void _mesa_sparc_transform_normalize_normals_no_rot(NORM_ARGS);
|
||||
extern void _mesa_sparc_transform_rescale_normals_no_rot(NORM_ARGS);
|
||||
extern void _mesa_sparc_transform_rescale_normals(NORM_ARGS);
|
||||
extern void _mesa_sparc_transform_normals_no_rot(NORM_ARGS);
|
||||
extern void _mesa_sparc_transform_normals(NORM_ARGS);
|
||||
extern void _mesa_sparc_normalize_normals(NORM_ARGS);
|
||||
extern void _mesa_sparc_rescale_normals(NORM_ARGS);
|
||||
|
||||
|
||||
|
||||
void _mesa_init_all_sparc_transform_asm(void)
|
||||
{
|
||||
ASSIGN_XFORM_GROUP(sparc, 1)
|
||||
ASSIGN_XFORM_GROUP(sparc, 2)
|
||||
ASSIGN_XFORM_GROUP(sparc, 3)
|
||||
ASSIGN_XFORM_GROUP(sparc, 4)
|
||||
|
||||
_mesa_clip_tab[4] = _mesa_sparc_cliptest_points4;
|
||||
_mesa_clip_np_tab[4] = _mesa_sparc_cliptest_points4_np;
|
||||
|
||||
_mesa_normal_tab[NORM_TRANSFORM | NORM_NORMALIZE] =
|
||||
_mesa_sparc_transform_normalize_normals;
|
||||
_mesa_normal_tab[NORM_TRANSFORM_NO_ROT | NORM_NORMALIZE] =
|
||||
_mesa_sparc_transform_normalize_normals_no_rot;
|
||||
_mesa_normal_tab[NORM_TRANSFORM_NO_ROT | NORM_RESCALE] =
|
||||
_mesa_sparc_transform_rescale_normals_no_rot;
|
||||
_mesa_normal_tab[NORM_TRANSFORM | NORM_RESCALE] =
|
||||
_mesa_sparc_transform_rescale_normals;
|
||||
_mesa_normal_tab[NORM_TRANSFORM_NO_ROT] =
|
||||
_mesa_sparc_transform_normals_no_rot;
|
||||
_mesa_normal_tab[NORM_TRANSFORM] =
|
||||
_mesa_sparc_transform_normals;
|
||||
_mesa_normal_tab[NORM_NORMALIZE] =
|
||||
_mesa_sparc_normalize_normals;
|
||||
_mesa_normal_tab[NORM_RESCALE] =
|
||||
_mesa_sparc_rescale_normals;
|
||||
|
||||
#ifdef DEBUG_MATH
|
||||
_math_test_all_transform_functions("sparc");
|
||||
_math_test_all_cliptest_functions("sparc");
|
||||
_math_test_all_normal_transform_functions("sparc");
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* USE_SPARC_ASM */
|
|
@ -1,36 +0,0 @@
|
|||
|
||||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* Copyright (C) 1999 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Sparc assembly code by David S. Miller
|
||||
*/
|
||||
|
||||
|
||||
#ifndef SPARC_H
|
||||
#define SPARC_H
|
||||
|
||||
extern void _mesa_init_all_sparc_transform_asm(void);
|
||||
|
||||
#endif /* !(SPARC_H) */
|
|
@ -1,220 +0,0 @@
|
|||
/*
|
||||
* Clip testing in SPARC assembly
|
||||
*/
|
||||
|
||||
#if __arch64__
|
||||
#define LDPTR ldx
|
||||
#define MATH_ASM_PTR_SIZE 8
|
||||
#include "math/m_vector_asm.h"
|
||||
#else
|
||||
#define LDPTR ld
|
||||
#define MATH_ASM_PTR_SIZE 4
|
||||
#include "math/m_vector_asm.h"
|
||||
#endif
|
||||
|
||||
.register %g2, #scratch
|
||||
.register %g3, #scratch
|
||||
|
||||
.text
|
||||
.align 64
|
||||
|
||||
one_dot_zero:
|
||||
.word 0x3f800000 /* 1.0f */
|
||||
|
||||
/* This trick is shamelessly stolen from the x86
|
||||
* Mesa asm. Very clever, and we can do it too
|
||||
* since we have the necessary add with carry
|
||||
* instructions on Sparc.
|
||||
*/
|
||||
clip_table:
|
||||
.byte 0, 1, 0, 2, 4, 5, 4, 6
|
||||
.byte 0, 1, 0, 2, 8, 9, 8, 10
|
||||
.byte 32, 33, 32, 34, 36, 37, 36, 38
|
||||
.byte 32, 33, 32, 34, 40, 41, 40, 42
|
||||
.byte 0, 1, 0, 2, 4, 5, 4, 6
|
||||
.byte 0, 1, 0, 2, 8, 9, 8, 10
|
||||
.byte 16, 17, 16, 18, 20, 21, 20, 22
|
||||
.byte 16, 17, 16, 18, 24, 25, 24, 26
|
||||
.byte 63, 61, 63, 62, 55, 53, 55, 54
|
||||
.byte 63, 61, 63, 62, 59, 57, 59, 58
|
||||
.byte 47, 45, 47, 46, 39, 37, 39, 38
|
||||
.byte 47, 45, 47, 46, 43, 41, 43, 42
|
||||
.byte 63, 61, 63, 62, 55, 53, 55, 54
|
||||
.byte 63, 61, 63, 62, 59, 57, 59, 58
|
||||
.byte 31, 29, 31, 30, 23, 21, 23, 22
|
||||
.byte 31, 29, 31, 30, 27, 25, 27, 26
|
||||
|
||||
/* GLvector4f *clip_vec, GLvector4f *proj_vec,
|
||||
GLubyte clipMask[], GLubyte *orMask, GLubyte *andMask,
|
||||
GLboolean viewport_z_enable */
|
||||
|
||||
.align 64
|
||||
__pc_tramp:
|
||||
retl
|
||||
nop
|
||||
|
||||
.globl _mesa_sparc_cliptest_points4
|
||||
_mesa_sparc_cliptest_points4:
|
||||
save %sp, -64, %sp
|
||||
call __pc_tramp
|
||||
sub %o7, (. - one_dot_zero - 4), %g1
|
||||
ld [%g1 + 0x0], %f4
|
||||
add %g1, 0x4, %g1
|
||||
|
||||
ld [%i0 + V4F_STRIDE], %l1
|
||||
ld [%i0 + V4F_COUNT], %l3
|
||||
LDPTR [%i0 + V4F_START], %i0
|
||||
LDPTR [%i1 + V4F_START], %i5
|
||||
ldub [%i3], %g2
|
||||
ldub [%i4], %g3
|
||||
sll %g3, 8, %g3
|
||||
or %g2, %g3, %g2
|
||||
|
||||
ld [%i1 + V4F_FLAGS], %g3
|
||||
or %g3, VEC_SIZE_4, %g3
|
||||
st %g3, [%i1 + V4F_FLAGS]
|
||||
mov 3, %g3
|
||||
st %g3, [%i1 + V4F_SIZE]
|
||||
st %l3, [%i1 + V4F_COUNT]
|
||||
clr %l2
|
||||
clr %l0
|
||||
|
||||
/* l0: i
|
||||
* l3: count
|
||||
* l1: stride
|
||||
* l2: c
|
||||
* g2: (tmpAndMask << 8) | tmpOrMask
|
||||
* g1: clip_table
|
||||
* i0: from[stride][i]
|
||||
* i2: clipMask
|
||||
* i5: vProj[4][i]
|
||||
*/
|
||||
|
||||
1: ld [%i0 + 0x0c], %f3 ! LSU Group
|
||||
ld [%i0 + 0x0c], %g5 ! LSU Group
|
||||
ld [%i0 + 0x08], %g4 ! LSU Group
|
||||
fdivs %f4, %f3, %f8 ! FGM
|
||||
addcc %g5, %g5, %g5 ! IEU1 Group
|
||||
addx %g0, 0x0, %g3 ! IEU1 Group
|
||||
addcc %g4, %g4, %g4 ! IEU1 Group
|
||||
addx %g3, %g3, %g3 ! IEU1 Group
|
||||
subcc %g5, %g4, %g0 ! IEU1 Group
|
||||
ld [%i0 + 0x04], %g4 ! LSU Group
|
||||
addx %g3, %g3, %g3 ! IEU1 Group
|
||||
addcc %g4, %g4, %g4 ! IEU1 Group
|
||||
addx %g3, %g3, %g3 ! IEU1 Group
|
||||
subcc %g5, %g4, %g0 ! IEU1 Group
|
||||
ld [%i0 + 0x00], %g4 ! LSU Group
|
||||
addx %g3, %g3, %g3 ! IEU1 Group
|
||||
addcc %g4, %g4, %g4 ! IEU1 Group
|
||||
addx %g3, %g3, %g3 ! IEU1 Group
|
||||
subcc %g5, %g4, %g0 ! IEU1 Group
|
||||
addx %g3, %g3, %g3 ! IEU1 Group
|
||||
ldub [%g1 + %g3], %g3 ! LSU Group
|
||||
cmp %g3, 0 ! IEU1 Group, stall
|
||||
be 2f ! CTI
|
||||
stb %g3, [%i2] ! LSU
|
||||
sll %g3, 8, %g4 ! IEU1 Group
|
||||
add %l2, 1, %l2 ! IEU0
|
||||
st %g0, [%i5 + 0x00] ! LSU
|
||||
or %g4, 0xff, %g4 ! IEU0 Group
|
||||
or %g2, %g3, %g2 ! IEU1
|
||||
st %g0, [%i5 + 0x04] ! LSU
|
||||
and %g2, %g4, %g2 ! IEU0 Group
|
||||
st %g0, [%i5 + 0x08] ! LSU
|
||||
b 3f ! CTI
|
||||
st %f4, [%i5 + 0x0c] ! LSU Group
|
||||
2: ld [%i0 + 0x00], %f0 ! LSU Group
|
||||
ld [%i0 + 0x04], %f1 ! LSU Group
|
||||
ld [%i0 + 0x08], %f2 ! LSU Group
|
||||
fmuls %f0, %f8, %f0 ! FGM
|
||||
st %f0, [%i5 + 0x00] ! LSU Group
|
||||
fmuls %f1, %f8, %f1 ! FGM
|
||||
st %f1, [%i5 + 0x04] ! LSU Group
|
||||
fmuls %f2, %f8, %f2 ! FGM
|
||||
st %f2, [%i5 + 0x08] ! LSU Group
|
||||
st %f8, [%i5 + 0x0c] ! LSU Group
|
||||
3: add %i5, 0x10, %i5 ! IEU1
|
||||
add %l0, 1, %l0 ! IEU0 Group
|
||||
add %i2, 1, %i2 ! IEU0 Group
|
||||
cmp %l0, %l3 ! IEU1 Group
|
||||
bne 1b ! CTI
|
||||
add %i0, %l1, %i0 ! IEU0 Group
|
||||
stb %g2, [%i3] ! LSU
|
||||
srl %g2, 8, %g3 ! IEU0 Group
|
||||
cmp %l2, %l3 ! IEU1 Group
|
||||
bl,a 1f ! CTI
|
||||
clr %g3 ! IEU0
|
||||
1: stb %g3, [%i4] ! LSU Group
|
||||
ret ! CTI Group
|
||||
restore %i1, 0x0, %o0
|
||||
|
||||
.globl _mesa_sparc_cliptest_points4_np
|
||||
_mesa_sparc_cliptest_points4_np:
|
||||
save %sp, -64, %sp
|
||||
|
||||
call __pc_tramp
|
||||
sub %o7, (. - one_dot_zero - 4), %g1
|
||||
add %g1, 0x4, %g1
|
||||
|
||||
ld [%i0 + V4F_STRIDE], %l1
|
||||
ld [%i0 + V4F_COUNT], %l3
|
||||
LDPTR [%i0 + V4F_START], %i0
|
||||
ldub [%i3], %g2
|
||||
ldub [%i4], %g3
|
||||
sll %g3, 8, %g3
|
||||
or %g2, %g3, %g2
|
||||
|
||||
clr %l2
|
||||
clr %l0
|
||||
|
||||
/* l0: i
|
||||
* l3: count
|
||||
* l1: stride
|
||||
* l2: c
|
||||
* g2: (tmpAndMask << 8) | tmpOrMask
|
||||
* g1: clip_table
|
||||
* i0: from[stride][i]
|
||||
* i2: clipMask
|
||||
*/
|
||||
|
||||
1: ld [%i0 + 0x0c], %g5 ! LSU Group
|
||||
ld [%i0 + 0x08], %g4 ! LSU Group
|
||||
addcc %g5, %g5, %g5 ! IEU1 Group
|
||||
addx %g0, 0x0, %g3 ! IEU1 Group
|
||||
addcc %g4, %g4, %g4 ! IEU1 Group
|
||||
addx %g3, %g3, %g3 ! IEU1 Group
|
||||
subcc %g5, %g4, %g0 ! IEU1 Group
|
||||
ld [%i0 + 0x04], %g4 ! LSU Group
|
||||
addx %g3, %g3, %g3 ! IEU1 Group
|
||||
addcc %g4, %g4, %g4 ! IEU1 Group
|
||||
addx %g3, %g3, %g3 ! IEU1 Group
|
||||
subcc %g5, %g4, %g0 ! IEU1 Group
|
||||
ld [%i0 + 0x00], %g4 ! LSU Group
|
||||
addx %g3, %g3, %g3 ! IEU1 Group
|
||||
addcc %g4, %g4, %g4 ! IEU1 Group
|
||||
addx %g3, %g3, %g3 ! IEU1 Group
|
||||
subcc %g5, %g4, %g0 ! IEU1 Group
|
||||
addx %g3, %g3, %g3 ! IEU1 Group
|
||||
ldub [%g1 + %g3], %g3 ! LSU Group
|
||||
cmp %g3, 0 ! IEU1 Group, stall
|
||||
be 2f ! CTI
|
||||
stb %g3, [%i2] ! LSU
|
||||
sll %g3, 8, %g4 ! IEU1 Group
|
||||
add %l2, 1, %l2 ! IEU0
|
||||
or %g4, 0xff, %g4 ! IEU0 Group
|
||||
or %g2, %g3, %g2 ! IEU1
|
||||
and %g2, %g4, %g2 ! IEU0 Group
|
||||
2: add %l0, 1, %l0 ! IEU0 Group
|
||||
add %i2, 1, %i2 ! IEU0 Group
|
||||
cmp %l0, %l3 ! IEU1 Group
|
||||
bne 1b ! CTI
|
||||
add %i0, %l1, %i0 ! IEU0 Group
|
||||
stb %g2, [%i3] ! LSU
|
||||
srl %g2, 8, %g3 ! IEU0 Group
|
||||
cmp %l2, %l3 ! IEU1 Group
|
||||
bl,a 1f ! CTI
|
||||
clr %g3 ! IEU0
|
||||
1: stb %g3, [%i4] ! LSU Group
|
||||
ret ! CTI Group
|
||||
restore %i1, 0x0, %o0
|
|
@ -1,153 +0,0 @@
|
|||
/*
|
||||
* SPARC assembly matrix code.
|
||||
*/
|
||||
|
||||
#ifndef _SPARC_MATRIX_H
|
||||
#define _SPARC_MATRIX_H
|
||||
|
||||
#ifdef __arch64__
|
||||
#define LDPTR ldx
|
||||
#define MATH_ASM_PTR_SIZE 8
|
||||
#include "math/m_vector_asm.h"
|
||||
#else
|
||||
#define LDPTR ld
|
||||
#define MATH_ASM_PTR_SIZE 4
|
||||
#include "math/m_vector_asm.h"
|
||||
#endif
|
||||
|
||||
#define M0 %f16
|
||||
#define M1 %f17
|
||||
#define M2 %f18
|
||||
#define M3 %f19
|
||||
#define M4 %f20
|
||||
#define M5 %f21
|
||||
#define M6 %f22
|
||||
#define M7 %f23
|
||||
#define M8 %f24
|
||||
#define M9 %f25
|
||||
#define M10 %f26
|
||||
#define M11 %f27
|
||||
#define M12 %f28
|
||||
#define M13 %f29
|
||||
#define M14 %f30
|
||||
#define M15 %f31
|
||||
|
||||
#define LDMATRIX_0_1_2_3_12_13_14_15(BASE) \
|
||||
ldd [BASE + ( 0 * 0x4)], M0; \
|
||||
ldd [BASE + ( 2 * 0x4)], M2; \
|
||||
ldd [BASE + (12 * 0x4)], M12; \
|
||||
ldd [BASE + (14 * 0x4)], M14
|
||||
|
||||
#define LDMATRIX_0_1_12_13(BASE) \
|
||||
ldd [BASE + ( 0 * 0x4)], M0; \
|
||||
ldd [BASE + (12 * 0x4)], M12
|
||||
|
||||
#define LDMATRIX_0_12_13(BASE) \
|
||||
ld [BASE + ( 0 * 0x4)], M0; \
|
||||
ldd [BASE + (12 * 0x4)], M12
|
||||
|
||||
#define LDMATRIX_0_1_2_12_13_14(BASE) \
|
||||
ldd [BASE + ( 0 * 0x4)], M0; \
|
||||
ld [BASE + ( 2 * 0x4)], M2; \
|
||||
ldd [BASE + (12 * 0x4)], M12; \
|
||||
ld [BASE + (14 * 0x4)], M14
|
||||
|
||||
#define LDMATRIX_0_12_13_14(BASE) \
|
||||
ld [BASE + ( 0 * 0x4)], M0; \
|
||||
ldd [BASE + (12 * 0x4)], M12; \
|
||||
ld [BASE + (14 * 0x4)], M14
|
||||
|
||||
#define LDMATRIX_0_14(BASE) \
|
||||
ld [BASE + ( 0 * 0x4)], M0; \
|
||||
ld [BASE + (14 * 0x4)], M14
|
||||
|
||||
#define LDMATRIX_0_1_2_3_4_5_6_7_12_13_14_15(BASE) \
|
||||
ldd [BASE + ( 0 * 0x4)], M0; \
|
||||
ldd [BASE + ( 2 * 0x4)], M2; \
|
||||
ldd [BASE + ( 4 * 0x4)], M4; \
|
||||
ldd [BASE + ( 6 * 0x4)], M6; \
|
||||
ldd [BASE + (12 * 0x4)], M12; \
|
||||
ldd [BASE + (14 * 0x4)], M14
|
||||
|
||||
#define LDMATRIX_0_5_12_13(BASE) \
|
||||
ld [BASE + ( 0 * 0x4)], M0; \
|
||||
ld [BASE + ( 5 * 0x4)], M5; \
|
||||
ldd [BASE + (12 * 0x4)], M12
|
||||
|
||||
#define LDMATRIX_0_1_2_3_4_5_6_12_13_14(BASE) \
|
||||
ldd [BASE + ( 0 * 0x4)], M0; \
|
||||
ldd [BASE + ( 2 * 0x4)], M2; \
|
||||
ldd [BASE + ( 4 * 0x4)], M4; \
|
||||
ld [BASE + ( 6 * 0x4)], M6; \
|
||||
ldd [BASE + (12 * 0x4)], M12; \
|
||||
ld [BASE + (14 * 0x4)], M14
|
||||
|
||||
#define LDMATRIX_0_5_12_13_14(BASE) \
|
||||
ld [BASE + ( 0 * 0x4)], M0; \
|
||||
ld [BASE + ( 5 * 0x4)], M5; \
|
||||
ldd [BASE + (12 * 0x4)], M12; \
|
||||
ld [BASE + (14 * 0x4)], M14
|
||||
|
||||
#define LDMATRIX_0_5_14(BASE) \
|
||||
ld [BASE + ( 0 * 0x4)], M0; \
|
||||
ld [BASE + ( 5 * 0x4)], M5; \
|
||||
ld [BASE + (14 * 0x4)], M14
|
||||
|
||||
#define LDMATRIX_0_1_2_3_4_5_6_7_8_9_10_11_12_13_14_15(BASE) \
|
||||
ldd [BASE + ( 0 * 0x4)], M0; \
|
||||
ldd [BASE + ( 2 * 0x4)], M2; \
|
||||
ldd [BASE + ( 4 * 0x4)], M4; \
|
||||
ldd [BASE + ( 6 * 0x4)], M6; \
|
||||
ldd [BASE + ( 8 * 0x4)], M8; \
|
||||
ldd [BASE + (10 * 0x4)], M10; \
|
||||
ldd [BASE + (12 * 0x4)], M12; \
|
||||
ldd [BASE + (14 * 0x4)], M14
|
||||
|
||||
#define LDMATRIX_0_1_4_5_12_13(BASE) \
|
||||
ldd [BASE + ( 0 * 0x4)], M0; \
|
||||
ldd [BASE + ( 4 * 0x4)], M4; \
|
||||
ldd [BASE + (12 * 0x4)], M12
|
||||
|
||||
#define LDMATRIX_0_5_12_13(BASE) \
|
||||
ld [BASE + ( 0 * 0x4)], M0; \
|
||||
ld [BASE + ( 5 * 0x4)], M5; \
|
||||
ldd [BASE + (12 * 0x4)], M12
|
||||
|
||||
#define LDMATRIX_0_1_2_4_5_6_8_9_10(BASE) \
|
||||
ldd [BASE + ( 0 * 0x4)], M0; \
|
||||
ld [BASE + ( 2 * 0x4)], M2; \
|
||||
ldd [BASE + ( 4 * 0x4)], M4; \
|
||||
ld [BASE + ( 6 * 0x4)], M6; \
|
||||
ldd [BASE + ( 8 * 0x4)], M8; \
|
||||
ld [BASE + (10 * 0x4)], M10
|
||||
|
||||
#define LDMATRIX_0_1_2_4_5_6_8_9_10_12_13_14(BASE) \
|
||||
ldd [BASE + ( 0 * 0x4)], M0; \
|
||||
ld [BASE + ( 2 * 0x4)], M2; \
|
||||
ldd [BASE + ( 4 * 0x4)], M4; \
|
||||
ld [BASE + ( 6 * 0x4)], M6; \
|
||||
ldd [BASE + ( 8 * 0x4)], M8; \
|
||||
ld [BASE + (10 * 0x4)], M10; \
|
||||
ldd [BASE + (12 * 0x4)], M12; \
|
||||
ld [BASE + (14 * 0x4)], M14
|
||||
|
||||
#define LDMATRIX_0_5_10(BASE) \
|
||||
ld [BASE + ( 0 * 0x4)], M0; \
|
||||
ld [BASE + ( 5 * 0x4)], M5; \
|
||||
ld [BASE + (10 * 0x4)], M10;
|
||||
|
||||
#define LDMATRIX_0_5_10_12_13_14(BASE) \
|
||||
ld [BASE + ( 0 * 0x4)], M0; \
|
||||
ld [BASE + ( 5 * 0x4)], M5; \
|
||||
ld [BASE + (10 * 0x4)], M10; \
|
||||
ldd [BASE + (12 * 0x4)], M12; \
|
||||
ld [BASE + (14 * 0x4)], M14
|
||||
|
||||
#define LDMATRIX_0_5_8_9_10_14(BASE) \
|
||||
ld [BASE + ( 0 * 0x4)], M0; \
|
||||
ld [BASE + ( 5 * 0x4)], M5; \
|
||||
ldd [BASE + ( 8 * 0x4)], M8; \
|
||||
ld [BASE + (10 * 0x4)], M10; \
|
||||
ld [BASE + (14 * 0x4)], M14
|
||||
|
||||
#endif /* !(_SPARC_MATRIX_H) */
|
File diff suppressed because it is too large
Load Diff
|
@ -1,55 +0,0 @@
|
|||
INTRODUCTION
|
||||
|
||||
Mesa's native software rasterizer. This module provides the fallback
|
||||
paths for rasterization operations and states that aren't accelerated
|
||||
in hardware drivers, and as the full rasterization engine in software
|
||||
drivers.
|
||||
|
||||
The swrast module 'stands alone', relying only on interfaces to core
|
||||
mesa and it's own driver interface. It knows nothing about the tnl or
|
||||
other modules, allowing it to be used for fallback paths in future tnl
|
||||
schemes without modification.
|
||||
|
||||
As well as providing triangle/line/point rasterization functionality,
|
||||
the module provides implementations of the pixel operations
|
||||
(ReadPixels, etc), and texture operations (CopyTexSubImage) which may
|
||||
be plugged in to the core Mesa driver interface where accelerated
|
||||
versions of these operations are unavailable.
|
||||
|
||||
|
||||
STATE
|
||||
|
||||
To create and destroy the module:
|
||||
|
||||
GLboolean _swrast_CreateContext( struct gl_context *ctx );
|
||||
void _swrast_DestroyContext( struct gl_context *ctx );
|
||||
|
||||
This module tracks state changes internally and maintains derived
|
||||
values based on the current state. For this to work, the driver
|
||||
ensure the following funciton is called whenever the state changes and
|
||||
the swsetup module is 'awake':
|
||||
|
||||
void _swrast_InvalidateState( struct gl_context *ctx, GLuint new_state );
|
||||
|
||||
There is no explicit call to put the swrast module to sleep.
|
||||
|
||||
|
||||
CUSTOMIZATION
|
||||
|
||||
void (*choose_point)( struct gl_context * );
|
||||
void (*choose_line)( struct gl_context * );
|
||||
void (*choose_triangle)( struct gl_context * );
|
||||
|
||||
Drivers may add additional triangle/line/point functions to swrast by
|
||||
overriding these functions. It is necessary for the driver to be very
|
||||
careful that it doesn't return an inappropriate function, eg a
|
||||
rasterization function in feedback mode. See the X11 driver for
|
||||
examples.
|
||||
|
||||
DRIVER INTERFACE
|
||||
|
||||
The swrast device driver provides swrast primarily with span- and
|
||||
pixel- level interfaces to a framebuffer, with a few additional hooks
|
||||
for locking and setting the read buffer.
|
||||
|
||||
See the definition of struct swrast_device_driver in swrast.h.
|
|
@ -1,493 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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 "c99_math.h"
|
||||
#include "main/glheader.h"
|
||||
#include "main/macros.h"
|
||||
#include "main/mtypes.h"
|
||||
#include "main/teximage.h"
|
||||
#include "swrast/s_aaline.h"
|
||||
#include "swrast/s_context.h"
|
||||
#include "swrast/s_span.h"
|
||||
#include "swrast/swrast.h"
|
||||
|
||||
|
||||
#define SUB_PIXEL 4
|
||||
|
||||
|
||||
/*
|
||||
* Info about the AA line we're rendering
|
||||
*/
|
||||
struct LineInfo
|
||||
{
|
||||
GLfloat x0, y0; /* start */
|
||||
GLfloat x1, y1; /* end */
|
||||
GLfloat dx, dy; /* direction vector */
|
||||
GLfloat len; /* length */
|
||||
GLfloat halfWidth; /* half of line width */
|
||||
GLfloat xAdj, yAdj; /* X and Y adjustment for quad corners around line */
|
||||
/* for coverage computation */
|
||||
GLfloat qx0, qy0; /* quad vertices */
|
||||
GLfloat qx1, qy1;
|
||||
GLfloat qx2, qy2;
|
||||
GLfloat qx3, qy3;
|
||||
GLfloat ex0, ey0; /* quad edge vectors */
|
||||
GLfloat ex1, ey1;
|
||||
GLfloat ex2, ey2;
|
||||
GLfloat ex3, ey3;
|
||||
|
||||
/* DO_Z */
|
||||
GLfloat zPlane[4];
|
||||
/* DO_RGBA - always enabled */
|
||||
GLfloat rPlane[4], gPlane[4], bPlane[4], aPlane[4];
|
||||
/* DO_ATTRIBS */
|
||||
GLfloat wPlane[4];
|
||||
GLfloat attrPlane[VARYING_SLOT_MAX][4][4];
|
||||
GLfloat lambda[VARYING_SLOT_MAX];
|
||||
GLfloat texWidth[VARYING_SLOT_MAX];
|
||||
GLfloat texHeight[VARYING_SLOT_MAX];
|
||||
|
||||
SWspan span;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Compute the equation of a plane used to interpolate line fragment data
|
||||
* such as color, Z, texture coords, etc.
|
||||
* Input: (x0, y0) and (x1,y1) are the endpoints of the line.
|
||||
* z0, and z1 are the end point values to interpolate.
|
||||
* Output: plane - the plane equation.
|
||||
*
|
||||
* Note: we don't really have enough parameters to specify a plane.
|
||||
* We take the endpoints of the line and compute a plane such that
|
||||
* the cross product of the line vector and the plane normal is
|
||||
* parallel to the projection plane.
|
||||
*/
|
||||
static void
|
||||
compute_plane(GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1,
|
||||
GLfloat z0, GLfloat z1, GLfloat plane[4])
|
||||
{
|
||||
#if 0
|
||||
/* original */
|
||||
const GLfloat px = x1 - x0;
|
||||
const GLfloat py = y1 - y0;
|
||||
const GLfloat pz = z1 - z0;
|
||||
const GLfloat qx = -py;
|
||||
const GLfloat qy = px;
|
||||
const GLfloat qz = 0;
|
||||
const GLfloat a = py * qz - pz * qy;
|
||||
const GLfloat b = pz * qx - px * qz;
|
||||
const GLfloat c = px * qy - py * qx;
|
||||
const GLfloat d = -(a * x0 + b * y0 + c * z0);
|
||||
plane[0] = a;
|
||||
plane[1] = b;
|
||||
plane[2] = c;
|
||||
plane[3] = d;
|
||||
#else
|
||||
/* simplified */
|
||||
const GLfloat px = x1 - x0;
|
||||
const GLfloat py = y1 - y0;
|
||||
const GLfloat pz = z0 - z1;
|
||||
const GLfloat a = pz * px;
|
||||
const GLfloat b = pz * py;
|
||||
const GLfloat c = px * px + py * py;
|
||||
const GLfloat d = -(a * x0 + b * y0 + c * z0);
|
||||
if (a == 0.0F && b == 0.0F && c == 0.0F && d == 0.0F) {
|
||||
plane[0] = 0.0F;
|
||||
plane[1] = 0.0F;
|
||||
plane[2] = 1.0F;
|
||||
plane[3] = 0.0F;
|
||||
}
|
||||
else {
|
||||
plane[0] = a;
|
||||
plane[1] = b;
|
||||
plane[2] = c;
|
||||
plane[3] = d;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
constant_plane(GLfloat value, GLfloat plane[4])
|
||||
{
|
||||
plane[0] = 0.0F;
|
||||
plane[1] = 0.0F;
|
||||
plane[2] = -1.0F;
|
||||
plane[3] = value;
|
||||
}
|
||||
|
||||
|
||||
static inline GLfloat
|
||||
solve_plane(GLfloat x, GLfloat y, const GLfloat plane[4])
|
||||
{
|
||||
const GLfloat z = (plane[3] + plane[0] * x + plane[1] * y) / -plane[2];
|
||||
return z;
|
||||
}
|
||||
|
||||
#define SOLVE_PLANE(X, Y, PLANE) \
|
||||
((PLANE[3] + PLANE[0] * (X) + PLANE[1] * (Y)) / -PLANE[2])
|
||||
|
||||
|
||||
/*
|
||||
* Return 1 / solve_plane().
|
||||
*/
|
||||
static inline GLfloat
|
||||
solve_plane_recip(GLfloat x, GLfloat y, const GLfloat plane[4])
|
||||
{
|
||||
const GLfloat denom = plane[3] + plane[0] * x + plane[1] * y;
|
||||
if (denom == 0.0F)
|
||||
return 0.0F;
|
||||
else
|
||||
return -plane[2] / denom;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Solve plane and return clamped GLchan value.
|
||||
*/
|
||||
static inline GLchan
|
||||
solve_plane_chan(GLfloat x, GLfloat y, const GLfloat plane[4])
|
||||
{
|
||||
const GLfloat z = (plane[3] + plane[0] * x + plane[1] * y) / -plane[2];
|
||||
#if CHAN_TYPE == GL_FLOAT
|
||||
return CLAMP(z, 0.0F, CHAN_MAXF);
|
||||
#else
|
||||
if (z < 0)
|
||||
return 0;
|
||||
else if (z > CHAN_MAX)
|
||||
return CHAN_MAX;
|
||||
return (GLchan) lroundf(z);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Compute mipmap level of detail.
|
||||
*/
|
||||
static inline GLfloat
|
||||
compute_lambda(const GLfloat sPlane[4], const GLfloat tPlane[4],
|
||||
GLfloat invQ, GLfloat width, GLfloat height)
|
||||
{
|
||||
GLfloat dudx = sPlane[0] / sPlane[2] * invQ * width;
|
||||
GLfloat dudy = sPlane[1] / sPlane[2] * invQ * width;
|
||||
GLfloat dvdx = tPlane[0] / tPlane[2] * invQ * height;
|
||||
GLfloat dvdy = tPlane[1] / tPlane[2] * invQ * height;
|
||||
GLfloat r1 = dudx * dudx + dudy * dudy;
|
||||
GLfloat r2 = dvdx * dvdx + dvdy * dvdy;
|
||||
GLfloat rho2 = r1 + r2;
|
||||
/* return log base 2 of rho */
|
||||
if (rho2 == 0.0F)
|
||||
return 0.0;
|
||||
else
|
||||
return logf(rho2) * 1.442695f * 0.5f;/* 1.442695 = 1/log(2) */
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Fill in the samples[] array with the (x,y) subpixel positions of
|
||||
* xSamples * ySamples sample positions.
|
||||
* Note that the four corner samples are put into the first four
|
||||
* positions of the array. This allows us to optimize for the common
|
||||
* case of all samples being inside the polygon.
|
||||
*/
|
||||
static void
|
||||
make_sample_table(GLint xSamples, GLint ySamples, GLfloat samples[][2])
|
||||
{
|
||||
const GLfloat dx = 1.0F / (GLfloat) xSamples;
|
||||
const GLfloat dy = 1.0F / (GLfloat) ySamples;
|
||||
GLint x, y;
|
||||
GLint i;
|
||||
|
||||
i = 4;
|
||||
for (x = 0; x < xSamples; x++) {
|
||||
for (y = 0; y < ySamples; y++) {
|
||||
GLint j;
|
||||
if (x == 0 && y == 0) {
|
||||
/* lower left */
|
||||
j = 0;
|
||||
}
|
||||
else if (x == xSamples - 1 && y == 0) {
|
||||
/* lower right */
|
||||
j = 1;
|
||||
}
|
||||
else if (x == 0 && y == ySamples - 1) {
|
||||
/* upper left */
|
||||
j = 2;
|
||||
}
|
||||
else if (x == xSamples - 1 && y == ySamples - 1) {
|
||||
/* upper right */
|
||||
j = 3;
|
||||
}
|
||||
else {
|
||||
j = i++;
|
||||
}
|
||||
samples[j][0] = x * dx + 0.5F * dx;
|
||||
samples[j][1] = y * dy + 0.5F * dy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Compute how much of the given pixel's area is inside the rectangle
|
||||
* defined by vertices v0, v1, v2, v3.
|
||||
* Vertices MUST be specified in counter-clockwise order.
|
||||
* Return: coverage in [0, 1].
|
||||
*/
|
||||
static GLfloat
|
||||
compute_coveragef(const struct LineInfo *info,
|
||||
GLint winx, GLint winy)
|
||||
{
|
||||
static GLfloat samples[SUB_PIXEL * SUB_PIXEL][2];
|
||||
static GLboolean haveSamples = GL_FALSE;
|
||||
const GLfloat x = (GLfloat) winx;
|
||||
const GLfloat y = (GLfloat) winy;
|
||||
GLint stop = 4, i;
|
||||
GLfloat insideCount = SUB_PIXEL * SUB_PIXEL;
|
||||
|
||||
if (!haveSamples) {
|
||||
make_sample_table(SUB_PIXEL, SUB_PIXEL, samples);
|
||||
haveSamples = GL_TRUE;
|
||||
}
|
||||
|
||||
#if 0 /*DEBUG*/
|
||||
{
|
||||
const GLfloat area = dx0 * dy1 - dx1 * dy0;
|
||||
assert(area >= 0.0);
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i = 0; i < stop; i++) {
|
||||
const GLfloat sx = x + samples[i][0];
|
||||
const GLfloat sy = y + samples[i][1];
|
||||
const GLfloat fx0 = sx - info->qx0;
|
||||
const GLfloat fy0 = sy - info->qy0;
|
||||
const GLfloat fx1 = sx - info->qx1;
|
||||
const GLfloat fy1 = sy - info->qy1;
|
||||
const GLfloat fx2 = sx - info->qx2;
|
||||
const GLfloat fy2 = sy - info->qy2;
|
||||
const GLfloat fx3 = sx - info->qx3;
|
||||
const GLfloat fy3 = sy - info->qy3;
|
||||
/* cross product determines if sample is inside or outside each edge */
|
||||
GLfloat cross0 = (info->ex0 * fy0 - info->ey0 * fx0);
|
||||
GLfloat cross1 = (info->ex1 * fy1 - info->ey1 * fx1);
|
||||
GLfloat cross2 = (info->ex2 * fy2 - info->ey2 * fx2);
|
||||
GLfloat cross3 = (info->ex3 * fy3 - info->ey3 * fx3);
|
||||
/* Check if the sample is exactly on an edge. If so, let cross be a
|
||||
* positive or negative value depending on the direction of the edge.
|
||||
*/
|
||||
if (cross0 == 0.0F)
|
||||
cross0 = info->ex0 + info->ey0;
|
||||
if (cross1 == 0.0F)
|
||||
cross1 = info->ex1 + info->ey1;
|
||||
if (cross2 == 0.0F)
|
||||
cross2 = info->ex2 + info->ey2;
|
||||
if (cross3 == 0.0F)
|
||||
cross3 = info->ex3 + info->ey3;
|
||||
if (cross0 < 0.0F || cross1 < 0.0F || cross2 < 0.0F || cross3 < 0.0F) {
|
||||
/* point is outside quadrilateral */
|
||||
insideCount -= 1.0F;
|
||||
stop = SUB_PIXEL * SUB_PIXEL;
|
||||
}
|
||||
}
|
||||
if (stop == 4)
|
||||
return 1.0F;
|
||||
else
|
||||
return insideCount * (1.0F / (SUB_PIXEL * SUB_PIXEL));
|
||||
}
|
||||
|
||||
|
||||
typedef void (*plot_func)(struct gl_context *ctx, struct LineInfo *line,
|
||||
int ix, int iy);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Draw an AA line segment (called many times per line when stippling)
|
||||
*/
|
||||
static void
|
||||
segment(struct gl_context *ctx,
|
||||
struct LineInfo *line,
|
||||
plot_func plot,
|
||||
GLfloat t0, GLfloat t1)
|
||||
{
|
||||
const GLfloat absDx = (line->dx < 0.0F) ? -line->dx : line->dx;
|
||||
const GLfloat absDy = (line->dy < 0.0F) ? -line->dy : line->dy;
|
||||
/* compute the actual segment's endpoints */
|
||||
const GLfloat x0 = line->x0 + t0 * line->dx;
|
||||
const GLfloat y0 = line->y0 + t0 * line->dy;
|
||||
const GLfloat x1 = line->x0 + t1 * line->dx;
|
||||
const GLfloat y1 = line->y0 + t1 * line->dy;
|
||||
|
||||
/* compute vertices of the line-aligned quadrilateral */
|
||||
line->qx0 = x0 - line->yAdj;
|
||||
line->qy0 = y0 + line->xAdj;
|
||||
line->qx1 = x0 + line->yAdj;
|
||||
line->qy1 = y0 - line->xAdj;
|
||||
line->qx2 = x1 + line->yAdj;
|
||||
line->qy2 = y1 - line->xAdj;
|
||||
line->qx3 = x1 - line->yAdj;
|
||||
line->qy3 = y1 + line->xAdj;
|
||||
/* compute the quad's edge vectors (for coverage calc) */
|
||||
line->ex0 = line->qx1 - line->qx0;
|
||||
line->ey0 = line->qy1 - line->qy0;
|
||||
line->ex1 = line->qx2 - line->qx1;
|
||||
line->ey1 = line->qy2 - line->qy1;
|
||||
line->ex2 = line->qx3 - line->qx2;
|
||||
line->ey2 = line->qy3 - line->qy2;
|
||||
line->ex3 = line->qx0 - line->qx3;
|
||||
line->ey3 = line->qy0 - line->qy3;
|
||||
|
||||
if (absDx > absDy) {
|
||||
/* X-major line */
|
||||
GLfloat dydx = line->dy / line->dx;
|
||||
GLfloat xLeft, xRight, yBot, yTop;
|
||||
GLint ix, ixRight;
|
||||
if (x0 < x1) {
|
||||
xLeft = x0 - line->halfWidth;
|
||||
xRight = x1 + line->halfWidth;
|
||||
if (line->dy >= 0.0F) {
|
||||
yBot = y0 - 3.0F * line->halfWidth;
|
||||
yTop = y0 + line->halfWidth;
|
||||
}
|
||||
else {
|
||||
yBot = y0 - line->halfWidth;
|
||||
yTop = y0 + 3.0F * line->halfWidth;
|
||||
}
|
||||
}
|
||||
else {
|
||||
xLeft = x1 - line->halfWidth;
|
||||
xRight = x0 + line->halfWidth;
|
||||
if (line->dy <= 0.0F) {
|
||||
yBot = y1 - 3.0F * line->halfWidth;
|
||||
yTop = y1 + line->halfWidth;
|
||||
}
|
||||
else {
|
||||
yBot = y1 - line->halfWidth;
|
||||
yTop = y1 + 3.0F * line->halfWidth;
|
||||
}
|
||||
}
|
||||
|
||||
/* scan along the line, left-to-right */
|
||||
ixRight = (GLint) (xRight + 1.0F);
|
||||
|
||||
/*printf("avg span height: %g\n", yTop - yBot);*/
|
||||
for (ix = (GLint) xLeft; ix < ixRight; ix++) {
|
||||
const GLint iyBot = (GLint) yBot;
|
||||
const GLint iyTop = (GLint) (yTop + 1.0F);
|
||||
GLint iy;
|
||||
/* scan across the line, bottom-to-top */
|
||||
for (iy = iyBot; iy < iyTop; iy++) {
|
||||
plot(ctx, line, ix, iy);
|
||||
}
|
||||
yBot += dydx;
|
||||
yTop += dydx;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Y-major line */
|
||||
GLfloat dxdy = line->dx / line->dy;
|
||||
GLfloat yBot, yTop, xLeft, xRight;
|
||||
GLint iy, iyTop;
|
||||
if (y0 < y1) {
|
||||
yBot = y0 - line->halfWidth;
|
||||
yTop = y1 + line->halfWidth;
|
||||
if (line->dx >= 0.0F) {
|
||||
xLeft = x0 - 3.0F * line->halfWidth;
|
||||
xRight = x0 + line->halfWidth;
|
||||
}
|
||||
else {
|
||||
xLeft = x0 - line->halfWidth;
|
||||
xRight = x0 + 3.0F * line->halfWidth;
|
||||
}
|
||||
}
|
||||
else {
|
||||
yBot = y1 - line->halfWidth;
|
||||
yTop = y0 + line->halfWidth;
|
||||
if (line->dx <= 0.0F) {
|
||||
xLeft = x1 - 3.0F * line->halfWidth;
|
||||
xRight = x1 + line->halfWidth;
|
||||
}
|
||||
else {
|
||||
xLeft = x1 - line->halfWidth;
|
||||
xRight = x1 + 3.0F * line->halfWidth;
|
||||
}
|
||||
}
|
||||
|
||||
/* scan along the line, bottom-to-top */
|
||||
iyTop = (GLint) (yTop + 1.0F);
|
||||
|
||||
/*printf("avg span width: %g\n", xRight - xLeft);*/
|
||||
for (iy = (GLint) yBot; iy < iyTop; iy++) {
|
||||
const GLint ixLeft = (GLint) xLeft;
|
||||
const GLint ixRight = (GLint) (xRight + 1.0F);
|
||||
GLint ix;
|
||||
/* scan across the line, left-to-right */
|
||||
for (ix = ixLeft; ix < ixRight; ix++) {
|
||||
plot(ctx, line, ix, iy);
|
||||
}
|
||||
xLeft += dxdy;
|
||||
xRight += dxdy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define NAME(x) aa_rgba_##x
|
||||
#define DO_Z
|
||||
#include "s_aalinetemp.h"
|
||||
|
||||
|
||||
#define NAME(x) aa_general_rgba_##x
|
||||
#define DO_Z
|
||||
#define DO_ATTRIBS
|
||||
#include "s_aalinetemp.h"
|
||||
|
||||
|
||||
|
||||
void
|
||||
_swrast_choose_aa_line_function(struct gl_context *ctx)
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
|
||||
assert(ctx->Line.SmoothFlag);
|
||||
|
||||
if (ctx->Texture._EnabledCoordUnits != 0
|
||||
|| _swrast_use_fragment_program(ctx)
|
||||
|| (ctx->Light.Enabled &&
|
||||
ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)
|
||||
|| ctx->Fog.ColorSumEnabled
|
||||
|| swrast->_FogEnabled) {
|
||||
swrast->Line = aa_general_rgba_line;
|
||||
}
|
||||
else {
|
||||
swrast->Line = aa_rgba_line;
|
||||
}
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
|
||||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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 S_AALINE_H
|
||||
#define S_AALINE_H
|
||||
|
||||
|
||||
struct gl_context;
|
||||
|
||||
|
||||
extern void
|
||||
_swrast_choose_aa_line_function(struct gl_context *ctx);
|
||||
|
||||
|
||||
#endif
|
|
@ -1,245 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Antialiased line template.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Function to render each fragment in the AA line.
|
||||
* \param ix - integer fragment window X coordiante
|
||||
* \param iy - integer fragment window Y coordiante
|
||||
*/
|
||||
static void
|
||||
NAME(plot)(struct gl_context *ctx, struct LineInfo *line, int ix, int iy)
|
||||
{
|
||||
const SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
const GLfloat fx = (GLfloat) ix;
|
||||
const GLfloat fy = (GLfloat) iy;
|
||||
const GLfloat coverage = compute_coveragef(line, ix, iy);
|
||||
const GLuint i = line->span.end;
|
||||
|
||||
(void) swrast;
|
||||
|
||||
if (coverage == 0.0F)
|
||||
return;
|
||||
|
||||
line->span.end++;
|
||||
line->span.array->coverage[i] = coverage;
|
||||
line->span.array->x[i] = ix;
|
||||
line->span.array->y[i] = iy;
|
||||
|
||||
/*
|
||||
* Compute Z, color, texture coords, fog for the fragment by
|
||||
* solving the plane equations at (ix,iy).
|
||||
*/
|
||||
#ifdef DO_Z
|
||||
line->span.array->z[i] = (GLuint) solve_plane(fx, fy, line->zPlane);
|
||||
#endif
|
||||
line->span.array->rgba[i][RCOMP] = solve_plane_chan(fx, fy, line->rPlane);
|
||||
line->span.array->rgba[i][GCOMP] = solve_plane_chan(fx, fy, line->gPlane);
|
||||
line->span.array->rgba[i][BCOMP] = solve_plane_chan(fx, fy, line->bPlane);
|
||||
line->span.array->rgba[i][ACOMP] = solve_plane_chan(fx, fy, line->aPlane);
|
||||
#if defined(DO_ATTRIBS)
|
||||
ATTRIB_LOOP_BEGIN
|
||||
GLfloat (*attribArray)[4] = line->span.array->attribs[attr];
|
||||
if (attr >= VARYING_SLOT_TEX0 && attr < VARYING_SLOT_VAR0
|
||||
&& !_swrast_use_fragment_program(ctx)) {
|
||||
/* texcoord w/ divide by Q */
|
||||
const GLuint unit = attr - VARYING_SLOT_TEX0;
|
||||
const GLfloat invQ = solve_plane_recip(fx, fy, line->attrPlane[attr][3]);
|
||||
GLuint c;
|
||||
for (c = 0; c < 3; c++) {
|
||||
attribArray[i][c] = solve_plane(fx, fy, line->attrPlane[attr][c]) * invQ;
|
||||
}
|
||||
line->span.array->lambda[unit][i]
|
||||
= compute_lambda(line->attrPlane[attr][0],
|
||||
line->attrPlane[attr][1], invQ,
|
||||
line->texWidth[attr], line->texHeight[attr]);
|
||||
}
|
||||
else {
|
||||
/* non-texture attrib */
|
||||
const GLfloat invW = solve_plane_recip(fx, fy, line->wPlane);
|
||||
GLuint c;
|
||||
for (c = 0; c < 4; c++) {
|
||||
attribArray[i][c] = solve_plane(fx, fy, line->attrPlane[attr][c]) * invW;
|
||||
}
|
||||
}
|
||||
ATTRIB_LOOP_END
|
||||
#endif
|
||||
|
||||
if (line->span.end == SWRAST_MAX_WIDTH) {
|
||||
_swrast_write_rgba_span(ctx, &(line->span));
|
||||
line->span.end = 0; /* reset counter */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Line setup
|
||||
*/
|
||||
static void
|
||||
NAME(line)(struct gl_context *ctx, const SWvertex *v0, const SWvertex *v1)
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
GLfloat tStart, tEnd; /* segment start, end along line length */
|
||||
GLboolean inSegment;
|
||||
GLint iLen, i;
|
||||
|
||||
/* Init the LineInfo struct */
|
||||
struct LineInfo line;
|
||||
line.x0 = v0->attrib[VARYING_SLOT_POS][0];
|
||||
line.y0 = v0->attrib[VARYING_SLOT_POS][1];
|
||||
line.x1 = v1->attrib[VARYING_SLOT_POS][0];
|
||||
line.y1 = v1->attrib[VARYING_SLOT_POS][1];
|
||||
line.dx = line.x1 - line.x0;
|
||||
line.dy = line.y1 - line.y0;
|
||||
line.len = sqrtf(line.dx * line.dx + line.dy * line.dy);
|
||||
line.halfWidth = 0.5F * CLAMP(ctx->Line.Width,
|
||||
ctx->Const.MinLineWidthAA,
|
||||
ctx->Const.MaxLineWidthAA);
|
||||
|
||||
if (line.len == 0.0F || util_is_inf_or_nan(line.len))
|
||||
return;
|
||||
|
||||
INIT_SPAN(line.span, GL_LINE);
|
||||
line.span.arrayMask = SPAN_XY | SPAN_COVERAGE;
|
||||
line.span.facing = swrast->PointLineFacing;
|
||||
line.xAdj = line.dx / line.len * line.halfWidth;
|
||||
line.yAdj = line.dy / line.len * line.halfWidth;
|
||||
|
||||
#ifdef DO_Z
|
||||
line.span.arrayMask |= SPAN_Z;
|
||||
compute_plane(line.x0, line.y0, line.x1, line.y1,
|
||||
v0->attrib[VARYING_SLOT_POS][2], v1->attrib[VARYING_SLOT_POS][2], line.zPlane);
|
||||
#endif
|
||||
line.span.arrayMask |= SPAN_RGBA;
|
||||
if (ctx->Light.ShadeModel == GL_SMOOTH) {
|
||||
compute_plane(line.x0, line.y0, line.x1, line.y1,
|
||||
v0->color[RCOMP], v1->color[RCOMP], line.rPlane);
|
||||
compute_plane(line.x0, line.y0, line.x1, line.y1,
|
||||
v0->color[GCOMP], v1->color[GCOMP], line.gPlane);
|
||||
compute_plane(line.x0, line.y0, line.x1, line.y1,
|
||||
v0->color[BCOMP], v1->color[BCOMP], line.bPlane);
|
||||
compute_plane(line.x0, line.y0, line.x1, line.y1,
|
||||
v0->color[ACOMP], v1->color[ACOMP], line.aPlane);
|
||||
}
|
||||
else {
|
||||
constant_plane(v1->color[RCOMP], line.rPlane);
|
||||
constant_plane(v1->color[GCOMP], line.gPlane);
|
||||
constant_plane(v1->color[BCOMP], line.bPlane);
|
||||
constant_plane(v1->color[ACOMP], line.aPlane);
|
||||
}
|
||||
#if defined(DO_ATTRIBS)
|
||||
{
|
||||
const GLfloat invW0 = v0->attrib[VARYING_SLOT_POS][3];
|
||||
const GLfloat invW1 = v1->attrib[VARYING_SLOT_POS][3];
|
||||
line.span.arrayMask |= SPAN_LAMBDA;
|
||||
compute_plane(line.x0, line.y0, line.x1, line.y1, invW0, invW1, line.wPlane);
|
||||
ATTRIB_LOOP_BEGIN
|
||||
GLuint c;
|
||||
if (swrast->_InterpMode[attr] == GL_FLAT) {
|
||||
for (c = 0; c < 4; c++) {
|
||||
constant_plane(v1->attrib[attr][c], line.attrPlane[attr][c]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (c = 0; c < 4; c++) {
|
||||
const GLfloat a0 = v0->attrib[attr][c] * invW0;
|
||||
const GLfloat a1 = v1->attrib[attr][c] * invW1;
|
||||
compute_plane(line.x0, line.y0, line.x1, line.y1, a0, a1,
|
||||
line.attrPlane[attr][c]);
|
||||
}
|
||||
}
|
||||
line.span.arrayAttribs |= BITFIELD64_BIT(attr);
|
||||
if (attr >= VARYING_SLOT_TEX0 && attr < VARYING_SLOT_VAR0) {
|
||||
const GLuint u = attr - VARYING_SLOT_TEX0;
|
||||
const struct gl_texture_object *obj = ctx->Texture.Unit[u]._Current;
|
||||
if (obj) {
|
||||
const struct gl_texture_image *texImage =
|
||||
_mesa_base_tex_image(obj);
|
||||
line.texWidth[attr] = (GLfloat) texImage->Width;
|
||||
line.texHeight[attr] = (GLfloat) texImage->Height;
|
||||
}
|
||||
}
|
||||
ATTRIB_LOOP_END
|
||||
}
|
||||
#endif
|
||||
|
||||
tStart = tEnd = 0.0;
|
||||
inSegment = GL_FALSE;
|
||||
iLen = (GLint) line.len;
|
||||
|
||||
if (ctx->Line.StippleFlag) {
|
||||
for (i = 0; i < iLen; i++) {
|
||||
const GLuint bit = (swrast->StippleCounter / ctx->Line.StippleFactor) & 0xf;
|
||||
if ((1 << bit) & ctx->Line.StipplePattern) {
|
||||
/* stipple bit is on */
|
||||
const GLfloat t = (GLfloat) i / (GLfloat) line.len;
|
||||
if (!inSegment) {
|
||||
/* start new segment */
|
||||
inSegment = GL_TRUE;
|
||||
tStart = t;
|
||||
}
|
||||
else {
|
||||
/* still in the segment, extend it */
|
||||
tEnd = t;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* stipple bit is off */
|
||||
if (inSegment && (tEnd > tStart)) {
|
||||
/* draw the segment */
|
||||
segment(ctx, &line, NAME(plot), tStart, tEnd);
|
||||
inSegment = GL_FALSE;
|
||||
}
|
||||
else {
|
||||
/* still between segments, do nothing */
|
||||
}
|
||||
}
|
||||
swrast->StippleCounter++;
|
||||
}
|
||||
|
||||
if (inSegment) {
|
||||
/* draw the final segment of the line */
|
||||
segment(ctx, &line, NAME(plot), tStart, 1.0F);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* non-stippled */
|
||||
segment(ctx, &line, NAME(plot), 0.0, 1.0);
|
||||
}
|
||||
|
||||
_swrast_write_rgba_span(ctx, &(line.span));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#undef DO_Z
|
||||
#undef DO_ATTRIBS
|
||||
#undef NAME
|
|
@ -1,296 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Antialiased Triangle rasterizers
|
||||
*/
|
||||
|
||||
|
||||
#include "main/glheader.h"
|
||||
#include "main/context.h"
|
||||
#include "main/macros.h"
|
||||
#include "main/state.h"
|
||||
#include "s_aatriangle.h"
|
||||
#include "s_context.h"
|
||||
#include "s_span.h"
|
||||
|
||||
|
||||
/*
|
||||
* Compute coefficients of a plane using the X,Y coords of the v0, v1, v2
|
||||
* vertices and the given Z values.
|
||||
* A point (x,y,z) lies on plane iff a*x+b*y+c*z+d = 0.
|
||||
*/
|
||||
static inline void
|
||||
compute_plane(const GLfloat v0[], const GLfloat v1[], const GLfloat v2[],
|
||||
GLfloat z0, GLfloat z1, GLfloat z2, GLfloat plane[4])
|
||||
{
|
||||
const GLfloat px = v1[0] - v0[0];
|
||||
const GLfloat py = v1[1] - v0[1];
|
||||
const GLfloat pz = z1 - z0;
|
||||
|
||||
const GLfloat qx = v2[0] - v0[0];
|
||||
const GLfloat qy = v2[1] - v0[1];
|
||||
const GLfloat qz = z2 - z0;
|
||||
|
||||
/* Crossproduct "(a,b,c):= dv1 x dv2" is orthogonal to plane. */
|
||||
const GLfloat a = py * qz - pz * qy;
|
||||
const GLfloat b = pz * qx - px * qz;
|
||||
const GLfloat c = px * qy - py * qx;
|
||||
/* Point on the plane = "r*(a,b,c) + w", with fixed "r" depending
|
||||
on the distance of plane from origin and arbitrary "w" parallel
|
||||
to the plane. */
|
||||
/* The scalar product "(r*(a,b,c)+w)*(a,b,c)" is "r*(a^2+b^2+c^2)",
|
||||
which is equal to "-d" below. */
|
||||
const GLfloat d = -(a * v0[0] + b * v0[1] + c * z0);
|
||||
|
||||
plane[0] = a;
|
||||
plane[1] = b;
|
||||
plane[2] = c;
|
||||
plane[3] = d;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Compute coefficients of a plane with a constant Z value.
|
||||
*/
|
||||
static inline void
|
||||
constant_plane(GLfloat value, GLfloat plane[4])
|
||||
{
|
||||
plane[0] = 0.0;
|
||||
plane[1] = 0.0;
|
||||
plane[2] = -1.0;
|
||||
plane[3] = value;
|
||||
}
|
||||
|
||||
#define CONSTANT_PLANE(VALUE, PLANE) \
|
||||
do { \
|
||||
PLANE[0] = 0.0F; \
|
||||
PLANE[1] = 0.0F; \
|
||||
PLANE[2] = -1.0F; \
|
||||
PLANE[3] = VALUE; \
|
||||
} while (0)
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Solve plane equation for Z at (X,Y).
|
||||
*/
|
||||
static inline GLfloat
|
||||
solve_plane(GLfloat x, GLfloat y, const GLfloat plane[4])
|
||||
{
|
||||
assert(plane[2] != 0.0F);
|
||||
return (plane[3] + plane[0] * x + plane[1] * y) / -plane[2];
|
||||
}
|
||||
|
||||
|
||||
#define SOLVE_PLANE(X, Y, PLANE) \
|
||||
((PLANE[3] + PLANE[0] * (X) + PLANE[1] * (Y)) / -PLANE[2])
|
||||
|
||||
|
||||
/*
|
||||
* Solve plane and return clamped GLchan value.
|
||||
*/
|
||||
static inline GLchan
|
||||
solve_plane_chan(GLfloat x, GLfloat y, const GLfloat plane[4])
|
||||
{
|
||||
const GLfloat z = (plane[3] + plane[0] * x + plane[1] * y) / -plane[2];
|
||||
#if CHAN_TYPE == GL_FLOAT
|
||||
return CLAMP(z, 0.0F, CHAN_MAXF);
|
||||
#else
|
||||
if (z < 0)
|
||||
return 0;
|
||||
else if (z > CHAN_MAX)
|
||||
return CHAN_MAX;
|
||||
return (GLchan) lroundf(z);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static inline GLfloat
|
||||
plane_dx(const GLfloat plane[4])
|
||||
{
|
||||
return -plane[0] / plane[2];
|
||||
}
|
||||
|
||||
static inline GLfloat
|
||||
plane_dy(const GLfloat plane[4])
|
||||
{
|
||||
return -plane[1] / plane[2];
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Compute how much (area) of the given pixel is inside the triangle.
|
||||
* Vertices MUST be specified in counter-clockwise order.
|
||||
* Return: coverage in [0, 1].
|
||||
*/
|
||||
static GLfloat
|
||||
compute_coveragef(const GLfloat v0[3], const GLfloat v1[3],
|
||||
const GLfloat v2[3], GLint winx, GLint winy)
|
||||
{
|
||||
/* Given a position [0,3]x[0,3] return the sub-pixel sample position.
|
||||
* Contributed by Ray Tice.
|
||||
*
|
||||
* Jitter sample positions -
|
||||
* - average should be .5 in x & y for each column
|
||||
* - each of the 16 rows and columns should be used once
|
||||
* - the rectangle formed by the first four points
|
||||
* should contain the other points
|
||||
* - the distrubition should be fairly even in any given direction
|
||||
*
|
||||
* The pattern drawn below isn't optimal, but it's better than a regular
|
||||
* grid. In the drawing, the center of each subpixel is surrounded by
|
||||
* four dots. The "x" marks the jittered position relative to the
|
||||
* subpixel center.
|
||||
*/
|
||||
#define POS(a, b) (0.5+a*4+b)/16
|
||||
static const GLfloat samples[16][2] = {
|
||||
/* start with the four corners */
|
||||
{ POS(0, 2), POS(0, 0) },
|
||||
{ POS(3, 3), POS(0, 2) },
|
||||
{ POS(0, 0), POS(3, 1) },
|
||||
{ POS(3, 1), POS(3, 3) },
|
||||
/* continue with interior samples */
|
||||
{ POS(1, 1), POS(0, 1) },
|
||||
{ POS(2, 0), POS(0, 3) },
|
||||
{ POS(0, 3), POS(1, 3) },
|
||||
{ POS(1, 2), POS(1, 0) },
|
||||
{ POS(2, 3), POS(1, 2) },
|
||||
{ POS(3, 2), POS(1, 1) },
|
||||
{ POS(0, 1), POS(2, 2) },
|
||||
{ POS(1, 0), POS(2, 1) },
|
||||
{ POS(2, 1), POS(2, 3) },
|
||||
{ POS(3, 0), POS(2, 0) },
|
||||
{ POS(1, 3), POS(3, 0) },
|
||||
{ POS(2, 2), POS(3, 2) }
|
||||
};
|
||||
|
||||
const GLfloat x = (GLfloat) winx;
|
||||
const GLfloat y = (GLfloat) winy;
|
||||
const GLfloat dx0 = v1[0] - v0[0];
|
||||
const GLfloat dy0 = v1[1] - v0[1];
|
||||
const GLfloat dx1 = v2[0] - v1[0];
|
||||
const GLfloat dy1 = v2[1] - v1[1];
|
||||
const GLfloat dx2 = v0[0] - v2[0];
|
||||
const GLfloat dy2 = v0[1] - v2[1];
|
||||
GLint stop = 4, i;
|
||||
GLfloat insideCount = 16.0F;
|
||||
|
||||
assert(dx0 * dy1 - dx1 * dy0 >= 0.0); /* area >= 0.0 */
|
||||
|
||||
for (i = 0; i < stop; i++) {
|
||||
const GLfloat sx = x + samples[i][0];
|
||||
const GLfloat sy = y + samples[i][1];
|
||||
/* cross product determines if sample is inside or outside each edge */
|
||||
GLfloat cross = (dx0 * (sy - v0[1]) - dy0 * (sx - v0[0]));
|
||||
/* Check if the sample is exactly on an edge. If so, let cross be a
|
||||
* positive or negative value depending on the direction of the edge.
|
||||
*/
|
||||
if (cross == 0.0F)
|
||||
cross = dx0 + dy0;
|
||||
if (cross < 0.0F) {
|
||||
/* sample point is outside first edge */
|
||||
insideCount -= 1.0F;
|
||||
stop = 16;
|
||||
}
|
||||
else {
|
||||
/* sample point is inside first edge */
|
||||
cross = (dx1 * (sy - v1[1]) - dy1 * (sx - v1[0]));
|
||||
if (cross == 0.0F)
|
||||
cross = dx1 + dy1;
|
||||
if (cross < 0.0F) {
|
||||
/* sample point is outside second edge */
|
||||
insideCount -= 1.0F;
|
||||
stop = 16;
|
||||
}
|
||||
else {
|
||||
/* sample point is inside first and second edges */
|
||||
cross = (dx2 * (sy - v2[1]) - dy2 * (sx - v2[0]));
|
||||
if (cross == 0.0F)
|
||||
cross = dx2 + dy2;
|
||||
if (cross < 0.0F) {
|
||||
/* sample point is outside third edge */
|
||||
insideCount -= 1.0F;
|
||||
stop = 16;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (stop == 4)
|
||||
return 1.0F;
|
||||
else
|
||||
return insideCount * (1.0F / 16.0F);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
rgba_aa_tri(struct gl_context *ctx,
|
||||
const SWvertex *v0,
|
||||
const SWvertex *v1,
|
||||
const SWvertex *v2)
|
||||
{
|
||||
#define DO_Z
|
||||
#include "s_aatritemp.h"
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
general_aa_tri(struct gl_context *ctx,
|
||||
const SWvertex *v0,
|
||||
const SWvertex *v1,
|
||||
const SWvertex *v2)
|
||||
{
|
||||
#define DO_Z
|
||||
#define DO_ATTRIBS
|
||||
#include "s_aatritemp.h"
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Examine GL state and set swrast->Triangle to an
|
||||
* appropriate antialiased triangle rasterizer function.
|
||||
*/
|
||||
void
|
||||
_swrast_set_aa_triangle_function(struct gl_context *ctx)
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
|
||||
assert(ctx->Polygon.SmoothFlag);
|
||||
|
||||
if (ctx->Texture._EnabledCoordUnits != 0
|
||||
|| _swrast_use_fragment_program(ctx)
|
||||
|| swrast->_FogEnabled
|
||||
|| _mesa_need_secondary_color(ctx)) {
|
||||
SWRAST_CONTEXT(ctx)->Triangle = general_aa_tri;
|
||||
}
|
||||
else {
|
||||
SWRAST_CONTEXT(ctx)->Triangle = rgba_aa_tri;
|
||||
}
|
||||
|
||||
assert(SWRAST_CONTEXT(ctx)->Triangle);
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
|
||||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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 S_AATRIANGLE_H
|
||||
#define S_AATRIANGLE_H
|
||||
|
||||
|
||||
struct gl_context;
|
||||
|
||||
|
||||
extern void
|
||||
_swrast_set_aa_triangle_function(struct gl_context *ctx);
|
||||
|
||||
|
||||
#endif
|
|
@ -1,343 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Antialiased Triangle Rasterizer Template
|
||||
*
|
||||
* This file is #include'd to generate custom AA triangle rasterizers.
|
||||
* NOTE: this code hasn't been optimized yet. That'll come after it
|
||||
* works correctly.
|
||||
*
|
||||
* The following macros may be defined to indicate what auxillary information
|
||||
* must be copmuted across the triangle:
|
||||
* DO_Z - if defined, compute Z values
|
||||
* DO_ATTRIBS - if defined, compute texcoords, varying, etc.
|
||||
*/
|
||||
|
||||
/*void triangle( struct gl_context *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint pv )*/
|
||||
{
|
||||
const SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
const GLfloat *p0 = v0->attrib[VARYING_SLOT_POS];
|
||||
const GLfloat *p1 = v1->attrib[VARYING_SLOT_POS];
|
||||
const GLfloat *p2 = v2->attrib[VARYING_SLOT_POS];
|
||||
const SWvertex *vMin, *vMid, *vMax;
|
||||
GLint iyMin, iyMax;
|
||||
GLfloat yMin, yMax;
|
||||
GLboolean ltor;
|
||||
GLfloat majDx, majDy; /* major (i.e. long) edge dx and dy */
|
||||
|
||||
SWspan span;
|
||||
|
||||
#ifdef DO_Z
|
||||
GLfloat zPlane[4];
|
||||
#endif
|
||||
GLfloat rPlane[4], gPlane[4], bPlane[4], aPlane[4];
|
||||
#if defined(DO_ATTRIBS)
|
||||
GLfloat attrPlane[VARYING_SLOT_MAX][4][4];
|
||||
GLfloat wPlane[4]; /* win[3] */
|
||||
#endif
|
||||
GLfloat bf = SWRAST_CONTEXT(ctx)->_BackfaceCullSign;
|
||||
|
||||
(void) swrast;
|
||||
|
||||
INIT_SPAN(span, GL_POLYGON);
|
||||
span.arrayMask = SPAN_COVERAGE;
|
||||
|
||||
/* determine bottom to top order of vertices */
|
||||
{
|
||||
GLfloat y0 = v0->attrib[VARYING_SLOT_POS][1];
|
||||
GLfloat y1 = v1->attrib[VARYING_SLOT_POS][1];
|
||||
GLfloat y2 = v2->attrib[VARYING_SLOT_POS][1];
|
||||
if (y0 <= y1) {
|
||||
if (y1 <= y2) {
|
||||
vMin = v0; vMid = v1; vMax = v2; /* y0<=y1<=y2 */
|
||||
}
|
||||
else if (y2 <= y0) {
|
||||
vMin = v2; vMid = v0; vMax = v1; /* y2<=y0<=y1 */
|
||||
}
|
||||
else {
|
||||
vMin = v0; vMid = v2; vMax = v1; bf = -bf; /* y0<=y2<=y1 */
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (y0 <= y2) {
|
||||
vMin = v1; vMid = v0; vMax = v2; bf = -bf; /* y1<=y0<=y2 */
|
||||
}
|
||||
else if (y2 <= y1) {
|
||||
vMin = v2; vMid = v1; vMax = v0; bf = -bf; /* y2<=y1<=y0 */
|
||||
}
|
||||
else {
|
||||
vMin = v1; vMid = v2; vMax = v0; /* y1<=y2<=y0 */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
majDx = vMax->attrib[VARYING_SLOT_POS][0] - vMin->attrib[VARYING_SLOT_POS][0];
|
||||
majDy = vMax->attrib[VARYING_SLOT_POS][1] - vMin->attrib[VARYING_SLOT_POS][1];
|
||||
|
||||
/* front/back-face determination and cullling */
|
||||
{
|
||||
const GLfloat botDx = vMid->attrib[VARYING_SLOT_POS][0] - vMin->attrib[VARYING_SLOT_POS][0];
|
||||
const GLfloat botDy = vMid->attrib[VARYING_SLOT_POS][1] - vMin->attrib[VARYING_SLOT_POS][1];
|
||||
const GLfloat area = majDx * botDy - botDx * majDy;
|
||||
/* Do backface culling */
|
||||
if (area * bf < 0 || area == 0 || util_is_inf_or_nan(area))
|
||||
return;
|
||||
ltor = (GLboolean) (area < 0.0F);
|
||||
|
||||
span.facing = area * swrast->_BackfaceSign > 0.0F;
|
||||
}
|
||||
|
||||
/* Plane equation setup:
|
||||
* We evaluate plane equations at window (x,y) coordinates in order
|
||||
* to compute color, Z, fog, texcoords, etc. This isn't terribly
|
||||
* efficient but it's easy and reliable.
|
||||
*/
|
||||
#ifdef DO_Z
|
||||
compute_plane(p0, p1, p2, p0[2], p1[2], p2[2], zPlane);
|
||||
span.arrayMask |= SPAN_Z;
|
||||
#endif
|
||||
if (ctx->Light.ShadeModel == GL_SMOOTH) {
|
||||
compute_plane(p0, p1, p2, v0->color[RCOMP], v1->color[RCOMP], v2->color[RCOMP], rPlane);
|
||||
compute_plane(p0, p1, p2, v0->color[GCOMP], v1->color[GCOMP], v2->color[GCOMP], gPlane);
|
||||
compute_plane(p0, p1, p2, v0->color[BCOMP], v1->color[BCOMP], v2->color[BCOMP], bPlane);
|
||||
compute_plane(p0, p1, p2, v0->color[ACOMP], v1->color[ACOMP], v2->color[ACOMP], aPlane);
|
||||
}
|
||||
else {
|
||||
constant_plane(v2->color[RCOMP], rPlane);
|
||||
constant_plane(v2->color[GCOMP], gPlane);
|
||||
constant_plane(v2->color[BCOMP], bPlane);
|
||||
constant_plane(v2->color[ACOMP], aPlane);
|
||||
}
|
||||
span.arrayMask |= SPAN_RGBA;
|
||||
#if defined(DO_ATTRIBS)
|
||||
{
|
||||
const GLfloat invW0 = v0->attrib[VARYING_SLOT_POS][3];
|
||||
const GLfloat invW1 = v1->attrib[VARYING_SLOT_POS][3];
|
||||
const GLfloat invW2 = v2->attrib[VARYING_SLOT_POS][3];
|
||||
compute_plane(p0, p1, p2, invW0, invW1, invW2, wPlane);
|
||||
span.attrStepX[VARYING_SLOT_POS][3] = plane_dx(wPlane);
|
||||
span.attrStepY[VARYING_SLOT_POS][3] = plane_dy(wPlane);
|
||||
ATTRIB_LOOP_BEGIN
|
||||
GLuint c;
|
||||
if (swrast->_InterpMode[attr] == GL_FLAT) {
|
||||
for (c = 0; c < 4; c++) {
|
||||
constant_plane(v2->attrib[attr][c] * invW2, attrPlane[attr][c]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (c = 0; c < 4; c++) {
|
||||
const GLfloat a0 = v0->attrib[attr][c] * invW0;
|
||||
const GLfloat a1 = v1->attrib[attr][c] * invW1;
|
||||
const GLfloat a2 = v2->attrib[attr][c] * invW2;
|
||||
compute_plane(p0, p1, p2, a0, a1, a2, attrPlane[attr][c]);
|
||||
}
|
||||
}
|
||||
for (c = 0; c < 4; c++) {
|
||||
span.attrStepX[attr][c] = plane_dx(attrPlane[attr][c]);
|
||||
span.attrStepY[attr][c] = plane_dy(attrPlane[attr][c]);
|
||||
}
|
||||
ATTRIB_LOOP_END
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Begin bottom-to-top scan over the triangle.
|
||||
* The long edge will either be on the left or right side of the
|
||||
* triangle. We always scan from the long edge toward the shorter
|
||||
* edges, stopping when we find that coverage = 0. If the long edge
|
||||
* is on the left we scan left-to-right. Else, we scan right-to-left.
|
||||
*/
|
||||
yMin = vMin->attrib[VARYING_SLOT_POS][1];
|
||||
yMax = vMax->attrib[VARYING_SLOT_POS][1];
|
||||
iyMin = (GLint) yMin;
|
||||
iyMax = (GLint) yMax + 1;
|
||||
|
||||
if (ltor) {
|
||||
/* scan left to right */
|
||||
const GLfloat *pMin = vMin->attrib[VARYING_SLOT_POS];
|
||||
const GLfloat *pMid = vMid->attrib[VARYING_SLOT_POS];
|
||||
const GLfloat *pMax = vMax->attrib[VARYING_SLOT_POS];
|
||||
const GLfloat dxdy = majDx / majDy;
|
||||
const GLfloat xAdj = dxdy < 0.0F ? -dxdy : 0.0F;
|
||||
GLint iy;
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for schedule(dynamic) private(iy) firstprivate(span)
|
||||
#endif
|
||||
for (iy = iyMin; iy < iyMax; iy++) {
|
||||
GLfloat x = pMin[0] - (yMin - iy) * dxdy;
|
||||
GLint ix, startX = (GLint) (x - xAdj);
|
||||
GLuint count;
|
||||
GLfloat coverage = 0.0F;
|
||||
|
||||
#ifdef _OPENMP
|
||||
/* each thread needs to use a different (global) SpanArrays variable */
|
||||
span.array = SWRAST_CONTEXT(ctx)->SpanArrays + omp_get_thread_num();
|
||||
#endif
|
||||
/* skip over fragments with zero coverage */
|
||||
while (startX < SWRAST_MAX_WIDTH) {
|
||||
coverage = compute_coveragef(pMin, pMid, pMax, startX, iy);
|
||||
if (coverage > 0.0F)
|
||||
break;
|
||||
startX++;
|
||||
}
|
||||
|
||||
/* enter interior of triangle */
|
||||
ix = startX;
|
||||
|
||||
#if defined(DO_ATTRIBS)
|
||||
/* compute attributes at left-most fragment */
|
||||
span.attrStart[VARYING_SLOT_POS][3] = solve_plane(ix + 0.5F, iy + 0.5F, wPlane);
|
||||
ATTRIB_LOOP_BEGIN
|
||||
GLuint c;
|
||||
for (c = 0; c < 4; c++) {
|
||||
span.attrStart[attr][c] = solve_plane(ix + 0.5F, iy + 0.5F, attrPlane[attr][c]);
|
||||
}
|
||||
ATTRIB_LOOP_END
|
||||
#endif
|
||||
|
||||
count = 0;
|
||||
while (coverage > 0.0F) {
|
||||
/* (cx,cy) = center of fragment */
|
||||
const GLfloat cx = ix + 0.5F, cy = iy + 0.5F;
|
||||
SWspanarrays *array = span.array;
|
||||
array->coverage[count] = coverage;
|
||||
#ifdef DO_Z
|
||||
array->z[count] = (GLuint) solve_plane(cx, cy, zPlane);
|
||||
#endif
|
||||
array->rgba[count][RCOMP] = solve_plane_chan(cx, cy, rPlane);
|
||||
array->rgba[count][GCOMP] = solve_plane_chan(cx, cy, gPlane);
|
||||
array->rgba[count][BCOMP] = solve_plane_chan(cx, cy, bPlane);
|
||||
array->rgba[count][ACOMP] = solve_plane_chan(cx, cy, aPlane);
|
||||
ix++;
|
||||
count++;
|
||||
coverage = compute_coveragef(pMin, pMid, pMax, ix, iy);
|
||||
}
|
||||
|
||||
if (ix > startX) {
|
||||
span.x = startX;
|
||||
span.y = iy;
|
||||
span.end = (GLuint) ix - (GLuint) startX;
|
||||
_swrast_write_rgba_span(ctx, &span);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* scan right to left */
|
||||
const GLfloat *pMin = vMin->attrib[VARYING_SLOT_POS];
|
||||
const GLfloat *pMid = vMid->attrib[VARYING_SLOT_POS];
|
||||
const GLfloat *pMax = vMax->attrib[VARYING_SLOT_POS];
|
||||
const GLfloat dxdy = majDx / majDy;
|
||||
const GLfloat xAdj = dxdy > 0 ? dxdy : 0.0F;
|
||||
GLint iy;
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for schedule(dynamic) private(iy) firstprivate(span)
|
||||
#endif
|
||||
for (iy = iyMin; iy < iyMax; iy++) {
|
||||
GLfloat x = pMin[0] - (yMin - iy) * dxdy;
|
||||
GLint ix, left, startX = (GLint) (x + xAdj);
|
||||
GLuint count, n;
|
||||
GLfloat coverage = 0.0F;
|
||||
|
||||
#ifdef _OPENMP
|
||||
/* each thread needs to use a different (global) SpanArrays variable */
|
||||
span.array = SWRAST_CONTEXT(ctx)->SpanArrays + omp_get_thread_num();
|
||||
#endif
|
||||
/* make sure we're not past the window edge */
|
||||
if (startX >= ctx->DrawBuffer->_Xmax) {
|
||||
startX = ctx->DrawBuffer->_Xmax - 1;
|
||||
}
|
||||
|
||||
/* skip fragments with zero coverage */
|
||||
while (startX > 0) {
|
||||
coverage = compute_coveragef(pMin, pMax, pMid, startX, iy);
|
||||
if (coverage > 0.0F)
|
||||
break;
|
||||
startX--;
|
||||
}
|
||||
|
||||
/* enter interior of triangle */
|
||||
ix = startX;
|
||||
count = 0;
|
||||
while (coverage > 0.0F) {
|
||||
/* (cx,cy) = center of fragment */
|
||||
const GLfloat cx = ix + 0.5F, cy = iy + 0.5F;
|
||||
SWspanarrays *array = span.array;
|
||||
assert(ix >= 0);
|
||||
array->coverage[ix] = coverage;
|
||||
#ifdef DO_Z
|
||||
array->z[ix] = (GLuint) solve_plane(cx, cy, zPlane);
|
||||
#endif
|
||||
array->rgba[ix][RCOMP] = solve_plane_chan(cx, cy, rPlane);
|
||||
array->rgba[ix][GCOMP] = solve_plane_chan(cx, cy, gPlane);
|
||||
array->rgba[ix][BCOMP] = solve_plane_chan(cx, cy, bPlane);
|
||||
array->rgba[ix][ACOMP] = solve_plane_chan(cx, cy, aPlane);
|
||||
ix--;
|
||||
count++;
|
||||
coverage = compute_coveragef(pMin, pMax, pMid, ix, iy);
|
||||
}
|
||||
|
||||
#if defined(DO_ATTRIBS)
|
||||
/* compute attributes at left-most fragment */
|
||||
span.attrStart[VARYING_SLOT_POS][3] = solve_plane(ix + 1.5F, iy + 0.5F, wPlane);
|
||||
ATTRIB_LOOP_BEGIN
|
||||
GLuint c;
|
||||
for (c = 0; c < 4; c++) {
|
||||
span.attrStart[attr][c] = solve_plane(ix + 1.5F, iy + 0.5F, attrPlane[attr][c]);
|
||||
}
|
||||
ATTRIB_LOOP_END
|
||||
#endif
|
||||
|
||||
if (startX > ix) {
|
||||
n = (GLuint) startX - (GLuint) ix;
|
||||
|
||||
left = ix + 1;
|
||||
|
||||
/* shift all values to the left */
|
||||
/* XXX this is temporary */
|
||||
{
|
||||
SWspanarrays *array = span.array;
|
||||
GLint j;
|
||||
for (j = 0; j < (GLint) n; j++) {
|
||||
array->coverage[j] = array->coverage[j + left];
|
||||
COPY_CHAN4(array->rgba[j], array->rgba[j + left]);
|
||||
#ifdef DO_Z
|
||||
array->z[j] = array->z[j + left];
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
span.x = left;
|
||||
span.y = iy;
|
||||
span.end = n;
|
||||
_swrast_write_rgba_span(ctx, &span);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#undef DO_Z
|
||||
#undef DO_ATTRIBS
|
||||
#undef DO_OCCLUSION_TEST
|
|
@ -1,159 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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 swrast/s_alpha.c
|
||||
* \brief Functions to apply alpha test.
|
||||
*/
|
||||
|
||||
#include "main/glheader.h"
|
||||
#include "main/context.h"
|
||||
#include "main/macros.h"
|
||||
|
||||
#include "s_alpha.h"
|
||||
#include "s_context.h"
|
||||
|
||||
|
||||
#define ALPHA_TEST(ALPHA, LOOP_CODE) \
|
||||
do { \
|
||||
switch (ctx->Color.AlphaFunc) { \
|
||||
case GL_LESS: \
|
||||
for (i = 0; i < n; i++) { \
|
||||
mask[i] &= (ALPHA < ref); \
|
||||
LOOP_CODE; \
|
||||
} \
|
||||
break; \
|
||||
case GL_LEQUAL: \
|
||||
for (i = 0; i < n; i++) { \
|
||||
mask[i] &= (ALPHA <= ref); \
|
||||
LOOP_CODE; \
|
||||
} \
|
||||
break; \
|
||||
case GL_GEQUAL: \
|
||||
for (i = 0; i < n; i++) { \
|
||||
mask[i] &= (ALPHA >= ref); \
|
||||
LOOP_CODE; \
|
||||
} \
|
||||
break; \
|
||||
case GL_GREATER: \
|
||||
for (i = 0; i < n; i++) { \
|
||||
mask[i] &= (ALPHA > ref); \
|
||||
LOOP_CODE; \
|
||||
} \
|
||||
break; \
|
||||
case GL_NOTEQUAL: \
|
||||
for (i = 0; i < n; i++) { \
|
||||
mask[i] &= (ALPHA != ref); \
|
||||
LOOP_CODE; \
|
||||
} \
|
||||
break; \
|
||||
case GL_EQUAL: \
|
||||
for (i = 0; i < n; i++) { \
|
||||
mask[i] &= (ALPHA == ref); \
|
||||
LOOP_CODE; \
|
||||
} \
|
||||
break; \
|
||||
default: \
|
||||
_mesa_problem(ctx, "Invalid alpha test in _swrast_alpha_test" ); \
|
||||
return 0; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Perform the alpha test for an array of pixels.
|
||||
* For pixels that fail the test, mask[i] will be set to 0.
|
||||
* \return 0 if all pixels in the span failed the alpha test,
|
||||
* 1 if one or more pixels passed the alpha test.
|
||||
*/
|
||||
GLint
|
||||
_swrast_alpha_test(const struct gl_context *ctx, SWspan *span)
|
||||
{
|
||||
const GLuint n = span->end;
|
||||
GLubyte *mask = span->array->mask;
|
||||
GLuint i;
|
||||
|
||||
if (ctx->Color.AlphaFunc == GL_ALWAYS) {
|
||||
/* do nothing */
|
||||
return 1;
|
||||
}
|
||||
else if (ctx->Color.AlphaFunc == GL_NEVER) {
|
||||
/* All pixels failed - caller should check for this return value and
|
||||
* act accordingly.
|
||||
*/
|
||||
span->writeAll = GL_FALSE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (span->arrayMask & SPAN_RGBA) {
|
||||
/* Use array's alpha values */
|
||||
if (span->array->ChanType == GL_UNSIGNED_BYTE) {
|
||||
GLubyte (*rgba)[4] = span->array->rgba8;
|
||||
GLubyte ref;
|
||||
CLAMPED_FLOAT_TO_UBYTE(ref, ctx->Color.AlphaRef);
|
||||
ALPHA_TEST(rgba[i][ACOMP], ;);
|
||||
}
|
||||
else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
|
||||
GLushort (*rgba)[4] = span->array->rgba16;
|
||||
GLushort ref;
|
||||
CLAMPED_FLOAT_TO_USHORT(ref, ctx->Color.AlphaRef);
|
||||
ALPHA_TEST(rgba[i][ACOMP], ;);
|
||||
}
|
||||
else {
|
||||
GLfloat (*rgba)[4] = span->array->attribs[VARYING_SLOT_COL0];
|
||||
const GLfloat ref = ctx->Color.AlphaRef;
|
||||
ALPHA_TEST(rgba[i][ACOMP], ;);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Interpolate alpha values */
|
||||
assert(span->interpMask & SPAN_RGBA);
|
||||
if (span->array->ChanType == GL_UNSIGNED_BYTE) {
|
||||
const GLfixed alphaStep = span->alphaStep;
|
||||
GLfixed alpha = span->alpha;
|
||||
GLubyte ref;
|
||||
CLAMPED_FLOAT_TO_UBYTE(ref, ctx->Color.AlphaRef);
|
||||
ALPHA_TEST(FixedToInt(alpha), alpha += alphaStep);
|
||||
}
|
||||
else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
|
||||
const GLfixed alphaStep = span->alphaStep;
|
||||
GLfixed alpha = span->alpha;
|
||||
GLushort ref;
|
||||
CLAMPED_FLOAT_TO_USHORT(ref, ctx->Color.AlphaRef);
|
||||
ALPHA_TEST(FixedToInt(alpha), alpha += alphaStep);
|
||||
}
|
||||
else {
|
||||
const GLfloat alphaStep = FixedToFloat(span->alphaStep);
|
||||
GLfloat alpha = FixedToFloat(span->alpha);
|
||||
const GLfloat ref = ctx->Color.AlphaRef;
|
||||
ALPHA_TEST(alpha, alpha += alphaStep);
|
||||
}
|
||||
}
|
||||
|
||||
span->writeAll = GL_FALSE;
|
||||
|
||||
/* XXX examine mask[] values? */
|
||||
return 1;
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* Copyright (C) 1999-2002 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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 S_ALPHA_H
|
||||
#define S_ALPHA_H
|
||||
|
||||
|
||||
#include "main/glheader.h"
|
||||
#include "s_span.h"
|
||||
|
||||
struct gl_context;
|
||||
|
||||
extern GLint
|
||||
_swrast_alpha_test( const struct gl_context *ctx, SWspan *span );
|
||||
|
||||
|
||||
#endif
|
|
@ -1,592 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2004 David Airlie 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
|
||||
* DAVID AIRLIE 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/macros.h"
|
||||
#include "main/atifragshader.h"
|
||||
#include "main/samplerobj.h"
|
||||
#include "swrast/s_atifragshader.h"
|
||||
#include "swrast/s_context.h"
|
||||
|
||||
#define ATI_FS_INPUT_PRIMARY 0
|
||||
#define ATI_FS_INPUT_SECONDARY 1
|
||||
|
||||
/**
|
||||
* State for executing ATI fragment shader.
|
||||
*/
|
||||
struct atifs_machine
|
||||
{
|
||||
GLfloat Registers[6][4]; /** six temporary registers */
|
||||
GLfloat PrevPassRegisters[6][4];
|
||||
GLfloat Inputs[2][4]; /** Primary, secondary input colors */
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Fetch a texel.
|
||||
*/
|
||||
static void
|
||||
fetch_texel(struct gl_context * ctx, const GLfloat texcoord[4], GLfloat lambda,
|
||||
GLuint unit, GLfloat color[4])
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
|
||||
/* XXX use a float-valued TextureSample routine here!!! */
|
||||
swrast->TextureSample[unit](ctx, _mesa_get_samplerobj(ctx, unit),
|
||||
ctx->Texture.Unit[unit]._Current,
|
||||
1, (const GLfloat(*)[4]) texcoord,
|
||||
&lambda, (GLfloat (*)[4]) color);
|
||||
}
|
||||
|
||||
static void
|
||||
apply_swizzle(GLfloat values[4], GLuint swizzle)
|
||||
{
|
||||
GLfloat s, t, r, q;
|
||||
|
||||
s = values[0];
|
||||
t = values[1];
|
||||
r = values[2];
|
||||
q = values[3];
|
||||
|
||||
switch (swizzle) {
|
||||
case GL_SWIZZLE_STR_ATI:
|
||||
values[0] = s;
|
||||
values[1] = t;
|
||||
values[2] = r;
|
||||
break;
|
||||
case GL_SWIZZLE_STQ_ATI:
|
||||
values[0] = s;
|
||||
values[1] = t;
|
||||
values[2] = q;
|
||||
break;
|
||||
case GL_SWIZZLE_STR_DR_ATI:
|
||||
values[0] = s / r;
|
||||
values[1] = t / r;
|
||||
values[2] = 1 / r;
|
||||
break;
|
||||
case GL_SWIZZLE_STQ_DQ_ATI:
|
||||
/* make sure q is not 0 to avoid problems later with infinite values (texture lookup)? */
|
||||
if (q == 0.0F)
|
||||
q = 0.000000001F;
|
||||
values[0] = s / q;
|
||||
values[1] = t / q;
|
||||
values[2] = 1.0F / q;
|
||||
break;
|
||||
}
|
||||
values[3] = 0.0;
|
||||
}
|
||||
|
||||
static void
|
||||
apply_src_rep(GLint optype, GLuint rep, GLfloat * val)
|
||||
{
|
||||
GLint i;
|
||||
GLint start, end;
|
||||
if (!rep)
|
||||
return;
|
||||
|
||||
start = optype ? 3 : 0;
|
||||
end = 4;
|
||||
|
||||
for (i = start; i < end; i++) {
|
||||
switch (rep) {
|
||||
case GL_RED:
|
||||
val[i] = val[0];
|
||||
break;
|
||||
case GL_GREEN:
|
||||
val[i] = val[1];
|
||||
break;
|
||||
case GL_BLUE:
|
||||
val[i] = val[2];
|
||||
break;
|
||||
case GL_ALPHA:
|
||||
val[i] = val[3];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
apply_src_mod(GLint optype, GLuint mod, GLfloat * val)
|
||||
{
|
||||
GLint i;
|
||||
GLint start, end;
|
||||
|
||||
if (!mod)
|
||||
return;
|
||||
|
||||
start = optype ? 3 : 0;
|
||||
end = 4;
|
||||
|
||||
for (i = start; i < end; i++) {
|
||||
if (mod & GL_COMP_BIT_ATI)
|
||||
val[i] = 1 - val[i];
|
||||
|
||||
if (mod & GL_BIAS_BIT_ATI)
|
||||
val[i] = val[i] - 0.5F;
|
||||
|
||||
if (mod & GL_2X_BIT_ATI)
|
||||
val[i] = 2 * val[i];
|
||||
|
||||
if (mod & GL_NEGATE_BIT_ATI)
|
||||
val[i] = -val[i];
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
apply_dst_mod(GLuint optype, GLuint mod, GLfloat * val)
|
||||
{
|
||||
GLint i;
|
||||
GLint has_sat = mod & GL_SATURATE_BIT_ATI;
|
||||
GLint start, end;
|
||||
|
||||
mod &= ~GL_SATURATE_BIT_ATI;
|
||||
|
||||
start = optype ? 3 : 0;
|
||||
end = optype ? 4 : 3;
|
||||
|
||||
for (i = start; i < end; i++) {
|
||||
switch (mod) {
|
||||
case GL_2X_BIT_ATI:
|
||||
val[i] = 2 * val[i];
|
||||
break;
|
||||
case GL_4X_BIT_ATI:
|
||||
val[i] = 4 * val[i];
|
||||
break;
|
||||
case GL_8X_BIT_ATI:
|
||||
val[i] = 8 * val[i];
|
||||
break;
|
||||
case GL_HALF_BIT_ATI:
|
||||
val[i] = val[i] * 0.5F;
|
||||
break;
|
||||
case GL_QUARTER_BIT_ATI:
|
||||
val[i] = val[i] * 0.25F;
|
||||
break;
|
||||
case GL_EIGHTH_BIT_ATI:
|
||||
val[i] = val[i] * 0.125F;
|
||||
break;
|
||||
}
|
||||
|
||||
if (has_sat) {
|
||||
if (val[i] < 0.0F)
|
||||
val[i] = 0.0F;
|
||||
else if (val[i] > 1.0F)
|
||||
val[i] = 1.0F;
|
||||
}
|
||||
else {
|
||||
if (val[i] < -8.0F)
|
||||
val[i] = -8.0F;
|
||||
else if (val[i] > 8.0F)
|
||||
val[i] = 8.0F;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
write_dst_addr(GLuint optype, GLuint mod, GLuint mask, GLfloat * src,
|
||||
GLfloat * dst)
|
||||
{
|
||||
GLint i;
|
||||
apply_dst_mod(optype, mod, src);
|
||||
|
||||
if (optype == ATI_FRAGMENT_SHADER_COLOR_OP) {
|
||||
if (mask) {
|
||||
if (mask & GL_RED_BIT_ATI)
|
||||
dst[0] = src[0];
|
||||
|
||||
if (mask & GL_GREEN_BIT_ATI)
|
||||
dst[1] = src[1];
|
||||
|
||||
if (mask & GL_BLUE_BIT_ATI)
|
||||
dst[2] = src[2];
|
||||
}
|
||||
else {
|
||||
for (i = 0; i < 3; i++)
|
||||
dst[i] = src[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
dst[3] = src[3];
|
||||
}
|
||||
|
||||
static void
|
||||
finish_pass(struct atifs_machine *machine)
|
||||
{
|
||||
GLint i;
|
||||
|
||||
for (i = 0; i < 6; i++) {
|
||||
COPY_4V(machine->PrevPassRegisters[i], machine->Registers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
handle_pass_op(struct atifs_machine *machine, struct atifs_setupinst *texinst,
|
||||
const SWspan *span, GLuint column, GLuint idx)
|
||||
{
|
||||
GLuint swizzle = texinst->swizzle;
|
||||
GLuint pass_tex = texinst->src;
|
||||
|
||||
if (pass_tex >= GL_TEXTURE0_ARB && pass_tex <= GL_TEXTURE7_ARB) {
|
||||
pass_tex -= GL_TEXTURE0_ARB;
|
||||
COPY_4V(machine->Registers[idx],
|
||||
span->array->attribs[VARYING_SLOT_TEX0 + pass_tex][column]);
|
||||
}
|
||||
else if (pass_tex >= GL_REG_0_ATI && pass_tex <= GL_REG_5_ATI) {
|
||||
pass_tex -= GL_REG_0_ATI;
|
||||
COPY_4V(machine->Registers[idx], machine->PrevPassRegisters[pass_tex]);
|
||||
}
|
||||
apply_swizzle(machine->Registers[idx], swizzle);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
handle_sample_op(struct gl_context * ctx, struct atifs_machine *machine,
|
||||
struct atifs_setupinst *texinst, const SWspan *span,
|
||||
GLuint column, GLuint idx)
|
||||
{
|
||||
/* sample from unit idx using texinst->src as coords */
|
||||
GLuint swizzle = texinst->swizzle;
|
||||
GLuint coord_source = texinst->src;
|
||||
GLfloat tex_coords[4] = { 0 };
|
||||
|
||||
if (coord_source >= GL_TEXTURE0_ARB && coord_source <= GL_TEXTURE7_ARB) {
|
||||
coord_source -= GL_TEXTURE0_ARB;
|
||||
COPY_4V(tex_coords,
|
||||
span->array->attribs[VARYING_SLOT_TEX0 + coord_source][column]);
|
||||
}
|
||||
else if (coord_source >= GL_REG_0_ATI && coord_source <= GL_REG_5_ATI) {
|
||||
coord_source -= GL_REG_0_ATI;
|
||||
COPY_4V(tex_coords, machine->PrevPassRegisters[coord_source]);
|
||||
}
|
||||
apply_swizzle(tex_coords, swizzle);
|
||||
fetch_texel(ctx, tex_coords, 0.0F, idx, machine->Registers[idx]);
|
||||
}
|
||||
|
||||
#define SETUP_SRC_REG(optype, i, x) \
|
||||
do { \
|
||||
COPY_4V(src[optype][i], x); \
|
||||
} while (0)
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Execute the given fragment shader.
|
||||
* NOTE: we do everything in single-precision floating point
|
||||
* \param ctx - rendering context
|
||||
* \param shader - the shader to execute
|
||||
* \param machine - virtual machine state
|
||||
* \param span - the SWspan we're operating on
|
||||
* \param column - which pixel [i] we're operating on in the span
|
||||
*/
|
||||
static void
|
||||
execute_shader(struct gl_context *ctx, const struct ati_fragment_shader *shader,
|
||||
struct atifs_machine *machine, const SWspan *span,
|
||||
GLuint column)
|
||||
{
|
||||
GLuint pc;
|
||||
struct atifs_instruction *inst;
|
||||
struct atifs_setupinst *texinst;
|
||||
GLint optype;
|
||||
GLuint i;
|
||||
GLint j, pass;
|
||||
GLint dstreg;
|
||||
GLfloat src[2][3][4];
|
||||
GLfloat zeros[4] = { 0.0, 0.0, 0.0, 0.0 };
|
||||
GLfloat ones[4] = { 1.0, 1.0, 1.0, 1.0 };
|
||||
GLfloat dst[2][4], *dstp;
|
||||
|
||||
for (pass = 0; pass < shader->NumPasses; pass++) {
|
||||
if (pass > 0)
|
||||
finish_pass(machine);
|
||||
for (j = 0; j < MAX_NUM_FRAGMENT_REGISTERS_ATI; j++) {
|
||||
texinst = &shader->SetupInst[pass][j];
|
||||
if (texinst->Opcode == ATI_FRAGMENT_SHADER_PASS_OP)
|
||||
handle_pass_op(machine, texinst, span, column, j);
|
||||
else if (texinst->Opcode == ATI_FRAGMENT_SHADER_SAMPLE_OP)
|
||||
handle_sample_op(ctx, machine, texinst, span, column, j);
|
||||
}
|
||||
|
||||
for (pc = 0; pc < shader->numArithInstr[pass]; pc++) {
|
||||
inst = &shader->Instructions[pass][pc];
|
||||
|
||||
/* setup the source registers for color and alpha ops */
|
||||
for (optype = 0; optype < 2; optype++) {
|
||||
for (i = 0; i < inst->ArgCount[optype]; i++) {
|
||||
GLint index = inst->SrcReg[optype][i].Index;
|
||||
|
||||
if (index >= GL_REG_0_ATI && index <= GL_REG_5_ATI)
|
||||
SETUP_SRC_REG(optype, i,
|
||||
machine->Registers[index - GL_REG_0_ATI]);
|
||||
else if (index >= GL_CON_0_ATI && index <= GL_CON_7_ATI) {
|
||||
if (shader->LocalConstDef & (1 << (index - GL_CON_0_ATI))) {
|
||||
SETUP_SRC_REG(optype, i,
|
||||
shader->Constants[index - GL_CON_0_ATI]);
|
||||
} else {
|
||||
SETUP_SRC_REG(optype, i,
|
||||
ctx->ATIFragmentShader.GlobalConstants[index - GL_CON_0_ATI]);
|
||||
}
|
||||
}
|
||||
else if (index == GL_ONE)
|
||||
SETUP_SRC_REG(optype, i, ones);
|
||||
else if (index == GL_ZERO)
|
||||
SETUP_SRC_REG(optype, i, zeros);
|
||||
else if (index == GL_PRIMARY_COLOR_EXT)
|
||||
SETUP_SRC_REG(optype, i,
|
||||
machine->Inputs[ATI_FS_INPUT_PRIMARY]);
|
||||
else if (index == GL_SECONDARY_INTERPOLATOR_ATI)
|
||||
SETUP_SRC_REG(optype, i,
|
||||
machine->Inputs[ATI_FS_INPUT_SECONDARY]);
|
||||
|
||||
apply_src_rep(optype, inst->SrcReg[optype][i].argRep,
|
||||
src[optype][i]);
|
||||
apply_src_mod(optype, inst->SrcReg[optype][i].argMod,
|
||||
src[optype][i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Execute the operations - color then alpha */
|
||||
for (optype = 0; optype < 2; optype++) {
|
||||
if (inst->Opcode[optype]) {
|
||||
switch (inst->Opcode[optype]) {
|
||||
case GL_ADD_ATI:
|
||||
if (!optype)
|
||||
for (i = 0; i < 3; i++) {
|
||||
dst[optype][i] =
|
||||
src[optype][0][i] + src[optype][1][i];
|
||||
}
|
||||
else
|
||||
dst[optype][3] = src[optype][0][3] + src[optype][1][3];
|
||||
break;
|
||||
case GL_SUB_ATI:
|
||||
if (!optype)
|
||||
for (i = 0; i < 3; i++) {
|
||||
dst[optype][i] =
|
||||
src[optype][0][i] - src[optype][1][i];
|
||||
}
|
||||
else
|
||||
dst[optype][3] = src[optype][0][3] - src[optype][1][3];
|
||||
break;
|
||||
case GL_MUL_ATI:
|
||||
if (!optype)
|
||||
for (i = 0; i < 3; i++) {
|
||||
dst[optype][i] =
|
||||
src[optype][0][i] * src[optype][1][i];
|
||||
}
|
||||
else
|
||||
dst[optype][3] = src[optype][0][3] * src[optype][1][3];
|
||||
break;
|
||||
case GL_MAD_ATI:
|
||||
if (!optype)
|
||||
for (i = 0; i < 3; i++) {
|
||||
dst[optype][i] =
|
||||
src[optype][0][i] * src[optype][1][i] +
|
||||
src[optype][2][i];
|
||||
}
|
||||
else
|
||||
dst[optype][3] =
|
||||
src[optype][0][3] * src[optype][1][3] +
|
||||
src[optype][2][3];
|
||||
break;
|
||||
case GL_LERP_ATI:
|
||||
if (!optype)
|
||||
for (i = 0; i < 3; i++) {
|
||||
dst[optype][i] =
|
||||
src[optype][0][i] * src[optype][1][i] + (1 -
|
||||
src
|
||||
[optype]
|
||||
[0][i]) *
|
||||
src[optype][2][i];
|
||||
}
|
||||
else
|
||||
dst[optype][3] =
|
||||
src[optype][0][3] * src[optype][1][3] + (1 -
|
||||
src[optype]
|
||||
[0][3]) *
|
||||
src[optype][2][3];
|
||||
break;
|
||||
|
||||
case GL_MOV_ATI:
|
||||
if (!optype)
|
||||
for (i = 0; i < 3; i++) {
|
||||
dst[optype][i] = src[optype][0][i];
|
||||
}
|
||||
else
|
||||
dst[optype][3] = src[optype][0][3];
|
||||
break;
|
||||
case GL_CND_ATI:
|
||||
if (!optype) {
|
||||
for (i = 0; i < 3; i++) {
|
||||
dst[optype][i] =
|
||||
(src[optype][2][i] >
|
||||
0.5F) ? src[optype][0][i] : src[optype][1][i];
|
||||
}
|
||||
}
|
||||
else {
|
||||
dst[optype][3] =
|
||||
(src[optype][2][3] >
|
||||
0.5F) ? src[optype][0][3] : src[optype][1][3];
|
||||
}
|
||||
break;
|
||||
|
||||
case GL_CND0_ATI:
|
||||
if (!optype)
|
||||
for (i = 0; i < 3; i++) {
|
||||
dst[optype][i] =
|
||||
(src[optype][2][i] >=
|
||||
0) ? src[optype][0][i] : src[optype][1][i];
|
||||
}
|
||||
else {
|
||||
dst[optype][3] =
|
||||
(src[optype][2][3] >=
|
||||
0) ? src[optype][0][3] : src[optype][1][3];
|
||||
}
|
||||
break;
|
||||
case GL_DOT2_ADD_ATI:
|
||||
{
|
||||
GLfloat result;
|
||||
|
||||
/* DOT 2 always uses the source from the color op */
|
||||
/* could save recalculation of dot products for alpha inst */
|
||||
result = src[0][0][0] * src[0][1][0] +
|
||||
src[0][0][1] * src[0][1][1] + src[0][2][2];
|
||||
if (!optype) {
|
||||
for (i = 0; i < 3; i++) {
|
||||
dst[optype][i] = result;
|
||||
}
|
||||
}
|
||||
else
|
||||
dst[optype][3] = result;
|
||||
}
|
||||
break;
|
||||
case GL_DOT3_ATI:
|
||||
{
|
||||
GLfloat result;
|
||||
|
||||
/* DOT 3 always uses the source from the color op */
|
||||
result = src[0][0][0] * src[0][1][0] +
|
||||
src[0][0][1] * src[0][1][1] +
|
||||
src[0][0][2] * src[0][1][2];
|
||||
|
||||
if (!optype) {
|
||||
for (i = 0; i < 3; i++) {
|
||||
dst[optype][i] = result;
|
||||
}
|
||||
}
|
||||
else
|
||||
dst[optype][3] = result;
|
||||
}
|
||||
break;
|
||||
case GL_DOT4_ATI:
|
||||
{
|
||||
GLfloat result;
|
||||
|
||||
/* DOT 4 always uses the source from the color op */
|
||||
result = src[0][0][0] * src[0][1][0] +
|
||||
src[0][0][1] * src[0][1][1] +
|
||||
src[0][0][2] * src[0][1][2] +
|
||||
src[0][0][3] * src[0][1][3];
|
||||
if (!optype) {
|
||||
for (i = 0; i < 3; i++) {
|
||||
dst[optype][i] = result;
|
||||
}
|
||||
}
|
||||
else
|
||||
dst[optype][3] = result;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* write out the destination registers */
|
||||
for (optype = 0; optype < 2; optype++) {
|
||||
if (inst->Opcode[optype]) {
|
||||
dstreg = inst->DstReg[optype].Index;
|
||||
dstp = machine->Registers[dstreg - GL_REG_0_ATI];
|
||||
|
||||
if ((optype == 0) || ((inst->Opcode[1] != GL_DOT2_ADD_ATI) &&
|
||||
(inst->Opcode[1] != GL_DOT3_ATI) && (inst->Opcode[1] != GL_DOT4_ATI)))
|
||||
write_dst_addr(optype, inst->DstReg[optype].dstMod,
|
||||
inst->DstReg[optype].dstMask, dst[optype],
|
||||
dstp);
|
||||
else
|
||||
write_dst_addr(1, inst->DstReg[0].dstMod, 0, dst[1], dstp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Init fragment shader virtual machine state.
|
||||
*/
|
||||
static void
|
||||
init_machine(struct gl_context * ctx, struct atifs_machine *machine,
|
||||
const struct ati_fragment_shader *shader,
|
||||
const SWspan *span, GLuint col)
|
||||
{
|
||||
GLfloat (*inputs)[4] = machine->Inputs;
|
||||
GLint i, j;
|
||||
|
||||
for (i = 0; i < 6; i++) {
|
||||
for (j = 0; j < 4; j++)
|
||||
machine->Registers[i][j] = 0.0;
|
||||
}
|
||||
|
||||
COPY_4V(inputs[ATI_FS_INPUT_PRIMARY], span->array->attribs[VARYING_SLOT_COL0][col]);
|
||||
COPY_4V(inputs[ATI_FS_INPUT_SECONDARY], span->array->attribs[VARYING_SLOT_COL1][col]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Execute the current ATI shader program, operating on the given span.
|
||||
*/
|
||||
void
|
||||
_swrast_exec_fragment_shader(struct gl_context * ctx, SWspan *span)
|
||||
{
|
||||
const struct ati_fragment_shader *shader = ctx->ATIFragmentShader.Current;
|
||||
struct atifs_machine machine;
|
||||
GLuint i;
|
||||
|
||||
/* incoming colors should be floats */
|
||||
assert(span->array->ChanType == GL_FLOAT);
|
||||
|
||||
for (i = 0; i < span->end; i++) {
|
||||
if (span->array->mask[i]) {
|
||||
init_machine(ctx, &machine, shader, span, i);
|
||||
|
||||
execute_shader(ctx, shader, &machine, span, i);
|
||||
|
||||
/* store result color */
|
||||
{
|
||||
const GLfloat *colOut = machine.Registers[0];
|
||||
/*fprintf(stderr,"outputs %f %f %f %f\n",
|
||||
colOut[0], colOut[1], colOut[2], colOut[3]); */
|
||||
COPY_4V(span->array->attribs[VARYING_SLOT_COL0][i], colOut);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* Copyright (C) 1999-2003 David Airlie 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
|
||||
* DAVID AIRLIE 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 S_ATIFRAGSHADER_H
|
||||
#define S_ATIFRAGSHADER_H
|
||||
|
||||
|
||||
#include "s_span.h"
|
||||
|
||||
struct gl_context;
|
||||
|
||||
extern void
|
||||
_swrast_exec_fragment_shader( struct gl_context *ctx, SWspan *span );
|
||||
|
||||
|
||||
#endif
|
|
@ -1,223 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* Copyright (C) 1999-2008 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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 swrast/s_bitmap.c
|
||||
* \brief glBitmap rendering.
|
||||
* \author Brian Paul
|
||||
*/
|
||||
|
||||
#include "main/glheader.h"
|
||||
#include "main/bufferobj.h"
|
||||
#include "main/condrender.h"
|
||||
#include "main/image.h"
|
||||
#include "main/macros.h"
|
||||
#include "main/pbo.h"
|
||||
|
||||
#include "s_context.h"
|
||||
#include "s_span.h"
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Render a bitmap.
|
||||
* Called via ctx->Driver.Bitmap()
|
||||
* All parameter error checking will have been done before this is called.
|
||||
*/
|
||||
void
|
||||
_swrast_Bitmap( struct gl_context *ctx, GLint px, GLint py,
|
||||
GLsizei width, GLsizei height,
|
||||
const struct gl_pixelstore_attrib *unpack,
|
||||
const GLubyte *bitmap )
|
||||
{
|
||||
GLint row, col;
|
||||
GLuint count = 0;
|
||||
SWspan span;
|
||||
|
||||
assert(ctx->RenderMode == GL_RENDER);
|
||||
|
||||
if (!_mesa_check_conditional_render(ctx))
|
||||
return; /* don't draw */
|
||||
|
||||
bitmap = (const GLubyte *) _mesa_map_pbo_source(ctx, unpack, bitmap);
|
||||
if (!bitmap)
|
||||
return;
|
||||
|
||||
swrast_render_start(ctx);
|
||||
|
||||
if (SWRAST_CONTEXT(ctx)->NewState)
|
||||
_swrast_validate_derived( ctx );
|
||||
|
||||
INIT_SPAN(span, GL_BITMAP);
|
||||
span.end = width;
|
||||
span.arrayMask = SPAN_XY;
|
||||
_swrast_span_default_attribs(ctx, &span);
|
||||
|
||||
for (row = 0; row < height; row++) {
|
||||
const GLubyte *src = (const GLubyte *) _mesa_image_address2d(unpack,
|
||||
bitmap, width, height, GL_COLOR_INDEX, GL_BITMAP, row, 0);
|
||||
|
||||
if (unpack->LsbFirst) {
|
||||
/* Lsb first */
|
||||
GLubyte mask = 1U << (unpack->SkipPixels & 0x7);
|
||||
for (col = 0; col < width; col++) {
|
||||
if (*src & mask) {
|
||||
span.array->x[count] = px + col;
|
||||
span.array->y[count] = py + row;
|
||||
count++;
|
||||
}
|
||||
if (mask == 128U) {
|
||||
src++;
|
||||
mask = 1U;
|
||||
}
|
||||
else {
|
||||
mask = mask << 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* get ready for next row */
|
||||
if (mask != 1)
|
||||
src++;
|
||||
}
|
||||
else {
|
||||
/* Msb first */
|
||||
GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
|
||||
for (col = 0; col < width; col++) {
|
||||
if (*src & mask) {
|
||||
span.array->x[count] = px + col;
|
||||
span.array->y[count] = py + row;
|
||||
count++;
|
||||
}
|
||||
if (mask == 1U) {
|
||||
src++;
|
||||
mask = 128U;
|
||||
}
|
||||
else {
|
||||
mask = mask >> 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* get ready for next row */
|
||||
if (mask != 128)
|
||||
src++;
|
||||
}
|
||||
|
||||
if (count + width >= SWRAST_MAX_WIDTH || row + 1 == height) {
|
||||
/* flush the span */
|
||||
span.end = count;
|
||||
_swrast_write_rgba_span(ctx, &span);
|
||||
span.end = 0;
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
swrast_render_finish(ctx);
|
||||
|
||||
_mesa_unmap_pbo_source(ctx, unpack);
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* XXX this is another way to implement Bitmap. Use horizontal runs of
|
||||
* fragments, initializing the mask array to indicate which fragments to
|
||||
* draw or skip.
|
||||
*/
|
||||
void
|
||||
_swrast_Bitmap( struct gl_context *ctx, GLint px, GLint py,
|
||||
GLsizei width, GLsizei height,
|
||||
const struct gl_pixelstore_attrib *unpack,
|
||||
const GLubyte *bitmap )
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
GLint row, col;
|
||||
SWspan span;
|
||||
|
||||
assert(ctx->RenderMode == GL_RENDER);
|
||||
assert(bitmap);
|
||||
|
||||
swrast_render_start(ctx);
|
||||
|
||||
if (SWRAST_CONTEXT(ctx)->NewState)
|
||||
_swrast_validate_derived( ctx );
|
||||
|
||||
INIT_SPAN(span, GL_BITMAP);
|
||||
span.end = width;
|
||||
span.arrayMask = SPAN_MASK;
|
||||
_swrast_span_default_attribs(ctx, &span);
|
||||
|
||||
/*span.arrayMask |= SPAN_MASK;*/ /* we'll init span.mask[] */
|
||||
span.x = px;
|
||||
span.y = py;
|
||||
/*span.end = width;*/
|
||||
|
||||
for (row=0; row<height; row++, span.y++) {
|
||||
const GLubyte *src = (const GLubyte *) _mesa_image_address2d(unpack,
|
||||
bitmap, width, height, GL_COLOR_INDEX, GL_BITMAP, row, 0);
|
||||
|
||||
if (unpack->LsbFirst) {
|
||||
/* Lsb first */
|
||||
GLubyte mask = 1U << (unpack->SkipPixels & 0x7);
|
||||
for (col=0; col<width; col++) {
|
||||
span.array->mask[col] = (*src & mask) ? GL_TRUE : GL_FALSE;
|
||||
if (mask == 128U) {
|
||||
src++;
|
||||
mask = 1U;
|
||||
}
|
||||
else {
|
||||
mask = mask << 1;
|
||||
}
|
||||
}
|
||||
|
||||
_swrast_write_rgba_span(ctx, &span);
|
||||
|
||||
/* get ready for next row */
|
||||
if (mask != 1)
|
||||
src++;
|
||||
}
|
||||
else {
|
||||
/* Msb first */
|
||||
GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
|
||||
for (col=0; col<width; col++) {
|
||||
span.array->mask[col] = (*src & mask) ? GL_TRUE : GL_FALSE;
|
||||
if (mask == 1U) {
|
||||
src++;
|
||||
mask = 128U;
|
||||
}
|
||||
else {
|
||||
mask = mask >> 1;
|
||||
}
|
||||
}
|
||||
|
||||
_swrast_write_rgba_span(ctx, &span);
|
||||
|
||||
/* get ready for next row */
|
||||
if (mask != 128)
|
||||
src++;
|
||||
}
|
||||
}
|
||||
|
||||
swrast_render_finish(ctx);
|
||||
}
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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 S_BLEND_H
|
||||
#define S_BLEND_H
|
||||
|
||||
|
||||
#include "main/glheader.h"
|
||||
#include "s_span.h"
|
||||
|
||||
struct gl_context;
|
||||
struct gl_renderbuffer;
|
||||
|
||||
|
||||
extern void
|
||||
_swrast_blend_span(struct gl_context *ctx, struct gl_renderbuffer *rb, SWspan *span);
|
||||
|
||||
|
||||
extern void
|
||||
_swrast_choose_blend_func(struct gl_context *ctx, GLenum chanType);
|
||||
|
||||
|
||||
#endif
|
|
@ -1,816 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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/condrender.h"
|
||||
#include "main/image.h"
|
||||
#include "main/macros.h"
|
||||
#include "main/format_unpack.h"
|
||||
#include "main/format_pack.h"
|
||||
#include "main/condrender.h"
|
||||
#include "s_context.h"
|
||||
|
||||
|
||||
#define ABS(X) ((X) < 0 ? -(X) : (X))
|
||||
|
||||
|
||||
/**
|
||||
* Generate a row resampler function for GL_NEAREST mode.
|
||||
*/
|
||||
#define RESAMPLE(NAME, PIXELTYPE, SIZE) \
|
||||
static void \
|
||||
NAME(GLint srcWidth, GLint dstWidth, \
|
||||
const GLvoid *srcBuffer, GLvoid *dstBuffer, \
|
||||
GLboolean flip) \
|
||||
{ \
|
||||
const PIXELTYPE *src = (const PIXELTYPE *) srcBuffer;\
|
||||
PIXELTYPE *dst = (PIXELTYPE *) dstBuffer; \
|
||||
GLint dstCol; \
|
||||
\
|
||||
if (flip) { \
|
||||
for (dstCol = 0; dstCol < dstWidth; dstCol++) { \
|
||||
GLint srcCol = (dstCol * srcWidth) / dstWidth; \
|
||||
assert(srcCol >= 0); \
|
||||
assert(srcCol < srcWidth); \
|
||||
srcCol = srcWidth - 1 - srcCol; /* flip */ \
|
||||
if (SIZE == 1) { \
|
||||
dst[dstCol] = src[srcCol]; \
|
||||
} \
|
||||
else if (SIZE == 2) { \
|
||||
dst[dstCol*2+0] = src[srcCol*2+0]; \
|
||||
dst[dstCol*2+1] = src[srcCol*2+1]; \
|
||||
} \
|
||||
else if (SIZE == 4) { \
|
||||
dst[dstCol*4+0] = src[srcCol*4+0]; \
|
||||
dst[dstCol*4+1] = src[srcCol*4+1]; \
|
||||
dst[dstCol*4+2] = src[srcCol*4+2]; \
|
||||
dst[dstCol*4+3] = src[srcCol*4+3]; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
else { \
|
||||
for (dstCol = 0; dstCol < dstWidth; dstCol++) { \
|
||||
GLint srcCol = (dstCol * srcWidth) / dstWidth; \
|
||||
assert(srcCol >= 0); \
|
||||
assert(srcCol < srcWidth); \
|
||||
if (SIZE == 1) { \
|
||||
dst[dstCol] = src[srcCol]; \
|
||||
} \
|
||||
else if (SIZE == 2) { \
|
||||
dst[dstCol*2+0] = src[srcCol*2+0]; \
|
||||
dst[dstCol*2+1] = src[srcCol*2+1]; \
|
||||
} \
|
||||
else if (SIZE == 4) { \
|
||||
dst[dstCol*4+0] = src[srcCol*4+0]; \
|
||||
dst[dstCol*4+1] = src[srcCol*4+1]; \
|
||||
dst[dstCol*4+2] = src[srcCol*4+2]; \
|
||||
dst[dstCol*4+3] = src[srcCol*4+3]; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
/**
|
||||
* Resamplers for 1, 2, 4, 8 and 16-byte pixels.
|
||||
*/
|
||||
RESAMPLE(resample_row_1, GLubyte, 1)
|
||||
RESAMPLE(resample_row_2, GLushort, 1)
|
||||
RESAMPLE(resample_row_4, GLuint, 1)
|
||||
RESAMPLE(resample_row_8, GLuint, 2)
|
||||
RESAMPLE(resample_row_16, GLuint, 4)
|
||||
|
||||
|
||||
/**
|
||||
* Blit color, depth or stencil with GL_NEAREST filtering.
|
||||
*/
|
||||
static void
|
||||
blit_nearest(struct gl_context *ctx,
|
||||
struct gl_framebuffer *readFb,
|
||||
struct gl_framebuffer *drawFb,
|
||||
GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
|
||||
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
|
||||
GLbitfield buffer)
|
||||
{
|
||||
struct gl_renderbuffer *readRb, *drawRb = NULL;
|
||||
struct gl_renderbuffer_attachment *readAtt = NULL, *drawAtt = NULL;
|
||||
GLuint numDrawBuffers = 0;
|
||||
GLuint i;
|
||||
|
||||
const GLint srcWidth = ABS(srcX1 - srcX0);
|
||||
const GLint dstWidth = ABS(dstX1 - dstX0);
|
||||
const GLint srcHeight = ABS(srcY1 - srcY0);
|
||||
const GLint dstHeight = ABS(dstY1 - dstY0);
|
||||
|
||||
const GLint srcXpos = MIN2(srcX0, srcX1);
|
||||
const GLint srcYpos = MIN2(srcY0, srcY1);
|
||||
const GLint dstXpos = MIN2(dstX0, dstX1);
|
||||
const GLint dstYpos = MIN2(dstY0, dstY1);
|
||||
|
||||
const GLboolean invertX = (srcX1 < srcX0) ^ (dstX1 < dstX0);
|
||||
const GLboolean invertY = (srcY1 < srcY0) ^ (dstY1 < dstY0);
|
||||
enum mode {
|
||||
DIRECT,
|
||||
UNPACK_RGBA_FLOAT,
|
||||
UNPACK_Z_FLOAT,
|
||||
UNPACK_Z_INT,
|
||||
UNPACK_S,
|
||||
} mode = DIRECT;
|
||||
GLubyte *srcMap, *dstMap;
|
||||
GLint srcRowStride, dstRowStride;
|
||||
GLint dstRow;
|
||||
|
||||
GLint pixelSize = 0;
|
||||
GLvoid *srcBuffer, *dstBuffer;
|
||||
GLint prevY = -1;
|
||||
|
||||
typedef void (*resample_func)(GLint srcWidth, GLint dstWidth,
|
||||
const GLvoid *srcBuffer, GLvoid *dstBuffer,
|
||||
GLboolean flip);
|
||||
resample_func resampleRow;
|
||||
|
||||
switch (buffer) {
|
||||
case GL_COLOR_BUFFER_BIT:
|
||||
readAtt = &readFb->Attachment[readFb->_ColorReadBufferIndex];
|
||||
readRb = readFb->_ColorReadBuffer;
|
||||
numDrawBuffers = drawFb->_NumColorDrawBuffers;
|
||||
break;
|
||||
case GL_DEPTH_BUFFER_BIT:
|
||||
readAtt = &readFb->Attachment[BUFFER_DEPTH];
|
||||
drawAtt = &drawFb->Attachment[BUFFER_DEPTH];
|
||||
readRb = readAtt->Renderbuffer;
|
||||
drawRb = drawAtt->Renderbuffer;
|
||||
numDrawBuffers = 1;
|
||||
|
||||
/* Note that for depth/stencil, the formats of src/dst must match. By
|
||||
* using the core helpers for pack/unpack, we avoid needing to handle
|
||||
* masking for things like DEPTH copies of Z24S8.
|
||||
*/
|
||||
if (readRb->Format == MESA_FORMAT_Z_FLOAT32 ||
|
||||
readRb->Format == MESA_FORMAT_Z32_FLOAT_S8X24_UINT) {
|
||||
mode = UNPACK_Z_FLOAT;
|
||||
} else {
|
||||
mode = UNPACK_Z_INT;
|
||||
}
|
||||
pixelSize = 4;
|
||||
break;
|
||||
case GL_STENCIL_BUFFER_BIT:
|
||||
readAtt = &readFb->Attachment[BUFFER_STENCIL];
|
||||
drawAtt = &drawFb->Attachment[BUFFER_STENCIL];
|
||||
readRb = readAtt->Renderbuffer;
|
||||
drawRb = drawAtt->Renderbuffer;
|
||||
numDrawBuffers = 1;
|
||||
mode = UNPACK_S;
|
||||
pixelSize = 1;
|
||||
break;
|
||||
default:
|
||||
_mesa_problem(ctx, "unexpected buffer in blit_nearest()");
|
||||
return;
|
||||
}
|
||||
|
||||
/* allocate the src/dst row buffers */
|
||||
srcBuffer = malloc(MAX_PIXEL_BYTES * srcWidth);
|
||||
dstBuffer = malloc(MAX_PIXEL_BYTES * dstWidth);
|
||||
if (!srcBuffer || !dstBuffer)
|
||||
goto fail_no_memory;
|
||||
|
||||
/* Blit to all the draw buffers */
|
||||
for (i = 0; i < numDrawBuffers; i++) {
|
||||
if (buffer == GL_COLOR_BUFFER_BIT) {
|
||||
gl_buffer_index idx = drawFb->_ColorDrawBufferIndexes[i];
|
||||
if (idx == BUFFER_NONE)
|
||||
continue;
|
||||
drawAtt = &drawFb->Attachment[idx];
|
||||
drawRb = drawAtt->Renderbuffer;
|
||||
|
||||
if (!drawRb)
|
||||
continue;
|
||||
|
||||
if (readRb->Format == drawRb->Format) {
|
||||
mode = DIRECT;
|
||||
pixelSize = _mesa_get_format_bytes(readRb->Format);
|
||||
} else {
|
||||
mode = UNPACK_RGBA_FLOAT;
|
||||
pixelSize = 16;
|
||||
}
|
||||
}
|
||||
|
||||
/* choose row resampler */
|
||||
switch (pixelSize) {
|
||||
case 1:
|
||||
resampleRow = resample_row_1;
|
||||
break;
|
||||
case 2:
|
||||
resampleRow = resample_row_2;
|
||||
break;
|
||||
case 4:
|
||||
resampleRow = resample_row_4;
|
||||
break;
|
||||
case 8:
|
||||
resampleRow = resample_row_8;
|
||||
break;
|
||||
case 16:
|
||||
resampleRow = resample_row_16;
|
||||
break;
|
||||
default:
|
||||
_mesa_problem(ctx, "unexpected pixel size (%d) in blit_nearest",
|
||||
pixelSize);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((readRb == drawRb) ||
|
||||
(readAtt->Texture && drawAtt->Texture &&
|
||||
(readAtt->Texture == drawAtt->Texture))) {
|
||||
/* map whole buffer for read/write */
|
||||
/* XXX we could be clever and just map the union region of the
|
||||
* source and dest rects.
|
||||
*/
|
||||
GLubyte *map;
|
||||
GLint rowStride;
|
||||
GLint formatSize = _mesa_get_format_bytes(readRb->Format);
|
||||
|
||||
ctx->Driver.MapRenderbuffer(ctx, readRb, 0, 0,
|
||||
readRb->Width, readRb->Height,
|
||||
GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
|
||||
&map, &rowStride, readFb->FlipY);
|
||||
if (!map) {
|
||||
goto fail_no_memory;
|
||||
}
|
||||
|
||||
srcMap = map + srcYpos * rowStride + srcXpos * formatSize;
|
||||
dstMap = map + dstYpos * rowStride + dstXpos * formatSize;
|
||||
|
||||
/* this handles overlapping copies */
|
||||
if (srcY0 < dstY0) {
|
||||
/* copy in reverse (top->down) order */
|
||||
srcMap += rowStride * (readRb->Height - 1);
|
||||
dstMap += rowStride * (readRb->Height - 1);
|
||||
srcRowStride = -rowStride;
|
||||
dstRowStride = -rowStride;
|
||||
}
|
||||
else {
|
||||
/* copy in normal (bottom->up) order */
|
||||
srcRowStride = rowStride;
|
||||
dstRowStride = rowStride;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* different src/dst buffers */
|
||||
ctx->Driver.MapRenderbuffer(ctx, readRb,
|
||||
srcXpos, srcYpos,
|
||||
srcWidth, srcHeight,
|
||||
GL_MAP_READ_BIT, &srcMap, &srcRowStride,
|
||||
readFb->FlipY);
|
||||
if (!srcMap) {
|
||||
goto fail_no_memory;
|
||||
}
|
||||
ctx->Driver.MapRenderbuffer(ctx, drawRb,
|
||||
dstXpos, dstYpos,
|
||||
dstWidth, dstHeight,
|
||||
GL_MAP_WRITE_BIT, &dstMap, &dstRowStride,
|
||||
drawFb->FlipY);
|
||||
if (!dstMap) {
|
||||
ctx->Driver.UnmapRenderbuffer(ctx, readRb);
|
||||
goto fail_no_memory;
|
||||
}
|
||||
}
|
||||
|
||||
for (dstRow = 0; dstRow < dstHeight; dstRow++) {
|
||||
GLfloat srcRowF = (dstRow + 0.5F) / dstHeight * srcHeight - 0.5F;
|
||||
GLint srcRow = lroundf(srcRowF);
|
||||
GLubyte *dstRowStart = dstMap + dstRowStride * dstRow;
|
||||
|
||||
assert(srcRow >= 0);
|
||||
assert(srcRow < srcHeight);
|
||||
|
||||
if (invertY) {
|
||||
srcRow = srcHeight - 1 - srcRow;
|
||||
}
|
||||
|
||||
/* get pixel row from source and resample to match dest width */
|
||||
if (prevY != srcRow) {
|
||||
GLubyte *srcRowStart = srcMap + srcRowStride * srcRow;
|
||||
|
||||
switch (mode) {
|
||||
case DIRECT:
|
||||
memcpy(srcBuffer, srcRowStart, pixelSize * srcWidth);
|
||||
break;
|
||||
case UNPACK_RGBA_FLOAT:
|
||||
_mesa_unpack_rgba_row(readRb->Format, srcWidth, srcRowStart,
|
||||
srcBuffer);
|
||||
break;
|
||||
case UNPACK_Z_FLOAT:
|
||||
_mesa_unpack_float_z_row(readRb->Format, srcWidth, srcRowStart,
|
||||
srcBuffer);
|
||||
break;
|
||||
case UNPACK_Z_INT:
|
||||
_mesa_unpack_uint_z_row(readRb->Format, srcWidth, srcRowStart,
|
||||
srcBuffer);
|
||||
break;
|
||||
case UNPACK_S:
|
||||
_mesa_unpack_ubyte_stencil_row(readRb->Format, srcWidth,
|
||||
srcRowStart, srcBuffer);
|
||||
break;
|
||||
}
|
||||
|
||||
resampleRow(srcWidth, dstWidth, srcBuffer, dstBuffer, invertX);
|
||||
prevY = srcRow;
|
||||
}
|
||||
|
||||
/* store pixel row in destination */
|
||||
switch (mode) {
|
||||
case DIRECT:
|
||||
memcpy(dstRowStart, dstBuffer, pixelSize * dstWidth);
|
||||
break;
|
||||
case UNPACK_RGBA_FLOAT:
|
||||
_mesa_pack_float_rgba_row(drawRb->Format, dstWidth, dstBuffer,
|
||||
dstRowStart);
|
||||
break;
|
||||
case UNPACK_Z_FLOAT:
|
||||
_mesa_pack_float_z_row(drawRb->Format, dstWidth, dstBuffer,
|
||||
dstRowStart);
|
||||
break;
|
||||
case UNPACK_Z_INT:
|
||||
_mesa_pack_uint_z_row(drawRb->Format, dstWidth, dstBuffer,
|
||||
dstRowStart);
|
||||
break;
|
||||
case UNPACK_S:
|
||||
_mesa_pack_ubyte_stencil_row(drawRb->Format, dstWidth, dstBuffer,
|
||||
dstRowStart);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ctx->Driver.UnmapRenderbuffer(ctx, readRb);
|
||||
if (drawRb != readRb) {
|
||||
ctx->Driver.UnmapRenderbuffer(ctx, drawRb);
|
||||
}
|
||||
}
|
||||
|
||||
fail:
|
||||
free(srcBuffer);
|
||||
free(dstBuffer);
|
||||
return;
|
||||
|
||||
fail_no_memory:
|
||||
free(srcBuffer);
|
||||
free(dstBuffer);
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBuffer");
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define LERP(T, A, B) ( (A) + (T) * ((B) - (A)) )
|
||||
|
||||
static inline GLfloat
|
||||
lerp_2d(GLfloat a, GLfloat b,
|
||||
GLfloat v00, GLfloat v10, GLfloat v01, GLfloat v11)
|
||||
{
|
||||
const GLfloat temp0 = LERP(a, v00, v10);
|
||||
const GLfloat temp1 = LERP(a, v01, v11);
|
||||
return LERP(b, temp0, temp1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Bilinear interpolation of two source rows.
|
||||
* GLubyte pixels.
|
||||
*/
|
||||
static void
|
||||
resample_linear_row_ub(GLint srcWidth, GLint dstWidth,
|
||||
const GLvoid *srcBuffer0, const GLvoid *srcBuffer1,
|
||||
GLvoid *dstBuffer, GLboolean flip, GLfloat rowWeight)
|
||||
{
|
||||
const GLubyte (*srcColor0)[4] = (const GLubyte (*)[4]) srcBuffer0;
|
||||
const GLubyte (*srcColor1)[4] = (const GLubyte (*)[4]) srcBuffer1;
|
||||
GLubyte (*dstColor)[4] = (GLubyte (*)[4]) dstBuffer;
|
||||
GLint dstCol;
|
||||
|
||||
for (dstCol = 0; dstCol < dstWidth; dstCol++) {
|
||||
const GLfloat srcCol = (dstCol + 0.5F) / dstWidth * srcWidth - 0.5F;
|
||||
GLint srcCol0 = MAX2(0, util_ifloor(srcCol));
|
||||
GLint srcCol1 = srcCol0 + 1;
|
||||
GLfloat colWeight = srcCol - srcCol0; /* fractional part of srcCol */
|
||||
GLfloat red, green, blue, alpha;
|
||||
|
||||
assert(srcCol0 < srcWidth);
|
||||
assert(srcCol1 <= srcWidth);
|
||||
|
||||
if (srcCol1 == srcWidth) {
|
||||
/* last column fudge */
|
||||
srcCol1--;
|
||||
colWeight = 0.0;
|
||||
}
|
||||
|
||||
if (flip) {
|
||||
srcCol0 = srcWidth - 1 - srcCol0;
|
||||
srcCol1 = srcWidth - 1 - srcCol1;
|
||||
}
|
||||
|
||||
red = lerp_2d(colWeight, rowWeight,
|
||||
srcColor0[srcCol0][RCOMP], srcColor0[srcCol1][RCOMP],
|
||||
srcColor1[srcCol0][RCOMP], srcColor1[srcCol1][RCOMP]);
|
||||
green = lerp_2d(colWeight, rowWeight,
|
||||
srcColor0[srcCol0][GCOMP], srcColor0[srcCol1][GCOMP],
|
||||
srcColor1[srcCol0][GCOMP], srcColor1[srcCol1][GCOMP]);
|
||||
blue = lerp_2d(colWeight, rowWeight,
|
||||
srcColor0[srcCol0][BCOMP], srcColor0[srcCol1][BCOMP],
|
||||
srcColor1[srcCol0][BCOMP], srcColor1[srcCol1][BCOMP]);
|
||||
alpha = lerp_2d(colWeight, rowWeight,
|
||||
srcColor0[srcCol0][ACOMP], srcColor0[srcCol1][ACOMP],
|
||||
srcColor1[srcCol0][ACOMP], srcColor1[srcCol1][ACOMP]);
|
||||
|
||||
dstColor[dstCol][RCOMP] = util_ifloor(red);
|
||||
dstColor[dstCol][GCOMP] = util_ifloor(green);
|
||||
dstColor[dstCol][BCOMP] = util_ifloor(blue);
|
||||
dstColor[dstCol][ACOMP] = util_ifloor(alpha);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Bilinear interpolation of two source rows. floating point pixels.
|
||||
*/
|
||||
static void
|
||||
resample_linear_row_float(GLint srcWidth, GLint dstWidth,
|
||||
const GLvoid *srcBuffer0, const GLvoid *srcBuffer1,
|
||||
GLvoid *dstBuffer, GLboolean flip, GLfloat rowWeight)
|
||||
{
|
||||
const GLfloat (*srcColor0)[4] = (const GLfloat (*)[4]) srcBuffer0;
|
||||
const GLfloat (*srcColor1)[4] = (const GLfloat (*)[4]) srcBuffer1;
|
||||
GLfloat (*dstColor)[4] = (GLfloat (*)[4]) dstBuffer;
|
||||
GLint dstCol;
|
||||
|
||||
for (dstCol = 0; dstCol < dstWidth; dstCol++) {
|
||||
const GLfloat srcCol = (dstCol + 0.5F) / dstWidth * srcWidth - 0.5F;
|
||||
GLint srcCol0 = MAX2(0, util_ifloor(srcCol));
|
||||
GLint srcCol1 = srcCol0 + 1;
|
||||
GLfloat colWeight = srcCol - srcCol0; /* fractional part of srcCol */
|
||||
GLfloat red, green, blue, alpha;
|
||||
|
||||
assert(srcCol0 < srcWidth);
|
||||
assert(srcCol1 <= srcWidth);
|
||||
|
||||
if (srcCol1 == srcWidth) {
|
||||
/* last column fudge */
|
||||
srcCol1--;
|
||||
colWeight = 0.0;
|
||||
}
|
||||
|
||||
if (flip) {
|
||||
srcCol0 = srcWidth - 1 - srcCol0;
|
||||
srcCol1 = srcWidth - 1 - srcCol1;
|
||||
}
|
||||
|
||||
red = lerp_2d(colWeight, rowWeight,
|
||||
srcColor0[srcCol0][RCOMP], srcColor0[srcCol1][RCOMP],
|
||||
srcColor1[srcCol0][RCOMP], srcColor1[srcCol1][RCOMP]);
|
||||
green = lerp_2d(colWeight, rowWeight,
|
||||
srcColor0[srcCol0][GCOMP], srcColor0[srcCol1][GCOMP],
|
||||
srcColor1[srcCol0][GCOMP], srcColor1[srcCol1][GCOMP]);
|
||||
blue = lerp_2d(colWeight, rowWeight,
|
||||
srcColor0[srcCol0][BCOMP], srcColor0[srcCol1][BCOMP],
|
||||
srcColor1[srcCol0][BCOMP], srcColor1[srcCol1][BCOMP]);
|
||||
alpha = lerp_2d(colWeight, rowWeight,
|
||||
srcColor0[srcCol0][ACOMP], srcColor0[srcCol1][ACOMP],
|
||||
srcColor1[srcCol0][ACOMP], srcColor1[srcCol1][ACOMP]);
|
||||
|
||||
dstColor[dstCol][RCOMP] = red;
|
||||
dstColor[dstCol][GCOMP] = green;
|
||||
dstColor[dstCol][BCOMP] = blue;
|
||||
dstColor[dstCol][ACOMP] = alpha;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Bilinear filtered blit (color only, non-integer values).
|
||||
*/
|
||||
static void
|
||||
blit_linear(struct gl_context *ctx,
|
||||
struct gl_framebuffer *readFb,
|
||||
struct gl_framebuffer *drawFb,
|
||||
GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
|
||||
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1)
|
||||
{
|
||||
struct gl_renderbuffer *readRb = readFb->_ColorReadBuffer;
|
||||
struct gl_renderbuffer_attachment *readAtt =
|
||||
&readFb->Attachment[readFb->_ColorReadBufferIndex];
|
||||
|
||||
const GLint srcWidth = ABS(srcX1 - srcX0);
|
||||
const GLint dstWidth = ABS(dstX1 - dstX0);
|
||||
const GLint srcHeight = ABS(srcY1 - srcY0);
|
||||
const GLint dstHeight = ABS(dstY1 - dstY0);
|
||||
|
||||
const GLint srcXpos = MIN2(srcX0, srcX1);
|
||||
const GLint srcYpos = MIN2(srcY0, srcY1);
|
||||
const GLint dstXpos = MIN2(dstX0, dstX1);
|
||||
const GLint dstYpos = MIN2(dstY0, dstY1);
|
||||
|
||||
const GLboolean invertX = (srcX1 < srcX0) ^ (dstX1 < dstX0);
|
||||
const GLboolean invertY = (srcY1 < srcY0) ^ (dstY1 < dstY0);
|
||||
|
||||
GLint dstRow;
|
||||
|
||||
GLint pixelSize;
|
||||
GLvoid *srcBuffer0, *srcBuffer1;
|
||||
GLint srcBufferY0 = -1, srcBufferY1 = -1;
|
||||
GLvoid *dstBuffer;
|
||||
|
||||
mesa_format readFormat = _mesa_get_srgb_format_linear(readRb->Format);
|
||||
GLuint bpp = _mesa_get_format_bytes(readFormat);
|
||||
|
||||
GLenum pixelType;
|
||||
|
||||
GLubyte *srcMap, *dstMap;
|
||||
GLint srcRowStride, dstRowStride;
|
||||
GLuint i;
|
||||
|
||||
|
||||
/* Determine datatype for resampling */
|
||||
if (_mesa_get_format_max_bits(readFormat) == 8 &&
|
||||
_mesa_get_format_datatype(readFormat) == GL_UNSIGNED_NORMALIZED) {
|
||||
pixelType = GL_UNSIGNED_BYTE;
|
||||
pixelSize = 4 * sizeof(GLubyte);
|
||||
}
|
||||
else {
|
||||
pixelType = GL_FLOAT;
|
||||
pixelSize = 4 * sizeof(GLfloat);
|
||||
}
|
||||
|
||||
/* Allocate the src/dst row buffers.
|
||||
* Keep two adjacent src rows around for bilinear sampling.
|
||||
*/
|
||||
srcBuffer0 = malloc(pixelSize * srcWidth);
|
||||
srcBuffer1 = malloc(pixelSize * srcWidth);
|
||||
dstBuffer = malloc(pixelSize * dstWidth);
|
||||
if (!srcBuffer0 || !srcBuffer1 || !dstBuffer) {
|
||||
goto fail_no_memory;
|
||||
}
|
||||
|
||||
for (i = 0; i < drawFb->_NumColorDrawBuffers; i++) {
|
||||
gl_buffer_index idx = drawFb->_ColorDrawBufferIndexes[i];
|
||||
struct gl_renderbuffer_attachment *drawAtt;
|
||||
struct gl_renderbuffer *drawRb;
|
||||
mesa_format drawFormat;
|
||||
|
||||
if (idx == BUFFER_NONE)
|
||||
continue;
|
||||
|
||||
drawAtt = &drawFb->Attachment[idx];
|
||||
drawRb = drawAtt->Renderbuffer;
|
||||
if (!drawRb)
|
||||
continue;
|
||||
|
||||
drawFormat = _mesa_get_srgb_format_linear(drawRb->Format);
|
||||
|
||||
/*
|
||||
* Map src / dst renderbuffers
|
||||
*/
|
||||
if ((readRb == drawRb) ||
|
||||
(readAtt->Texture && drawAtt->Texture &&
|
||||
(readAtt->Texture == drawAtt->Texture))) {
|
||||
/* map whole buffer for read/write */
|
||||
ctx->Driver.MapRenderbuffer(ctx, readRb,
|
||||
0, 0, readRb->Width, readRb->Height,
|
||||
GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
|
||||
&srcMap, &srcRowStride,
|
||||
readFb->FlipY);
|
||||
if (!srcMap) {
|
||||
goto fail_no_memory;
|
||||
}
|
||||
|
||||
dstMap = srcMap;
|
||||
dstRowStride = srcRowStride;
|
||||
}
|
||||
else {
|
||||
/* different src/dst buffers */
|
||||
/* XXX with a bit of work we could just map the regions to be
|
||||
* read/written instead of the whole buffers.
|
||||
*/
|
||||
ctx->Driver.MapRenderbuffer(ctx, readRb,
|
||||
0, 0, readRb->Width, readRb->Height,
|
||||
GL_MAP_READ_BIT, &srcMap, &srcRowStride,
|
||||
readFb->FlipY);
|
||||
if (!srcMap) {
|
||||
goto fail_no_memory;
|
||||
}
|
||||
ctx->Driver.MapRenderbuffer(ctx, drawRb,
|
||||
0, 0, drawRb->Width, drawRb->Height,
|
||||
GL_MAP_WRITE_BIT, &dstMap, &dstRowStride,
|
||||
drawFb->FlipY);
|
||||
if (!dstMap) {
|
||||
ctx->Driver.UnmapRenderbuffer(ctx, readRb);
|
||||
goto fail_no_memory;
|
||||
}
|
||||
}
|
||||
|
||||
for (dstRow = 0; dstRow < dstHeight; dstRow++) {
|
||||
const GLint dstY = dstYpos + dstRow;
|
||||
GLfloat srcRow = (dstRow + 0.5F) / dstHeight * srcHeight - 0.5F;
|
||||
GLint srcRow0 = MAX2(0, util_ifloor(srcRow));
|
||||
GLint srcRow1 = srcRow0 + 1;
|
||||
GLfloat rowWeight = srcRow - srcRow0; /* fractional part of srcRow */
|
||||
|
||||
if (srcRow1 == srcHeight) {
|
||||
/* last row fudge */
|
||||
srcRow1 = srcRow0;
|
||||
rowWeight = 0.0;
|
||||
}
|
||||
|
||||
if (invertY) {
|
||||
srcRow0 = srcHeight - 1 - srcRow0;
|
||||
srcRow1 = srcHeight - 1 - srcRow1;
|
||||
}
|
||||
|
||||
srcY0 = srcYpos + srcRow0;
|
||||
srcY1 = srcYpos + srcRow1;
|
||||
|
||||
/* get the two source rows */
|
||||
if (srcY0 == srcBufferY0 && srcY1 == srcBufferY1) {
|
||||
/* use same source row buffers again */
|
||||
}
|
||||
else if (srcY0 == srcBufferY1) {
|
||||
/* move buffer1 into buffer0 by swapping pointers */
|
||||
GLvoid *tmp = srcBuffer0;
|
||||
srcBuffer0 = srcBuffer1;
|
||||
srcBuffer1 = tmp;
|
||||
/* get y1 row */
|
||||
{
|
||||
GLubyte *src = srcMap + srcY1 * srcRowStride + srcXpos * bpp;
|
||||
if (pixelType == GL_UNSIGNED_BYTE) {
|
||||
_mesa_unpack_ubyte_rgba_row(readFormat, srcWidth,
|
||||
src, srcBuffer1);
|
||||
}
|
||||
else {
|
||||
_mesa_unpack_rgba_row(readFormat, srcWidth,
|
||||
src, srcBuffer1);
|
||||
}
|
||||
}
|
||||
srcBufferY0 = srcY0;
|
||||
srcBufferY1 = srcY1;
|
||||
}
|
||||
else {
|
||||
/* get both new rows */
|
||||
{
|
||||
GLubyte *src0 = srcMap + srcY0 * srcRowStride + srcXpos * bpp;
|
||||
GLubyte *src1 = srcMap + srcY1 * srcRowStride + srcXpos * bpp;
|
||||
if (pixelType == GL_UNSIGNED_BYTE) {
|
||||
_mesa_unpack_ubyte_rgba_row(readFormat, srcWidth,
|
||||
src0, srcBuffer0);
|
||||
_mesa_unpack_ubyte_rgba_row(readFormat, srcWidth,
|
||||
src1, srcBuffer1);
|
||||
}
|
||||
else {
|
||||
_mesa_unpack_rgba_row(readFormat, srcWidth, src0, srcBuffer0);
|
||||
_mesa_unpack_rgba_row(readFormat, srcWidth, src1, srcBuffer1);
|
||||
}
|
||||
}
|
||||
srcBufferY0 = srcY0;
|
||||
srcBufferY1 = srcY1;
|
||||
}
|
||||
|
||||
if (pixelType == GL_UNSIGNED_BYTE) {
|
||||
resample_linear_row_ub(srcWidth, dstWidth, srcBuffer0, srcBuffer1,
|
||||
dstBuffer, invertX, rowWeight);
|
||||
}
|
||||
else {
|
||||
resample_linear_row_float(srcWidth, dstWidth, srcBuffer0, srcBuffer1,
|
||||
dstBuffer, invertX, rowWeight);
|
||||
}
|
||||
|
||||
/* store pixel row in destination */
|
||||
{
|
||||
GLubyte *dst = dstMap + dstY * dstRowStride + dstXpos * bpp;
|
||||
if (pixelType == GL_UNSIGNED_BYTE) {
|
||||
_mesa_pack_ubyte_rgba_row(drawFormat, dstWidth, dstBuffer, dst);
|
||||
}
|
||||
else {
|
||||
_mesa_pack_float_rgba_row(drawFormat, dstWidth, dstBuffer, dst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx->Driver.UnmapRenderbuffer(ctx, readRb);
|
||||
if (drawRb != readRb) {
|
||||
ctx->Driver.UnmapRenderbuffer(ctx, drawRb);
|
||||
}
|
||||
}
|
||||
|
||||
free(srcBuffer0);
|
||||
free(srcBuffer1);
|
||||
free(dstBuffer);
|
||||
return;
|
||||
|
||||
fail_no_memory:
|
||||
free(srcBuffer0);
|
||||
free(srcBuffer1);
|
||||
free(dstBuffer);
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Software fallback for glBlitFramebufferEXT().
|
||||
*/
|
||||
void
|
||||
_swrast_BlitFramebuffer(struct gl_context *ctx,
|
||||
struct gl_framebuffer *readFb,
|
||||
struct gl_framebuffer *drawFb,
|
||||
GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
|
||||
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
|
||||
GLbitfield mask, GLenum filter)
|
||||
{
|
||||
static const GLbitfield buffers[3] = {
|
||||
GL_COLOR_BUFFER_BIT,
|
||||
GL_DEPTH_BUFFER_BIT,
|
||||
GL_STENCIL_BUFFER_BIT
|
||||
};
|
||||
static const GLenum buffer_enums[3] = {
|
||||
GL_COLOR,
|
||||
GL_DEPTH,
|
||||
GL_STENCIL,
|
||||
};
|
||||
GLint i;
|
||||
|
||||
/* Page 679 of OpenGL 4.4 spec says:
|
||||
* "Added BlitFramebuffer to commands affected by conditional rendering in
|
||||
* section 10.10 (Bug 9562)."
|
||||
*/
|
||||
if (!_mesa_check_conditional_render(ctx))
|
||||
return; /* Do not blit */
|
||||
|
||||
if (!_mesa_clip_blit(ctx, readFb, drawFb, &srcX0, &srcY0, &srcX1, &srcY1,
|
||||
&dstX0, &dstY0, &dstX1, &dstY1)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (SWRAST_CONTEXT(ctx)->NewState)
|
||||
_swrast_validate_derived(ctx);
|
||||
|
||||
/* First, try covering whatever buffers possible using the fast 1:1 copy
|
||||
* path.
|
||||
*/
|
||||
if (srcX1 - srcX0 == dstX1 - dstX0 &&
|
||||
srcY1 - srcY0 == dstY1 - dstY0 &&
|
||||
srcX0 < srcX1 &&
|
||||
srcY0 < srcY1 &&
|
||||
dstX0 < dstX1 &&
|
||||
dstY0 < dstY1) {
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (mask & buffers[i]) {
|
||||
if (swrast_fast_copy_pixels(ctx,
|
||||
readFb, drawFb,
|
||||
srcX0, srcY0,
|
||||
srcX1 - srcX0, srcY1 - srcY0,
|
||||
dstX0, dstY0,
|
||||
buffer_enums[i])) {
|
||||
mask &= ~buffers[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!mask)
|
||||
return;
|
||||
}
|
||||
|
||||
if (filter == GL_NEAREST) {
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (mask & buffers[i]) {
|
||||
blit_nearest(ctx, readFb, drawFb, srcX0, srcY0, srcX1, srcY1,
|
||||
dstX0, dstY0, dstX1, dstY1, buffers[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
assert(filter == GL_LINEAR);
|
||||
if (mask & GL_COLOR_BUFFER_BIT) { /* depth/stencil not allowed */
|
||||
blit_linear(ctx, readFb, drawFb, srcX0, srcY0, srcX1, srcY1,
|
||||
dstX0, dstY0, dstX1, dstY1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,128 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* Copyright (C) 2011 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Types, macros, etc for the GLchan datatype.
|
||||
* The swrast module is kind of hard-coded for 8bpp color channels but
|
||||
* may be recompiled to use 16- or 32-bit color channels. But that
|
||||
* feature is seldom used and is likely broken in various ways.
|
||||
*/
|
||||
|
||||
#ifndef U_CHAN_H
|
||||
#define U_CHAN_H
|
||||
|
||||
|
||||
#include "main/config.h"
|
||||
|
||||
|
||||
/**
|
||||
* Default bits per color channel: 8, 16 or 32
|
||||
*/
|
||||
#ifndef CHAN_BITS
|
||||
#define CHAN_BITS 8
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Color channel data type.
|
||||
*/
|
||||
#if CHAN_BITS == 8
|
||||
typedef GLubyte GLchan;
|
||||
#define CHAN_MAX 255
|
||||
#define CHAN_MAXF 255.0F
|
||||
#define CHAN_TYPE GL_UNSIGNED_BYTE
|
||||
#elif CHAN_BITS == 16
|
||||
typedef GLushort GLchan;
|
||||
#define CHAN_MAX 65535
|
||||
#define CHAN_MAXF 65535.0F
|
||||
#define CHAN_TYPE GL_UNSIGNED_SHORT
|
||||
#elif CHAN_BITS == 32
|
||||
typedef GLfloat GLchan;
|
||||
#define CHAN_MAX 1.0
|
||||
#define CHAN_MAXF 1.0F
|
||||
#define CHAN_TYPE GL_FLOAT
|
||||
#else
|
||||
#error "illegal number of color channel bits"
|
||||
#endif
|
||||
|
||||
|
||||
#if CHAN_BITS == 8
|
||||
|
||||
#define CHAN_TO_UBYTE(c) (c)
|
||||
#define CHAN_TO_USHORT(c) (((c) << 8) | (c))
|
||||
#define CHAN_TO_SHORT(c) (((c) << 7) | ((c) >> 1))
|
||||
#define CHAN_TO_FLOAT(c) UBYTE_TO_FLOAT(c)
|
||||
|
||||
#define CLAMPED_FLOAT_TO_CHAN(c, f) CLAMPED_FLOAT_TO_UBYTE(c, f)
|
||||
#define UNCLAMPED_FLOAT_TO_CHAN(c, f) UNCLAMPED_FLOAT_TO_UBYTE(c, f)
|
||||
|
||||
#define COPY_CHAN4(DST, SRC) COPY_4UBV(DST, SRC)
|
||||
|
||||
#elif CHAN_BITS == 16
|
||||
|
||||
#define CHAN_TO_UBYTE(c) ((c) >> 8)
|
||||
#define CHAN_TO_USHORT(c) (c)
|
||||
#define CHAN_TO_SHORT(c) ((c) >> 1)
|
||||
#define CHAN_TO_FLOAT(c) ((GLfloat) ((c) * (1.0 / CHAN_MAXF)))
|
||||
|
||||
#define CLAMPED_FLOAT_TO_CHAN(c, f) CLAMPED_FLOAT_TO_USHORT(c, f)
|
||||
#define UNCLAMPED_FLOAT_TO_CHAN(c, f) UNCLAMPED_FLOAT_TO_USHORT(c, f)
|
||||
|
||||
#define COPY_CHAN4(DST, SRC) COPY_4V(DST, SRC)
|
||||
|
||||
#elif CHAN_BITS == 32
|
||||
|
||||
#define CHAN_TO_UBYTE(c) FLOAT_TO_UBYTE(c)
|
||||
#define CHAN_TO_USHORT(c) ((GLushort) (SATURATE((c)) * 65535.0))
|
||||
#define CHAN_TO_SHORT(c) ((GLshort) (SATURATE((c)) * 32767.0))
|
||||
#define CHAN_TO_FLOAT(c) (c)
|
||||
|
||||
#define CLAMPED_FLOAT_TO_CHAN(c, f) c = (f)
|
||||
#define UNCLAMPED_FLOAT_TO_CHAN(c, f) c = (f)
|
||||
|
||||
#define COPY_CHAN4(DST, SRC) COPY_4V(DST, SRC)
|
||||
|
||||
#else
|
||||
|
||||
#error unexpected CHAN_BITS size
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Convert 4 floats to GLchan values.
|
||||
* \param dst pointer to destination GLchan[4] array.
|
||||
* \param f pointer to source GLfloat[4] array.
|
||||
*/
|
||||
#define UNCLAMPED_FLOAT_TO_RGBA_CHAN(dst, f) \
|
||||
do { \
|
||||
UNCLAMPED_FLOAT_TO_CHAN((dst)[0], (f)[0]); \
|
||||
UNCLAMPED_FLOAT_TO_CHAN((dst)[1], (f)[1]); \
|
||||
UNCLAMPED_FLOAT_TO_CHAN((dst)[2], (f)[2]); \
|
||||
UNCLAMPED_FLOAT_TO_CHAN((dst)[3], (f)[3]); \
|
||||
} while (0)
|
||||
|
||||
|
||||
|
||||
#endif /* U_CHAN_H */
|
|
@ -1,333 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* Copyright (C) 1999-2008 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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/accum.h"
|
||||
#include "main/condrender.h"
|
||||
#include "main/format_pack.h"
|
||||
#include "main/macros.h"
|
||||
|
||||
#include "main/mtypes.h"
|
||||
|
||||
#include "s_context.h"
|
||||
#include "s_depth.h"
|
||||
#include "s_stencil.h"
|
||||
|
||||
|
||||
/**
|
||||
* Convert a boolean color mask to a packed color where each channel of
|
||||
* the packed value at dst will be 0 or ~0 depending on the colorMask.
|
||||
*/
|
||||
static void
|
||||
_pack_colormask(mesa_format format, const uint8_t colorMask[4], void *dst)
|
||||
{
|
||||
float maskColor[4];
|
||||
|
||||
switch (_mesa_get_format_datatype(format)) {
|
||||
case GL_UNSIGNED_NORMALIZED:
|
||||
/* simple: 1.0 will convert to ~0 in the right bit positions */
|
||||
maskColor[0] = colorMask[0] ? 1.0f : 0.0f;
|
||||
maskColor[1] = colorMask[1] ? 1.0f : 0.0f;
|
||||
maskColor[2] = colorMask[2] ? 1.0f : 0.0f;
|
||||
maskColor[3] = colorMask[3] ? 1.0f : 0.0f;
|
||||
_mesa_pack_float_rgba_row(format, 1,
|
||||
(const float (*)[4]) maskColor, dst);
|
||||
break;
|
||||
case GL_SIGNED_NORMALIZED:
|
||||
case GL_FLOAT:
|
||||
/* These formats are harder because it's hard to know the floating
|
||||
* point values that will convert to ~0 for each color channel's bits.
|
||||
* This solution just generates a non-zero value for each color channel
|
||||
* then fixes up the non-zero values to be ~0.
|
||||
* Note: we'll need to add special case code if we ever have to deal
|
||||
* with formats with unequal color channel sizes, like R11_G11_B10.
|
||||
* We issue a warning below for channel sizes other than 8,16,32.
|
||||
*/
|
||||
{
|
||||
uint32_t bits = _mesa_get_format_max_bits(format); /* bits per chan */
|
||||
uint32_t bytes = _mesa_get_format_bytes(format);
|
||||
uint32_t i;
|
||||
|
||||
/* this should put non-zero values into the channels of dst */
|
||||
maskColor[0] = colorMask[0] ? -1.0f : 0.0f;
|
||||
maskColor[1] = colorMask[1] ? -1.0f : 0.0f;
|
||||
maskColor[2] = colorMask[2] ? -1.0f : 0.0f;
|
||||
maskColor[3] = colorMask[3] ? -1.0f : 0.0f;
|
||||
_mesa_pack_float_rgba_row(format, 1,
|
||||
(const float (*)[4]) maskColor, dst);
|
||||
|
||||
/* fix-up the dst channels by converting non-zero values to ~0 */
|
||||
if (bits == 8) {
|
||||
uint8_t *d = (uint8_t *) dst;
|
||||
for (i = 0; i < bytes; i++) {
|
||||
d[i] = d[i] ? 0xff : 0x0;
|
||||
}
|
||||
}
|
||||
else if (bits == 16) {
|
||||
uint16_t *d = (uint16_t *) dst;
|
||||
for (i = 0; i < bytes / 2; i++) {
|
||||
d[i] = d[i] ? 0xffff : 0x0;
|
||||
}
|
||||
}
|
||||
else if (bits == 32) {
|
||||
uint32_t *d = (uint32_t *) dst;
|
||||
for (i = 0; i < bytes / 4; i++) {
|
||||
d[i] = d[i] ? 0xffffffffU : 0x0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
unreachable("unexpected size in _mesa_pack_colormask()");
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
unreachable("unexpected format data type in gen_color_mask()");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear an rgba color buffer with masking if needed.
|
||||
*/
|
||||
static void
|
||||
clear_rgba_buffer(struct gl_context *ctx, struct gl_renderbuffer *rb,
|
||||
const GLubyte colorMask[4])
|
||||
{
|
||||
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;
|
||||
const GLuint pixelSize = _mesa_get_format_bytes(rb->Format);
|
||||
const GLboolean doMasking = (colorMask[0] == 0 ||
|
||||
colorMask[1] == 0 ||
|
||||
colorMask[2] == 0 ||
|
||||
colorMask[3] == 0);
|
||||
const GLfloat (*clearColor)[4] =
|
||||
(const GLfloat (*)[4]) ctx->Color.ClearColor.f;
|
||||
GLbitfield mapMode = GL_MAP_WRITE_BIT;
|
||||
GLubyte *map;
|
||||
GLint rowStride;
|
||||
GLint i, j;
|
||||
|
||||
if (doMasking) {
|
||||
/* we'll need to read buffer values too */
|
||||
mapMode |= GL_MAP_READ_BIT;
|
||||
}
|
||||
|
||||
/* map dest buffer */
|
||||
ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height,
|
||||
mapMode, &map, &rowStride,
|
||||
ctx->DrawBuffer->FlipY);
|
||||
if (!map) {
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glClear(color)");
|
||||
return;
|
||||
}
|
||||
|
||||
/* for 1, 2, 4-byte clearing */
|
||||
#define SIMPLE_TYPE_CLEAR(TYPE) \
|
||||
do { \
|
||||
TYPE pixel, pixelMask; \
|
||||
_mesa_pack_float_rgba_row(rb->Format, 1, clearColor, &pixel); \
|
||||
if (doMasking) { \
|
||||
_pack_colormask(rb->Format, colorMask, &pixelMask); \
|
||||
pixel &= pixelMask; \
|
||||
pixelMask = ~pixelMask; \
|
||||
} \
|
||||
for (i = 0; i < height; i++) { \
|
||||
TYPE *row = (TYPE *) map; \
|
||||
if (doMasking) { \
|
||||
for (j = 0; j < width; j++) { \
|
||||
row[j] = (row[j] & pixelMask) | pixel; \
|
||||
} \
|
||||
} \
|
||||
else { \
|
||||
for (j = 0; j < width; j++) { \
|
||||
row[j] = pixel; \
|
||||
} \
|
||||
} \
|
||||
map += rowStride; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
/* for 3, 6, 8, 12, 16-byte clearing */
|
||||
#define MULTI_WORD_CLEAR(TYPE, N) \
|
||||
do { \
|
||||
TYPE pixel[N], pixelMask[N]; \
|
||||
GLuint k; \
|
||||
_mesa_pack_float_rgba_row(rb->Format, 1, clearColor, pixel); \
|
||||
if (doMasking) { \
|
||||
_pack_colormask(rb->Format, colorMask, pixelMask); \
|
||||
for (k = 0; k < N; k++) { \
|
||||
pixel[k] &= pixelMask[k]; \
|
||||
pixelMask[k] = ~pixelMask[k]; \
|
||||
} \
|
||||
} \
|
||||
for (i = 0; i < height; i++) { \
|
||||
TYPE *row = (TYPE *) map; \
|
||||
if (doMasking) { \
|
||||
for (j = 0; j < width; j++) { \
|
||||
for (k = 0; k < N; k++) { \
|
||||
row[j * N + k] = \
|
||||
(row[j * N + k] & pixelMask[k]) | pixel[k]; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
else { \
|
||||
for (j = 0; j < width; j++) { \
|
||||
for (k = 0; k < N; k++) { \
|
||||
row[j * N + k] = pixel[k]; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
map += rowStride; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
switch (pixelSize) {
|
||||
case 1:
|
||||
SIMPLE_TYPE_CLEAR(GLubyte);
|
||||
break;
|
||||
case 2:
|
||||
SIMPLE_TYPE_CLEAR(GLushort);
|
||||
break;
|
||||
case 3:
|
||||
MULTI_WORD_CLEAR(GLubyte, 3);
|
||||
break;
|
||||
case 4:
|
||||
SIMPLE_TYPE_CLEAR(GLuint);
|
||||
break;
|
||||
case 6:
|
||||
MULTI_WORD_CLEAR(GLushort, 3);
|
||||
break;
|
||||
case 8:
|
||||
MULTI_WORD_CLEAR(GLuint, 2);
|
||||
break;
|
||||
case 12:
|
||||
MULTI_WORD_CLEAR(GLuint, 3);
|
||||
break;
|
||||
case 16:
|
||||
MULTI_WORD_CLEAR(GLuint, 4);
|
||||
break;
|
||||
default:
|
||||
_mesa_problem(ctx, "bad pixel size in clear_rgba_buffer()");
|
||||
}
|
||||
|
||||
/* unmap buffer */
|
||||
ctx->Driver.UnmapRenderbuffer(ctx, rb);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clear the front/back/left/right/aux color buffers.
|
||||
* This function is usually only called if the device driver can't
|
||||
* clear its own color buffers for some reason (such as with masking).
|
||||
*/
|
||||
static void
|
||||
clear_color_buffers(struct gl_context *ctx)
|
||||
{
|
||||
GLuint buf;
|
||||
|
||||
for (buf = 0; buf < ctx->DrawBuffer->_NumColorDrawBuffers; buf++) {
|
||||
struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[buf];
|
||||
|
||||
/* If this is an ES2 context or GL_ARB_ES2_compatibility is supported,
|
||||
* the framebuffer can be complete with some attachments be missing. In
|
||||
* this case the _ColorDrawBuffers pointer will be NULL.
|
||||
*/
|
||||
if (rb == NULL)
|
||||
continue;
|
||||
|
||||
const GLubyte colormask[4] = {
|
||||
GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 0) ? 0xff : 0,
|
||||
GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 1) ? 0xff : 0,
|
||||
GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 2) ? 0xff : 0,
|
||||
GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 3) ? 0xff : 0,
|
||||
};
|
||||
clear_rgba_buffer(ctx, rb, colormask);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called via the device driver's ctx->Driver.Clear() function if the
|
||||
* device driver can't clear one or more of the buffers itself.
|
||||
* \param buffers bitfield of BUFFER_BIT_* values indicating which
|
||||
* renderbuffers are to be cleared.
|
||||
* \param all if GL_TRUE, clear whole buffer, else clear specified region.
|
||||
*/
|
||||
void
|
||||
_swrast_Clear(struct gl_context *ctx, GLbitfield buffers)
|
||||
{
|
||||
const GLbitfield BUFFER_DS = BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL;
|
||||
|
||||
#ifdef DEBUG_FOO
|
||||
{
|
||||
const GLbitfield legalBits =
|
||||
BUFFER_BIT_FRONT_LEFT |
|
||||
BUFFER_BIT_FRONT_RIGHT |
|
||||
BUFFER_BIT_BACK_LEFT |
|
||||
BUFFER_BIT_BACK_RIGHT |
|
||||
BUFFER_BIT_DEPTH |
|
||||
BUFFER_BIT_STENCIL |
|
||||
BUFFER_BIT_ACCUM;
|
||||
assert((buffers & (~legalBits)) == 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!_mesa_check_conditional_render(ctx))
|
||||
return; /* don't clear */
|
||||
|
||||
if (SWRAST_CONTEXT(ctx)->NewState)
|
||||
_swrast_validate_derived(ctx);
|
||||
|
||||
if ((buffers & BUFFER_BITS_COLOR)
|
||||
&& (ctx->DrawBuffer->_NumColorDrawBuffers > 0)) {
|
||||
clear_color_buffers(ctx);
|
||||
}
|
||||
|
||||
if (buffers & BUFFER_BIT_ACCUM) {
|
||||
_mesa_clear_accum_buffer(ctx);
|
||||
}
|
||||
|
||||
if (buffers & BUFFER_DS) {
|
||||
struct gl_renderbuffer *depthRb =
|
||||
ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
|
||||
struct gl_renderbuffer *stencilRb =
|
||||
ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
|
||||
|
||||
if ((buffers & BUFFER_DS) == BUFFER_DS && depthRb == stencilRb) {
|
||||
/* clear depth and stencil together */
|
||||
_swrast_clear_depth_stencil_buffer(ctx);
|
||||
}
|
||||
else {
|
||||
/* clear depth, stencil separately */
|
||||
if (buffers & BUFFER_BIT_DEPTH) {
|
||||
_swrast_clear_depth_buffer(ctx);
|
||||
}
|
||||
if (buffers & BUFFER_BIT_STENCIL) {
|
||||
_swrast_clear_stencil_buffer(ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,953 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* Copyright (C) 1999-2008 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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@vmware.com> Brian Paul
|
||||
*/
|
||||
|
||||
#include "main/errors.h"
|
||||
|
||||
#include "main/bufferobj.h"
|
||||
#include "main/mtypes.h"
|
||||
#include "main/samplerobj.h"
|
||||
#include "main/state.h"
|
||||
#include "main/stencil.h"
|
||||
#include "main/teximage.h"
|
||||
#include "program/prog_parameter.h"
|
||||
#include "program/prog_statevars.h"
|
||||
#include "swrast.h"
|
||||
#include "s_blend.h"
|
||||
#include "s_context.h"
|
||||
#include "s_lines.h"
|
||||
#include "s_points.h"
|
||||
#include "s_span.h"
|
||||
#include "s_texfetch.h"
|
||||
#include "s_triangle.h"
|
||||
#include "s_texfilter.h"
|
||||
|
||||
|
||||
/**
|
||||
* Recompute the value of swrast->_RasterMask, etc. according to
|
||||
* the current context. The _RasterMask field can be easily tested by
|
||||
* drivers to determine certain basic GL state (does the primitive need
|
||||
* stenciling, logic-op, fog, etc?).
|
||||
*/
|
||||
static void
|
||||
_swrast_update_rasterflags( struct gl_context *ctx )
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
GLbitfield rasterMask = 0;
|
||||
GLuint i;
|
||||
|
||||
if (ctx->Color.AlphaEnabled) rasterMask |= ALPHATEST_BIT;
|
||||
if (ctx->Color.BlendEnabled) rasterMask |= BLEND_BIT;
|
||||
if (ctx->Depth.Test) rasterMask |= DEPTH_BIT;
|
||||
if (swrast->_FogEnabled) rasterMask |= FOG_BIT;
|
||||
if (ctx->Scissor.EnableFlags) rasterMask |= CLIP_BIT;
|
||||
if (_mesa_stencil_is_enabled(ctx)) rasterMask |= STENCIL_BIT;
|
||||
for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
|
||||
if (GET_COLORMASK(ctx->Color.ColorMask, i) != 0xf) {
|
||||
rasterMask |= MASKING_BIT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ctx->Color.ColorLogicOpEnabled) rasterMask |= LOGIC_OP_BIT;
|
||||
if (ctx->Texture._MaxEnabledTexImageUnit >= 0) rasterMask |= TEXTURE_BIT;
|
||||
if ( ctx->ViewportArray[0].X < 0
|
||||
|| ctx->ViewportArray[0].X + ctx->ViewportArray[0].Width > (GLfloat) ctx->DrawBuffer->Width
|
||||
|| ctx->ViewportArray[0].Y < 0
|
||||
|| ctx->ViewportArray[0].Y + ctx->ViewportArray[0].Height > (GLfloat) ctx->DrawBuffer->Height) {
|
||||
rasterMask |= CLIP_BIT;
|
||||
}
|
||||
|
||||
if (ctx->Query.CurrentOcclusionObject)
|
||||
rasterMask |= OCCLUSION_BIT;
|
||||
|
||||
|
||||
/* If we're not drawing to exactly one color buffer set the
|
||||
* MULTI_DRAW_BIT flag. Also set it if we're drawing to no
|
||||
* buffers or the RGBA or CI mask disables all writes.
|
||||
*/
|
||||
if (ctx->DrawBuffer->_NumColorDrawBuffers != 1) {
|
||||
/* more than one color buffer designated for writing (or zero buffers) */
|
||||
rasterMask |= MULTI_DRAW_BIT;
|
||||
}
|
||||
|
||||
for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
|
||||
if (GET_COLORMASK(ctx->Color.ColorMask, i) == 0) {
|
||||
rasterMask |= MULTI_DRAW_BIT; /* all RGBA channels disabled */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (_swrast_use_fragment_program(ctx)) {
|
||||
rasterMask |= FRAGPROG_BIT;
|
||||
}
|
||||
|
||||
if (_mesa_ati_fragment_shader_enabled(ctx)) {
|
||||
rasterMask |= ATIFRAGSHADER_BIT;
|
||||
}
|
||||
|
||||
#if CHAN_TYPE == GL_FLOAT
|
||||
if (ctx->Color.ClampFragmentColor == GL_TRUE) {
|
||||
rasterMask |= CLAMPING_BIT;
|
||||
}
|
||||
#endif
|
||||
|
||||
SWRAST_CONTEXT(ctx)->_RasterMask = rasterMask;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Examine polygon cull state to compute the _BackfaceCullSign field.
|
||||
* _BackfaceCullSign will be 0 if no culling, -1 if culling back-faces,
|
||||
* and 1 if culling front-faces. The Polygon FrontFace state also
|
||||
* factors in.
|
||||
*/
|
||||
static void
|
||||
_swrast_update_polygon( struct gl_context *ctx )
|
||||
{
|
||||
GLfloat backface_sign;
|
||||
|
||||
if (ctx->Polygon.CullFlag) {
|
||||
switch (ctx->Polygon.CullFaceMode) {
|
||||
case GL_BACK:
|
||||
backface_sign = -1.0F;
|
||||
break;
|
||||
case GL_FRONT:
|
||||
backface_sign = 1.0F;
|
||||
break;
|
||||
case GL_FRONT_AND_BACK:
|
||||
FALLTHROUGH;
|
||||
default:
|
||||
backface_sign = 0.0F;
|
||||
}
|
||||
}
|
||||
else {
|
||||
backface_sign = 0.0F;
|
||||
}
|
||||
|
||||
SWRAST_CONTEXT(ctx)->_BackfaceCullSign = backface_sign;
|
||||
|
||||
/* This is for front/back-face determination, but not for culling */
|
||||
SWRAST_CONTEXT(ctx)->_BackfaceSign
|
||||
= (ctx->Polygon.FrontFace == GL_CW) ? -1.0F : 1.0F;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Update the _PreferPixelFog field to indicate if we need to compute
|
||||
* fog blend factors (from the fog coords) per-fragment.
|
||||
*/
|
||||
static void
|
||||
_swrast_update_fog_hint( struct gl_context *ctx )
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
swrast->_PreferPixelFog = (!swrast->AllowVertexFog ||
|
||||
_swrast_use_fragment_program(ctx) ||
|
||||
(ctx->Hint.Fog == GL_NICEST &&
|
||||
swrast->AllowPixelFog));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Update the swrast->_TextureCombinePrimary flag.
|
||||
*/
|
||||
static void
|
||||
_swrast_update_texture_env( struct gl_context *ctx )
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
GLuint i;
|
||||
|
||||
swrast->_TextureCombinePrimary = GL_FALSE;
|
||||
|
||||
for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
|
||||
const struct gl_tex_env_combine_state *combine =
|
||||
ctx->Texture.FixedFuncUnit[i]._CurrentCombine;
|
||||
GLuint term;
|
||||
for (term = 0; term < combine->_NumArgsRGB; term++) {
|
||||
if (combine->SourceRGB[term] == GL_PRIMARY_COLOR) {
|
||||
swrast->_TextureCombinePrimary = GL_TRUE;
|
||||
return;
|
||||
}
|
||||
if (combine->SourceA[term] == GL_PRIMARY_COLOR) {
|
||||
swrast->_TextureCombinePrimary = GL_TRUE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine if we can defer texturing/shading until after Z/stencil
|
||||
* testing. This potentially allows us to skip texturing/shading for
|
||||
* lots of fragments.
|
||||
*/
|
||||
static void
|
||||
_swrast_update_deferred_texture(struct gl_context *ctx)
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
if (ctx->Color.AlphaEnabled) {
|
||||
/* alpha test depends on post-texture/shader colors */
|
||||
swrast->_DeferredTexture = GL_FALSE;
|
||||
}
|
||||
else {
|
||||
GLboolean use_fprog = _swrast_use_fragment_program(ctx);
|
||||
const struct gl_program *fprog = ctx->FragmentProgram._Current;
|
||||
if (use_fprog &&
|
||||
(fprog->info.outputs_written & (1 << FRAG_RESULT_DEPTH))) {
|
||||
/* Z comes from fragment program/shader */
|
||||
swrast->_DeferredTexture = GL_FALSE;
|
||||
}
|
||||
else if (use_fprog && fprog->info.fs.uses_discard) {
|
||||
swrast->_DeferredTexture = GL_FALSE;
|
||||
}
|
||||
else if (ctx->Query.CurrentOcclusionObject) {
|
||||
/* occlusion query depends on shader discard/kill results */
|
||||
swrast->_DeferredTexture = GL_FALSE;
|
||||
}
|
||||
else {
|
||||
swrast->_DeferredTexture = GL_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update swrast->_FogColor and swrast->_FogEnable values.
|
||||
*/
|
||||
static void
|
||||
_swrast_update_fog_state( struct gl_context *ctx )
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
const struct gl_program *fp = ctx->FragmentProgram._Current;
|
||||
|
||||
assert(fp == NULL || fp->Target == GL_FRAGMENT_PROGRAM_ARB);
|
||||
(void) fp; /* silence unused var warning */
|
||||
|
||||
/* determine if fog is needed, and if so, which fog mode */
|
||||
swrast->_FogEnabled = (!_swrast_use_fragment_program(ctx) &&
|
||||
ctx->Fog.Enabled);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update state for running fragment programs. Basically, load the
|
||||
* program parameters with current state values.
|
||||
*/
|
||||
static void
|
||||
_swrast_update_fragment_program(struct gl_context *ctx, GLbitfield newState)
|
||||
{
|
||||
if (!_swrast_use_fragment_program(ctx))
|
||||
return;
|
||||
|
||||
_mesa_load_state_parameters(ctx,
|
||||
ctx->FragmentProgram._Current->Parameters);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* See if we can do early diffuse+specular (primary+secondary) color
|
||||
* add per vertex instead of per-fragment.
|
||||
*/
|
||||
static void
|
||||
_swrast_update_specular_vertex_add(struct gl_context *ctx)
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
GLboolean separateSpecular = ctx->Fog.ColorSumEnabled ||
|
||||
(ctx->Light.Enabled &&
|
||||
ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR);
|
||||
|
||||
swrast->SpecularVertexAdd = (separateSpecular
|
||||
&& ctx->Texture._MaxEnabledTexImageUnit == -1
|
||||
&& !_swrast_use_fragment_program(ctx)
|
||||
&& !_mesa_ati_fragment_shader_enabled(ctx));
|
||||
}
|
||||
|
||||
|
||||
#define _SWRAST_NEW_DERIVED (_SWRAST_NEW_RASTERMASK | \
|
||||
_NEW_PROGRAM_CONSTANTS | \
|
||||
_NEW_TEXTURE | \
|
||||
_NEW_HINT | \
|
||||
_NEW_POLYGON )
|
||||
|
||||
/* State referenced by _swrast_choose_triangle, _swrast_choose_line.
|
||||
*/
|
||||
#define _SWRAST_NEW_TRIANGLE (_SWRAST_NEW_DERIVED | \
|
||||
_NEW_RENDERMODE| \
|
||||
_NEW_POLYGON| \
|
||||
_NEW_DEPTH| \
|
||||
_NEW_STENCIL| \
|
||||
_NEW_COLOR| \
|
||||
_NEW_TEXTURE| \
|
||||
_SWRAST_NEW_RASTERMASK| \
|
||||
_NEW_LIGHT| \
|
||||
_NEW_FOG | \
|
||||
_MESA_NEW_SEPARATE_SPECULAR)
|
||||
|
||||
#define _SWRAST_NEW_LINE (_SWRAST_NEW_DERIVED | \
|
||||
_NEW_RENDERMODE| \
|
||||
_NEW_LINE| \
|
||||
_NEW_TEXTURE| \
|
||||
_NEW_LIGHT| \
|
||||
_NEW_FOG| \
|
||||
_NEW_DEPTH | \
|
||||
_MESA_NEW_SEPARATE_SPECULAR)
|
||||
|
||||
#define _SWRAST_NEW_POINT (_SWRAST_NEW_DERIVED | \
|
||||
_NEW_RENDERMODE | \
|
||||
_NEW_POINT | \
|
||||
_NEW_TEXTURE | \
|
||||
_NEW_LIGHT | \
|
||||
_NEW_FOG | \
|
||||
_MESA_NEW_SEPARATE_SPECULAR)
|
||||
|
||||
#define _SWRAST_NEW_TEXTURE_SAMPLE_FUNC _NEW_TEXTURE
|
||||
|
||||
#define _SWRAST_NEW_TEXTURE_ENV_MODE _NEW_TEXTURE
|
||||
|
||||
#define _SWRAST_NEW_BLEND_FUNC _NEW_COLOR
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Stub for swrast->Triangle to select a true triangle function
|
||||
* after a state change.
|
||||
*/
|
||||
static void
|
||||
_swrast_validate_triangle( struct gl_context *ctx,
|
||||
const SWvertex *v0,
|
||||
const SWvertex *v1,
|
||||
const SWvertex *v2 )
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
|
||||
_swrast_validate_derived( ctx );
|
||||
swrast->choose_triangle( ctx );
|
||||
assert(swrast->Triangle);
|
||||
|
||||
if (swrast->SpecularVertexAdd) {
|
||||
/* separate specular color, but no texture */
|
||||
swrast->SpecTriangle = swrast->Triangle;
|
||||
swrast->Triangle = _swrast_add_spec_terms_triangle;
|
||||
}
|
||||
|
||||
swrast->Triangle( ctx, v0, v1, v2 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Called via swrast->Line. Examine current GL state and choose a software
|
||||
* line routine. Then call it.
|
||||
*/
|
||||
static void
|
||||
_swrast_validate_line( struct gl_context *ctx, const SWvertex *v0, const SWvertex *v1 )
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
|
||||
_swrast_validate_derived( ctx );
|
||||
swrast->choose_line( ctx );
|
||||
assert(swrast->Line);
|
||||
|
||||
if (swrast->SpecularVertexAdd) {
|
||||
swrast->SpecLine = swrast->Line;
|
||||
swrast->Line = _swrast_add_spec_terms_line;
|
||||
}
|
||||
|
||||
swrast->Line( ctx, v0, v1 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Called via swrast->Point. Examine current GL state and choose a software
|
||||
* point routine. Then call it.
|
||||
*/
|
||||
static void
|
||||
_swrast_validate_point( struct gl_context *ctx, const SWvertex *v0 )
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
|
||||
_swrast_validate_derived( ctx );
|
||||
swrast->choose_point( ctx );
|
||||
|
||||
if (swrast->SpecularVertexAdd) {
|
||||
swrast->SpecPoint = swrast->Point;
|
||||
swrast->Point = _swrast_add_spec_terms_point;
|
||||
}
|
||||
|
||||
swrast->Point( ctx, v0 );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called via swrast->BlendFunc. Examine GL state to choose a blending
|
||||
* function, then call it.
|
||||
*/
|
||||
static void
|
||||
_swrast_validate_blend_func(struct gl_context *ctx, GLuint n, const GLubyte mask[],
|
||||
GLvoid *src, const GLvoid *dst,
|
||||
GLenum chanType )
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
|
||||
_swrast_validate_derived( ctx ); /* why is this needed? */
|
||||
_swrast_choose_blend_func( ctx, chanType );
|
||||
|
||||
swrast->BlendFunc( ctx, n, mask, src, dst, chanType );
|
||||
}
|
||||
|
||||
static void
|
||||
_swrast_sleep( struct gl_context *ctx, GLbitfield new_state )
|
||||
{
|
||||
(void) ctx; (void) new_state;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
_swrast_invalidate_state( struct gl_context *ctx, GLbitfield new_state )
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
GLuint i;
|
||||
|
||||
swrast->NewState |= new_state;
|
||||
|
||||
/* After 10 statechanges without any swrast functions being called,
|
||||
* put the module to sleep.
|
||||
*/
|
||||
if (++swrast->StateChanges > 10) {
|
||||
swrast->InvalidateState = _swrast_sleep;
|
||||
swrast->NewState = ~0;
|
||||
new_state = ~0;
|
||||
}
|
||||
|
||||
if (new_state & swrast->InvalidateTriangleMask)
|
||||
swrast->Triangle = _swrast_validate_triangle;
|
||||
|
||||
if (new_state & swrast->InvalidateLineMask)
|
||||
swrast->Line = _swrast_validate_line;
|
||||
|
||||
if (new_state & swrast->InvalidatePointMask)
|
||||
swrast->Point = _swrast_validate_point;
|
||||
|
||||
if (new_state & _SWRAST_NEW_BLEND_FUNC)
|
||||
swrast->BlendFunc = _swrast_validate_blend_func;
|
||||
|
||||
if (new_state & _SWRAST_NEW_TEXTURE_SAMPLE_FUNC)
|
||||
for (i = 0 ; i < ARRAY_SIZE(swrast->TextureSample); i++)
|
||||
swrast->TextureSample[i] = NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_swrast_update_texture_samplers(struct gl_context *ctx)
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
GLuint u;
|
||||
|
||||
if (!swrast)
|
||||
return; /* pipe hack */
|
||||
|
||||
for (u = 0; u < ARRAY_SIZE(swrast->TextureSample); u++) {
|
||||
struct gl_texture_object *tObj = ctx->Texture.Unit[u]._Current;
|
||||
/* Note: If tObj is NULL, the sample function will be a simple
|
||||
* function that just returns opaque black (0,0,0,1).
|
||||
*/
|
||||
_mesa_update_fetch_functions(ctx, u);
|
||||
swrast->TextureSample[u] =
|
||||
_swrast_choose_texture_sample_func(ctx, tObj,
|
||||
_mesa_get_samplerobj(ctx, u));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update swrast->_ActiveAttribs, swrast->_NumActiveAttribs,
|
||||
* swrast->_ActiveAtttribMask.
|
||||
*/
|
||||
static void
|
||||
_swrast_update_active_attribs(struct gl_context *ctx)
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
GLbitfield64 attribsMask;
|
||||
|
||||
/*
|
||||
* Compute _ActiveAttribsMask = which fragment attributes are needed.
|
||||
*/
|
||||
if (_swrast_use_fragment_program(ctx)) {
|
||||
/* fragment program/shader */
|
||||
attribsMask = ctx->FragmentProgram._Current->info.inputs_read;
|
||||
attribsMask &= ~VARYING_BIT_POS; /* WPOS is always handled specially */
|
||||
}
|
||||
else if (_mesa_ati_fragment_shader_enabled(ctx)) {
|
||||
attribsMask = VARYING_BIT_COL0 | VARYING_BIT_COL1 |
|
||||
VARYING_BIT_FOGC | VARYING_BITS_TEX_ANY;
|
||||
}
|
||||
else {
|
||||
/* fixed function */
|
||||
attribsMask = 0x0;
|
||||
|
||||
#if CHAN_TYPE == GL_FLOAT
|
||||
attribsMask |= VARYING_BIT_COL0;
|
||||
#endif
|
||||
|
||||
if (ctx->Fog.ColorSumEnabled ||
|
||||
(ctx->Light.Enabled &&
|
||||
ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) {
|
||||
attribsMask |= VARYING_BIT_COL1;
|
||||
}
|
||||
|
||||
if (swrast->_FogEnabled)
|
||||
attribsMask |= VARYING_BIT_FOGC;
|
||||
|
||||
attribsMask |= (ctx->Texture._EnabledCoordUnits << VARYING_SLOT_TEX0);
|
||||
}
|
||||
|
||||
swrast->_ActiveAttribMask = attribsMask;
|
||||
|
||||
/* Update _ActiveAttribs[] list */
|
||||
{
|
||||
GLuint i, num = 0;
|
||||
for (i = 0; i < VARYING_SLOT_MAX; i++) {
|
||||
if (attribsMask & BITFIELD64_BIT(i)) {
|
||||
swrast->_ActiveAttribs[num++] = i;
|
||||
/* how should this attribute be interpolated? */
|
||||
if (i == VARYING_SLOT_COL0 || i == VARYING_SLOT_COL1)
|
||||
swrast->_InterpMode[i] = ctx->Light.ShadeModel;
|
||||
else
|
||||
swrast->_InterpMode[i] = GL_SMOOTH;
|
||||
}
|
||||
}
|
||||
swrast->_NumActiveAttribs = num;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_swrast_validate_derived( struct gl_context *ctx )
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
|
||||
if (swrast->NewState) {
|
||||
if (swrast->NewState & _NEW_POLYGON)
|
||||
_swrast_update_polygon( ctx );
|
||||
|
||||
if (swrast->NewState & (_NEW_HINT | _NEW_PROGRAM))
|
||||
_swrast_update_fog_hint( ctx );
|
||||
|
||||
if (swrast->NewState & _SWRAST_NEW_TEXTURE_ENV_MODE)
|
||||
_swrast_update_texture_env( ctx );
|
||||
|
||||
if (swrast->NewState & (_NEW_FOG | _NEW_PROGRAM))
|
||||
_swrast_update_fog_state( ctx );
|
||||
|
||||
if (swrast->NewState & (_NEW_PROGRAM_CONSTANTS | _NEW_PROGRAM))
|
||||
_swrast_update_fragment_program( ctx, swrast->NewState );
|
||||
|
||||
if (swrast->NewState & (_NEW_TEXTURE | _NEW_PROGRAM)) {
|
||||
_swrast_update_texture_samplers( ctx );
|
||||
}
|
||||
|
||||
if (swrast->NewState & (_NEW_COLOR | _NEW_PROGRAM))
|
||||
_swrast_update_deferred_texture(ctx);
|
||||
|
||||
if (swrast->NewState & _SWRAST_NEW_RASTERMASK)
|
||||
_swrast_update_rasterflags( ctx );
|
||||
|
||||
if (swrast->NewState & (_NEW_DEPTH |
|
||||
_NEW_FOG |
|
||||
_NEW_LIGHT |
|
||||
_NEW_PROGRAM |
|
||||
_NEW_TEXTURE))
|
||||
_swrast_update_active_attribs(ctx);
|
||||
|
||||
if (swrast->NewState & (_NEW_FOG |
|
||||
_NEW_PROGRAM |
|
||||
_NEW_LIGHT |
|
||||
_NEW_TEXTURE))
|
||||
_swrast_update_specular_vertex_add(ctx);
|
||||
|
||||
swrast->NewState = 0;
|
||||
swrast->StateChanges = 0;
|
||||
swrast->InvalidateState = _swrast_invalidate_state;
|
||||
}
|
||||
}
|
||||
|
||||
#define SWRAST_DEBUG 0
|
||||
|
||||
/* Public entrypoints: See also s_bitmap.c, etc.
|
||||
*/
|
||||
void
|
||||
_swrast_Quad( struct gl_context *ctx,
|
||||
const SWvertex *v0, const SWvertex *v1,
|
||||
const SWvertex *v2, const SWvertex *v3 )
|
||||
{
|
||||
if (SWRAST_DEBUG) {
|
||||
_mesa_debug(ctx, "_swrast_Quad\n");
|
||||
_swrast_print_vertex( ctx, v0 );
|
||||
_swrast_print_vertex( ctx, v1 );
|
||||
_swrast_print_vertex( ctx, v2 );
|
||||
_swrast_print_vertex( ctx, v3 );
|
||||
}
|
||||
SWRAST_CONTEXT(ctx)->Triangle( ctx, v0, v1, v3 );
|
||||
SWRAST_CONTEXT(ctx)->Triangle( ctx, v1, v2, v3 );
|
||||
}
|
||||
|
||||
void
|
||||
_swrast_Triangle( struct gl_context *ctx, const SWvertex *v0,
|
||||
const SWvertex *v1, const SWvertex *v2 )
|
||||
{
|
||||
if (SWRAST_DEBUG) {
|
||||
_mesa_debug(ctx, "_swrast_Triangle\n");
|
||||
_swrast_print_vertex( ctx, v0 );
|
||||
_swrast_print_vertex( ctx, v1 );
|
||||
_swrast_print_vertex( ctx, v2 );
|
||||
}
|
||||
SWRAST_CONTEXT(ctx)->Triangle( ctx, v0, v1, v2 );
|
||||
}
|
||||
|
||||
void
|
||||
_swrast_Line( struct gl_context *ctx, const SWvertex *v0, const SWvertex *v1 )
|
||||
{
|
||||
if (SWRAST_DEBUG) {
|
||||
_mesa_debug(ctx, "_swrast_Line\n");
|
||||
_swrast_print_vertex( ctx, v0 );
|
||||
_swrast_print_vertex( ctx, v1 );
|
||||
}
|
||||
SWRAST_CONTEXT(ctx)->Line( ctx, v0, v1 );
|
||||
}
|
||||
|
||||
void
|
||||
_swrast_Point( struct gl_context *ctx, const SWvertex *v0 )
|
||||
{
|
||||
if (SWRAST_DEBUG) {
|
||||
_mesa_debug(ctx, "_swrast_Point\n");
|
||||
_swrast_print_vertex( ctx, v0 );
|
||||
}
|
||||
SWRAST_CONTEXT(ctx)->Point( ctx, v0 );
|
||||
}
|
||||
|
||||
void
|
||||
_swrast_InvalidateState( struct gl_context *ctx, GLbitfield new_state )
|
||||
{
|
||||
if (SWRAST_DEBUG) {
|
||||
_mesa_debug(ctx, "_swrast_InvalidateState\n");
|
||||
}
|
||||
SWRAST_CONTEXT(ctx)->InvalidateState( ctx, new_state );
|
||||
}
|
||||
|
||||
void
|
||||
_swrast_ResetLineStipple( struct gl_context *ctx )
|
||||
{
|
||||
if (SWRAST_DEBUG) {
|
||||
_mesa_debug(ctx, "_swrast_ResetLineStipple\n");
|
||||
}
|
||||
SWRAST_CONTEXT(ctx)->StippleCounter = 0;
|
||||
}
|
||||
|
||||
void
|
||||
_swrast_SetFacing(struct gl_context *ctx, GLuint facing)
|
||||
{
|
||||
SWRAST_CONTEXT(ctx)->PointLineFacing = facing;
|
||||
}
|
||||
|
||||
void
|
||||
_swrast_allow_vertex_fog( struct gl_context *ctx, GLboolean value )
|
||||
{
|
||||
if (SWRAST_DEBUG) {
|
||||
_mesa_debug(ctx, "_swrast_allow_vertex_fog %d\n", value);
|
||||
}
|
||||
SWRAST_CONTEXT(ctx)->InvalidateState( ctx, _NEW_HINT );
|
||||
SWRAST_CONTEXT(ctx)->AllowVertexFog = value;
|
||||
}
|
||||
|
||||
void
|
||||
_swrast_allow_pixel_fog( struct gl_context *ctx, GLboolean value )
|
||||
{
|
||||
if (SWRAST_DEBUG) {
|
||||
_mesa_debug(ctx, "_swrast_allow_pixel_fog %d\n", value);
|
||||
}
|
||||
SWRAST_CONTEXT(ctx)->InvalidateState( ctx, _NEW_HINT );
|
||||
SWRAST_CONTEXT(ctx)->AllowPixelFog = value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize native program limits by copying the logical limits.
|
||||
* See comments in init_program_limits() in context.c
|
||||
*/
|
||||
static void
|
||||
init_program_native_limits(struct gl_program_constants *prog)
|
||||
{
|
||||
prog->MaxNativeInstructions = prog->MaxInstructions;
|
||||
prog->MaxNativeAluInstructions = prog->MaxAluInstructions;
|
||||
prog->MaxNativeTexInstructions = prog->MaxTexInstructions;
|
||||
prog->MaxNativeTexIndirections = prog->MaxTexIndirections;
|
||||
prog->MaxNativeAttribs = prog->MaxAttribs;
|
||||
prog->MaxNativeTemps = prog->MaxTemps;
|
||||
prog->MaxNativeAddressRegs = prog->MaxAddressRegs;
|
||||
prog->MaxNativeParameters = prog->MaxParameters;
|
||||
}
|
||||
|
||||
|
||||
GLboolean
|
||||
_swrast_CreateContext( struct gl_context *ctx )
|
||||
{
|
||||
GLuint i;
|
||||
SWcontext *swrast = calloc(1, sizeof(SWcontext));
|
||||
#ifdef _OPENMP
|
||||
const GLuint maxThreads = omp_get_max_threads();
|
||||
#else
|
||||
const GLuint maxThreads = 1;
|
||||
#endif
|
||||
|
||||
assert(ctx->Const.MaxViewportWidth <= SWRAST_MAX_WIDTH);
|
||||
assert(ctx->Const.MaxViewportHeight <= SWRAST_MAX_WIDTH);
|
||||
|
||||
assert(ctx->Const.MaxRenderbufferSize <= SWRAST_MAX_WIDTH);
|
||||
|
||||
/* make sure largest texture image is <= SWRAST_MAX_WIDTH in size */
|
||||
assert(ctx->Const.MaxTextureSize <= SWRAST_MAX_WIDTH);
|
||||
assert((1 << (ctx->Const.MaxCubeTextureLevels - 1)) <= SWRAST_MAX_WIDTH);
|
||||
assert((1 << (ctx->Const.Max3DTextureLevels - 1)) <= SWRAST_MAX_WIDTH);
|
||||
|
||||
assert(PROG_MAX_WIDTH == SWRAST_MAX_WIDTH);
|
||||
|
||||
if (SWRAST_DEBUG) {
|
||||
_mesa_debug(ctx, "_swrast_CreateContext\n");
|
||||
}
|
||||
|
||||
if (!swrast)
|
||||
return GL_FALSE;
|
||||
|
||||
swrast->NewState = ~0;
|
||||
|
||||
swrast->choose_point = _swrast_choose_point;
|
||||
swrast->choose_line = _swrast_choose_line;
|
||||
swrast->choose_triangle = _swrast_choose_triangle;
|
||||
|
||||
swrast->InvalidatePointMask = _SWRAST_NEW_POINT;
|
||||
swrast->InvalidateLineMask = _SWRAST_NEW_LINE;
|
||||
swrast->InvalidateTriangleMask = _SWRAST_NEW_TRIANGLE;
|
||||
|
||||
swrast->Point = _swrast_validate_point;
|
||||
swrast->Line = _swrast_validate_line;
|
||||
swrast->Triangle = _swrast_validate_triangle;
|
||||
swrast->InvalidateState = _swrast_sleep;
|
||||
swrast->BlendFunc = _swrast_validate_blend_func;
|
||||
|
||||
swrast->AllowVertexFog = GL_TRUE;
|
||||
swrast->AllowPixelFog = GL_TRUE;
|
||||
|
||||
swrast->Driver.SpanRenderStart = _swrast_span_render_start;
|
||||
swrast->Driver.SpanRenderFinish = _swrast_span_render_finish;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(swrast->TextureSample); i++)
|
||||
swrast->TextureSample[i] = NULL;
|
||||
|
||||
/* SpanArrays is global and shared by all SWspan instances. However, when
|
||||
* using multiple threads, it is necessary to have one SpanArrays instance
|
||||
* per thread.
|
||||
*/
|
||||
swrast->SpanArrays = malloc(maxThreads * sizeof(SWspanarrays));
|
||||
if (!swrast->SpanArrays) {
|
||||
free(swrast);
|
||||
return GL_FALSE;
|
||||
}
|
||||
for(i = 0; i < maxThreads; i++) {
|
||||
swrast->SpanArrays[i].ChanType = CHAN_TYPE;
|
||||
#if CHAN_TYPE == GL_UNSIGNED_BYTE
|
||||
swrast->SpanArrays[i].rgba = swrast->SpanArrays[i].rgba8;
|
||||
#elif CHAN_TYPE == GL_UNSIGNED_SHORT
|
||||
swrast->SpanArrays[i].rgba = swrast->SpanArrays[i].rgba16;
|
||||
#else
|
||||
swrast->SpanArrays[i].rgba = swrast->SpanArrays[i].attribs[VARYING_SLOT_COL0];
|
||||
#endif
|
||||
}
|
||||
|
||||
/* init point span buffer */
|
||||
swrast->PointSpan.primitive = GL_POINT;
|
||||
swrast->PointSpan.end = 0;
|
||||
swrast->PointSpan.facing = 0;
|
||||
swrast->PointSpan.array = swrast->SpanArrays;
|
||||
|
||||
init_program_native_limits(&ctx->Const.Program[MESA_SHADER_VERTEX]);
|
||||
init_program_native_limits(&ctx->Const.Program[MESA_SHADER_GEOMETRY]);
|
||||
init_program_native_limits(&ctx->Const.Program[MESA_SHADER_FRAGMENT]);
|
||||
|
||||
ctx->swrast_context = swrast;
|
||||
|
||||
swrast->stencil_temp.buf1 = malloc(SWRAST_MAX_WIDTH * sizeof(GLubyte));
|
||||
swrast->stencil_temp.buf2 = malloc(SWRAST_MAX_WIDTH * sizeof(GLubyte));
|
||||
swrast->stencil_temp.buf3 = malloc(SWRAST_MAX_WIDTH * sizeof(GLubyte));
|
||||
swrast->stencil_temp.buf4 = malloc(SWRAST_MAX_WIDTH * sizeof(GLubyte));
|
||||
|
||||
if (!swrast->stencil_temp.buf1 ||
|
||||
!swrast->stencil_temp.buf2 ||
|
||||
!swrast->stencil_temp.buf3 ||
|
||||
!swrast->stencil_temp.buf4) {
|
||||
_swrast_DestroyContext(ctx);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
_swrast_DestroyContext( struct gl_context *ctx )
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
|
||||
if (SWRAST_DEBUG) {
|
||||
_mesa_debug(ctx, "_swrast_DestroyContext\n");
|
||||
}
|
||||
|
||||
free( swrast->SpanArrays );
|
||||
free( swrast->ZoomedArrays );
|
||||
free( swrast->TexelBuffer );
|
||||
|
||||
free(swrast->stencil_temp.buf1);
|
||||
free(swrast->stencil_temp.buf2);
|
||||
free(swrast->stencil_temp.buf3);
|
||||
free(swrast->stencil_temp.buf4);
|
||||
|
||||
free( swrast );
|
||||
|
||||
ctx->swrast_context = 0;
|
||||
}
|
||||
|
||||
|
||||
struct swrast_device_driver *
|
||||
_swrast_GetDeviceDriverReference( struct gl_context *ctx )
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
return &swrast->Driver;
|
||||
}
|
||||
|
||||
void
|
||||
_swrast_flush( struct gl_context *ctx )
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
/* flush any pending fragments from rendering points */
|
||||
if (swrast->PointSpan.end > 0) {
|
||||
_swrast_write_rgba_span(ctx, &(swrast->PointSpan));
|
||||
swrast->PointSpan.end = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_swrast_render_primitive( struct gl_context *ctx, GLenum prim )
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
if (swrast->Primitive == GL_POINTS && prim != GL_POINTS) {
|
||||
_swrast_flush(ctx);
|
||||
}
|
||||
swrast->Primitive = prim;
|
||||
}
|
||||
|
||||
|
||||
/** called via swrast->Driver.SpanRenderStart() */
|
||||
void
|
||||
_swrast_span_render_start(struct gl_context *ctx)
|
||||
{
|
||||
_swrast_map_textures(ctx);
|
||||
_swrast_map_renderbuffers(ctx);
|
||||
}
|
||||
|
||||
|
||||
/** called via swrast->Driver.SpanRenderFinish() */
|
||||
void
|
||||
_swrast_span_render_finish(struct gl_context *ctx)
|
||||
{
|
||||
_swrast_unmap_textures(ctx);
|
||||
_swrast_unmap_renderbuffers(ctx);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_swrast_render_start( struct gl_context *ctx )
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
if (swrast->Driver.SpanRenderStart)
|
||||
swrast->Driver.SpanRenderStart( ctx );
|
||||
swrast->PointSpan.end = 0;
|
||||
}
|
||||
|
||||
void
|
||||
_swrast_render_finish( struct gl_context *ctx )
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
struct gl_query_object *query = ctx->Query.CurrentOcclusionObject;
|
||||
|
||||
_swrast_flush(ctx);
|
||||
|
||||
if (swrast->Driver.SpanRenderFinish)
|
||||
swrast->Driver.SpanRenderFinish( ctx );
|
||||
|
||||
if (query && (query->Target == GL_ANY_SAMPLES_PASSED ||
|
||||
query->Target == GL_ANY_SAMPLES_PASSED_CONSERVATIVE))
|
||||
query->Result = !!query->Result;
|
||||
}
|
||||
|
||||
|
||||
#define SWRAST_DEBUG_VERTICES 0
|
||||
|
||||
void
|
||||
_swrast_print_vertex( struct gl_context *ctx, const SWvertex *v )
|
||||
{
|
||||
GLuint i;
|
||||
|
||||
if (SWRAST_DEBUG_VERTICES) {
|
||||
_mesa_debug(ctx, "win %f %f %f %f\n",
|
||||
v->attrib[VARYING_SLOT_POS][0],
|
||||
v->attrib[VARYING_SLOT_POS][1],
|
||||
v->attrib[VARYING_SLOT_POS][2],
|
||||
v->attrib[VARYING_SLOT_POS][3]);
|
||||
|
||||
for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++)
|
||||
if (ctx->Texture.Unit[i]._Current)
|
||||
_mesa_debug(ctx, "texcoord[%d] %f %f %f %f\n", i,
|
||||
v->attrib[VARYING_SLOT_TEX0 + i][0],
|
||||
v->attrib[VARYING_SLOT_TEX0 + i][1],
|
||||
v->attrib[VARYING_SLOT_TEX0 + i][2],
|
||||
v->attrib[VARYING_SLOT_TEX0 + i][3]);
|
||||
|
||||
#if CHAN_TYPE == GL_FLOAT
|
||||
_mesa_debug(ctx, "color %f %f %f %f\n",
|
||||
v->color[0], v->color[1], v->color[2], v->color[3]);
|
||||
#else
|
||||
_mesa_debug(ctx, "color %d %d %d %d\n",
|
||||
v->color[0], v->color[1], v->color[2], v->color[3]);
|
||||
#endif
|
||||
_mesa_debug(ctx, "spec %g %g %g %g\n",
|
||||
v->attrib[VARYING_SLOT_COL1][0],
|
||||
v->attrib[VARYING_SLOT_COL1][1],
|
||||
v->attrib[VARYING_SLOT_COL1][2],
|
||||
v->attrib[VARYING_SLOT_COL1][3]);
|
||||
_mesa_debug(ctx, "fog %f\n", v->attrib[VARYING_SLOT_FOGC][0]);
|
||||
_mesa_debug(ctx, "index %f\n", v->attrib[VARYING_SLOT_CI][0]);
|
||||
_mesa_debug(ctx, "pointsize %f\n", v->pointSize);
|
||||
_mesa_debug(ctx, "\n");
|
||||
}
|
||||
}
|
|
@ -1,499 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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 swrast/s_context.h
|
||||
* \brief Software rasterization context and private types.
|
||||
* \author Keith Whitwell <keithw@vmware.com>
|
||||
*/
|
||||
|
||||
/**
|
||||
* \mainpage swrast module
|
||||
*
|
||||
* This module, software rasterization, contains the software fallback
|
||||
* routines for drawing points, lines, triangles, bitmaps and images.
|
||||
* All rendering boils down to writing spans (arrays) of pixels with
|
||||
* particular colors. The span-writing routines must be implemented
|
||||
* by the device driver.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef S_CONTEXT_H
|
||||
#define S_CONTEXT_H
|
||||
|
||||
#include "main/mtypes.h"
|
||||
#include "main/texcompress.h"
|
||||
#include "program/prog_execute.h"
|
||||
#include "swrast.h"
|
||||
#include "s_fragprog.h"
|
||||
#include "s_span.h"
|
||||
#include "util/rounding.h"
|
||||
|
||||
|
||||
typedef void (*texture_sample_func)(struct gl_context *ctx,
|
||||
const struct gl_sampler_object *samp,
|
||||
const struct gl_texture_object *tObj,
|
||||
GLuint n, const GLfloat texcoords[][4],
|
||||
const GLfloat lambda[], GLfloat rgba[][4]);
|
||||
|
||||
typedef void (*swrast_blend_func)(struct gl_context *ctx, GLuint n,
|
||||
const GLubyte mask[],
|
||||
GLvoid *src, const GLvoid *dst,
|
||||
GLenum chanType);
|
||||
|
||||
typedef void (*swrast_point_func)( struct gl_context *ctx, const SWvertex *);
|
||||
|
||||
typedef void (*swrast_line_func)( struct gl_context *ctx,
|
||||
const SWvertex *, const SWvertex *);
|
||||
|
||||
typedef void (*swrast_tri_func)( struct gl_context *ctx, const SWvertex *,
|
||||
const SWvertex *, const SWvertex *);
|
||||
|
||||
|
||||
typedef void (*validate_texture_image_func)(struct gl_context *ctx,
|
||||
struct gl_texture_object *texObj,
|
||||
GLuint face, GLuint level);
|
||||
|
||||
|
||||
/**
|
||||
* \defgroup Bitmasks
|
||||
* Bitmasks to indicate which rasterization options are enabled
|
||||
* (RasterMask)
|
||||
*/
|
||||
/*@{*/
|
||||
#define ALPHATEST_BIT 0x001 /**< Alpha-test pixels */
|
||||
#define BLEND_BIT 0x002 /**< Blend pixels */
|
||||
#define DEPTH_BIT 0x004 /**< Depth-test pixels */
|
||||
#define FOG_BIT 0x008 /**< Fog pixels */
|
||||
#define LOGIC_OP_BIT 0x010 /**< Apply logic op in software */
|
||||
#define CLIP_BIT 0x020 /**< Scissor or window clip pixels */
|
||||
#define STENCIL_BIT 0x040 /**< Stencil pixels */
|
||||
#define MASKING_BIT 0x080 /**< Do glColorMask or glIndexMask */
|
||||
#define MULTI_DRAW_BIT 0x400 /**< Write to more than one color- */
|
||||
/**< buffer or no buffers. */
|
||||
#define OCCLUSION_BIT 0x800 /**< GL_HP_occlusion_test enabled */
|
||||
#define TEXTURE_BIT 0x1000 /**< Texturing really enabled */
|
||||
#define FRAGPROG_BIT 0x2000 /**< Fragment program enabled */
|
||||
#define ATIFRAGSHADER_BIT 0x4000 /**< ATI Fragment shader enabled */
|
||||
#define CLAMPING_BIT 0x8000 /**< Clamp colors to [0,1] */
|
||||
/*@}*/
|
||||
|
||||
#define _SWRAST_NEW_RASTERMASK (_NEW_BUFFERS| \
|
||||
_NEW_SCISSOR| \
|
||||
_NEW_COLOR| \
|
||||
_NEW_DEPTH| \
|
||||
_NEW_FOG| \
|
||||
_NEW_PROGRAM| \
|
||||
_NEW_STENCIL| \
|
||||
_NEW_TEXTURE| \
|
||||
_NEW_VIEWPORT| \
|
||||
_NEW_DEPTH)
|
||||
|
||||
|
||||
struct swrast_texture_image;
|
||||
|
||||
|
||||
/**
|
||||
* Fetch a texel from texture image at given position.
|
||||
*/
|
||||
typedef void (*FetchTexelFunc)(const struct swrast_texture_image *texImage,
|
||||
GLint col, GLint row, GLint img,
|
||||
GLfloat *texelOut);
|
||||
|
||||
|
||||
/**
|
||||
* Subclass of gl_texture_image.
|
||||
* We need extra fields/info to keep tracking of mapped texture buffers,
|
||||
* strides and Fetch functions.
|
||||
*/
|
||||
struct swrast_texture_image
|
||||
{
|
||||
struct gl_texture_image Base;
|
||||
|
||||
GLboolean _IsPowerOfTwo; /**< Are all dimensions powers of two? */
|
||||
|
||||
/** used for mipmap LOD computation */
|
||||
GLfloat WidthScale, HeightScale, DepthScale;
|
||||
|
||||
/**
|
||||
* Byte stride between rows in ImageSlices.
|
||||
*
|
||||
* For compressed textures, this is the byte stride between one row of
|
||||
* blocks and the next row of blocks.
|
||||
*
|
||||
* Only valid while one of the ImageSlices is mapped, and must be the same
|
||||
* between all slices.
|
||||
*/
|
||||
GLint RowStride;
|
||||
/**
|
||||
* When a texture image is mapped for swrast, this array contains pointers
|
||||
* to the beginning of each slice.
|
||||
*
|
||||
* For swrast-allocated textures, these pointers will always stay
|
||||
* initialized to point within Buffer.
|
||||
*/
|
||||
void **ImageSlices;
|
||||
|
||||
/** Malloc'd texture memory */
|
||||
GLubyte *Buffer;
|
||||
|
||||
FetchTexelFunc FetchTexel;
|
||||
|
||||
/** For fetching texels from compressed textures */
|
||||
compressed_fetch_func FetchCompressedTexel;
|
||||
};
|
||||
|
||||
|
||||
/** cast wrapper */
|
||||
static inline struct swrast_texture_image *
|
||||
swrast_texture_image(struct gl_texture_image *img)
|
||||
{
|
||||
return (struct swrast_texture_image *) img;
|
||||
}
|
||||
|
||||
/** cast wrapper */
|
||||
static inline const struct swrast_texture_image *
|
||||
swrast_texture_image_const(const struct gl_texture_image *img)
|
||||
{
|
||||
return (const struct swrast_texture_image *) img;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Subclass of gl_renderbuffer with extra fields needed for software
|
||||
* rendering.
|
||||
*/
|
||||
struct swrast_renderbuffer
|
||||
{
|
||||
struct gl_renderbuffer Base;
|
||||
|
||||
GLubyte *Buffer; /**< The malloc'd memory for buffer */
|
||||
|
||||
/** These fields are only valid while buffer is mapped for rendering */
|
||||
GLubyte *Map;
|
||||
GLint RowStride; /**< in bytes */
|
||||
|
||||
/** For span rendering */
|
||||
GLenum ColorType;
|
||||
};
|
||||
|
||||
|
||||
/** cast wrapper */
|
||||
static inline struct swrast_renderbuffer *
|
||||
swrast_renderbuffer(struct gl_renderbuffer *img)
|
||||
{
|
||||
return (struct swrast_renderbuffer *) img;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* \struct SWcontext
|
||||
* \brief Per-context state that's private to the software rasterizer module.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/** Driver interface:
|
||||
*/
|
||||
struct swrast_device_driver Driver;
|
||||
|
||||
/** Configuration mechanisms to make software rasterizer match
|
||||
* characteristics of the hardware rasterizer (if present):
|
||||
*/
|
||||
GLboolean AllowVertexFog;
|
||||
GLboolean AllowPixelFog;
|
||||
|
||||
/** Derived values, invalidated on statechanges, updated from
|
||||
* _swrast_validate_derived():
|
||||
*/
|
||||
GLbitfield _RasterMask;
|
||||
GLfloat _BackfaceSign; /** +1 or -1 */
|
||||
GLfloat _BackfaceCullSign; /** +1, 0, or -1 */
|
||||
GLboolean _PreferPixelFog; /* Compute fog blend factor per fragment? */
|
||||
GLboolean _TextureCombinePrimary;
|
||||
GLboolean _FogEnabled;
|
||||
GLboolean _DeferredTexture;
|
||||
|
||||
/** List/array of the fragment attributes to interpolate */
|
||||
GLuint _ActiveAttribs[VARYING_SLOT_MAX];
|
||||
/** Same info, but as a bitmask of VARYING_BIT_x bits */
|
||||
GLbitfield64 _ActiveAttribMask;
|
||||
/** Number of fragment attributes to interpolate */
|
||||
GLuint _NumActiveAttribs;
|
||||
/** Indicates how each attrib is to be interpolated (lines/tris) */
|
||||
GLenum _InterpMode[VARYING_SLOT_MAX]; /* GL_FLAT or GL_SMOOTH (for now) */
|
||||
|
||||
/* Working values:
|
||||
*/
|
||||
GLuint StippleCounter; /**< Line stipple counter */
|
||||
GLuint PointLineFacing;
|
||||
GLbitfield NewState;
|
||||
GLuint StateChanges;
|
||||
GLenum Primitive; /* current primitive being drawn (ala glBegin) */
|
||||
GLboolean SpecularVertexAdd; /**< Add specular/secondary color per vertex */
|
||||
|
||||
void (*InvalidateState)( struct gl_context *ctx, GLbitfield new_state );
|
||||
|
||||
/**
|
||||
* When the NewState mask intersects these masks, we invalidate the
|
||||
* Point/Line/Triangle function pointers below.
|
||||
*/
|
||||
/*@{*/
|
||||
GLbitfield InvalidatePointMask;
|
||||
GLbitfield InvalidateLineMask;
|
||||
GLbitfield InvalidateTriangleMask;
|
||||
/*@}*/
|
||||
|
||||
/**
|
||||
* Device drivers plug in functions for these callbacks.
|
||||
* Will be called when the GL state change mask intersects the above masks.
|
||||
*/
|
||||
/*@{*/
|
||||
void (*choose_point)( struct gl_context * );
|
||||
void (*choose_line)( struct gl_context * );
|
||||
void (*choose_triangle)( struct gl_context * );
|
||||
/*@}*/
|
||||
|
||||
/**
|
||||
* Current point, line and triangle drawing functions.
|
||||
*/
|
||||
/*@{*/
|
||||
swrast_point_func Point;
|
||||
swrast_line_func Line;
|
||||
swrast_tri_func Triangle;
|
||||
/*@}*/
|
||||
|
||||
/**
|
||||
* Placeholders for when separate specular (or secondary color) is
|
||||
* enabled but texturing is not.
|
||||
*/
|
||||
/*@{*/
|
||||
swrast_point_func SpecPoint;
|
||||
swrast_line_func SpecLine;
|
||||
swrast_tri_func SpecTriangle;
|
||||
/*@}*/
|
||||
|
||||
/**
|
||||
* Typically, we'll allocate a sw_span structure as a local variable
|
||||
* and set its 'array' pointer to point to this object. The reason is
|
||||
* this object is big and causes problems when allocated on the stack
|
||||
* on some systems.
|
||||
*/
|
||||
SWspanarrays *SpanArrays;
|
||||
SWspanarrays *ZoomedArrays; /**< For pixel zooming */
|
||||
|
||||
/**
|
||||
* Used to buffer N GL_POINTS, instead of rendering one by one.
|
||||
*/
|
||||
SWspan PointSpan;
|
||||
|
||||
/** Internal hooks, kept up to date by the same mechanism as above.
|
||||
*/
|
||||
swrast_blend_func BlendFunc;
|
||||
texture_sample_func TextureSample[MAX_COMBINED_TEXTURE_IMAGE_UNITS];
|
||||
|
||||
/** Buffer for saving the sampled texture colors.
|
||||
* Needed for GL_ARB_texture_env_crossbar implementation.
|
||||
*/
|
||||
GLfloat *TexelBuffer;
|
||||
|
||||
validate_texture_image_func ValidateTextureImage;
|
||||
|
||||
/** State used during execution of fragment programs */
|
||||
struct gl_program_machine FragProgMachine;
|
||||
|
||||
/** Temporary arrays for stencil operations. To avoid large stack
|
||||
* allocations.
|
||||
*/
|
||||
struct {
|
||||
GLubyte *buf1, *buf2, *buf3, *buf4;
|
||||
} stencil_temp;
|
||||
|
||||
} SWcontext;
|
||||
|
||||
|
||||
extern void
|
||||
_swrast_validate_derived( struct gl_context *ctx );
|
||||
|
||||
extern void
|
||||
_swrast_update_texture_samplers(struct gl_context *ctx);
|
||||
|
||||
|
||||
/** Return SWcontext for the given struct gl_context */
|
||||
static inline SWcontext *
|
||||
SWRAST_CONTEXT(struct gl_context *ctx)
|
||||
{
|
||||
return (SWcontext *) ctx->swrast_context;
|
||||
}
|
||||
|
||||
/** const version of above */
|
||||
static inline const SWcontext *
|
||||
CONST_SWRAST_CONTEXT(const struct gl_context *ctx)
|
||||
{
|
||||
return (const SWcontext *) ctx->swrast_context;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called prior to framebuffer reading/writing.
|
||||
* For drivers that rely on swrast for fallback rendering, this is the
|
||||
* driver's opportunity to map renderbuffers and textures.
|
||||
*/
|
||||
static inline void
|
||||
swrast_render_start(struct gl_context *ctx)
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
if (swrast->Driver.SpanRenderStart)
|
||||
swrast->Driver.SpanRenderStart(ctx);
|
||||
}
|
||||
|
||||
|
||||
/** Called after framebuffer reading/writing */
|
||||
static inline void
|
||||
swrast_render_finish(struct gl_context *ctx)
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
if (swrast->Driver.SpanRenderFinish)
|
||||
swrast->Driver.SpanRenderFinish(ctx);
|
||||
}
|
||||
|
||||
|
||||
extern void
|
||||
_swrast_span_render_start(struct gl_context *ctx);
|
||||
|
||||
extern void
|
||||
_swrast_span_render_finish(struct gl_context *ctx);
|
||||
|
||||
extern void
|
||||
_swrast_map_textures(struct gl_context *ctx);
|
||||
|
||||
extern void
|
||||
_swrast_unmap_textures(struct gl_context *ctx);
|
||||
|
||||
extern unsigned int
|
||||
_swrast_teximage_slice_height(struct gl_texture_image *texImage);
|
||||
|
||||
extern void
|
||||
_swrast_map_texture(struct gl_context *ctx, struct gl_texture_object *texObj);
|
||||
|
||||
extern void
|
||||
_swrast_unmap_texture(struct gl_context *ctx, struct gl_texture_object *texObj);
|
||||
|
||||
|
||||
extern void
|
||||
_swrast_map_renderbuffers(struct gl_context *ctx);
|
||||
|
||||
extern void
|
||||
_swrast_unmap_renderbuffers(struct gl_context *ctx);
|
||||
|
||||
|
||||
/**
|
||||
* Size of an RGBA pixel, in bytes, for given datatype.
|
||||
*/
|
||||
#define RGBA_PIXEL_SIZE(TYPE) \
|
||||
((TYPE == GL_UNSIGNED_BYTE) ? 4 * sizeof(GLubyte) : \
|
||||
((TYPE == GL_UNSIGNED_SHORT) ? 4 * sizeof(GLushort) \
|
||||
: 4 * sizeof(GLfloat)))
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Fixed point arithmetic macros
|
||||
*/
|
||||
#ifndef FIXED_FRAC_BITS
|
||||
#define FIXED_FRAC_BITS 11
|
||||
#endif
|
||||
|
||||
#define FIXED_SHIFT FIXED_FRAC_BITS
|
||||
#define FIXED_ONE (1 << FIXED_SHIFT)
|
||||
#define FIXED_HALF (1 << (FIXED_SHIFT-1))
|
||||
#define FIXED_FRAC_MASK (FIXED_ONE - 1)
|
||||
#define FIXED_INT_MASK (~FIXED_FRAC_MASK)
|
||||
#define FIXED_EPSILON 1
|
||||
#define FIXED_SCALE ((float) FIXED_ONE)
|
||||
#define FIXED_DBL_SCALE ((double) FIXED_ONE)
|
||||
#define FloatToFixed(X) (lroundf((X) * FIXED_SCALE))
|
||||
#define FixedToDouble(X) ((X) * (1.0 / FIXED_DBL_SCALE))
|
||||
#define IntToFixed(I) ((I) << FIXED_SHIFT)
|
||||
#define FixedToInt(X) ((X) >> FIXED_SHIFT)
|
||||
#define FixedToUns(X) (((unsigned int)(X)) >> FIXED_SHIFT)
|
||||
#define FixedCeil(X) (((X) + FIXED_ONE - FIXED_EPSILON) & FIXED_INT_MASK)
|
||||
#define FixedFloor(X) ((X) & FIXED_INT_MASK)
|
||||
#define FixedToFloat(X) ((X) * (1.0F / FIXED_SCALE))
|
||||
#define PosFloatToFixed(X) FloatToFixed(X)
|
||||
#define SignedFloatToFixed(X) FloatToFixed(X)
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* XXX these macros are just bandages for now in order to make
|
||||
* CHAN_BITS==32 compile cleanly.
|
||||
* These should probably go elsewhere at some point.
|
||||
*/
|
||||
#if CHAN_TYPE == GL_FLOAT
|
||||
#define ChanToFixed(X) (X)
|
||||
#define FixedToChan(X) (X)
|
||||
#else
|
||||
#define ChanToFixed(X) IntToFixed(X)
|
||||
#define FixedToChan(X) FixedToInt(X)
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* For looping over fragment attributes in the pointe, line
|
||||
* triangle rasterizers.
|
||||
*/
|
||||
#define ATTRIB_LOOP_BEGIN \
|
||||
{ \
|
||||
GLuint a; \
|
||||
for (a = 0; a < swrast->_NumActiveAttribs; a++) { \
|
||||
const GLuint attr = swrast->_ActiveAttribs[a];
|
||||
|
||||
#define ATTRIB_LOOP_END } }
|
||||
|
||||
|
||||
/**
|
||||
* Return the address of a pixel value in a mapped renderbuffer.
|
||||
*/
|
||||
static inline GLubyte *
|
||||
_swrast_pixel_address(struct gl_renderbuffer *rb, GLint x, GLint y)
|
||||
{
|
||||
struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
|
||||
const GLint bpp = _mesa_get_format_bytes(rb->Format);
|
||||
const GLint rowStride = srb->RowStride;
|
||||
assert(x >= 0);
|
||||
assert(y >= 0);
|
||||
/* NOTE: using <= only because of s_tritemp.h which gets a pixel
|
||||
* address but doesn't necessarily access it.
|
||||
*/
|
||||
assert(x <= (GLint) rb->Width);
|
||||
assert(y <= (GLint) rb->Height);
|
||||
assert(srb->Map);
|
||||
return (GLubyte *) srb->Map + y * rowStride + x * bpp;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -1,668 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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/context.h"
|
||||
#include "main/condrender.h"
|
||||
#include "main/macros.h"
|
||||
#include "main/blit.h"
|
||||
#include "main/pixeltransfer.h"
|
||||
|
||||
|
||||
#include "s_context.h"
|
||||
#include "s_depth.h"
|
||||
#include "s_span.h"
|
||||
#include "s_stencil.h"
|
||||
#include "s_zoom.h"
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Determine if there's overlap in an image copy.
|
||||
* This test also compensates for the fact that copies are done from
|
||||
* bottom to top and overlaps can sometimes be handled correctly
|
||||
* without making a temporary image copy.
|
||||
* \return GL_TRUE if the regions overlap, GL_FALSE otherwise.
|
||||
*/
|
||||
static GLboolean
|
||||
regions_overlap(GLint srcx, GLint srcy,
|
||||
GLint dstx, GLint dsty,
|
||||
GLint width, GLint height,
|
||||
GLfloat zoomX, GLfloat zoomY)
|
||||
{
|
||||
if (zoomX == 1.0F && zoomY == 1.0F) {
|
||||
return _mesa_regions_overlap(srcx, srcy, srcx + width, srcy + height,
|
||||
dstx, dsty, dstx + width, dsty + height);
|
||||
}
|
||||
else {
|
||||
/* add one pixel of slop when zooming, just to be safe */
|
||||
if (srcx > (dstx + ((zoomX > 0.0F) ? (width * zoomX + 1.0F) : 0.0F))) {
|
||||
/* src is completely right of dest */
|
||||
return GL_FALSE;
|
||||
}
|
||||
else if (srcx + width + 1.0F < dstx + ((zoomX > 0.0F) ? 0.0F : (width * zoomX))) {
|
||||
/* src is completely left of dest */
|
||||
return GL_FALSE;
|
||||
}
|
||||
else if ((srcy < dsty) && (srcy + height < dsty + (height * zoomY))) {
|
||||
/* src is completely below dest */
|
||||
return GL_FALSE;
|
||||
}
|
||||
else if ((srcy > dsty) && (srcy + height > dsty + (height * zoomY))) {
|
||||
/* src is completely above dest */
|
||||
return GL_FALSE;
|
||||
}
|
||||
else {
|
||||
return GL_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* RGBA copypixels
|
||||
*/
|
||||
static void
|
||||
copy_rgba_pixels(struct gl_context *ctx, GLint srcx, GLint srcy,
|
||||
GLint width, GLint height, GLint destx, GLint desty)
|
||||
{
|
||||
GLfloat *tmpImage, *p;
|
||||
GLint sy, dy, stepy, row;
|
||||
const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
|
||||
GLint overlapping;
|
||||
GLuint transferOps = ctx->_ImageTransferState;
|
||||
SWspan span;
|
||||
|
||||
if (!ctx->ReadBuffer->_ColorReadBuffer) {
|
||||
/* no readbuffer - OK */
|
||||
return;
|
||||
}
|
||||
|
||||
if (ctx->DrawBuffer == ctx->ReadBuffer) {
|
||||
overlapping = regions_overlap(srcx, srcy, destx, desty, width, height,
|
||||
ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
|
||||
}
|
||||
else {
|
||||
overlapping = GL_FALSE;
|
||||
}
|
||||
|
||||
/* Determine if copy should be done bottom-to-top or top-to-bottom */
|
||||
if (!overlapping && srcy < desty) {
|
||||
/* top-down max-to-min */
|
||||
sy = srcy + height - 1;
|
||||
dy = desty + height - 1;
|
||||
stepy = -1;
|
||||
}
|
||||
else {
|
||||
/* bottom-up min-to-max */
|
||||
sy = srcy;
|
||||
dy = desty;
|
||||
stepy = 1;
|
||||
}
|
||||
|
||||
INIT_SPAN(span, GL_BITMAP);
|
||||
_swrast_span_default_attribs(ctx, &span);
|
||||
span.arrayMask = SPAN_RGBA;
|
||||
span.arrayAttribs = VARYING_BIT_COL0; /* we'll fill in COL0 attrib values */
|
||||
|
||||
if (overlapping) {
|
||||
tmpImage = malloc(width * height * sizeof(GLfloat) * 4);
|
||||
if (!tmpImage) {
|
||||
_mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" );
|
||||
return;
|
||||
}
|
||||
/* read the source image as RGBA/float */
|
||||
p = tmpImage;
|
||||
for (row = 0; row < height; row++) {
|
||||
_swrast_read_rgba_span( ctx, ctx->ReadBuffer->_ColorReadBuffer,
|
||||
width, srcx, sy + row, p );
|
||||
p += width * 4;
|
||||
}
|
||||
p = tmpImage;
|
||||
}
|
||||
else {
|
||||
tmpImage = NULL; /* silence compiler warnings */
|
||||
p = NULL;
|
||||
}
|
||||
|
||||
assert(width < SWRAST_MAX_WIDTH);
|
||||
|
||||
for (row = 0; row < height; row++, sy += stepy, dy += stepy) {
|
||||
GLvoid *rgba = span.array->attribs[VARYING_SLOT_COL0];
|
||||
|
||||
/* Get row/span of source pixels */
|
||||
if (overlapping) {
|
||||
/* get from buffered image */
|
||||
memcpy(rgba, p, width * sizeof(GLfloat) * 4);
|
||||
p += width * 4;
|
||||
}
|
||||
else {
|
||||
/* get from framebuffer */
|
||||
_swrast_read_rgba_span( ctx, ctx->ReadBuffer->_ColorReadBuffer,
|
||||
width, srcx, sy, rgba );
|
||||
}
|
||||
|
||||
if (transferOps) {
|
||||
_mesa_apply_rgba_transfer_ops(ctx, transferOps, width,
|
||||
(GLfloat (*)[4]) rgba);
|
||||
}
|
||||
|
||||
/* Write color span */
|
||||
span.x = destx;
|
||||
span.y = dy;
|
||||
span.end = width;
|
||||
span.array->ChanType = GL_FLOAT;
|
||||
if (zoom) {
|
||||
_swrast_write_zoomed_rgba_span(ctx, destx, desty, &span, rgba);
|
||||
}
|
||||
else {
|
||||
_swrast_write_rgba_span(ctx, &span);
|
||||
}
|
||||
}
|
||||
|
||||
span.array->ChanType = CHAN_TYPE; /* restore */
|
||||
|
||||
if (overlapping)
|
||||
free(tmpImage);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert floating point Z values to integer Z values with pixel transfer's
|
||||
* Z scale and bias.
|
||||
*/
|
||||
static void
|
||||
scale_and_bias_z(struct gl_context *ctx, GLuint width,
|
||||
const GLfloat depth[], GLuint z[])
|
||||
{
|
||||
const GLuint depthMax = ctx->DrawBuffer->_DepthMax;
|
||||
GLuint i;
|
||||
|
||||
if (depthMax <= 0xffffff &&
|
||||
ctx->Pixel.DepthScale == 1.0F &&
|
||||
ctx->Pixel.DepthBias == 0.0F) {
|
||||
/* no scale or bias and no clamping and no worry of overflow */
|
||||
const GLfloat depthMaxF = ctx->DrawBuffer->_DepthMaxF;
|
||||
for (i = 0; i < width; i++) {
|
||||
z[i] = (GLuint) (depth[i] * depthMaxF);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* need to be careful with overflow */
|
||||
const GLdouble depthMaxF = ctx->DrawBuffer->_DepthMaxF;
|
||||
for (i = 0; i < width; i++) {
|
||||
GLdouble d = depth[i] * ctx->Pixel.DepthScale + ctx->Pixel.DepthBias;
|
||||
d = SATURATE(d) * depthMaxF;
|
||||
if (d >= depthMaxF)
|
||||
z[i] = depthMax;
|
||||
else
|
||||
z[i] = (GLuint) d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* TODO: Optimize!!!!
|
||||
*/
|
||||
static void
|
||||
copy_depth_pixels( struct gl_context *ctx, GLint srcx, GLint srcy,
|
||||
GLint width, GLint height,
|
||||
GLint destx, GLint desty )
|
||||
{
|
||||
struct gl_framebuffer *fb = ctx->ReadBuffer;
|
||||
struct gl_renderbuffer *readRb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
|
||||
GLfloat *p, *tmpImage, *depth;
|
||||
GLint sy, dy, stepy;
|
||||
GLint j;
|
||||
const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
|
||||
GLint overlapping;
|
||||
SWspan span;
|
||||
|
||||
if (!readRb) {
|
||||
/* no readbuffer - OK */
|
||||
return;
|
||||
}
|
||||
|
||||
INIT_SPAN(span, GL_BITMAP);
|
||||
_swrast_span_default_attribs(ctx, &span);
|
||||
span.arrayMask = SPAN_Z;
|
||||
|
||||
if (ctx->DrawBuffer == ctx->ReadBuffer) {
|
||||
overlapping = regions_overlap(srcx, srcy, destx, desty, width, height,
|
||||
ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
|
||||
}
|
||||
else {
|
||||
overlapping = GL_FALSE;
|
||||
}
|
||||
|
||||
/* Determine if copy should be bottom-to-top or top-to-bottom */
|
||||
if (!overlapping && srcy < desty) {
|
||||
/* top-down max-to-min */
|
||||
sy = srcy + height - 1;
|
||||
dy = desty + height - 1;
|
||||
stepy = -1;
|
||||
}
|
||||
else {
|
||||
/* bottom-up min-to-max */
|
||||
sy = srcy;
|
||||
dy = desty;
|
||||
stepy = 1;
|
||||
}
|
||||
|
||||
if (overlapping) {
|
||||
GLint ssy = sy;
|
||||
tmpImage = malloc(width * height * sizeof(GLfloat));
|
||||
if (!tmpImage) {
|
||||
_mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" );
|
||||
return;
|
||||
}
|
||||
p = tmpImage;
|
||||
for (j = 0; j < height; j++, ssy += stepy) {
|
||||
_swrast_read_depth_span_float(ctx, readRb, width, srcx, ssy, p);
|
||||
p += width;
|
||||
}
|
||||
p = tmpImage;
|
||||
}
|
||||
else {
|
||||
tmpImage = NULL; /* silence compiler warning */
|
||||
p = NULL;
|
||||
}
|
||||
|
||||
depth = malloc(width * sizeof(GLfloat));
|
||||
if (!depth) {
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels()");
|
||||
goto end;
|
||||
}
|
||||
|
||||
for (j = 0; j < height; j++, sy += stepy, dy += stepy) {
|
||||
/* get depth values */
|
||||
if (overlapping) {
|
||||
memcpy(depth, p, width * sizeof(GLfloat));
|
||||
p += width;
|
||||
}
|
||||
else {
|
||||
_swrast_read_depth_span_float(ctx, readRb, width, srcx, sy, depth);
|
||||
}
|
||||
|
||||
/* apply scale and bias */
|
||||
scale_and_bias_z(ctx, width, depth, span.array->z);
|
||||
|
||||
/* write depth values */
|
||||
span.x = destx;
|
||||
span.y = dy;
|
||||
span.end = width;
|
||||
if (zoom)
|
||||
_swrast_write_zoomed_depth_span(ctx, destx, desty, &span);
|
||||
else
|
||||
_swrast_write_rgba_span(ctx, &span);
|
||||
}
|
||||
|
||||
free(depth);
|
||||
|
||||
end:
|
||||
if (overlapping)
|
||||
free(tmpImage);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
copy_stencil_pixels( struct gl_context *ctx, GLint srcx, GLint srcy,
|
||||
GLint width, GLint height,
|
||||
GLint destx, GLint desty )
|
||||
{
|
||||
struct gl_framebuffer *fb = ctx->ReadBuffer;
|
||||
struct gl_renderbuffer *rb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
|
||||
GLint sy, dy, stepy;
|
||||
GLint j;
|
||||
GLubyte *p, *tmpImage, *stencil;
|
||||
const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
|
||||
GLint overlapping;
|
||||
|
||||
if (!rb) {
|
||||
/* no readbuffer - OK */
|
||||
return;
|
||||
}
|
||||
|
||||
if (ctx->DrawBuffer == ctx->ReadBuffer) {
|
||||
overlapping = regions_overlap(srcx, srcy, destx, desty, width, height,
|
||||
ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
|
||||
}
|
||||
else {
|
||||
overlapping = GL_FALSE;
|
||||
}
|
||||
|
||||
/* Determine if copy should be bottom-to-top or top-to-bottom */
|
||||
if (!overlapping && srcy < desty) {
|
||||
/* top-down max-to-min */
|
||||
sy = srcy + height - 1;
|
||||
dy = desty + height - 1;
|
||||
stepy = -1;
|
||||
}
|
||||
else {
|
||||
/* bottom-up min-to-max */
|
||||
sy = srcy;
|
||||
dy = desty;
|
||||
stepy = 1;
|
||||
}
|
||||
|
||||
if (overlapping) {
|
||||
GLint ssy = sy;
|
||||
tmpImage = malloc(width * height * sizeof(GLubyte));
|
||||
if (!tmpImage) {
|
||||
_mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" );
|
||||
return;
|
||||
}
|
||||
p = tmpImage;
|
||||
for (j = 0; j < height; j++, ssy += stepy) {
|
||||
_swrast_read_stencil_span( ctx, rb, width, srcx, ssy, p );
|
||||
p += width;
|
||||
}
|
||||
p = tmpImage;
|
||||
}
|
||||
else {
|
||||
tmpImage = NULL; /* silence compiler warning */
|
||||
p = NULL;
|
||||
}
|
||||
|
||||
stencil = malloc(width * sizeof(GLubyte));
|
||||
if (!stencil) {
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels()");
|
||||
goto end;
|
||||
}
|
||||
|
||||
for (j = 0; j < height; j++, sy += stepy, dy += stepy) {
|
||||
/* Get stencil values */
|
||||
if (overlapping) {
|
||||
memcpy(stencil, p, width * sizeof(GLubyte));
|
||||
p += width;
|
||||
}
|
||||
else {
|
||||
_swrast_read_stencil_span( ctx, rb, width, srcx, sy, stencil );
|
||||
}
|
||||
|
||||
_mesa_apply_stencil_transfer_ops(ctx, width, stencil);
|
||||
|
||||
/* Write stencil values */
|
||||
if (zoom) {
|
||||
_swrast_write_zoomed_stencil_span(ctx, destx, desty, width,
|
||||
destx, dy, stencil);
|
||||
}
|
||||
else {
|
||||
_swrast_write_stencil_span( ctx, width, destx, dy, stencil );
|
||||
}
|
||||
}
|
||||
|
||||
free(stencil);
|
||||
|
||||
end:
|
||||
if (overlapping)
|
||||
free(tmpImage);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Try to do a fast 1:1 blit with memcpy.
|
||||
* \return GL_TRUE if successful, GL_FALSE otherwise.
|
||||
*/
|
||||
GLboolean
|
||||
swrast_fast_copy_pixels(struct gl_context *ctx,
|
||||
struct gl_framebuffer *srcFb,
|
||||
struct gl_framebuffer *dstFb,
|
||||
GLint srcX, GLint srcY, GLsizei width, GLsizei height,
|
||||
GLint dstX, GLint dstY, GLenum type)
|
||||
{
|
||||
struct gl_renderbuffer *srcRb, *dstRb;
|
||||
GLint row;
|
||||
GLuint pixelBytes, widthInBytes;
|
||||
GLubyte *srcMap, *dstMap;
|
||||
GLint srcRowStride, dstRowStride;
|
||||
|
||||
if (type == GL_COLOR) {
|
||||
if (dstFb->_NumColorDrawBuffers != 1)
|
||||
return GL_FALSE;
|
||||
srcRb = srcFb->_ColorReadBuffer;
|
||||
dstRb = dstFb->_ColorDrawBuffers[0];
|
||||
}
|
||||
else if (type == GL_STENCIL) {
|
||||
srcRb = srcFb->Attachment[BUFFER_STENCIL].Renderbuffer;
|
||||
dstRb = dstFb->Attachment[BUFFER_STENCIL].Renderbuffer;
|
||||
}
|
||||
else if (type == GL_DEPTH) {
|
||||
srcRb = srcFb->Attachment[BUFFER_DEPTH].Renderbuffer;
|
||||
dstRb = dstFb->Attachment[BUFFER_DEPTH].Renderbuffer;
|
||||
}
|
||||
else {
|
||||
assert(type == GL_DEPTH_STENCIL_EXT);
|
||||
/* XXX correct? */
|
||||
srcRb = srcFb->Attachment[BUFFER_DEPTH].Renderbuffer;
|
||||
dstRb = dstFb->Attachment[BUFFER_DEPTH].Renderbuffer;
|
||||
}
|
||||
|
||||
/* src and dst renderbuffers must be same format */
|
||||
if (!srcRb || !dstRb || srcRb->Format != dstRb->Format) {
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
if (type == GL_STENCIL || type == GL_DEPTH_COMPONENT) {
|
||||
/* can't handle packed depth+stencil here */
|
||||
if (_mesa_is_format_packed_depth_stencil(srcRb->Format) ||
|
||||
_mesa_is_format_packed_depth_stencil(dstRb->Format))
|
||||
return GL_FALSE;
|
||||
}
|
||||
else if (type == GL_DEPTH_STENCIL) {
|
||||
/* can't handle separate depth/stencil buffers */
|
||||
if (srcRb != srcFb->Attachment[BUFFER_STENCIL].Renderbuffer ||
|
||||
dstRb != dstFb->Attachment[BUFFER_STENCIL].Renderbuffer)
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
/* clipping not supported */
|
||||
if (srcX < 0 || srcX + width > (GLint) srcFb->Width ||
|
||||
srcY < 0 || srcY + height > (GLint) srcFb->Height ||
|
||||
dstX < dstFb->_Xmin || dstX + width > dstFb->_Xmax ||
|
||||
dstY < dstFb->_Ymin || dstY + height > dstFb->_Ymax) {
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
pixelBytes = _mesa_get_format_bytes(srcRb->Format);
|
||||
widthInBytes = width * pixelBytes;
|
||||
|
||||
if (srcRb == dstRb) {
|
||||
/* map whole buffer for read/write */
|
||||
/* XXX we could be clever and just map the union region of the
|
||||
* source and dest rects.
|
||||
*/
|
||||
GLubyte *map;
|
||||
GLint rowStride;
|
||||
|
||||
ctx->Driver.MapRenderbuffer(ctx, srcRb, 0, 0,
|
||||
srcRb->Width, srcRb->Height,
|
||||
GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
|
||||
&map, &rowStride, srcFb->FlipY);
|
||||
if (!map) {
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels");
|
||||
return GL_TRUE; /* don't retry with slow path */
|
||||
}
|
||||
|
||||
srcMap = map + srcY * rowStride + srcX * pixelBytes;
|
||||
dstMap = map + dstY * rowStride + dstX * pixelBytes;
|
||||
|
||||
/* this handles overlapping copies */
|
||||
if (srcY < dstY) {
|
||||
/* copy in reverse (top->down) order */
|
||||
srcMap += rowStride * (height - 1);
|
||||
dstMap += rowStride * (height - 1);
|
||||
srcRowStride = -rowStride;
|
||||
dstRowStride = -rowStride;
|
||||
}
|
||||
else {
|
||||
/* copy in normal (bottom->up) order */
|
||||
srcRowStride = rowStride;
|
||||
dstRowStride = rowStride;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* different src/dst buffers */
|
||||
ctx->Driver.MapRenderbuffer(ctx, srcRb, srcX, srcY,
|
||||
width, height,
|
||||
GL_MAP_READ_BIT, &srcMap, &srcRowStride,
|
||||
srcFb->FlipY);
|
||||
if (!srcMap) {
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels");
|
||||
return GL_TRUE; /* don't retry with slow path */
|
||||
}
|
||||
ctx->Driver.MapRenderbuffer(ctx, dstRb, dstX, dstY,
|
||||
width, height,
|
||||
GL_MAP_WRITE_BIT, &dstMap, &dstRowStride,
|
||||
dstFb->FlipY);
|
||||
if (!dstMap) {
|
||||
ctx->Driver.UnmapRenderbuffer(ctx, srcRb);
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels");
|
||||
return GL_TRUE; /* don't retry with slow path */
|
||||
}
|
||||
}
|
||||
|
||||
for (row = 0; row < height; row++) {
|
||||
/* memmove() in case of overlap */
|
||||
memmove(dstMap, srcMap, widthInBytes);
|
||||
dstMap += dstRowStride;
|
||||
srcMap += srcRowStride;
|
||||
}
|
||||
|
||||
ctx->Driver.UnmapRenderbuffer(ctx, srcRb);
|
||||
if (dstRb != srcRb) {
|
||||
ctx->Driver.UnmapRenderbuffer(ctx, dstRb);
|
||||
}
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find/map the renderbuffer that we'll be reading from.
|
||||
* The swrast_render_start() function only maps the drawing buffers,
|
||||
* not the read buffer.
|
||||
*/
|
||||
static struct gl_renderbuffer *
|
||||
map_readbuffer(struct gl_context *ctx, GLenum type)
|
||||
{
|
||||
struct gl_framebuffer *fb = ctx->ReadBuffer;
|
||||
struct gl_renderbuffer *rb;
|
||||
struct swrast_renderbuffer *srb;
|
||||
|
||||
switch (type) {
|
||||
case GL_COLOR:
|
||||
rb = fb->Attachment[fb->_ColorReadBufferIndex].Renderbuffer;
|
||||
break;
|
||||
case GL_DEPTH:
|
||||
case GL_DEPTH_STENCIL:
|
||||
rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
|
||||
break;
|
||||
case GL_STENCIL:
|
||||
rb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
srb = swrast_renderbuffer(rb);
|
||||
|
||||
if (!srb || srb->Map) {
|
||||
/* no buffer, or buffer is mapped already, we're done */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx->Driver.MapRenderbuffer(ctx, rb,
|
||||
0, 0, rb->Width, rb->Height,
|
||||
GL_MAP_READ_BIT,
|
||||
&srb->Map, &srb->RowStride,
|
||||
fb->FlipY);
|
||||
|
||||
return rb;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Do software-based glCopyPixels.
|
||||
* By time we get here, all parameters will have been error-checked.
|
||||
*/
|
||||
void
|
||||
_swrast_CopyPixels(struct gl_context *ctx,
|
||||
GLint srcx, GLint srcy, GLsizei width, GLsizei height,
|
||||
GLint destx, GLint desty, GLenum type)
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
struct gl_renderbuffer *rb;
|
||||
|
||||
if (!_mesa_check_conditional_render(ctx))
|
||||
return; /* don't copy */
|
||||
|
||||
if (swrast->NewState)
|
||||
_swrast_validate_derived( ctx );
|
||||
|
||||
if (!(SWRAST_CONTEXT(ctx)->_RasterMask != 0x0 ||
|
||||
ctx->Pixel.ZoomX != 1.0F ||
|
||||
ctx->Pixel.ZoomY != 1.0F ||
|
||||
ctx->_ImageTransferState) &&
|
||||
swrast_fast_copy_pixels(ctx, ctx->ReadBuffer, ctx->DrawBuffer,
|
||||
srcx, srcy, width, height, destx, desty,
|
||||
type)) {
|
||||
/* all done */
|
||||
return;
|
||||
}
|
||||
|
||||
swrast_render_start(ctx);
|
||||
rb = map_readbuffer(ctx, type);
|
||||
|
||||
switch (type) {
|
||||
case GL_COLOR:
|
||||
copy_rgba_pixels( ctx, srcx, srcy, width, height, destx, desty );
|
||||
break;
|
||||
case GL_DEPTH:
|
||||
copy_depth_pixels( ctx, srcx, srcy, width, height, destx, desty );
|
||||
break;
|
||||
case GL_STENCIL:
|
||||
copy_stencil_pixels( ctx, srcx, srcy, width, height, destx, desty );
|
||||
break;
|
||||
case GL_DEPTH_STENCIL_EXT:
|
||||
/* Copy buffers separately (if the fast copy path wasn't taken) */
|
||||
copy_depth_pixels(ctx, srcx, srcy, width, height, destx, desty);
|
||||
copy_stencil_pixels(ctx, srcx, srcy, width, height, destx, desty);
|
||||
break;
|
||||
default:
|
||||
_mesa_problem(ctx, "unexpected type in _swrast_CopyPixels");
|
||||
}
|
||||
|
||||
swrast_render_finish(ctx);
|
||||
|
||||
if (rb) {
|
||||
struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
|
||||
ctx->Driver.UnmapRenderbuffer(ctx, rb);
|
||||
srb->Map = NULL;
|
||||
}
|
||||
}
|
|
@ -1,854 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* Copyright (C) 1999-2008 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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/context.h"
|
||||
#include "main/formats.h"
|
||||
#include "main/format_unpack.h"
|
||||
#include "main/format_pack.h"
|
||||
#include "main/macros.h"
|
||||
|
||||
|
||||
#include "s_context.h"
|
||||
#include "s_depth.h"
|
||||
#include "s_span.h"
|
||||
|
||||
|
||||
|
||||
#define Z_TEST(COMPARE) \
|
||||
do { \
|
||||
GLuint i; \
|
||||
for (i = 0; i < n; i++) { \
|
||||
if (mask[i]) { \
|
||||
if (COMPARE) { \
|
||||
/* pass */ \
|
||||
if (write) { \
|
||||
zbuffer[i] = zfrag[i]; \
|
||||
} \
|
||||
passed++; \
|
||||
} \
|
||||
else { \
|
||||
/* fail */ \
|
||||
mask[i] = 0; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
/**
|
||||
* Do depth test for an array of 16-bit Z values.
|
||||
* @param zbuffer array of Z buffer values (16-bit)
|
||||
* @param zfrag array of fragment Z values (use 16-bit in 32-bit uint)
|
||||
* @param mask which fragments are alive, killed afterward
|
||||
* @return number of fragments which pass the test.
|
||||
*/
|
||||
static GLuint
|
||||
depth_test_span16( struct gl_context *ctx, GLuint n,
|
||||
GLushort zbuffer[], const GLuint zfrag[], GLubyte mask[] )
|
||||
{
|
||||
const GLboolean write = ctx->Depth.Mask;
|
||||
GLuint passed = 0;
|
||||
|
||||
/* switch cases ordered from most frequent to less frequent */
|
||||
switch (ctx->Depth.Func) {
|
||||
case GL_LESS:
|
||||
Z_TEST(zfrag[i] < zbuffer[i]);
|
||||
break;
|
||||
case GL_LEQUAL:
|
||||
Z_TEST(zfrag[i] <= zbuffer[i]);
|
||||
break;
|
||||
case GL_GEQUAL:
|
||||
Z_TEST(zfrag[i] >= zbuffer[i]);
|
||||
break;
|
||||
case GL_GREATER:
|
||||
Z_TEST(zfrag[i] > zbuffer[i]);
|
||||
break;
|
||||
case GL_NOTEQUAL:
|
||||
Z_TEST(zfrag[i] != zbuffer[i]);
|
||||
break;
|
||||
case GL_EQUAL:
|
||||
Z_TEST(zfrag[i] == zbuffer[i]);
|
||||
break;
|
||||
case GL_ALWAYS:
|
||||
Z_TEST(1);
|
||||
break;
|
||||
case GL_NEVER:
|
||||
memset(mask, 0, n * sizeof(GLubyte));
|
||||
break;
|
||||
default:
|
||||
_mesa_problem(ctx, "Bad depth func in depth_test_span16");
|
||||
}
|
||||
|
||||
return passed;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Do depth test for an array of 32-bit Z values.
|
||||
* @param zbuffer array of Z buffer values (32-bit)
|
||||
* @param zfrag array of fragment Z values (use 32-bits in 32-bit uint)
|
||||
* @param mask which fragments are alive, killed afterward
|
||||
* @return number of fragments which pass the test.
|
||||
*/
|
||||
static GLuint
|
||||
depth_test_span32( struct gl_context *ctx, GLuint n,
|
||||
GLuint zbuffer[], const GLuint zfrag[], GLubyte mask[])
|
||||
{
|
||||
const GLboolean write = ctx->Depth.Mask;
|
||||
GLuint passed = 0;
|
||||
|
||||
/* switch cases ordered from most frequent to less frequent */
|
||||
switch (ctx->Depth.Func) {
|
||||
case GL_LESS:
|
||||
Z_TEST(zfrag[i] < zbuffer[i]);
|
||||
break;
|
||||
case GL_LEQUAL:
|
||||
Z_TEST(zfrag[i] <= zbuffer[i]);
|
||||
break;
|
||||
case GL_GEQUAL:
|
||||
Z_TEST(zfrag[i] >= zbuffer[i]);
|
||||
break;
|
||||
case GL_GREATER:
|
||||
Z_TEST(zfrag[i] > zbuffer[i]);
|
||||
break;
|
||||
case GL_NOTEQUAL:
|
||||
Z_TEST(zfrag[i] != zbuffer[i]);
|
||||
break;
|
||||
case GL_EQUAL:
|
||||
Z_TEST(zfrag[i] == zbuffer[i]);
|
||||
break;
|
||||
case GL_ALWAYS:
|
||||
Z_TEST(1);
|
||||
break;
|
||||
case GL_NEVER:
|
||||
memset(mask, 0, n * sizeof(GLubyte));
|
||||
break;
|
||||
default:
|
||||
_mesa_problem(ctx, "Bad depth func in depth_test_span32");
|
||||
}
|
||||
|
||||
return passed;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clamp fragment Z values to the depth near/far range (glDepthRange()).
|
||||
* This is used when GL_ARB_depth_clamp/GL_DEPTH_CLAMP is turned on.
|
||||
* In that case, vertexes are not clipped against the near/far planes
|
||||
* so rasterization will produce fragment Z values outside the usual
|
||||
* [0,1] range.
|
||||
*/
|
||||
void
|
||||
_swrast_depth_clamp_span( struct gl_context *ctx, SWspan *span )
|
||||
{
|
||||
struct gl_framebuffer *fb = ctx->DrawBuffer;
|
||||
const GLuint count = span->end;
|
||||
GLint *zValues = (GLint *) span->array->z; /* sign change */
|
||||
GLint min, max;
|
||||
GLfloat min_f, max_f;
|
||||
GLuint i;
|
||||
|
||||
if (ctx->ViewportArray[0].Near < ctx->ViewportArray[0].Far) {
|
||||
min_f = ctx->ViewportArray[0].Near;
|
||||
max_f = ctx->ViewportArray[0].Far;
|
||||
} else {
|
||||
min_f = ctx->ViewportArray[0].Far;
|
||||
max_f = ctx->ViewportArray[0].Near;
|
||||
}
|
||||
|
||||
/* Convert floating point values in [0,1] to device Z coordinates in
|
||||
* [0, DepthMax].
|
||||
* ex: If the Z buffer has 24 bits, DepthMax = 0xffffff.
|
||||
*
|
||||
* XXX this all falls apart if we have 31 or more bits of Z because
|
||||
* the triangle rasterization code produces unsigned Z values. Negative
|
||||
* vertex Z values come out as large fragment Z uints.
|
||||
*/
|
||||
min = (GLint) (min_f * fb->_DepthMaxF);
|
||||
max = (GLint) (max_f * fb->_DepthMaxF);
|
||||
if (max < 0)
|
||||
max = 0x7fffffff; /* catch over flow for 30-bit z */
|
||||
|
||||
/* Note that we do the comparisons here using signed integers.
|
||||
*/
|
||||
for (i = 0; i < count; i++) {
|
||||
if (zValues[i] < min)
|
||||
zValues[i] = min;
|
||||
if (zValues[i] > max)
|
||||
zValues[i] = max;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get array of 32-bit z values from the depth buffer. With clipping.
|
||||
* Note: the returned values are always in the range [0, 2^32-1].
|
||||
*/
|
||||
static void
|
||||
get_z32_values(struct gl_context *ctx, struct gl_renderbuffer *rb,
|
||||
GLuint count, const GLint x[], const GLint y[],
|
||||
GLuint zbuffer[])
|
||||
{
|
||||
struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
|
||||
const GLint w = rb->Width, h = rb->Height;
|
||||
const GLubyte *map = _swrast_pixel_address(rb, 0, 0);
|
||||
GLuint i;
|
||||
|
||||
if (rb->Format == MESA_FORMAT_Z_UNORM32) {
|
||||
const GLint rowStride = srb->RowStride;
|
||||
for (i = 0; i < count; i++) {
|
||||
if (x[i] >= 0 && y[i] >= 0 && x[i] < w && y[i] < h) {
|
||||
zbuffer[i] = *((GLuint *) (map + y[i] * rowStride + x[i] * 4));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
const GLint bpp = _mesa_get_format_bytes(rb->Format);
|
||||
const GLint rowStride = srb->RowStride;
|
||||
for (i = 0; i < count; i++) {
|
||||
if (x[i] >= 0 && y[i] >= 0 && x[i] < w && y[i] < h) {
|
||||
const GLubyte *src = map + y[i] * rowStride+ x[i] * bpp;
|
||||
_mesa_unpack_uint_z_row(rb->Format, 1, src, &zbuffer[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Helper struct for MESA_FORMAT_Z32_FLOAT_S8X24_UINT */
|
||||
struct z32f_x24s8
|
||||
{
|
||||
float z;
|
||||
uint32_t x24s8;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
** Pack uint Z pixels. The incoming src value is always in
|
||||
** the range [0, 2^32-1].
|
||||
**/
|
||||
|
||||
static void
|
||||
pack_uint_S8_UINT_Z24_UNORM(const uint32_t *src, void *dst)
|
||||
{
|
||||
/* don't disturb the stencil values */
|
||||
uint32_t *d = ((uint32_t *) dst);
|
||||
uint32_t s = *d & 0xff;
|
||||
uint32_t z = *src & 0xffffff00;
|
||||
*d = z | s;
|
||||
}
|
||||
|
||||
static void
|
||||
pack_uint_Z24_UNORM_S8_UINT(const uint32_t *src, void *dst)
|
||||
{
|
||||
/* don't disturb the stencil values */
|
||||
uint32_t *d = ((uint32_t *) dst);
|
||||
uint32_t s = *d & 0xff000000;
|
||||
uint32_t z = *src >> 8;
|
||||
*d = s | z;
|
||||
}
|
||||
|
||||
static void
|
||||
pack_uint_Z_UNORM16(const uint32_t *src, void *dst)
|
||||
{
|
||||
uint16_t *d = ((uint16_t *) dst);
|
||||
*d = *src >> 16;
|
||||
}
|
||||
|
||||
static void
|
||||
pack_uint_Z_UNORM32(const uint32_t *src, void *dst)
|
||||
{
|
||||
uint32_t *d = ((uint32_t *) dst);
|
||||
*d = *src;
|
||||
}
|
||||
|
||||
/**
|
||||
** Pack uint to Z_FLOAT32 or Z_FLOAT32_X24S8.
|
||||
**/
|
||||
|
||||
static void
|
||||
pack_uint_Z_FLOAT32(const uint32_t *src, void *dst)
|
||||
{
|
||||
float *d = ((float *) dst);
|
||||
const double scale = 1.0 / (double) 0xffffffff;
|
||||
*d = (float) (*src * scale);
|
||||
assert(*d >= 0.0f);
|
||||
assert(*d <= 1.0f);
|
||||
}
|
||||
|
||||
/** Pack a uint32_t Z value to dest address */
|
||||
typedef void (*mesa_pack_uint_z_func)(const uint32_t *src, void *dst);
|
||||
|
||||
static mesa_pack_uint_z_func
|
||||
get_pack_uint_z_func(mesa_format format)
|
||||
{
|
||||
switch (format) {
|
||||
case MESA_FORMAT_S8_UINT_Z24_UNORM:
|
||||
case MESA_FORMAT_X8_UINT_Z24_UNORM:
|
||||
return pack_uint_S8_UINT_Z24_UNORM;
|
||||
case MESA_FORMAT_Z24_UNORM_S8_UINT:
|
||||
case MESA_FORMAT_Z24_UNORM_X8_UINT:
|
||||
return pack_uint_Z24_UNORM_S8_UINT;
|
||||
case MESA_FORMAT_Z_UNORM16:
|
||||
return pack_uint_Z_UNORM16;
|
||||
case MESA_FORMAT_Z_UNORM32:
|
||||
return pack_uint_Z_UNORM32;
|
||||
case MESA_FORMAT_Z_FLOAT32:
|
||||
case MESA_FORMAT_Z32_FLOAT_S8X24_UINT:
|
||||
return pack_uint_Z_FLOAT32;
|
||||
default:
|
||||
unreachable("unexpected format in get_pack_uint_z_func()");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Put an array of 32-bit z values into the depth buffer.
|
||||
* Note: the z values are always in the range [0, 2^32-1].
|
||||
*/
|
||||
static void
|
||||
put_z32_values(struct gl_context *ctx, struct gl_renderbuffer *rb,
|
||||
GLuint count, const GLint x[], const GLint y[],
|
||||
const GLuint zvalues[], const GLubyte mask[])
|
||||
{
|
||||
struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
|
||||
const GLint w = rb->Width, h = rb->Height;
|
||||
GLubyte *map = _swrast_pixel_address(rb, 0, 0);
|
||||
GLuint i;
|
||||
|
||||
if (rb->Format == MESA_FORMAT_Z_UNORM32) {
|
||||
const GLint rowStride = srb->RowStride;
|
||||
for (i = 0; i < count; i++) {
|
||||
if (mask[i] && x[i] >= 0 && y[i] >= 0 && x[i] < w && y[i] < h) {
|
||||
GLuint *dst = (GLuint *) (map + y[i] * rowStride + x[i] * 4);
|
||||
*dst = zvalues[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
mesa_pack_uint_z_func packZ = get_pack_uint_z_func(rb->Format);
|
||||
const GLint bpp = _mesa_get_format_bytes(rb->Format);
|
||||
const GLint rowStride = srb->RowStride;
|
||||
for (i = 0; i < count; i++) {
|
||||
if (mask[i] && x[i] >= 0 && y[i] >= 0 && x[i] < w && y[i] < h) {
|
||||
void *dst = map + y[i] * rowStride + x[i] * bpp;
|
||||
packZ(zvalues + i, dst);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Apply depth (Z) buffer testing to the span.
|
||||
* \return approx number of pixels that passed (only zero is reliable)
|
||||
*/
|
||||
GLuint
|
||||
_swrast_depth_test_span(struct gl_context *ctx, SWspan *span)
|
||||
{
|
||||
struct gl_framebuffer *fb = ctx->DrawBuffer;
|
||||
struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
|
||||
const GLint bpp = _mesa_get_format_bytes(rb->Format);
|
||||
void *zStart;
|
||||
const GLuint count = span->end;
|
||||
const GLuint *fragZ = span->array->z;
|
||||
GLubyte *mask = span->array->mask;
|
||||
void *zBufferVals;
|
||||
GLuint *zBufferTemp = NULL;
|
||||
GLuint passed;
|
||||
GLuint zBits = _mesa_get_format_bits(rb->Format, GL_DEPTH_BITS);
|
||||
GLboolean ztest16 = GL_FALSE;
|
||||
|
||||
if (span->arrayMask & SPAN_XY)
|
||||
zStart = NULL;
|
||||
else
|
||||
zStart = _swrast_pixel_address(rb, span->x, span->y);
|
||||
|
||||
if (rb->Format == MESA_FORMAT_Z_UNORM16 && !(span->arrayMask & SPAN_XY)) {
|
||||
/* directly read/write row of 16-bit Z values */
|
||||
zBufferVals = zStart;
|
||||
ztest16 = GL_TRUE;
|
||||
}
|
||||
else if (rb->Format == MESA_FORMAT_Z_UNORM32 && !(span->arrayMask & SPAN_XY)) {
|
||||
/* directly read/write row of 32-bit Z values */
|
||||
zBufferVals = zStart;
|
||||
}
|
||||
else {
|
||||
/* copy Z buffer values into temp buffer (32-bit Z values) */
|
||||
zBufferTemp = malloc(count * sizeof(GLuint));
|
||||
if (!zBufferTemp)
|
||||
return 0;
|
||||
|
||||
if (span->arrayMask & SPAN_XY) {
|
||||
get_z32_values(ctx, rb, count,
|
||||
span->array->x, span->array->y, zBufferTemp);
|
||||
}
|
||||
else {
|
||||
_mesa_unpack_uint_z_row(rb->Format, count, zStart, zBufferTemp);
|
||||
}
|
||||
|
||||
if (zBits == 24) {
|
||||
GLuint i;
|
||||
/* Convert depth buffer values from 32 to 24 bits to match the
|
||||
* fragment Z values generated by rasterization.
|
||||
*/
|
||||
for (i = 0; i < count; i++) {
|
||||
zBufferTemp[i] >>= 8;
|
||||
}
|
||||
}
|
||||
else if (zBits == 16) {
|
||||
GLuint i;
|
||||
/* Convert depth buffer values from 32 to 16 bits */
|
||||
for (i = 0; i < count; i++) {
|
||||
zBufferTemp[i] >>= 16;
|
||||
}
|
||||
}
|
||||
else {
|
||||
assert(zBits == 32);
|
||||
}
|
||||
|
||||
zBufferVals = zBufferTemp;
|
||||
}
|
||||
|
||||
/* do the depth test either with 16 or 32-bit values */
|
||||
if (ztest16)
|
||||
passed = depth_test_span16(ctx, count, zBufferVals, fragZ, mask);
|
||||
else
|
||||
passed = depth_test_span32(ctx, count, zBufferVals, fragZ, mask);
|
||||
|
||||
if (zBufferTemp) {
|
||||
/* need to write temp Z values back into the buffer */
|
||||
|
||||
/* Convert depth buffer values back to 32-bit values. The least
|
||||
* significant bits don't matter since they'll get dropped when
|
||||
* they're packed back into the depth buffer.
|
||||
*/
|
||||
if (zBits == 24) {
|
||||
GLuint i;
|
||||
for (i = 0; i < count; i++) {
|
||||
zBufferTemp[i] = (zBufferTemp[i] << 8);
|
||||
}
|
||||
}
|
||||
else if (zBits == 16) {
|
||||
GLuint i;
|
||||
for (i = 0; i < count; i++) {
|
||||
zBufferTemp[i] = zBufferTemp[i] << 16;
|
||||
}
|
||||
}
|
||||
|
||||
if (span->arrayMask & SPAN_XY) {
|
||||
/* random locations */
|
||||
put_z32_values(ctx, rb, count, span->array->x, span->array->y,
|
||||
zBufferTemp, mask);
|
||||
}
|
||||
else {
|
||||
/* horizontal row */
|
||||
mesa_pack_uint_z_func packZ = get_pack_uint_z_func(rb->Format);
|
||||
GLubyte *dst = zStart;
|
||||
GLuint i;
|
||||
for (i = 0; i < count; i++) {
|
||||
if (mask[i]) {
|
||||
packZ(&zBufferTemp[i], dst);
|
||||
}
|
||||
dst += bpp;
|
||||
}
|
||||
}
|
||||
|
||||
free(zBufferTemp);
|
||||
}
|
||||
|
||||
if (passed < count) {
|
||||
span->writeAll = GL_FALSE;
|
||||
}
|
||||
return passed;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* GL_EXT_depth_bounds_test extension.
|
||||
* Discard fragments depending on whether the corresponding Z-buffer
|
||||
* values are outside the depth bounds test range.
|
||||
* Note: we test the Z buffer values, not the fragment Z values!
|
||||
* \return GL_TRUE if any fragments pass, GL_FALSE if no fragments pass
|
||||
*/
|
||||
GLboolean
|
||||
_swrast_depth_bounds_test( struct gl_context *ctx, SWspan *span )
|
||||
{
|
||||
struct gl_framebuffer *fb = ctx->DrawBuffer;
|
||||
struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
|
||||
GLubyte *zStart;
|
||||
GLuint zMin = (GLuint)((double)ctx->Depth.BoundsMin * 0xffffffff);
|
||||
GLuint zMax = (GLuint)((double)ctx->Depth.BoundsMax * 0xffffffff);
|
||||
GLubyte *mask = span->array->mask;
|
||||
const GLuint count = span->end;
|
||||
GLuint i;
|
||||
GLboolean anyPass = GL_FALSE;
|
||||
GLuint *zBufferTemp;
|
||||
const GLuint *zBufferVals;
|
||||
|
||||
zBufferTemp = malloc(count * sizeof(GLuint));
|
||||
if (!zBufferTemp) {
|
||||
/* don't generate a stream of OUT_OF_MEMORY errors here */
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
if (span->arrayMask & SPAN_XY)
|
||||
zStart = NULL;
|
||||
else
|
||||
zStart = _swrast_pixel_address(rb, span->x, span->y);
|
||||
|
||||
if (rb->Format == MESA_FORMAT_Z_UNORM32 && !(span->arrayMask & SPAN_XY)) {
|
||||
/* directly access 32-bit values in the depth buffer */
|
||||
zBufferVals = (const GLuint *) zStart;
|
||||
}
|
||||
else {
|
||||
/* Round the bounds to the precision of the zbuffer. */
|
||||
if (rb->Format == MESA_FORMAT_Z_UNORM16) {
|
||||
zMin = (zMin & 0xffff0000) | (zMin >> 16);
|
||||
zMax = (zMax & 0xffff0000) | (zMax >> 16);
|
||||
} else {
|
||||
/* 24 bits */
|
||||
zMin = (zMin & 0xffffff00) | (zMin >> 24);
|
||||
zMax = (zMax & 0xffffff00) | (zMax >> 24);
|
||||
}
|
||||
|
||||
/* unpack Z values into a temporary array */
|
||||
if (span->arrayMask & SPAN_XY) {
|
||||
get_z32_values(ctx, rb, count, span->array->x, span->array->y,
|
||||
zBufferTemp);
|
||||
}
|
||||
else {
|
||||
_mesa_unpack_uint_z_row(rb->Format, count, zStart, zBufferTemp);
|
||||
}
|
||||
zBufferVals = zBufferTemp;
|
||||
}
|
||||
|
||||
/* Now do the tests */
|
||||
for (i = 0; i < count; i++) {
|
||||
if (mask[i]) {
|
||||
if (zBufferVals[i] < zMin || zBufferVals[i] > zMax)
|
||||
mask[i] = GL_FALSE;
|
||||
else
|
||||
anyPass = GL_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
free(zBufferTemp);
|
||||
|
||||
return anyPass;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**********************************************************************/
|
||||
/***** Read Depth Buffer *****/
|
||||
/**********************************************************************/
|
||||
|
||||
|
||||
/**
|
||||
* Read a span of depth values from the given depth renderbuffer, returning
|
||||
* the values as GLfloats.
|
||||
* This function does clipping to prevent reading outside the depth buffer's
|
||||
* bounds.
|
||||
*/
|
||||
void
|
||||
_swrast_read_depth_span_float(struct gl_context *ctx,
|
||||
struct gl_renderbuffer *rb,
|
||||
GLint n, GLint x, GLint y, GLfloat depth[])
|
||||
{
|
||||
if (!rb) {
|
||||
/* really only doing this to prevent FP exceptions later */
|
||||
memset(depth, 0, n * sizeof(GLfloat));
|
||||
return;
|
||||
}
|
||||
|
||||
if (y < 0 || y >= (GLint) rb->Height ||
|
||||
x + n <= 0 || x >= (GLint) rb->Width) {
|
||||
/* span is completely outside framebuffer */
|
||||
memset(depth, 0, n * sizeof(GLfloat));
|
||||
return;
|
||||
}
|
||||
|
||||
if (x < 0) {
|
||||
GLint dx = -x;
|
||||
GLint i;
|
||||
for (i = 0; i < dx; i++)
|
||||
depth[i] = 0.0;
|
||||
x = 0;
|
||||
n -= dx;
|
||||
depth += dx;
|
||||
}
|
||||
if (x + n > (GLint) rb->Width) {
|
||||
GLint dx = x + n - (GLint) rb->Width;
|
||||
GLint i;
|
||||
for (i = 0; i < dx; i++)
|
||||
depth[n - i - 1] = 0.0;
|
||||
n -= dx;
|
||||
}
|
||||
if (n <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
_mesa_unpack_float_z_row(rb->Format, n, _swrast_pixel_address(rb, x, y),
|
||||
depth);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clear the given z/depth renderbuffer. If the buffer is a combined
|
||||
* depth+stencil buffer, only the Z bits will be touched.
|
||||
*/
|
||||
void
|
||||
_swrast_clear_depth_buffer(struct gl_context *ctx)
|
||||
{
|
||||
struct gl_renderbuffer *rb =
|
||||
ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
|
||||
GLint x, y, width, height;
|
||||
GLubyte *map;
|
||||
GLint rowStride, i, j;
|
||||
GLbitfield mapMode;
|
||||
|
||||
if (!rb || !ctx->Depth.Mask) {
|
||||
/* no depth buffer, or writing to it is disabled */
|
||||
return;
|
||||
}
|
||||
|
||||
/* compute region to clear */
|
||||
x = ctx->DrawBuffer->_Xmin;
|
||||
y = ctx->DrawBuffer->_Ymin;
|
||||
width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
|
||||
height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
|
||||
|
||||
mapMode = GL_MAP_WRITE_BIT;
|
||||
if (rb->Format == MESA_FORMAT_Z24_UNORM_S8_UINT ||
|
||||
rb->Format == MESA_FORMAT_Z24_UNORM_X8_UINT ||
|
||||
rb->Format == MESA_FORMAT_S8_UINT_Z24_UNORM ||
|
||||
rb->Format == MESA_FORMAT_X8_UINT_Z24_UNORM) {
|
||||
mapMode |= GL_MAP_READ_BIT;
|
||||
}
|
||||
|
||||
ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height,
|
||||
mapMode, &map, &rowStride,
|
||||
ctx->DrawBuffer->FlipY);
|
||||
if (!map) {
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glClear(depth)");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (rb->Format) {
|
||||
case MESA_FORMAT_Z_UNORM16:
|
||||
{
|
||||
GLfloat clear = (GLfloat) ctx->Depth.Clear;
|
||||
GLushort clearVal = 0;
|
||||
_mesa_pack_float_z_row(rb->Format, 1, &clear, &clearVal);
|
||||
if (clearVal == 0xffff && width * 2 == rowStride) {
|
||||
/* common case */
|
||||
memset(map, 0xff, width * height * 2);
|
||||
}
|
||||
else {
|
||||
for (i = 0; i < height; i++) {
|
||||
GLushort *row = (GLushort *) map;
|
||||
for (j = 0; j < width; j++) {
|
||||
row[j] = clearVal;
|
||||
}
|
||||
map += rowStride;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MESA_FORMAT_Z_UNORM32:
|
||||
case MESA_FORMAT_Z_FLOAT32:
|
||||
{
|
||||
GLfloat clear = (GLfloat) ctx->Depth.Clear;
|
||||
GLuint clearVal = 0;
|
||||
_mesa_pack_float_z_row(rb->Format, 1, &clear, &clearVal);
|
||||
for (i = 0; i < height; i++) {
|
||||
GLuint *row = (GLuint *) map;
|
||||
for (j = 0; j < width; j++) {
|
||||
row[j] = clearVal;
|
||||
}
|
||||
map += rowStride;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MESA_FORMAT_Z24_UNORM_S8_UINT:
|
||||
case MESA_FORMAT_Z24_UNORM_X8_UINT:
|
||||
case MESA_FORMAT_S8_UINT_Z24_UNORM:
|
||||
case MESA_FORMAT_X8_UINT_Z24_UNORM:
|
||||
{
|
||||
GLfloat clear = (GLfloat) ctx->Depth.Clear;
|
||||
GLuint clearVal = 0;
|
||||
GLuint mask;
|
||||
|
||||
if (rb->Format == MESA_FORMAT_Z24_UNORM_S8_UINT ||
|
||||
rb->Format == MESA_FORMAT_Z24_UNORM_X8_UINT)
|
||||
mask = 0xff000000;
|
||||
else
|
||||
mask = 0xff;
|
||||
|
||||
_mesa_pack_float_z_row(rb->Format, 1, &clear, &clearVal);
|
||||
for (i = 0; i < height; i++) {
|
||||
GLuint *row = (GLuint *) map;
|
||||
for (j = 0; j < width; j++) {
|
||||
row[j] = (row[j] & mask) | clearVal;
|
||||
}
|
||||
map += rowStride;
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
case MESA_FORMAT_Z32_FLOAT_S8X24_UINT:
|
||||
/* XXX untested */
|
||||
{
|
||||
GLfloat clearVal = (GLfloat) ctx->Depth.Clear;
|
||||
for (i = 0; i < height; i++) {
|
||||
GLfloat *row = (GLfloat *) map;
|
||||
for (j = 0; j < width; j++) {
|
||||
row[j * 2] = clearVal;
|
||||
}
|
||||
map += rowStride;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
_mesa_problem(ctx, "Unexpected depth buffer format %s"
|
||||
" in _swrast_clear_depth_buffer()",
|
||||
_mesa_get_format_name(rb->Format));
|
||||
}
|
||||
|
||||
ctx->Driver.UnmapRenderbuffer(ctx, rb);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Clear both depth and stencil values in a combined depth+stencil buffer.
|
||||
*/
|
||||
void
|
||||
_swrast_clear_depth_stencil_buffer(struct gl_context *ctx)
|
||||
{
|
||||
const GLubyte stencilBits = ctx->DrawBuffer->Visual.stencilBits;
|
||||
const GLuint writeMask = ctx->Stencil.WriteMask[0];
|
||||
const GLuint stencilMax = (1 << stencilBits) - 1;
|
||||
struct gl_renderbuffer *rb =
|
||||
ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
|
||||
GLint x, y, width, height;
|
||||
GLbitfield mapMode;
|
||||
GLubyte *map;
|
||||
GLint rowStride, i, j;
|
||||
|
||||
/* check that we really have a combined depth+stencil buffer */
|
||||
assert(rb == ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer);
|
||||
|
||||
/* compute region to clear */
|
||||
x = ctx->DrawBuffer->_Xmin;
|
||||
y = ctx->DrawBuffer->_Ymin;
|
||||
width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
|
||||
height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
|
||||
|
||||
mapMode = GL_MAP_WRITE_BIT;
|
||||
if ((writeMask & stencilMax) != stencilMax) {
|
||||
/* need to mask stencil values */
|
||||
mapMode |= GL_MAP_READ_BIT;
|
||||
}
|
||||
|
||||
ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height,
|
||||
mapMode, &map, &rowStride,
|
||||
ctx->DrawBuffer->FlipY);
|
||||
if (!map) {
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glClear(depth+stencil)");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (rb->Format) {
|
||||
case MESA_FORMAT_Z24_UNORM_S8_UINT:
|
||||
case MESA_FORMAT_S8_UINT_Z24_UNORM:
|
||||
{
|
||||
GLfloat zClear = (GLfloat) ctx->Depth.Clear;
|
||||
GLuint clear = 0, mask;
|
||||
|
||||
_mesa_pack_float_z_row(rb->Format, 1, &zClear, &clear);
|
||||
|
||||
if (rb->Format == MESA_FORMAT_Z24_UNORM_S8_UINT) {
|
||||
mask = ((~writeMask) & 0xff) << 24;
|
||||
clear |= (ctx->Stencil.Clear & writeMask & 0xff) << 24;
|
||||
}
|
||||
else {
|
||||
mask = ((~writeMask) & 0xff);
|
||||
clear |= (ctx->Stencil.Clear & writeMask & 0xff);
|
||||
}
|
||||
|
||||
for (i = 0; i < height; i++) {
|
||||
GLuint *row = (GLuint *) map;
|
||||
if (mask != 0x0) {
|
||||
for (j = 0; j < width; j++) {
|
||||
row[j] = (row[j] & mask) | clear;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (j = 0; j < width; j++) {
|
||||
row[j] = clear;
|
||||
}
|
||||
}
|
||||
map += rowStride;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MESA_FORMAT_Z32_FLOAT_S8X24_UINT:
|
||||
/* XXX untested */
|
||||
{
|
||||
const GLfloat zClear = (GLfloat) ctx->Depth.Clear;
|
||||
const GLuint sClear = ctx->Stencil.Clear & writeMask;
|
||||
const GLuint sMask = (~writeMask) & 0xff;
|
||||
for (i = 0; i < height; i++) {
|
||||
GLfloat *zRow = (GLfloat *) map;
|
||||
GLuint *sRow = (GLuint *) map;
|
||||
for (j = 0; j < width; j++) {
|
||||
zRow[j * 2 + 0] = zClear;
|
||||
}
|
||||
if (sMask != 0) {
|
||||
for (j = 0; j < width; j++) {
|
||||
sRow[j * 2 + 1] = (sRow[j * 2 + 1] & sMask) | sClear;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (j = 0; j < width; j++) {
|
||||
sRow[j * 2 + 1] = sClear;
|
||||
}
|
||||
}
|
||||
map += rowStride;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
_mesa_problem(ctx, "Unexpected depth buffer format %s"
|
||||
" in _swrast_clear_depth_buffer()",
|
||||
_mesa_get_format_name(rb->Format));
|
||||
}
|
||||
|
||||
ctx->Driver.UnmapRenderbuffer(ctx, rb);
|
||||
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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 S_DEPTH_H
|
||||
#define S_DEPTH_H
|
||||
|
||||
|
||||
#include "main/glheader.h"
|
||||
#include "s_span.h"
|
||||
|
||||
struct gl_context;
|
||||
struct gl_renderbuffer;
|
||||
|
||||
|
||||
extern GLuint
|
||||
_swrast_depth_test_span( struct gl_context *ctx, SWspan *span);
|
||||
|
||||
extern void
|
||||
_swrast_depth_clamp_span( struct gl_context *ctx, SWspan *span );
|
||||
|
||||
extern GLboolean
|
||||
_swrast_depth_bounds_test( struct gl_context *ctx, SWspan *span );
|
||||
|
||||
|
||||
extern void
|
||||
_swrast_read_depth_span_float( struct gl_context *ctx, struct gl_renderbuffer *rb,
|
||||
GLint n, GLint x, GLint y, GLfloat depth[] );
|
||||
|
||||
extern void
|
||||
_swrast_clear_depth_buffer(struct gl_context *ctx);
|
||||
|
||||
extern void
|
||||
_swrast_clear_depth_stencil_buffer(struct gl_context *ctx);
|
||||
|
||||
|
||||
#endif
|
|
@ -1,791 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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/bufferobj.h"
|
||||
#include "main/colormac.h"
|
||||
#include "main/condrender.h"
|
||||
#include "main/context.h"
|
||||
#include "main/format_pack.h"
|
||||
#include "main/format_utils.h"
|
||||
#include "main/glformats.h"
|
||||
#include "main/image.h"
|
||||
|
||||
#include "main/macros.h"
|
||||
#include "main/pack.h"
|
||||
#include "main/pbo.h"
|
||||
#include "main/pixeltransfer.h"
|
||||
#include "main/state.h"
|
||||
|
||||
#include "s_context.h"
|
||||
#include "s_span.h"
|
||||
#include "s_stencil.h"
|
||||
#include "s_zoom.h"
|
||||
|
||||
|
||||
/**
|
||||
* Handle a common case of drawing GL_RGB/GL_UNSIGNED_BYTE into a
|
||||
* MESA_FORMAT_XRGB888 or MESA_FORMAT_ARGB888 renderbuffer.
|
||||
*/
|
||||
static void
|
||||
fast_draw_rgb_ubyte_pixels(struct gl_context *ctx,
|
||||
struct gl_renderbuffer *rb,
|
||||
GLint x, GLint y,
|
||||
GLsizei width, GLsizei height,
|
||||
const struct gl_pixelstore_attrib *unpack,
|
||||
const GLvoid *pixels,
|
||||
bool flip_y)
|
||||
{
|
||||
const GLubyte *src = (const GLubyte *)
|
||||
_mesa_image_address2d(unpack, pixels, width,
|
||||
height, GL_RGB, GL_UNSIGNED_BYTE, 0, 0);
|
||||
const GLint srcRowStride = _mesa_image_row_stride(unpack, width,
|
||||
GL_RGB, GL_UNSIGNED_BYTE);
|
||||
GLint i, j;
|
||||
GLubyte *dst;
|
||||
GLint dstRowStride;
|
||||
|
||||
ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height,
|
||||
GL_MAP_WRITE_BIT, &dst, &dstRowStride,
|
||||
flip_y);
|
||||
|
||||
if (!dst) {
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ctx->Pixel.ZoomY == -1.0f) {
|
||||
dst = dst + (height - 1) * dstRowStride;
|
||||
dstRowStride = -dstRowStride;
|
||||
}
|
||||
|
||||
for (i = 0; i < height; i++) {
|
||||
GLuint *dst4 = (GLuint *) dst;
|
||||
for (j = 0; j < width; j++) {
|
||||
dst4[j] = PACK_COLOR_8888(0xff, src[j*3+0], src[j*3+1], src[j*3+2]);
|
||||
}
|
||||
dst += dstRowStride;
|
||||
src += srcRowStride;
|
||||
}
|
||||
|
||||
ctx->Driver.UnmapRenderbuffer(ctx, rb);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle a common case of drawing GL_RGBA/GL_UNSIGNED_BYTE into a
|
||||
* MESA_FORMAT_ARGB888 or MESA_FORMAT_xRGB888 renderbuffer.
|
||||
*/
|
||||
static void
|
||||
fast_draw_rgba_ubyte_pixels(struct gl_context *ctx,
|
||||
struct gl_renderbuffer *rb,
|
||||
GLint x, GLint y,
|
||||
GLsizei width, GLsizei height,
|
||||
const struct gl_pixelstore_attrib *unpack,
|
||||
const GLvoid *pixels,
|
||||
bool flip_y)
|
||||
{
|
||||
const GLubyte *src = (const GLubyte *)
|
||||
_mesa_image_address2d(unpack, pixels, width,
|
||||
height, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0);
|
||||
const GLint srcRowStride =
|
||||
_mesa_image_row_stride(unpack, width, GL_RGBA, GL_UNSIGNED_BYTE);
|
||||
GLint i, j;
|
||||
GLubyte *dst;
|
||||
GLint dstRowStride;
|
||||
|
||||
ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height,
|
||||
GL_MAP_WRITE_BIT, &dst, &dstRowStride,
|
||||
flip_y);
|
||||
|
||||
if (!dst) {
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ctx->Pixel.ZoomY == -1.0f) {
|
||||
dst = dst + (height - 1) * dstRowStride;
|
||||
dstRowStride = -dstRowStride;
|
||||
}
|
||||
|
||||
for (i = 0; i < height; i++) {
|
||||
GLuint *dst4 = (GLuint *) dst;
|
||||
for (j = 0; j < width; j++) {
|
||||
dst4[j] = PACK_COLOR_8888(src[j*4+3], src[j*4+0],
|
||||
src[j*4+1], src[j*4+2]);
|
||||
}
|
||||
dst += dstRowStride;
|
||||
src += srcRowStride;
|
||||
}
|
||||
|
||||
ctx->Driver.UnmapRenderbuffer(ctx, rb);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle a common case of drawing a format/type combination that
|
||||
* exactly matches the renderbuffer format.
|
||||
*/
|
||||
static void
|
||||
fast_draw_generic_pixels(struct gl_context *ctx,
|
||||
struct gl_renderbuffer *rb,
|
||||
GLint x, GLint y,
|
||||
GLsizei width, GLsizei height,
|
||||
GLenum format, GLenum type,
|
||||
const struct gl_pixelstore_attrib *unpack,
|
||||
const GLvoid *pixels,
|
||||
bool flip_y)
|
||||
{
|
||||
const GLubyte *src = (const GLubyte *)
|
||||
_mesa_image_address2d(unpack, pixels, width,
|
||||
height, format, type, 0, 0);
|
||||
const GLint srcRowStride =
|
||||
_mesa_image_row_stride(unpack, width, format, type);
|
||||
const GLint rowLength = width * _mesa_get_format_bytes(rb->Format);
|
||||
GLint i;
|
||||
GLubyte *dst;
|
||||
GLint dstRowStride;
|
||||
|
||||
ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height,
|
||||
GL_MAP_WRITE_BIT, &dst, &dstRowStride,
|
||||
flip_y);
|
||||
|
||||
if (!dst) {
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ctx->Pixel.ZoomY == -1.0f) {
|
||||
dst = dst + (height - 1) * dstRowStride;
|
||||
dstRowStride = -dstRowStride;
|
||||
}
|
||||
|
||||
for (i = 0; i < height; i++) {
|
||||
memcpy(dst, src, rowLength);
|
||||
dst += dstRowStride;
|
||||
src += srcRowStride;
|
||||
}
|
||||
|
||||
ctx->Driver.UnmapRenderbuffer(ctx, rb);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Try to do a fast and simple RGB(a) glDrawPixels.
|
||||
* Return: GL_TRUE if success, GL_FALSE if slow path must be used instead
|
||||
*/
|
||||
static GLboolean
|
||||
fast_draw_rgba_pixels(struct gl_context *ctx, GLint x, GLint y,
|
||||
GLsizei width, GLsizei height,
|
||||
GLenum format, GLenum type,
|
||||
const struct gl_pixelstore_attrib *userUnpack,
|
||||
const GLvoid *pixels)
|
||||
{
|
||||
struct gl_framebuffer *fb = ctx->DrawBuffer;
|
||||
struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0];
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
struct gl_pixelstore_attrib unpack;
|
||||
|
||||
if (!rb)
|
||||
return GL_TRUE; /* no-op */
|
||||
|
||||
if (ctx->DrawBuffer->_NumColorDrawBuffers > 1 ||
|
||||
(swrast->_RasterMask & ~CLIP_BIT) ||
|
||||
ctx->Texture._EnabledCoordUnits ||
|
||||
userUnpack->SwapBytes ||
|
||||
ctx->Pixel.ZoomX != 1.0f ||
|
||||
fabsf(ctx->Pixel.ZoomY) != 1.0f ||
|
||||
ctx->_ImageTransferState) {
|
||||
/* can't handle any of those conditions */
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
unpack = *userUnpack;
|
||||
|
||||
/* clipping */
|
||||
if (!_mesa_clip_drawpixels(ctx, &x, &y, &width, &height, &unpack)) {
|
||||
/* image was completely clipped: no-op, all done */
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
if (format == GL_RGB &&
|
||||
type == GL_UNSIGNED_BYTE &&
|
||||
(rb->Format == MESA_FORMAT_B8G8R8X8_UNORM ||
|
||||
rb->Format == MESA_FORMAT_B8G8R8A8_UNORM)) {
|
||||
fast_draw_rgb_ubyte_pixels(ctx, rb, x, y, width, height,
|
||||
&unpack, pixels, fb->FlipY);
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
if (format == GL_RGBA &&
|
||||
type == GL_UNSIGNED_BYTE &&
|
||||
(rb->Format == MESA_FORMAT_B8G8R8X8_UNORM ||
|
||||
rb->Format == MESA_FORMAT_B8G8R8A8_UNORM)) {
|
||||
fast_draw_rgba_ubyte_pixels(ctx, rb, x, y, width, height,
|
||||
&unpack, pixels, fb->FlipY);
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
if (_mesa_format_matches_format_and_type(rb->Format, format, type,
|
||||
ctx->Unpack.SwapBytes, NULL)) {
|
||||
fast_draw_generic_pixels(ctx, rb, x, y, width, height,
|
||||
format, type, &unpack, pixels,
|
||||
fb->FlipY);
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
/* can't handle this pixel format and/or data type */
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Draw stencil image.
|
||||
*/
|
||||
static void
|
||||
draw_stencil_pixels( struct gl_context *ctx, GLint x, GLint y,
|
||||
GLsizei width, GLsizei height,
|
||||
GLenum type,
|
||||
const struct gl_pixelstore_attrib *unpack,
|
||||
const GLvoid *pixels )
|
||||
{
|
||||
const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
|
||||
const GLenum destType = GL_UNSIGNED_BYTE;
|
||||
GLint row;
|
||||
GLubyte *values;
|
||||
|
||||
values = malloc(width * sizeof(GLubyte));
|
||||
if (!values) {
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
|
||||
return;
|
||||
}
|
||||
|
||||
for (row = 0; row < height; row++) {
|
||||
const GLvoid *source = _mesa_image_address2d(unpack, pixels,
|
||||
width, height,
|
||||
GL_STENCIL_INDEX, type,
|
||||
row, 0);
|
||||
_mesa_unpack_stencil_span(ctx, width, destType, values,
|
||||
type, source, unpack,
|
||||
ctx->_ImageTransferState);
|
||||
if (zoom) {
|
||||
_swrast_write_zoomed_stencil_span(ctx, x, y, width,
|
||||
x, y, values);
|
||||
}
|
||||
else {
|
||||
_swrast_write_stencil_span(ctx, width, x, y, values);
|
||||
}
|
||||
|
||||
y++;
|
||||
}
|
||||
|
||||
free(values);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Draw depth image.
|
||||
*/
|
||||
static void
|
||||
draw_depth_pixels( struct gl_context *ctx, GLint x, GLint y,
|
||||
GLsizei width, GLsizei height,
|
||||
GLenum type,
|
||||
const struct gl_pixelstore_attrib *unpack,
|
||||
const GLvoid *pixels )
|
||||
{
|
||||
const GLboolean scaleOrBias
|
||||
= ctx->Pixel.DepthScale != 1.0f || ctx->Pixel.DepthBias != 0.0f;
|
||||
const GLboolean zoom = ctx->Pixel.ZoomX != 1.0f || ctx->Pixel.ZoomY != 1.0f;
|
||||
SWspan span;
|
||||
|
||||
INIT_SPAN(span, GL_BITMAP);
|
||||
span.arrayMask = SPAN_Z;
|
||||
_swrast_span_default_attribs(ctx, &span);
|
||||
|
||||
if (type == GL_UNSIGNED_SHORT
|
||||
&& ctx->DrawBuffer->Visual.depthBits == 16
|
||||
&& !scaleOrBias
|
||||
&& !zoom
|
||||
&& width <= SWRAST_MAX_WIDTH
|
||||
&& !unpack->SwapBytes) {
|
||||
/* Special case: directly write 16-bit depth values */
|
||||
GLint row;
|
||||
for (row = 0; row < height; row++) {
|
||||
const GLushort *zSrc = (const GLushort *)
|
||||
_mesa_image_address2d(unpack, pixels, width, height,
|
||||
GL_DEPTH_COMPONENT, type, row, 0);
|
||||
GLint i;
|
||||
for (i = 0; i < width; i++)
|
||||
span.array->z[i] = zSrc[i];
|
||||
span.x = x;
|
||||
span.y = y + row;
|
||||
span.end = width;
|
||||
_swrast_write_rgba_span(ctx, &span);
|
||||
}
|
||||
}
|
||||
else if (type == GL_UNSIGNED_INT
|
||||
&& !scaleOrBias
|
||||
&& !zoom
|
||||
&& width <= SWRAST_MAX_WIDTH
|
||||
&& !unpack->SwapBytes) {
|
||||
/* Special case: shift 32-bit values down to Visual.depthBits */
|
||||
const GLint shift = 32 - ctx->DrawBuffer->Visual.depthBits;
|
||||
GLint row;
|
||||
for (row = 0; row < height; row++) {
|
||||
const GLuint *zSrc = (const GLuint *)
|
||||
_mesa_image_address2d(unpack, pixels, width, height,
|
||||
GL_DEPTH_COMPONENT, type, row, 0);
|
||||
if (shift == 0) {
|
||||
memcpy(span.array->z, zSrc, width * sizeof(GLuint));
|
||||
}
|
||||
else {
|
||||
GLint col;
|
||||
for (col = 0; col < width; col++)
|
||||
span.array->z[col] = zSrc[col] >> shift;
|
||||
}
|
||||
span.x = x;
|
||||
span.y = y + row;
|
||||
span.end = width;
|
||||
_swrast_write_rgba_span(ctx, &span);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* General case */
|
||||
const GLuint depthMax = ctx->DrawBuffer->_DepthMax;
|
||||
GLint skipPixels = 0;
|
||||
|
||||
/* in case width > SWRAST_MAX_WIDTH do the copy in chunks */
|
||||
while (skipPixels < width) {
|
||||
const GLint spanWidth = MIN2(width - skipPixels, SWRAST_MAX_WIDTH);
|
||||
GLint row;
|
||||
assert(span.end <= SWRAST_MAX_WIDTH);
|
||||
for (row = 0; row < height; row++) {
|
||||
const GLvoid *zSrc = _mesa_image_address2d(unpack,
|
||||
pixels, width, height,
|
||||
GL_DEPTH_COMPONENT, type,
|
||||
row, skipPixels);
|
||||
|
||||
/* Set these for each row since the _swrast_write_* function may
|
||||
* change them while clipping.
|
||||
*/
|
||||
span.x = x + skipPixels;
|
||||
span.y = y + row;
|
||||
span.end = spanWidth;
|
||||
|
||||
_mesa_unpack_depth_span(ctx, spanWidth,
|
||||
GL_UNSIGNED_INT, span.array->z, depthMax,
|
||||
type, zSrc, unpack);
|
||||
if (zoom) {
|
||||
_swrast_write_zoomed_depth_span(ctx, x, y, &span);
|
||||
}
|
||||
else {
|
||||
_swrast_write_rgba_span(ctx, &span);
|
||||
}
|
||||
}
|
||||
skipPixels += spanWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Draw RGBA image.
|
||||
*/
|
||||
static void
|
||||
draw_rgba_pixels( 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 )
|
||||
{
|
||||
const GLint imgX = x, imgY = y;
|
||||
const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
|
||||
GLbitfield transferOps = ctx->_ImageTransferState;
|
||||
SWspan span;
|
||||
|
||||
/* Try an optimized glDrawPixels first */
|
||||
if (fast_draw_rgba_pixels(ctx, x, y, width, height, format, type,
|
||||
unpack, pixels)) {
|
||||
return;
|
||||
}
|
||||
|
||||
swrast_render_start(ctx);
|
||||
|
||||
INIT_SPAN(span, GL_BITMAP);
|
||||
_swrast_span_default_attribs(ctx, &span);
|
||||
span.arrayMask = SPAN_RGBA;
|
||||
span.arrayAttribs = VARYING_BIT_COL0; /* we're fill in COL0 attrib values */
|
||||
|
||||
if (ctx->DrawBuffer->_NumColorDrawBuffers > 0) {
|
||||
GLenum datatype = _mesa_get_format_datatype(
|
||||
ctx->DrawBuffer->_ColorDrawBuffers[0]->Format);
|
||||
if (datatype != GL_FLOAT &&
|
||||
ctx->Color.ClampFragmentColor != GL_FALSE) {
|
||||
/* need to clamp colors before applying fragment ops */
|
||||
transferOps |= IMAGE_CLAMP_BIT;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* General solution
|
||||
*/
|
||||
{
|
||||
const GLbitfield interpMask = span.interpMask;
|
||||
const GLbitfield arrayMask = span.arrayMask;
|
||||
GLint skipPixels = 0;
|
||||
/* use span array for temp color storage */
|
||||
GLfloat *rgba = (GLfloat *) span.array->attribs[VARYING_SLOT_COL0];
|
||||
void *tempImage = NULL;
|
||||
|
||||
/* We have to deal with GL_COLOR_INDEX manually because
|
||||
* _mesa_format_convert does not handle this format. So what we do here is
|
||||
* convert it to RGBA ubyte first and then convert from that to dst as
|
||||
* usual.
|
||||
*/
|
||||
if (format == GL_COLOR_INDEX) {
|
||||
/* This will handle byte swapping and transferops if needed */
|
||||
tempImage =
|
||||
_mesa_unpack_color_index_to_rgba_ubyte(ctx, 2,
|
||||
pixels, format, type,
|
||||
width, height, 1,
|
||||
unpack,
|
||||
transferOps);
|
||||
if (!tempImage) {
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
|
||||
return;
|
||||
}
|
||||
|
||||
transferOps = 0;
|
||||
pixels = tempImage;
|
||||
format = GL_RGBA;
|
||||
type = GL_UNSIGNED_BYTE;
|
||||
} else if (unpack->SwapBytes) {
|
||||
/* We have to handle byte-swapping scenarios before calling
|
||||
* _mesa_format_convert
|
||||
*/
|
||||
GLint swapSize = _mesa_sizeof_packed_type(type);
|
||||
if (swapSize == 2 || swapSize == 4) {
|
||||
int imageStride = _mesa_image_image_stride(unpack, width, height, format, type);
|
||||
|
||||
tempImage = malloc(imageStride);
|
||||
if (!tempImage) {
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
|
||||
return;
|
||||
}
|
||||
|
||||
_mesa_swap_bytes_2d_image(format, type, unpack,
|
||||
width, height, tempImage, pixels);
|
||||
|
||||
pixels = tempImage;
|
||||
}
|
||||
}
|
||||
|
||||
const GLint srcStride
|
||||
= _mesa_image_row_stride(unpack, width, format, type);
|
||||
|
||||
/* if the span is wider than SWRAST_MAX_WIDTH we have to do it in chunks */
|
||||
while (skipPixels < width) {
|
||||
const GLint spanWidth = MIN2(width - skipPixels, SWRAST_MAX_WIDTH);
|
||||
const GLubyte *source
|
||||
= (const GLubyte *) _mesa_image_address2d(unpack, pixels,
|
||||
width, height, format,
|
||||
type, 0, skipPixels);
|
||||
GLint row;
|
||||
|
||||
/* get image row as float/RGBA */
|
||||
uint32_t srcMesaFormat = _mesa_format_from_format_and_type(format, type);
|
||||
for (row = 0; row < height; row++) {
|
||||
int dstRowStride = 4 * width * sizeof(float);
|
||||
_mesa_format_convert(rgba, RGBA32_FLOAT, dstRowStride,
|
||||
(void*)source, srcMesaFormat, srcStride,
|
||||
spanWidth, 1, NULL);
|
||||
if (transferOps)
|
||||
_mesa_apply_rgba_transfer_ops(ctx, transferOps, spanWidth, (GLfloat (*)[4])rgba);
|
||||
/* Set these for each row since the _swrast_write_* functions
|
||||
* may change them while clipping/rendering.
|
||||
*/
|
||||
span.array->ChanType = GL_FLOAT;
|
||||
span.x = x + skipPixels;
|
||||
span.y = y + row;
|
||||
span.end = spanWidth;
|
||||
span.arrayMask = arrayMask;
|
||||
span.interpMask = interpMask;
|
||||
if (zoom) {
|
||||
_swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span, rgba);
|
||||
}
|
||||
else {
|
||||
_swrast_write_rgba_span(ctx, &span);
|
||||
}
|
||||
|
||||
source += srcStride;
|
||||
} /* for row */
|
||||
|
||||
skipPixels += spanWidth;
|
||||
} /* while skipPixels < width */
|
||||
|
||||
/* XXX this is ugly/temporary, to undo above change */
|
||||
span.array->ChanType = CHAN_TYPE;
|
||||
|
||||
free(tempImage);
|
||||
}
|
||||
|
||||
swrast_render_finish(ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Incoming Z/stencil values are always in uint_24_8 format.
|
||||
*/
|
||||
static void
|
||||
pack_uint_24_8_depth_stencil_row(mesa_format format, uint32_t n,
|
||||
const uint32_t *src, void *dst)
|
||||
{
|
||||
switch (format) {
|
||||
case MESA_FORMAT_S8_UINT_Z24_UNORM:
|
||||
memcpy(dst, src, n * sizeof(uint32_t));
|
||||
break;
|
||||
case MESA_FORMAT_Z24_UNORM_S8_UINT:
|
||||
{
|
||||
uint32_t *d = ((uint32_t *) dst);
|
||||
uint32_t i;
|
||||
for (i = 0; i < n; i++) {
|
||||
uint32_t s = src[i] << 24;
|
||||
uint32_t z = src[i] >> 8;
|
||||
d[i] = s | z;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
unreachable("bad format in _mesa_pack_ubyte_s_row");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw depth+stencil values into a MESA_FORAMT_Z24_S8 or MESA_FORMAT_Z24_UNORM_S8_UINT
|
||||
* renderbuffer. No masking, zooming, scaling, etc.
|
||||
*/
|
||||
static void
|
||||
fast_draw_depth_stencil(struct gl_context *ctx, GLint x, GLint y,
|
||||
GLsizei width, GLsizei height,
|
||||
const struct gl_pixelstore_attrib *unpack,
|
||||
const GLvoid *pixels)
|
||||
{
|
||||
const GLenum format = GL_DEPTH_STENCIL_EXT;
|
||||
const GLenum type = GL_UNSIGNED_INT_24_8;
|
||||
struct gl_renderbuffer *rb =
|
||||
ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
|
||||
struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
|
||||
GLubyte *src, *dst;
|
||||
GLint srcRowStride, dstRowStride;
|
||||
GLint i;
|
||||
|
||||
src = _mesa_image_address2d(unpack, pixels, width, height,
|
||||
format, type, 0, 0);
|
||||
srcRowStride = _mesa_image_row_stride(unpack, width, format, type);
|
||||
|
||||
dst = _swrast_pixel_address(rb, x, y);
|
||||
dstRowStride = srb->RowStride;
|
||||
|
||||
for (i = 0; i < height; i++) {
|
||||
pack_uint_24_8_depth_stencil_row(rb->Format, width, (const GLuint *) src, dst);
|
||||
dst += dstRowStride;
|
||||
src += srcRowStride;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This is a bit different from drawing GL_DEPTH_COMPONENT pixels.
|
||||
* The only per-pixel operations that apply are depth scale/bias,
|
||||
* stencil offset/shift, GL_DEPTH_WRITEMASK and GL_STENCIL_WRITEMASK,
|
||||
* and pixel zoom.
|
||||
* Also, only the depth buffer and stencil buffers are touched, not the
|
||||
* color buffer(s).
|
||||
*/
|
||||
static void
|
||||
draw_depth_stencil_pixels(struct gl_context *ctx, GLint x, GLint y,
|
||||
GLsizei width, GLsizei height, GLenum type,
|
||||
const struct gl_pixelstore_attrib *unpack,
|
||||
const GLvoid *pixels)
|
||||
{
|
||||
const GLint imgX = x, imgY = y;
|
||||
const GLboolean scaleOrBias
|
||||
= ctx->Pixel.DepthScale != 1.0F || ctx->Pixel.DepthBias != 0.0F;
|
||||
const GLuint stencilMask = ctx->Stencil.WriteMask[0];
|
||||
const GLenum stencilType = GL_UNSIGNED_BYTE;
|
||||
const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
|
||||
struct gl_renderbuffer *depthRb, *stencilRb;
|
||||
struct gl_pixelstore_attrib clippedUnpack = *unpack;
|
||||
|
||||
if (!zoom) {
|
||||
if (!_mesa_clip_drawpixels(ctx, &x, &y, &width, &height,
|
||||
&clippedUnpack)) {
|
||||
/* totally clipped */
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
depthRb = ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
|
||||
stencilRb = ctx->ReadBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
|
||||
assert(depthRb);
|
||||
assert(stencilRb);
|
||||
|
||||
if (depthRb == stencilRb &&
|
||||
(depthRb->Format == MESA_FORMAT_S8_UINT_Z24_UNORM ||
|
||||
depthRb->Format == MESA_FORMAT_Z24_UNORM_S8_UINT) &&
|
||||
type == GL_UNSIGNED_INT_24_8 &&
|
||||
!scaleOrBias &&
|
||||
!zoom &&
|
||||
ctx->Depth.Mask &&
|
||||
(stencilMask & 0xff) == 0xff) {
|
||||
fast_draw_depth_stencil(ctx, x, y, width, height,
|
||||
&clippedUnpack, pixels);
|
||||
}
|
||||
else {
|
||||
/* sub-optimal cases:
|
||||
* Separate depth/stencil buffers, or pixel transfer ops required.
|
||||
*/
|
||||
/* XXX need to handle very wide images (skippixels) */
|
||||
GLuint *zValues; /* 32-bit Z values */
|
||||
GLint i;
|
||||
|
||||
zValues = malloc(width * sizeof(GLuint));
|
||||
if (!zValues) {
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < height; i++) {
|
||||
const GLuint *depthStencilSrc = (const GLuint *)
|
||||
_mesa_image_address2d(&clippedUnpack, pixels, width, height,
|
||||
GL_DEPTH_STENCIL_EXT, type, i, 0);
|
||||
|
||||
if (ctx->Depth.Mask) {
|
||||
_mesa_unpack_depth_span(ctx, width,
|
||||
GL_UNSIGNED_INT, /* dest type */
|
||||
zValues, /* dest addr */
|
||||
0xffffffff, /* depth max */
|
||||
type, /* src type */
|
||||
depthStencilSrc, /* src addr */
|
||||
&clippedUnpack);
|
||||
if (zoom) {
|
||||
_swrast_write_zoomed_z_span(ctx, imgX, imgY, width, x,
|
||||
y + i, zValues);
|
||||
}
|
||||
else {
|
||||
GLubyte *dst = _swrast_pixel_address(depthRb, x, y + i);
|
||||
_mesa_pack_uint_z_row(depthRb->Format, width, zValues, dst);
|
||||
}
|
||||
}
|
||||
|
||||
if (stencilMask != 0x0) {
|
||||
GLubyte *stencilValues = (GLubyte *) zValues; /* re-use buffer */
|
||||
/* get stencil values, with shift/offset/mapping */
|
||||
_mesa_unpack_stencil_span(ctx, width, stencilType, stencilValues,
|
||||
type, depthStencilSrc, &clippedUnpack,
|
||||
ctx->_ImageTransferState);
|
||||
if (zoom)
|
||||
_swrast_write_zoomed_stencil_span(ctx, imgX, imgY, width,
|
||||
x, y + i, stencilValues);
|
||||
else
|
||||
_swrast_write_stencil_span(ctx, width, x, y + i, stencilValues);
|
||||
}
|
||||
}
|
||||
|
||||
free(zValues);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Execute software-based glDrawPixels.
|
||||
* By time we get here, all error checking will have been done.
|
||||
*/
|
||||
void
|
||||
_swrast_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 )
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
GLboolean save_vp_override = ctx->VertexProgram._Overriden;
|
||||
|
||||
if (!_mesa_check_conditional_render(ctx))
|
||||
return; /* don't draw */
|
||||
|
||||
/* We are creating fragments directly, without going through vertex
|
||||
* programs.
|
||||
*
|
||||
* This override flag tells the fragment processing code that its input
|
||||
* comes from a non-standard source, and it may therefore not rely on
|
||||
* optimizations that assume e.g. constant color if there is no color
|
||||
* vertex array.
|
||||
*/
|
||||
_mesa_set_vp_override(ctx, GL_TRUE);
|
||||
|
||||
if (ctx->NewState)
|
||||
_mesa_update_state(ctx);
|
||||
|
||||
if (swrast->NewState)
|
||||
_swrast_validate_derived( ctx );
|
||||
|
||||
pixels = _mesa_map_pbo_source(ctx, unpack, pixels);
|
||||
if (!pixels) {
|
||||
_mesa_set_vp_override(ctx, save_vp_override);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* By time we get here, all error checking should have been done.
|
||||
*/
|
||||
switch (format) {
|
||||
case GL_STENCIL_INDEX:
|
||||
swrast_render_start(ctx);
|
||||
draw_stencil_pixels( ctx, x, y, width, height, type, unpack, pixels );
|
||||
swrast_render_finish(ctx);
|
||||
break;
|
||||
case GL_DEPTH_COMPONENT:
|
||||
swrast_render_start(ctx);
|
||||
draw_depth_pixels( ctx, x, y, width, height, type, unpack, pixels );
|
||||
swrast_render_finish(ctx);
|
||||
break;
|
||||
case GL_DEPTH_STENCIL_EXT:
|
||||
swrast_render_start(ctx);
|
||||
draw_depth_stencil_pixels(ctx, x, y, width, height, type, unpack, pixels);
|
||||
swrast_render_finish(ctx);
|
||||
break;
|
||||
default:
|
||||
/* all other formats should be color formats */
|
||||
draw_rgba_pixels(ctx, x, y, width, height, format, type, unpack, pixels);
|
||||
}
|
||||
|
||||
_mesa_set_vp_override(ctx, save_vp_override);
|
||||
|
||||
_mesa_unmap_pbo_source(ctx, unpack);
|
||||
}
|
|
@ -1,137 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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/feedback.h"
|
||||
#include "main/macros.h"
|
||||
|
||||
#include "s_context.h"
|
||||
#include "s_feedback.h"
|
||||
#include "s_triangle.h"
|
||||
|
||||
|
||||
|
||||
static void
|
||||
feedback_vertex(struct gl_context * ctx, const SWvertex * v, const SWvertex * pv)
|
||||
{
|
||||
GLfloat win[4];
|
||||
const GLfloat *vtc = v->attrib[VARYING_SLOT_TEX0];
|
||||
const GLfloat *color = v->attrib[VARYING_SLOT_COL0];
|
||||
|
||||
win[0] = v->attrib[VARYING_SLOT_POS][0];
|
||||
win[1] = v->attrib[VARYING_SLOT_POS][1];
|
||||
win[2] = v->attrib[VARYING_SLOT_POS][2] / ctx->DrawBuffer->_DepthMaxF;
|
||||
win[3] = 1.0F / v->attrib[VARYING_SLOT_POS][3];
|
||||
|
||||
_mesa_feedback_vertex(ctx, win, color, vtc);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Put triangle in feedback buffer.
|
||||
*/
|
||||
void
|
||||
_swrast_feedback_triangle(struct gl_context *ctx, const SWvertex *v0,
|
||||
const SWvertex *v1, const SWvertex *v2)
|
||||
{
|
||||
if (!_swrast_culltriangle(ctx, v0, v1, v2)) {
|
||||
_mesa_feedback_token(ctx, (GLfloat) (GLint) GL_POLYGON_TOKEN);
|
||||
_mesa_feedback_token(ctx, (GLfloat) 3); /* three vertices */
|
||||
|
||||
if (ctx->Light.ShadeModel == GL_SMOOTH) {
|
||||
feedback_vertex(ctx, v0, v0);
|
||||
feedback_vertex(ctx, v1, v1);
|
||||
feedback_vertex(ctx, v2, v2);
|
||||
}
|
||||
else {
|
||||
feedback_vertex(ctx, v0, v2);
|
||||
feedback_vertex(ctx, v1, v2);
|
||||
feedback_vertex(ctx, v2, v2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_swrast_feedback_line(struct gl_context *ctx, const SWvertex *v0,
|
||||
const SWvertex *v1)
|
||||
{
|
||||
GLenum token = GL_LINE_TOKEN;
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
|
||||
if (swrast->StippleCounter == 0)
|
||||
token = GL_LINE_RESET_TOKEN;
|
||||
|
||||
_mesa_feedback_token(ctx, (GLfloat) (GLint) token);
|
||||
|
||||
if (ctx->Light.ShadeModel == GL_SMOOTH) {
|
||||
feedback_vertex(ctx, v0, v0);
|
||||
feedback_vertex(ctx, v1, v1);
|
||||
}
|
||||
else {
|
||||
feedback_vertex(ctx, v0, v1);
|
||||
feedback_vertex(ctx, v1, v1);
|
||||
}
|
||||
|
||||
swrast->StippleCounter++;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_swrast_feedback_point(struct gl_context *ctx, const SWvertex *v)
|
||||
{
|
||||
_mesa_feedback_token(ctx, (GLfloat) (GLint) GL_POINT_TOKEN);
|
||||
feedback_vertex(ctx, v, v);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_swrast_select_triangle(struct gl_context *ctx, const SWvertex *v0,
|
||||
const SWvertex *v1, const SWvertex *v2)
|
||||
{
|
||||
if (!_swrast_culltriangle(ctx, v0, v1, v2)) {
|
||||
const GLfloat zs = 1.0F / ctx->DrawBuffer->_DepthMaxF;
|
||||
|
||||
_mesa_update_hitflag( ctx, v0->attrib[VARYING_SLOT_POS][2] * zs );
|
||||
_mesa_update_hitflag( ctx, v1->attrib[VARYING_SLOT_POS][2] * zs );
|
||||
_mesa_update_hitflag( ctx, v2->attrib[VARYING_SLOT_POS][2] * zs );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_swrast_select_line(struct gl_context *ctx, const SWvertex *v0, const SWvertex *v1)
|
||||
{
|
||||
const GLfloat zs = 1.0F / ctx->DrawBuffer->_DepthMaxF;
|
||||
_mesa_update_hitflag( ctx, v0->attrib[VARYING_SLOT_POS][2] * zs );
|
||||
_mesa_update_hitflag( ctx, v1->attrib[VARYING_SLOT_POS][2] * zs );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_swrast_select_point(struct gl_context *ctx, const SWvertex *v)
|
||||
{
|
||||
const GLfloat zs = 1.0F / ctx->DrawBuffer->_DepthMaxF;
|
||||
_mesa_update_hitflag( ctx, v->attrib[VARYING_SLOT_POS][2] * zs );
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
|
||||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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 S_FEEDBACK_H
|
||||
#define S_FEEDBACK_H
|
||||
|
||||
|
||||
#include "swrast.h"
|
||||
|
||||
|
||||
extern void _swrast_feedback_point( struct gl_context *ctx, const SWvertex *v );
|
||||
|
||||
extern void _swrast_feedback_line( struct gl_context *ctx,
|
||||
const SWvertex *v1, const SWvertex *v2 );
|
||||
|
||||
extern void _swrast_feedback_triangle( struct gl_context *ctx, const SWvertex *v0,
|
||||
const SWvertex *v1, const SWvertex *v2 );
|
||||
|
||||
extern void _swrast_select_point( struct gl_context *ctx, const SWvertex *v );
|
||||
|
||||
extern void _swrast_select_line( struct gl_context *ctx,
|
||||
const SWvertex *v1, const SWvertex *v2 );
|
||||
|
||||
extern void _swrast_select_triangle( struct gl_context *ctx, const SWvertex *v0,
|
||||
const SWvertex *v1, const SWvertex *v2 );
|
||||
|
||||
#endif
|
|
@ -1,245 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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 "c99_math.h"
|
||||
#include "main/errors.h"
|
||||
#include "main/glheader.h"
|
||||
#include "main/macros.h"
|
||||
|
||||
#include "s_context.h"
|
||||
#include "s_fog.h"
|
||||
|
||||
|
||||
/**
|
||||
* Used to convert current raster distance to a fog factor in [0,1].
|
||||
*/
|
||||
GLfloat
|
||||
_swrast_z_to_fogfactor(struct gl_context *ctx, GLfloat z)
|
||||
{
|
||||
GLfloat d, f;
|
||||
|
||||
switch (ctx->Fog.Mode) {
|
||||
case GL_LINEAR:
|
||||
if (ctx->Fog.Start == ctx->Fog.End)
|
||||
d = 1.0F;
|
||||
else
|
||||
d = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
|
||||
f = (ctx->Fog.End - z) * d;
|
||||
return CLAMP(f, 0.0F, 1.0F);
|
||||
case GL_EXP:
|
||||
d = ctx->Fog.Density;
|
||||
f = expf(-d * z);
|
||||
f = CLAMP(f, 0.0F, 1.0F);
|
||||
return f;
|
||||
case GL_EXP2:
|
||||
d = ctx->Fog.Density;
|
||||
f = expf(-(d * d * z * z));
|
||||
f = CLAMP(f, 0.0F, 1.0F);
|
||||
return f;
|
||||
default:
|
||||
_mesa_problem(ctx, "Bad fog mode in _swrast_z_to_fogfactor");
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define LINEAR_FOG(f, coord) f = (fogEnd - coord) * fogScale
|
||||
|
||||
#define EXP_FOG(f, coord) f = expf(density * coord)
|
||||
|
||||
#define EXP2_FOG(f, coord) \
|
||||
do { \
|
||||
GLfloat tmp = negDensitySquared * coord * coord; \
|
||||
if (tmp < FLT_MIN_10_EXP) \
|
||||
tmp = FLT_MIN_10_EXP; \
|
||||
f = expf(tmp); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define BLEND_FOG(f, coord) f = coord
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Template code for computing fog blend factor and applying it to colors.
|
||||
* \param TYPE either GLubyte, GLushort or GLfloat.
|
||||
* \param COMPUTE_F code to compute the fog blend factor, f.
|
||||
*/
|
||||
#define FOG_LOOP(TYPE, FOG_FUNC) \
|
||||
if (span->arrayAttribs & VARYING_BIT_FOGC) { \
|
||||
GLuint i; \
|
||||
for (i = 0; i < span->end; i++) { \
|
||||
const GLfloat fogCoord = span->array->attribs[VARYING_SLOT_FOGC][i][0]; \
|
||||
const GLfloat c = fabsf(fogCoord); \
|
||||
GLfloat f, oneMinusF; \
|
||||
FOG_FUNC(f, c); \
|
||||
f = CLAMP(f, 0.0F, 1.0F); \
|
||||
oneMinusF = 1.0F - f; \
|
||||
rgba[i][RCOMP] = (TYPE) (f * rgba[i][RCOMP] + oneMinusF * rFog); \
|
||||
rgba[i][GCOMP] = (TYPE) (f * rgba[i][GCOMP] + oneMinusF * gFog); \
|
||||
rgba[i][BCOMP] = (TYPE) (f * rgba[i][BCOMP] + oneMinusF * bFog); \
|
||||
} \
|
||||
} \
|
||||
else { \
|
||||
const GLfloat fogStep = span->attrStepX[VARYING_SLOT_FOGC][0]; \
|
||||
GLfloat fogCoord = span->attrStart[VARYING_SLOT_FOGC][0]; \
|
||||
const GLfloat wStep = span->attrStepX[VARYING_SLOT_POS][3]; \
|
||||
GLfloat w = span->attrStart[VARYING_SLOT_POS][3]; \
|
||||
GLuint i; \
|
||||
for (i = 0; i < span->end; i++) { \
|
||||
const GLfloat c = fabsf(fogCoord) / w; \
|
||||
GLfloat f, oneMinusF; \
|
||||
FOG_FUNC(f, c); \
|
||||
f = CLAMP(f, 0.0F, 1.0F); \
|
||||
oneMinusF = 1.0F - f; \
|
||||
rgba[i][RCOMP] = (TYPE) (f * rgba[i][RCOMP] + oneMinusF * rFog); \
|
||||
rgba[i][GCOMP] = (TYPE) (f * rgba[i][GCOMP] + oneMinusF * gFog); \
|
||||
rgba[i][BCOMP] = (TYPE) (f * rgba[i][BCOMP] + oneMinusF * bFog); \
|
||||
fogCoord += fogStep; \
|
||||
w += wStep; \
|
||||
} \
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply fog to a span of RGBA pixels.
|
||||
* The fog value are either in the span->array->fog array or interpolated from
|
||||
* the fog/fogStep values.
|
||||
* They fog values are either fog coordinates (Z) or fog blend factors.
|
||||
* _PreferPixelFog should be in sync with that state!
|
||||
*/
|
||||
void
|
||||
_swrast_fog_rgba_span( const struct gl_context *ctx, SWspan *span )
|
||||
{
|
||||
const SWcontext *swrast = CONST_SWRAST_CONTEXT(ctx);
|
||||
GLfloat rFog, gFog, bFog;
|
||||
|
||||
assert(swrast->_FogEnabled);
|
||||
assert(span->arrayMask & SPAN_RGBA);
|
||||
|
||||
/* compute (scaled) fog color */
|
||||
if (span->array->ChanType == GL_UNSIGNED_BYTE) {
|
||||
rFog = ctx->Fog.Color[RCOMP] * 255.0F;
|
||||
gFog = ctx->Fog.Color[GCOMP] * 255.0F;
|
||||
bFog = ctx->Fog.Color[BCOMP] * 255.0F;
|
||||
}
|
||||
else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
|
||||
rFog = ctx->Fog.Color[RCOMP] * 65535.0F;
|
||||
gFog = ctx->Fog.Color[GCOMP] * 65535.0F;
|
||||
bFog = ctx->Fog.Color[BCOMP] * 65535.0F;
|
||||
}
|
||||
else {
|
||||
rFog = ctx->Fog.Color[RCOMP];
|
||||
gFog = ctx->Fog.Color[GCOMP];
|
||||
bFog = ctx->Fog.Color[BCOMP];
|
||||
}
|
||||
|
||||
if (swrast->_PreferPixelFog) {
|
||||
/* The span's fog values are fog coordinates, now compute blend factors
|
||||
* and blend the fragment colors with the fog color.
|
||||
*/
|
||||
switch (ctx->Fog.Mode) {
|
||||
case GL_LINEAR:
|
||||
{
|
||||
const GLfloat fogEnd = ctx->Fog.End;
|
||||
const GLfloat fogScale = (ctx->Fog.Start == ctx->Fog.End)
|
||||
? 1.0F : 1.0F / (ctx->Fog.End - ctx->Fog.Start);
|
||||
if (span->array->ChanType == GL_UNSIGNED_BYTE) {
|
||||
GLubyte (*rgba)[4] = span->array->rgba8;
|
||||
FOG_LOOP(GLubyte, LINEAR_FOG);
|
||||
}
|
||||
else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
|
||||
GLushort (*rgba)[4] = span->array->rgba16;
|
||||
FOG_LOOP(GLushort, LINEAR_FOG);
|
||||
}
|
||||
else {
|
||||
GLfloat (*rgba)[4] = span->array->attribs[VARYING_SLOT_COL0];
|
||||
assert(span->array->ChanType == GL_FLOAT);
|
||||
FOG_LOOP(GLfloat, LINEAR_FOG);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GL_EXP:
|
||||
{
|
||||
const GLfloat density = -ctx->Fog.Density;
|
||||
if (span->array->ChanType == GL_UNSIGNED_BYTE) {
|
||||
GLubyte (*rgba)[4] = span->array->rgba8;
|
||||
FOG_LOOP(GLubyte, EXP_FOG);
|
||||
}
|
||||
else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
|
||||
GLushort (*rgba)[4] = span->array->rgba16;
|
||||
FOG_LOOP(GLushort, EXP_FOG);
|
||||
}
|
||||
else {
|
||||
GLfloat (*rgba)[4] = span->array->attribs[VARYING_SLOT_COL0];
|
||||
assert(span->array->ChanType == GL_FLOAT);
|
||||
FOG_LOOP(GLfloat, EXP_FOG);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GL_EXP2:
|
||||
{
|
||||
const GLfloat negDensitySquared = -ctx->Fog.Density * ctx->Fog.Density;
|
||||
if (span->array->ChanType == GL_UNSIGNED_BYTE) {
|
||||
GLubyte (*rgba)[4] = span->array->rgba8;
|
||||
FOG_LOOP(GLubyte, EXP2_FOG);
|
||||
}
|
||||
else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
|
||||
GLushort (*rgba)[4] = span->array->rgba16;
|
||||
FOG_LOOP(GLushort, EXP2_FOG);
|
||||
}
|
||||
else {
|
||||
GLfloat (*rgba)[4] = span->array->attribs[VARYING_SLOT_COL0];
|
||||
assert(span->array->ChanType == GL_FLOAT);
|
||||
FOG_LOOP(GLfloat, EXP2_FOG);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
_mesa_problem(ctx, "Bad fog mode in _swrast_fog_rgba_span");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* The span's fog start/step/array values are blend factors in [0,1].
|
||||
* They were previously computed per-vertex.
|
||||
*/
|
||||
if (span->array->ChanType == GL_UNSIGNED_BYTE) {
|
||||
GLubyte (*rgba)[4] = span->array->rgba8;
|
||||
FOG_LOOP(GLubyte, BLEND_FOG);
|
||||
}
|
||||
else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
|
||||
GLushort (*rgba)[4] = span->array->rgba16;
|
||||
FOG_LOOP(GLushort, BLEND_FOG);
|
||||
}
|
||||
else {
|
||||
GLfloat (*rgba)[4] = span->array->attribs[VARYING_SLOT_COL0];
|
||||
assert(span->array->ChanType == GL_FLOAT);
|
||||
FOG_LOOP(GLfloat, BLEND_FOG);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
|
||||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* Copyright (C) 1999-2002 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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 S_FOG_H
|
||||
#define S_FOG_H
|
||||
|
||||
|
||||
#include "main/glheader.h"
|
||||
#include "s_span.h"
|
||||
|
||||
struct gl_context;
|
||||
|
||||
extern GLfloat
|
||||
_swrast_z_to_fogfactor(struct gl_context *ctx, GLfloat z);
|
||||
|
||||
extern void
|
||||
_swrast_fog_rgba_span( const struct gl_context *ctx, SWspan *span );
|
||||
|
||||
#endif
|
|
@ -1,284 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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/macros.h"
|
||||
#include "main/samplerobj.h"
|
||||
#include "main/teximage.h"
|
||||
#include "program/prog_instruction.h"
|
||||
|
||||
#include "s_context.h"
|
||||
#include "s_fragprog.h"
|
||||
#include "s_span.h"
|
||||
|
||||
/**
|
||||
* \brief Should swrast use a fragment program?
|
||||
*
|
||||
* \return true if the current fragment program exists and is not the fixed
|
||||
* function fragment program
|
||||
*/
|
||||
GLboolean
|
||||
_swrast_use_fragment_program(struct gl_context *ctx)
|
||||
{
|
||||
struct gl_program *fp = ctx->FragmentProgram._Current;
|
||||
return fp && !(fp == ctx->FragmentProgram._TexEnvProgram
|
||||
&& fp->arb.NumInstructions == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply texture object's swizzle (X/Y/Z/W/0/1) to incoming 'texel'
|
||||
* and return results in 'colorOut'.
|
||||
*/
|
||||
static inline void
|
||||
swizzle_texel(const GLfloat texel[4], GLfloat colorOut[4], GLuint swizzle)
|
||||
{
|
||||
if (swizzle == SWIZZLE_NOOP) {
|
||||
COPY_4V(colorOut, texel);
|
||||
}
|
||||
else {
|
||||
GLfloat vector[6];
|
||||
vector[SWIZZLE_X] = texel[0];
|
||||
vector[SWIZZLE_Y] = texel[1];
|
||||
vector[SWIZZLE_Z] = texel[2];
|
||||
vector[SWIZZLE_W] = texel[3];
|
||||
vector[SWIZZLE_ZERO] = 0.0F;
|
||||
vector[SWIZZLE_ONE] = 1.0F;
|
||||
colorOut[0] = vector[GET_SWZ(swizzle, 0)];
|
||||
colorOut[1] = vector[GET_SWZ(swizzle, 1)];
|
||||
colorOut[2] = vector[GET_SWZ(swizzle, 2)];
|
||||
colorOut[3] = vector[GET_SWZ(swizzle, 3)];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetch a texel with given lod.
|
||||
* Called via machine->FetchTexelLod()
|
||||
*/
|
||||
static void
|
||||
fetch_texel_lod( struct gl_context *ctx, const GLfloat texcoord[4], GLfloat lambda,
|
||||
GLuint unit, GLfloat color[4] )
|
||||
{
|
||||
const struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current;
|
||||
|
||||
if (texObj) {
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
GLfloat rgba[4];
|
||||
const struct gl_sampler_object *samp = _mesa_get_samplerobj(ctx, unit);
|
||||
|
||||
lambda = CLAMP(lambda, samp->Attrib.MinLod, samp->Attrib.MaxLod);
|
||||
|
||||
swrast->TextureSample[unit](ctx, samp, ctx->Texture.Unit[unit]._Current,
|
||||
1, (const GLfloat (*)[4]) texcoord,
|
||||
&lambda, &rgba);
|
||||
swizzle_texel(rgba, color, texObj->Attrib._Swizzle);
|
||||
}
|
||||
else {
|
||||
ASSIGN_4V(color, 0.0F, 0.0F, 0.0F, 1.0F);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetch a texel with the given partial derivatives to compute a level
|
||||
* of detail in the mipmap.
|
||||
* Called via machine->FetchTexelDeriv()
|
||||
* \param lodBias the lod bias which may be specified by a TXB instruction,
|
||||
* otherwise zero.
|
||||
*/
|
||||
static void
|
||||
fetch_texel_deriv( struct gl_context *ctx, const GLfloat texcoord[4],
|
||||
const GLfloat texdx[4], const GLfloat texdy[4],
|
||||
GLfloat lodBias, GLuint unit, GLfloat color[4] )
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
|
||||
const struct gl_texture_object *texObj = texUnit->_Current;
|
||||
|
||||
if (texObj) {
|
||||
const struct gl_texture_image *texImg = _mesa_base_tex_image(texObj);
|
||||
const struct swrast_texture_image *swImg =
|
||||
swrast_texture_image_const(texImg);
|
||||
const struct gl_sampler_object *samp = _mesa_get_samplerobj(ctx, unit);
|
||||
const GLfloat texW = (GLfloat) swImg->WidthScale;
|
||||
const GLfloat texH = (GLfloat) swImg->HeightScale;
|
||||
GLfloat lambda;
|
||||
GLfloat rgba[4];
|
||||
|
||||
lambda = _swrast_compute_lambda(texdx[0], texdy[0], /* ds/dx, ds/dy */
|
||||
texdx[1], texdy[1], /* dt/dx, dt/dy */
|
||||
texdx[3], texdy[3], /* dq/dx, dq/dy */
|
||||
texW, texH,
|
||||
texcoord[0], texcoord[1], texcoord[3],
|
||||
1.0F / texcoord[3]);
|
||||
|
||||
lambda += lodBias + texUnit->LodBias + samp->Attrib.LodBias;
|
||||
|
||||
lambda = CLAMP(lambda, samp->Attrib.MinLod, samp->Attrib.MaxLod);
|
||||
|
||||
swrast->TextureSample[unit](ctx, samp, ctx->Texture.Unit[unit]._Current,
|
||||
1, (const GLfloat (*)[4]) texcoord,
|
||||
&lambda, &rgba);
|
||||
swizzle_texel(rgba, color, texObj->Attrib._Swizzle);
|
||||
}
|
||||
else {
|
||||
ASSIGN_4V(color, 0.0F, 0.0F, 0.0F, 1.0F);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the virtual fragment program machine state prior to running
|
||||
* fragment program on a fragment. This involves initializing the input
|
||||
* registers, condition codes, etc.
|
||||
* \param machine the virtual machine state to init
|
||||
* \param program the fragment program we're about to run
|
||||
* \param span the span of pixels we'll operate on
|
||||
* \param col which element (column) of the span we'll operate on
|
||||
*/
|
||||
static void
|
||||
init_machine(struct gl_context *ctx, struct gl_program_machine *machine,
|
||||
const struct gl_program *program, const SWspan *span, GLuint col)
|
||||
{
|
||||
GLfloat *wpos = span->array->attribs[VARYING_SLOT_POS][col];
|
||||
|
||||
/* ARB_fragment_coord_conventions */
|
||||
if (program->info.fs.origin_upper_left)
|
||||
wpos[1] = ctx->DrawBuffer->Height - 1 - wpos[1];
|
||||
if (!program->info.fs.pixel_center_integer) {
|
||||
wpos[0] += 0.5F;
|
||||
wpos[1] += 0.5F;
|
||||
}
|
||||
|
||||
/* Setup pointer to input attributes */
|
||||
machine->Attribs = span->array->attribs;
|
||||
|
||||
machine->DerivX = (GLfloat (*)[4]) span->attrStepX;
|
||||
machine->DerivY = (GLfloat (*)[4]) span->attrStepY;
|
||||
machine->NumDeriv = VARYING_SLOT_MAX;
|
||||
|
||||
machine->Samplers = program->SamplerUnits;
|
||||
|
||||
/* if running a GLSL program (not ARB_fragment_program) */
|
||||
if (ctx->_Shader->CurrentProgram[MESA_SHADER_FRAGMENT]) {
|
||||
/* Store front/back facing value */
|
||||
machine->Attribs[VARYING_SLOT_FACE][col][0] = 1.0F - span->facing;
|
||||
}
|
||||
|
||||
machine->CurElement = col;
|
||||
|
||||
/* init call stack */
|
||||
machine->StackDepth = 0;
|
||||
|
||||
machine->FetchTexelLod = fetch_texel_lod;
|
||||
machine->FetchTexelDeriv = fetch_texel_deriv;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Run fragment program on the pixels in span from 'start' to 'end' - 1.
|
||||
*/
|
||||
static void
|
||||
run_program(struct gl_context *ctx, SWspan *span, GLuint start, GLuint end)
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
const struct gl_program *program = ctx->FragmentProgram._Current;
|
||||
const GLbitfield64 outputsWritten = program->info.outputs_written;
|
||||
struct gl_program_machine *machine = &swrast->FragProgMachine;
|
||||
GLuint i;
|
||||
|
||||
for (i = start; i < end; i++) {
|
||||
if (span->array->mask[i]) {
|
||||
init_machine(ctx, machine, program, span, i);
|
||||
|
||||
if (_mesa_execute_program(ctx, program, machine)) {
|
||||
|
||||
/* Store result color */
|
||||
if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_COLOR)) {
|
||||
COPY_4V(span->array->attribs[VARYING_SLOT_COL0][i],
|
||||
machine->Outputs[FRAG_RESULT_COLOR]);
|
||||
}
|
||||
else {
|
||||
/* Multiple drawbuffers / render targets
|
||||
* Note that colors beyond 0 and 1 will overwrite other
|
||||
* attributes, such as FOGC, TEX0, TEX1, etc. That's OK.
|
||||
*/
|
||||
GLuint buf;
|
||||
for (buf = 0; buf < ctx->DrawBuffer->_NumColorDrawBuffers; buf++) {
|
||||
if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_DATA0 + buf)) {
|
||||
COPY_4V(span->array->attribs[VARYING_SLOT_COL0 + buf][i],
|
||||
machine->Outputs[FRAG_RESULT_DATA0 + buf]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Store result depth/z */
|
||||
if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) {
|
||||
const GLfloat depth = machine->Outputs[FRAG_RESULT_DEPTH][2];
|
||||
if (depth <= 0.0F)
|
||||
span->array->z[i] = 0;
|
||||
else if (depth >= 1.0F)
|
||||
span->array->z[i] = ctx->DrawBuffer->_DepthMax;
|
||||
else
|
||||
span->array->z[i] =
|
||||
(GLuint) (depth * ctx->DrawBuffer->_DepthMaxF + 0.5F);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* killed fragment */
|
||||
span->array->mask[i] = GL_FALSE;
|
||||
span->writeAll = GL_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Execute the current fragment program for all the fragments
|
||||
* in the given span.
|
||||
*/
|
||||
void
|
||||
_swrast_exec_fragment_program( struct gl_context *ctx, SWspan *span )
|
||||
{
|
||||
const struct gl_program *program = ctx->FragmentProgram._Current;
|
||||
|
||||
/* incoming colors should be floats */
|
||||
if (program->info.inputs_read & VARYING_BIT_COL0) {
|
||||
assert(span->array->ChanType == GL_FLOAT);
|
||||
}
|
||||
|
||||
run_program(ctx, span, 0, span->end);
|
||||
|
||||
if (program->info.outputs_written & BITFIELD64_BIT(FRAG_RESULT_COLOR)) {
|
||||
span->interpMask &= ~SPAN_RGBA;
|
||||
span->arrayMask |= SPAN_RGBA;
|
||||
}
|
||||
|
||||
if (program->info.outputs_written & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) {
|
||||
span->interpMask &= ~SPAN_Z;
|
||||
span->arrayMask |= SPAN_Z;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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 S_FRAGPROG_H
|
||||
#define S_FRAGPROG_H
|
||||
|
||||
|
||||
#include "s_span.h"
|
||||
|
||||
struct gl_context;
|
||||
|
||||
GLboolean
|
||||
_swrast_use_fragment_program(struct gl_context *ctx);
|
||||
|
||||
extern void
|
||||
_swrast_exec_fragment_program(struct gl_context *ctx, SWspan *span);
|
||||
|
||||
|
||||
#endif /* S_FRAGPROG_H */
|
||||
|
|
@ -1,267 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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/context.h"
|
||||
#include "main/macros.h"
|
||||
#include "s_aaline.h"
|
||||
#include "s_context.h"
|
||||
#include "s_feedback.h"
|
||||
#include "s_lines.h"
|
||||
#include "s_span.h"
|
||||
|
||||
|
||||
/*
|
||||
* Init the mask[] array to implement a line stipple.
|
||||
*/
|
||||
static void
|
||||
compute_stipple_mask( struct gl_context *ctx, GLuint len, GLubyte mask[] )
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
GLuint i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
GLuint bit = (swrast->StippleCounter / ctx->Line.StippleFactor) & 0xf;
|
||||
if ((1 << bit) & ctx->Line.StipplePattern) {
|
||||
mask[i] = GL_TRUE;
|
||||
}
|
||||
else {
|
||||
mask[i] = GL_FALSE;
|
||||
}
|
||||
swrast->StippleCounter++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* To draw a wide line we can simply redraw the span N times, side by side.
|
||||
*/
|
||||
static void
|
||||
draw_wide_line( struct gl_context *ctx, SWspan *span, GLboolean xMajor )
|
||||
{
|
||||
const GLint width = (GLint) CLAMP(ctx->Line.Width,
|
||||
ctx->Const.MinLineWidth,
|
||||
ctx->Const.MaxLineWidth);
|
||||
GLint start;
|
||||
|
||||
assert(span->end < SWRAST_MAX_WIDTH);
|
||||
|
||||
if (width & 1)
|
||||
start = width / 2;
|
||||
else
|
||||
start = width / 2 - 1;
|
||||
|
||||
if (xMajor) {
|
||||
GLint *y = span->array->y;
|
||||
GLuint i;
|
||||
GLint w;
|
||||
for (w = 0; w < width; w++) {
|
||||
if (w == 0) {
|
||||
for (i = 0; i < span->end; i++)
|
||||
y[i] -= start;
|
||||
}
|
||||
else {
|
||||
for (i = 0; i < span->end; i++)
|
||||
y[i]++;
|
||||
}
|
||||
_swrast_write_rgba_span(ctx, span);
|
||||
}
|
||||
}
|
||||
else {
|
||||
GLint *x = span->array->x;
|
||||
GLuint i;
|
||||
GLint w;
|
||||
for (w = 0; w < width; w++) {
|
||||
if (w == 0) {
|
||||
for (i = 0; i < span->end; i++)
|
||||
x[i] -= start;
|
||||
}
|
||||
else {
|
||||
for (i = 0; i < span->end; i++)
|
||||
x[i]++;
|
||||
}
|
||||
_swrast_write_rgba_span(ctx, span);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**********************************************************************/
|
||||
/***** Rasterization *****/
|
||||
/**********************************************************************/
|
||||
|
||||
/* Simple RGBA index line (no stipple, width=1, no Z, no fog, no tex)*/
|
||||
#define NAME simple_no_z_rgba_line
|
||||
#define INTERP_RGBA
|
||||
#define RENDER_SPAN(span) _swrast_write_rgba_span(ctx, &span);
|
||||
#include "s_linetemp.h"
|
||||
|
||||
|
||||
/* Z, fog, wide, stipple RGBA line */
|
||||
#define NAME rgba_line
|
||||
#define INTERP_RGBA
|
||||
#define INTERP_Z
|
||||
#define RENDER_SPAN(span) \
|
||||
if (ctx->Line.StippleFlag) { \
|
||||
span.arrayMask |= SPAN_MASK; \
|
||||
compute_stipple_mask(ctx, span.end, span.array->mask); \
|
||||
} \
|
||||
if (ctx->Line.Width > 1.0) { \
|
||||
draw_wide_line(ctx, &span, (GLboolean)(dx > dy)); \
|
||||
} \
|
||||
else { \
|
||||
_swrast_write_rgba_span(ctx, &span); \
|
||||
}
|
||||
#include "s_linetemp.h"
|
||||
|
||||
|
||||
/* General-purpose line (any/all features). */
|
||||
#define NAME general_line
|
||||
#define INTERP_RGBA
|
||||
#define INTERP_Z
|
||||
#define INTERP_ATTRIBS
|
||||
#define RENDER_SPAN(span) \
|
||||
if (ctx->Line.StippleFlag) { \
|
||||
span.arrayMask |= SPAN_MASK; \
|
||||
compute_stipple_mask(ctx, span.end, span.array->mask); \
|
||||
} \
|
||||
if (ctx->Line.Width > 1.0) { \
|
||||
draw_wide_line(ctx, &span, (GLboolean)(dx > dy)); \
|
||||
} \
|
||||
else { \
|
||||
_swrast_write_rgba_span(ctx, &span); \
|
||||
}
|
||||
#include "s_linetemp.h"
|
||||
|
||||
|
||||
|
||||
void
|
||||
_swrast_add_spec_terms_line(struct gl_context *ctx,
|
||||
const SWvertex *v0, const SWvertex *v1)
|
||||
{
|
||||
SWvertex *ncv0 = (SWvertex *)v0;
|
||||
SWvertex *ncv1 = (SWvertex *)v1;
|
||||
GLfloat rSum, gSum, bSum;
|
||||
GLchan cSave[2][4];
|
||||
|
||||
/* save original colors */
|
||||
COPY_CHAN4(cSave[0], ncv0->color);
|
||||
COPY_CHAN4(cSave[1], ncv1->color);
|
||||
/* sum v0 */
|
||||
rSum = CHAN_TO_FLOAT(ncv0->color[0]) + ncv0->attrib[VARYING_SLOT_COL1][0];
|
||||
gSum = CHAN_TO_FLOAT(ncv0->color[1]) + ncv0->attrib[VARYING_SLOT_COL1][1];
|
||||
bSum = CHAN_TO_FLOAT(ncv0->color[2]) + ncv0->attrib[VARYING_SLOT_COL1][2];
|
||||
UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[0], rSum);
|
||||
UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[1], gSum);
|
||||
UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[2], bSum);
|
||||
/* sum v1 */
|
||||
rSum = CHAN_TO_FLOAT(ncv1->color[0]) + ncv1->attrib[VARYING_SLOT_COL1][0];
|
||||
gSum = CHAN_TO_FLOAT(ncv1->color[1]) + ncv1->attrib[VARYING_SLOT_COL1][1];
|
||||
bSum = CHAN_TO_FLOAT(ncv1->color[2]) + ncv1->attrib[VARYING_SLOT_COL1][2];
|
||||
UNCLAMPED_FLOAT_TO_CHAN(ncv1->color[0], rSum);
|
||||
UNCLAMPED_FLOAT_TO_CHAN(ncv1->color[1], gSum);
|
||||
UNCLAMPED_FLOAT_TO_CHAN(ncv1->color[2], bSum);
|
||||
/* draw */
|
||||
SWRAST_CONTEXT(ctx)->SpecLine( ctx, ncv0, ncv1 );
|
||||
/* restore original colors */
|
||||
COPY_CHAN4(ncv0->color, cSave[0]);
|
||||
COPY_CHAN4(ncv1->color, cSave[1]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
/* record the current line function name */
|
||||
static const char *lineFuncName = NULL;
|
||||
|
||||
#define USE(lineFunc) \
|
||||
do { \
|
||||
lineFuncName = #lineFunc; \
|
||||
/*printf("%s\n", lineFuncName);*/ \
|
||||
swrast->Line = lineFunc; \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
|
||||
#define USE(lineFunc) swrast->Line = lineFunc
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Determine which line drawing function to use given the current
|
||||
* rendering context.
|
||||
*
|
||||
* Please update the summary flag _SWRAST_NEW_LINE if you add or remove
|
||||
* tests to this code.
|
||||
*/
|
||||
void
|
||||
_swrast_choose_line( struct gl_context *ctx )
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
GLboolean specular = (ctx->Fog.ColorSumEnabled ||
|
||||
(ctx->Light.Enabled &&
|
||||
ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR));
|
||||
|
||||
if (ctx->RenderMode == GL_RENDER) {
|
||||
if (ctx->Line.SmoothFlag) {
|
||||
/* antialiased lines */
|
||||
_swrast_choose_aa_line_function(ctx);
|
||||
assert(swrast->Line);
|
||||
}
|
||||
else if (ctx->Texture._EnabledCoordUnits
|
||||
|| _swrast_use_fragment_program(ctx)
|
||||
|| swrast->_FogEnabled
|
||||
|| specular) {
|
||||
USE(general_line);
|
||||
}
|
||||
else if (ctx->Depth.Test
|
||||
|| ctx->Line.Width != 1.0F
|
||||
|| ctx->Line.StippleFlag) {
|
||||
/* no texture, but Z, fog, width>1, stipple, etc. */
|
||||
#if CHAN_BITS == 32
|
||||
USE(general_line);
|
||||
#else
|
||||
USE(rgba_line);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
assert(!ctx->Depth.Test);
|
||||
assert(ctx->Line.Width == 1.0F);
|
||||
/* simple lines */
|
||||
USE(simple_no_z_rgba_line);
|
||||
}
|
||||
}
|
||||
else if (ctx->RenderMode == GL_FEEDBACK) {
|
||||
USE(_swrast_feedback_line);
|
||||
}
|
||||
else {
|
||||
assert(ctx->RenderMode == GL_SELECT);
|
||||
USE(_swrast_select_line);
|
||||
}
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
|
||||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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 S_LINES_H
|
||||
#define S_LINES_H
|
||||
|
||||
#include "swrast.h"
|
||||
|
||||
void
|
||||
_swrast_choose_line( struct gl_context *ctx );
|
||||
|
||||
void
|
||||
_swrast_add_spec_terms_line( struct gl_context *ctx,
|
||||
const SWvertex *v0,
|
||||
const SWvertex *v1 );
|
||||
|
||||
|
||||
#endif
|
|
@ -1,402 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Line Rasterizer Template
|
||||
*
|
||||
* This file is #include'd to generate custom line rasterizers.
|
||||
*
|
||||
* The following macros may be defined to indicate what auxillary information
|
||||
* must be interplated along the line:
|
||||
* INTERP_Z - if defined, interpolate Z values
|
||||
* INTERP_ATTRIBS - if defined, interpolate attribs (texcoords, varying, etc)
|
||||
*
|
||||
* When one can directly address pixels in the color buffer the following
|
||||
* macros can be defined and used to directly compute pixel addresses during
|
||||
* rasterization (see pixelPtr):
|
||||
* PIXEL_TYPE - the datatype of a pixel (GLubyte, GLushort, GLuint)
|
||||
* BYTES_PER_ROW - number of bytes per row in the color buffer
|
||||
* PIXEL_ADDRESS(X,Y) - returns the address of pixel at (X,Y) where
|
||||
* Y==0 at bottom of screen and increases upward.
|
||||
*
|
||||
* Similarly, for direct depth buffer access, this type is used for depth
|
||||
* buffer addressing:
|
||||
* DEPTH_TYPE - either GLushort or GLuint
|
||||
*
|
||||
* Optionally, one may provide one-time setup code
|
||||
* SETUP_CODE - code which is to be executed once per line
|
||||
*
|
||||
* To actually "plot" each pixel the PLOT macro must be defined...
|
||||
* PLOT(X,Y) - code to plot a pixel. Example:
|
||||
* if (Z < *zPtr) {
|
||||
* *zPtr = Z;
|
||||
* color = pack_rgb( FixedToInt(r0), FixedToInt(g0),
|
||||
* FixedToInt(b0) );
|
||||
* put_pixel( X, Y, color );
|
||||
* }
|
||||
*
|
||||
* This code was designed for the origin to be in the lower-left corner.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
static void
|
||||
NAME( struct gl_context *ctx, const SWvertex *vert0, const SWvertex *vert1 )
|
||||
{
|
||||
const SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
SWspan span;
|
||||
GLuint interpFlags = 0;
|
||||
GLint x0 = (GLint) vert0->attrib[VARYING_SLOT_POS][0];
|
||||
GLint x1 = (GLint) vert1->attrib[VARYING_SLOT_POS][0];
|
||||
GLint y0 = (GLint) vert0->attrib[VARYING_SLOT_POS][1];
|
||||
GLint y1 = (GLint) vert1->attrib[VARYING_SLOT_POS][1];
|
||||
GLint dx, dy;
|
||||
GLint numPixels;
|
||||
GLint xstep, ystep;
|
||||
#if defined(DEPTH_TYPE)
|
||||
const GLint depthBits = ctx->DrawBuffer->Visual.depthBits;
|
||||
const GLint fixedToDepthShift = depthBits <= 16 ? FIXED_SHIFT : 0;
|
||||
struct gl_renderbuffer *zrb = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
|
||||
#define FixedToDepth(F) ((F) >> fixedToDepthShift)
|
||||
GLint zPtrXstep, zPtrYstep;
|
||||
DEPTH_TYPE *zPtr;
|
||||
#elif defined(INTERP_Z)
|
||||
const GLint depthBits = ctx->DrawBuffer->Visual.depthBits;
|
||||
#endif
|
||||
#ifdef PIXEL_ADDRESS
|
||||
PIXEL_TYPE *pixelPtr;
|
||||
GLint pixelXstep, pixelYstep;
|
||||
#endif
|
||||
|
||||
#ifdef SETUP_CODE
|
||||
SETUP_CODE
|
||||
#endif
|
||||
|
||||
(void) swrast;
|
||||
|
||||
/* Cull primitives with malformed coordinates.
|
||||
*/
|
||||
{
|
||||
GLfloat tmp = vert0->attrib[VARYING_SLOT_POS][0] + vert0->attrib[VARYING_SLOT_POS][1]
|
||||
+ vert1->attrib[VARYING_SLOT_POS][0] + vert1->attrib[VARYING_SLOT_POS][1];
|
||||
if (util_is_inf_or_nan(tmp))
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
printf("%s():\n", __func__);
|
||||
printf(" (%f, %f, %f) -> (%f, %f, %f)\n",
|
||||
vert0->attrib[VARYING_SLOT_POS][0],
|
||||
vert0->attrib[VARYING_SLOT_POS][1],
|
||||
vert0->attrib[VARYING_SLOT_POS][2],
|
||||
vert1->attrib[VARYING_SLOT_POS][0],
|
||||
vert1->attrib[VARYING_SLOT_POS][1],
|
||||
vert1->attrib[VARYING_SLOT_POS][2]);
|
||||
printf(" (%d, %d, %d) -> (%d, %d, %d)\n",
|
||||
vert0->color[0], vert0->color[1], vert0->color[2],
|
||||
vert1->color[0], vert1->color[1], vert1->color[2]);
|
||||
printf(" (%d, %d, %d) -> (%d, %d, %d)\n",
|
||||
vert0->specular[0], vert0->specular[1], vert0->specular[2],
|
||||
vert1->specular[0], vert1->specular[1], vert1->specular[2]);
|
||||
*/
|
||||
|
||||
/*
|
||||
* Despite being clipped to the view volume, the line's window coordinates
|
||||
* may just lie outside the window bounds. That is, if the legal window
|
||||
* coordinates are [0,W-1][0,H-1], it's possible for x==W and/or y==H.
|
||||
* This quick and dirty code nudges the endpoints inside the window if
|
||||
* necessary.
|
||||
*/
|
||||
#ifdef CLIP_HACK
|
||||
{
|
||||
GLint w = ctx->DrawBuffer->Width;
|
||||
GLint h = ctx->DrawBuffer->Height;
|
||||
if ((x0==w) | (x1==w)) {
|
||||
if ((x0==w) & (x1==w))
|
||||
return;
|
||||
x0 -= x0==w;
|
||||
x1 -= x1==w;
|
||||
}
|
||||
if ((y0==h) | (y1==h)) {
|
||||
if ((y0==h) & (y1==h))
|
||||
return;
|
||||
y0 -= y0==h;
|
||||
y1 -= y1==h;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
dx = x1 - x0;
|
||||
dy = y1 - y0;
|
||||
if (dx == 0 && dy == 0)
|
||||
return;
|
||||
|
||||
/*
|
||||
printf("%s %d,%d %g %g %g %g %g %g %g %g\n", __func__, dx, dy,
|
||||
vert0->attrib[VARYING_SLOT_COL1][0],
|
||||
vert0->attrib[VARYING_SLOT_COL1][1],
|
||||
vert0->attrib[VARYING_SLOT_COL1][2],
|
||||
vert0->attrib[VARYING_SLOT_COL1][3],
|
||||
vert1->attrib[VARYING_SLOT_COL1][0],
|
||||
vert1->attrib[VARYING_SLOT_COL1][1],
|
||||
vert1->attrib[VARYING_SLOT_COL1][2],
|
||||
vert1->attrib[VARYING_SLOT_COL1][3]);
|
||||
*/
|
||||
|
||||
#ifdef DEPTH_TYPE
|
||||
zPtr = (DEPTH_TYPE *) _swrast_pixel_address(zrb, x0, y0);
|
||||
#endif
|
||||
#ifdef PIXEL_ADDRESS
|
||||
pixelPtr = (PIXEL_TYPE *) PIXEL_ADDRESS(x0,y0);
|
||||
#endif
|
||||
|
||||
if (dx<0) {
|
||||
dx = -dx; /* make positive */
|
||||
xstep = -1;
|
||||
#ifdef DEPTH_TYPE
|
||||
zPtrXstep = -((GLint)sizeof(DEPTH_TYPE));
|
||||
#endif
|
||||
#ifdef PIXEL_ADDRESS
|
||||
pixelXstep = -((GLint)sizeof(PIXEL_TYPE));
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
xstep = 1;
|
||||
#ifdef DEPTH_TYPE
|
||||
zPtrXstep = ((GLint)sizeof(DEPTH_TYPE));
|
||||
#endif
|
||||
#ifdef PIXEL_ADDRESS
|
||||
pixelXstep = ((GLint)sizeof(PIXEL_TYPE));
|
||||
#endif
|
||||
}
|
||||
|
||||
if (dy<0) {
|
||||
dy = -dy; /* make positive */
|
||||
ystep = -1;
|
||||
#ifdef DEPTH_TYPE
|
||||
zPtrYstep = -((GLint) (ctx->DrawBuffer->Width * sizeof(DEPTH_TYPE)));
|
||||
#endif
|
||||
#ifdef PIXEL_ADDRESS
|
||||
pixelYstep = BYTES_PER_ROW;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
ystep = 1;
|
||||
#ifdef DEPTH_TYPE
|
||||
zPtrYstep = (GLint) (ctx->DrawBuffer->Width * sizeof(DEPTH_TYPE));
|
||||
#endif
|
||||
#ifdef PIXEL_ADDRESS
|
||||
pixelYstep = -(BYTES_PER_ROW);
|
||||
#endif
|
||||
}
|
||||
|
||||
assert(dx >= 0);
|
||||
assert(dy >= 0);
|
||||
|
||||
numPixels = MAX2(dx, dy);
|
||||
|
||||
/*
|
||||
* Span setup: compute start and step values for all interpolated values.
|
||||
*/
|
||||
interpFlags |= SPAN_RGBA;
|
||||
if (ctx->Light.ShadeModel == GL_SMOOTH) {
|
||||
span.red = ChanToFixed(vert0->color[0]);
|
||||
span.green = ChanToFixed(vert0->color[1]);
|
||||
span.blue = ChanToFixed(vert0->color[2]);
|
||||
span.alpha = ChanToFixed(vert0->color[3]);
|
||||
span.redStep = (ChanToFixed(vert1->color[0]) - span.red ) / numPixels;
|
||||
span.greenStep = (ChanToFixed(vert1->color[1]) - span.green) / numPixels;
|
||||
span.blueStep = (ChanToFixed(vert1->color[2]) - span.blue ) / numPixels;
|
||||
span.alphaStep = (ChanToFixed(vert1->color[3]) - span.alpha) / numPixels;
|
||||
}
|
||||
else {
|
||||
span.red = ChanToFixed(vert1->color[0]);
|
||||
span.green = ChanToFixed(vert1->color[1]);
|
||||
span.blue = ChanToFixed(vert1->color[2]);
|
||||
span.alpha = ChanToFixed(vert1->color[3]);
|
||||
span.redStep = 0;
|
||||
span.greenStep = 0;
|
||||
span.blueStep = 0;
|
||||
span.alphaStep = 0;
|
||||
}
|
||||
#if defined(INTERP_Z) || defined(DEPTH_TYPE)
|
||||
interpFlags |= SPAN_Z;
|
||||
{
|
||||
if (depthBits <= 16) {
|
||||
span.z = FloatToFixed(vert0->attrib[VARYING_SLOT_POS][2]) + FIXED_HALF;
|
||||
span.zStep = FloatToFixed( vert1->attrib[VARYING_SLOT_POS][2]
|
||||
- vert0->attrib[VARYING_SLOT_POS][2]) / numPixels;
|
||||
}
|
||||
else {
|
||||
/* don't use fixed point */
|
||||
span.z = (GLuint) vert0->attrib[VARYING_SLOT_POS][2];
|
||||
span.zStep = (GLint) (( vert1->attrib[VARYING_SLOT_POS][2]
|
||||
- vert0->attrib[VARYING_SLOT_POS][2]) / numPixels);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(INTERP_ATTRIBS)
|
||||
{
|
||||
const GLfloat invLen = 1.0F / numPixels;
|
||||
const GLfloat invw0 = vert0->attrib[VARYING_SLOT_POS][3];
|
||||
const GLfloat invw1 = vert1->attrib[VARYING_SLOT_POS][3];
|
||||
|
||||
span.attrStart[VARYING_SLOT_POS][3] = invw0;
|
||||
span.attrStepX[VARYING_SLOT_POS][3] = (invw1 - invw0) * invLen;
|
||||
span.attrStepY[VARYING_SLOT_POS][3] = 0.0;
|
||||
|
||||
ATTRIB_LOOP_BEGIN
|
||||
if (swrast->_InterpMode[attr] == GL_FLAT) {
|
||||
COPY_4V(span.attrStart[attr], vert1->attrib[attr]);
|
||||
ASSIGN_4V(span.attrStepX[attr], 0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
else {
|
||||
GLuint c;
|
||||
for (c = 0; c < 4; c++) {
|
||||
float da;
|
||||
span.attrStart[attr][c] = invw0 * vert0->attrib[attr][c];
|
||||
da = (invw1 * vert1->attrib[attr][c]) - span.attrStart[attr][c];
|
||||
span.attrStepX[attr][c] = da * invLen;
|
||||
}
|
||||
}
|
||||
ASSIGN_4V(span.attrStepY[attr], 0.0, 0.0, 0.0, 0.0);
|
||||
ATTRIB_LOOP_END
|
||||
}
|
||||
#endif
|
||||
|
||||
INIT_SPAN(span, GL_LINE);
|
||||
span.end = numPixels;
|
||||
span.interpMask = interpFlags;
|
||||
span.arrayMask = SPAN_XY;
|
||||
|
||||
span.facing = swrast->PointLineFacing;
|
||||
|
||||
|
||||
/*
|
||||
* Draw
|
||||
*/
|
||||
|
||||
if (dx > dy) {
|
||||
/*** X-major line ***/
|
||||
GLint i;
|
||||
GLint errorInc = dy+dy;
|
||||
GLint error = errorInc-dx;
|
||||
GLint errorDec = error-dx;
|
||||
|
||||
for (i = 0; i < dx; i++) {
|
||||
#ifdef DEPTH_TYPE
|
||||
GLuint Z = FixedToDepth(span.z);
|
||||
#endif
|
||||
#ifdef PLOT
|
||||
PLOT( x0, y0 );
|
||||
#else
|
||||
span.array->x[i] = x0;
|
||||
span.array->y[i] = y0;
|
||||
#endif
|
||||
x0 += xstep;
|
||||
#ifdef DEPTH_TYPE
|
||||
zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrXstep);
|
||||
span.z += span.zStep;
|
||||
#endif
|
||||
#ifdef PIXEL_ADDRESS
|
||||
pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelXstep);
|
||||
#endif
|
||||
if (error < 0) {
|
||||
error += errorInc;
|
||||
}
|
||||
else {
|
||||
error += errorDec;
|
||||
y0 += ystep;
|
||||
#ifdef DEPTH_TYPE
|
||||
zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrYstep);
|
||||
#endif
|
||||
#ifdef PIXEL_ADDRESS
|
||||
pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelYstep);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*** Y-major line ***/
|
||||
GLint i;
|
||||
GLint errorInc = dx+dx;
|
||||
GLint error = errorInc-dy;
|
||||
GLint errorDec = error-dy;
|
||||
|
||||
for (i=0;i<dy;i++) {
|
||||
#ifdef DEPTH_TYPE
|
||||
GLuint Z = FixedToDepth(span.z);
|
||||
#endif
|
||||
#ifdef PLOT
|
||||
PLOT( x0, y0 );
|
||||
#else
|
||||
span.array->x[i] = x0;
|
||||
span.array->y[i] = y0;
|
||||
#endif
|
||||
y0 += ystep;
|
||||
#ifdef DEPTH_TYPE
|
||||
zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrYstep);
|
||||
span.z += span.zStep;
|
||||
#endif
|
||||
#ifdef PIXEL_ADDRESS
|
||||
pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelYstep);
|
||||
#endif
|
||||
if (error<0) {
|
||||
error += errorInc;
|
||||
}
|
||||
else {
|
||||
error += errorDec;
|
||||
x0 += xstep;
|
||||
#ifdef DEPTH_TYPE
|
||||
zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrXstep);
|
||||
#endif
|
||||
#ifdef PIXEL_ADDRESS
|
||||
pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelXstep);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef RENDER_SPAN
|
||||
RENDER_SPAN( span );
|
||||
#endif
|
||||
|
||||
(void)span;
|
||||
|
||||
}
|
||||
|
||||
|
||||
#undef NAME
|
||||
#undef INTERP_Z
|
||||
#undef INTERP_ATTRIBS
|
||||
#undef PIXEL_ADDRESS
|
||||
#undef PIXEL_TYPE
|
||||
#undef DEPTH_TYPE
|
||||
#undef BYTES_PER_ROW
|
||||
#undef SETUP_CODE
|
||||
#undef PLOT
|
||||
#undef CLIP_HACK
|
||||
#undef FixedToDepth
|
||||
#undef RENDER_SPAN
|
|
@ -1,218 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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/context.h"
|
||||
|
||||
#include "main/macros.h"
|
||||
|
||||
#include "s_context.h"
|
||||
#include "s_logic.h"
|
||||
#include "s_span.h"
|
||||
|
||||
|
||||
/**
|
||||
* We do all logic ops on 4-byte GLuints.
|
||||
* Depending on bytes per pixel, the mask array elements correspond to
|
||||
* 1, 2 or 4 GLuints.
|
||||
*/
|
||||
#define LOGIC_OP_LOOP(MODE, MASKSTRIDE) \
|
||||
do { \
|
||||
GLuint i; \
|
||||
switch (MODE) { \
|
||||
case GL_CLEAR: \
|
||||
for (i = 0; i < n; i++) { \
|
||||
if (mask[i / MASKSTRIDE]) { \
|
||||
src[i] = 0; \
|
||||
} \
|
||||
} \
|
||||
break; \
|
||||
case GL_SET: \
|
||||
for (i = 0; i < n; i++) { \
|
||||
if (mask[i / MASKSTRIDE]) { \
|
||||
src[i] = ~0; \
|
||||
} \
|
||||
} \
|
||||
break; \
|
||||
case GL_COPY: \
|
||||
/* do nothing */ \
|
||||
break; \
|
||||
case GL_COPY_INVERTED: \
|
||||
for (i = 0; i < n; i++) { \
|
||||
if (mask[i / MASKSTRIDE]) { \
|
||||
src[i] = ~src[i]; \
|
||||
} \
|
||||
} \
|
||||
break; \
|
||||
case GL_NOOP: \
|
||||
for (i = 0; i < n; i++) { \
|
||||
if (mask[i / MASKSTRIDE]) { \
|
||||
src[i] = dest[i]; \
|
||||
} \
|
||||
} \
|
||||
break; \
|
||||
case GL_INVERT: \
|
||||
for (i = 0; i < n; i++) { \
|
||||
if (mask[i / MASKSTRIDE]) { \
|
||||
src[i] = ~dest[i]; \
|
||||
} \
|
||||
} \
|
||||
break; \
|
||||
case GL_AND: \
|
||||
for (i = 0; i < n; i++) { \
|
||||
if (mask[i / MASKSTRIDE]) { \
|
||||
src[i] &= dest[i]; \
|
||||
} \
|
||||
} \
|
||||
break; \
|
||||
case GL_NAND: \
|
||||
for (i = 0; i < n; i++) { \
|
||||
if (mask[i / MASKSTRIDE]) { \
|
||||
src[i] = ~(src[i] & dest[i]); \
|
||||
} \
|
||||
} \
|
||||
break; \
|
||||
case GL_OR: \
|
||||
for (i = 0; i < n; i++) { \
|
||||
if (mask[i / MASKSTRIDE]) { \
|
||||
src[i] |= dest[i]; \
|
||||
} \
|
||||
} \
|
||||
break; \
|
||||
case GL_NOR: \
|
||||
for (i = 0; i < n; i++) { \
|
||||
if (mask[i / MASKSTRIDE]) { \
|
||||
src[i] = ~(src[i] | dest[i]); \
|
||||
} \
|
||||
} \
|
||||
break; \
|
||||
case GL_XOR: \
|
||||
for (i = 0; i < n; i++) { \
|
||||
if (mask[i / MASKSTRIDE]) { \
|
||||
src[i] ^= dest[i]; \
|
||||
} \
|
||||
} \
|
||||
break; \
|
||||
case GL_EQUIV: \
|
||||
for (i = 0; i < n; i++) { \
|
||||
if (mask[i / MASKSTRIDE]) { \
|
||||
src[i] = ~(src[i] ^ dest[i]); \
|
||||
} \
|
||||
} \
|
||||
break; \
|
||||
case GL_AND_REVERSE: \
|
||||
for (i = 0; i < n; i++) { \
|
||||
if (mask[i / MASKSTRIDE]) { \
|
||||
src[i] = src[i] & ~dest[i]; \
|
||||
} \
|
||||
} \
|
||||
break; \
|
||||
case GL_AND_INVERTED: \
|
||||
for (i = 0; i < n; i++) { \
|
||||
if (mask[i / MASKSTRIDE]) { \
|
||||
src[i] = ~src[i] & dest[i]; \
|
||||
} \
|
||||
} \
|
||||
break; \
|
||||
case GL_OR_REVERSE: \
|
||||
for (i = 0; i < n; i++) { \
|
||||
if (mask[i / MASKSTRIDE]) { \
|
||||
src[i] = src[i] | ~dest[i]; \
|
||||
} \
|
||||
} \
|
||||
break; \
|
||||
case GL_OR_INVERTED: \
|
||||
for (i = 0; i < n; i++) { \
|
||||
if (mask[i / MASKSTRIDE]) { \
|
||||
src[i] = ~src[i] | dest[i]; \
|
||||
} \
|
||||
} \
|
||||
break; \
|
||||
default: \
|
||||
_mesa_problem(ctx, "bad logicop mode");\
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
|
||||
static inline void
|
||||
logicop_uint1(struct gl_context *ctx, GLuint n, GLuint src[], const GLuint dest[],
|
||||
const GLubyte mask[])
|
||||
{
|
||||
LOGIC_OP_LOOP(ctx->Color.LogicOp, 1);
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
logicop_uint2(struct gl_context *ctx, GLuint n, GLuint src[], const GLuint dest[],
|
||||
const GLubyte mask[])
|
||||
{
|
||||
LOGIC_OP_LOOP(ctx->Color.LogicOp, 2);
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
logicop_uint4(struct gl_context *ctx, GLuint n, GLuint src[], const GLuint dest[],
|
||||
const GLubyte mask[])
|
||||
{
|
||||
LOGIC_OP_LOOP(ctx->Color.LogicOp, 4);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Apply the current logic operator to a span of RGBA pixels.
|
||||
* We can handle horizontal runs of pixels (spans) or arrays of x/y
|
||||
* pixel coordinates.
|
||||
*/
|
||||
void
|
||||
_swrast_logicop_rgba_span(struct gl_context *ctx, struct gl_renderbuffer *rb,
|
||||
SWspan *span)
|
||||
{
|
||||
void *rbPixels;
|
||||
|
||||
assert(span->end < SWRAST_MAX_WIDTH);
|
||||
assert(span->arrayMask & SPAN_RGBA);
|
||||
|
||||
rbPixels = _swrast_get_dest_rgba(ctx, rb, span);
|
||||
|
||||
if (span->array->ChanType == GL_UNSIGNED_BYTE) {
|
||||
/* treat 4*GLubyte as GLuint */
|
||||
logicop_uint1(ctx, span->end,
|
||||
(GLuint *) span->array->rgba8,
|
||||
(const GLuint *) rbPixels, span->array->mask);
|
||||
}
|
||||
else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
|
||||
/* treat 2*GLushort as GLuint */
|
||||
logicop_uint2(ctx, 2 * span->end,
|
||||
(GLuint *) span->array->rgba16,
|
||||
(const GLuint *) rbPixels, span->array->mask);
|
||||
}
|
||||
else {
|
||||
logicop_uint4(ctx, 4 * span->end,
|
||||
(GLuint *) span->array->attribs[VARYING_SLOT_COL0],
|
||||
(const GLuint *) rbPixels, span->array->mask);
|
||||
}
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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 S_LOGIC_H
|
||||
#define S_LOGIC_H
|
||||
|
||||
|
||||
#include "s_span.h"
|
||||
|
||||
struct gl_context;
|
||||
struct gl_renderbuffer;
|
||||
|
||||
extern void
|
||||
_swrast_logicop_rgba_span(struct gl_context *ctx, struct gl_renderbuffer *rb,
|
||||
SWspan *span);
|
||||
|
||||
|
||||
#endif
|
|
@ -1,108 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Implement the effect of glColorMask and glIndexMask in software.
|
||||
*/
|
||||
|
||||
|
||||
#include "main/glheader.h"
|
||||
#include "main/macros.h"
|
||||
|
||||
#include "s_context.h"
|
||||
#include "s_masking.h"
|
||||
#include "s_span.h"
|
||||
|
||||
|
||||
/**
|
||||
* Apply the color mask to a span of rgba values.
|
||||
*/
|
||||
void
|
||||
_swrast_mask_rgba_span(struct gl_context *ctx, struct gl_renderbuffer *rb,
|
||||
SWspan *span, GLuint buf)
|
||||
{
|
||||
const GLuint n = span->end;
|
||||
void *rbPixels;
|
||||
|
||||
assert(n < SWRAST_MAX_WIDTH);
|
||||
assert(span->arrayMask & SPAN_RGBA);
|
||||
|
||||
rbPixels = _swrast_get_dest_rgba(ctx, rb, span);
|
||||
|
||||
/*
|
||||
* Do component masking.
|
||||
* Note that we're not using span->array->mask[] here. We could...
|
||||
*/
|
||||
if (span->array->ChanType == GL_UNSIGNED_BYTE) {
|
||||
const GLubyte colormask[4] = {
|
||||
GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 0) ? 0xff : 0,
|
||||
GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 1) ? 0xff : 0,
|
||||
GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 2) ? 0xff : 0,
|
||||
GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 3) ? 0xff : 0,
|
||||
};
|
||||
GLuint srcMask;
|
||||
memcpy(&srcMask, colormask, sizeof(srcMask));
|
||||
const GLuint dstMask = ~srcMask;
|
||||
const GLuint *dst = (const GLuint *) rbPixels;
|
||||
GLuint *src = (GLuint *) span->array->rgba8;
|
||||
GLuint i;
|
||||
for (i = 0; i < n; i++) {
|
||||
src[i] = (src[i] & srcMask) | (dst[i] & dstMask);
|
||||
}
|
||||
}
|
||||
else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
|
||||
/* 2-byte components */
|
||||
/* XXX try to use 64-bit arithmetic someday */
|
||||
const GLushort rMask = GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 0) ? 0xffff : 0x0;
|
||||
const GLushort gMask = GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 1) ? 0xffff : 0x0;
|
||||
const GLushort bMask = GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 2) ? 0xffff : 0x0;
|
||||
const GLushort aMask = GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 3) ? 0xffff : 0x0;
|
||||
const GLushort (*dst)[4] = (const GLushort (*)[4]) rbPixels;
|
||||
GLushort (*src)[4] = span->array->rgba16;
|
||||
GLuint i;
|
||||
for (i = 0; i < n; i++) {
|
||||
src[i][RCOMP] = (src[i][RCOMP] & rMask) | (dst[i][RCOMP] & ~rMask);
|
||||
src[i][GCOMP] = (src[i][GCOMP] & gMask) | (dst[i][GCOMP] & ~gMask);
|
||||
src[i][BCOMP] = (src[i][BCOMP] & bMask) | (dst[i][BCOMP] & ~bMask);
|
||||
src[i][ACOMP] = (src[i][ACOMP] & aMask) | (dst[i][ACOMP] & ~aMask);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* 4-byte components */
|
||||
const GLuint rMask = GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 0) ? ~0x0 : 0x0;
|
||||
const GLuint gMask = GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 1) ? ~0x0 : 0x0;
|
||||
const GLuint bMask = GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 2) ? ~0x0 : 0x0;
|
||||
const GLuint aMask = GET_COLORMASK_BIT(ctx->Color.ColorMask, buf, 3) ? ~0x0 : 0x0;
|
||||
const GLuint (*dst)[4] = (const GLuint (*)[4]) rbPixels;
|
||||
GLuint (*src)[4] = (GLuint (*)[4]) span->array->attribs[VARYING_SLOT_COL0];
|
||||
GLuint i;
|
||||
for (i = 0; i < n; i++) {
|
||||
src[i][RCOMP] = (src[i][RCOMP] & rMask) | (dst[i][RCOMP] & ~rMask);
|
||||
src[i][GCOMP] = (src[i][GCOMP] & gMask) | (dst[i][GCOMP] & ~gMask);
|
||||
src[i][BCOMP] = (src[i][BCOMP] & bMask) | (dst[i][BCOMP] & ~bMask);
|
||||
src[i][ACOMP] = (src[i][ACOMP] & aMask) | (dst[i][ACOMP] & ~aMask);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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 S_MASKING_H
|
||||
#define S_MASKING_H
|
||||
|
||||
|
||||
#include "main/glheader.h"
|
||||
#include "s_span.h"
|
||||
|
||||
struct gl_context;
|
||||
struct gl_renderbuffer;
|
||||
|
||||
|
||||
extern void
|
||||
_swrast_mask_rgba_span(struct gl_context *ctx, struct gl_renderbuffer *rb,
|
||||
SWspan *span, GLuint buf);
|
||||
|
||||
#endif
|
|
@ -1,564 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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/framebuffer.h"
|
||||
#include "main/glheader.h"
|
||||
#include "main/macros.h"
|
||||
#include "s_context.h"
|
||||
#include "s_feedback.h"
|
||||
#include "s_points.h"
|
||||
#include "s_span.h"
|
||||
|
||||
|
||||
/**
|
||||
* Used to cull points with invalid coords
|
||||
*/
|
||||
#define CULL_INVALID(V) \
|
||||
do { \
|
||||
float tmp = (V)->attrib[VARYING_SLOT_POS][0] \
|
||||
+ (V)->attrib[VARYING_SLOT_POS][1]; \
|
||||
if (util_is_inf_or_nan(tmp)) \
|
||||
return; \
|
||||
} while(0)
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get/compute the point size.
|
||||
* The size may come from a vertex shader, or computed with attentuation
|
||||
* or just the glPointSize value.
|
||||
* Must also clamp to user-defined range and implmentation limits.
|
||||
*/
|
||||
static inline GLfloat
|
||||
get_size(const struct gl_context *ctx, const SWvertex *vert, GLboolean smoothed)
|
||||
{
|
||||
GLfloat size;
|
||||
|
||||
if (ctx->Point._Attenuated || ctx->VertexProgram.PointSizeEnabled) {
|
||||
/* use vertex's point size */
|
||||
size = vert->pointSize;
|
||||
}
|
||||
else {
|
||||
/* use constant point size */
|
||||
size = ctx->Point.Size;
|
||||
}
|
||||
/* always clamp to user-specified limits */
|
||||
size = CLAMP(size, ctx->Point.MinSize, ctx->Point.MaxSize);
|
||||
/* clamp to implementation limits */
|
||||
if (smoothed)
|
||||
size = CLAMP(size, ctx->Const.MinPointSizeAA, ctx->Const.MaxPointSizeAA);
|
||||
else
|
||||
size = CLAMP(size, ctx->Const.MinPointSize, ctx->Const.MaxPointSize);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Draw a point sprite
|
||||
*/
|
||||
static void
|
||||
sprite_point(struct gl_context *ctx, const SWvertex *vert)
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
SWspan span;
|
||||
GLfloat size;
|
||||
GLuint tCoords[MAX_TEXTURE_COORD_UNITS + 1];
|
||||
GLuint numTcoords = 0;
|
||||
GLfloat t0, dtdy;
|
||||
|
||||
CULL_INVALID(vert);
|
||||
|
||||
/* z coord */
|
||||
if (ctx->DrawBuffer->Visual.depthBits <= 16)
|
||||
span.z = FloatToFixed(vert->attrib[VARYING_SLOT_POS][2] + 0.5F);
|
||||
else
|
||||
span.z = (GLuint) (vert->attrib[VARYING_SLOT_POS][2] + 0.5F);
|
||||
span.zStep = 0;
|
||||
|
||||
size = get_size(ctx, vert, GL_FALSE);
|
||||
|
||||
/* span init */
|
||||
INIT_SPAN(span, GL_POINT);
|
||||
span.interpMask = SPAN_Z | SPAN_RGBA;
|
||||
|
||||
span.facing = swrast->PointLineFacing;
|
||||
|
||||
span.red = ChanToFixed(vert->color[0]);
|
||||
span.green = ChanToFixed(vert->color[1]);
|
||||
span.blue = ChanToFixed(vert->color[2]);
|
||||
span.alpha = ChanToFixed(vert->color[3]);
|
||||
span.redStep = 0;
|
||||
span.greenStep = 0;
|
||||
span.blueStep = 0;
|
||||
span.alphaStep = 0;
|
||||
|
||||
/* need these for fragment programs */
|
||||
span.attrStart[VARYING_SLOT_POS][3] = 1.0F;
|
||||
span.attrStepX[VARYING_SLOT_POS][3] = 0.0F;
|
||||
span.attrStepY[VARYING_SLOT_POS][3] = 0.0F;
|
||||
|
||||
{
|
||||
GLfloat s, dsdx;
|
||||
|
||||
/* texcoord / pointcoord interpolants */
|
||||
s = 0.0F;
|
||||
dsdx = 1.0F / size;
|
||||
if (ctx->Point.SpriteOrigin == GL_LOWER_LEFT) {
|
||||
dtdy = 1.0F / size;
|
||||
t0 = 0.5F * dtdy;
|
||||
}
|
||||
else {
|
||||
/* GL_UPPER_LEFT */
|
||||
dtdy = -1.0F / size;
|
||||
t0 = 1.0F + 0.5F * dtdy;
|
||||
}
|
||||
|
||||
ATTRIB_LOOP_BEGIN
|
||||
if (attr >= VARYING_SLOT_TEX0 && attr <= VARYING_SLOT_TEX7) {
|
||||
/* a texcoord attribute */
|
||||
const GLuint u = attr - VARYING_SLOT_TEX0;
|
||||
assert(u < MAX_TEXTURE_COORD_UNITS);
|
||||
if (ctx->Point.CoordReplace & (1u << u)) {
|
||||
tCoords[numTcoords++] = attr;
|
||||
|
||||
span.attrStart[attr][0] = s;
|
||||
span.attrStart[attr][1] = 0.0; /* overwritten below */
|
||||
span.attrStart[attr][2] = 0.0;
|
||||
span.attrStart[attr][3] = 1.0;
|
||||
|
||||
span.attrStepX[attr][0] = dsdx;
|
||||
span.attrStepX[attr][1] = 0.0;
|
||||
span.attrStepX[attr][2] = 0.0;
|
||||
span.attrStepX[attr][3] = 0.0;
|
||||
|
||||
span.attrStepY[attr][0] = 0.0;
|
||||
span.attrStepY[attr][1] = dtdy;
|
||||
span.attrStepY[attr][2] = 0.0;
|
||||
span.attrStepY[attr][3] = 0.0;
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (attr == VARYING_SLOT_PNTC) {
|
||||
/* GLSL gl_PointCoord.xy (.zw undefined) */
|
||||
span.attrStart[VARYING_SLOT_PNTC][0] = 0.0;
|
||||
span.attrStart[VARYING_SLOT_PNTC][1] = 0.0; /* t0 set below */
|
||||
span.attrStepX[VARYING_SLOT_PNTC][0] = dsdx;
|
||||
span.attrStepX[VARYING_SLOT_PNTC][1] = 0.0;
|
||||
span.attrStepY[VARYING_SLOT_PNTC][0] = 0.0;
|
||||
span.attrStepY[VARYING_SLOT_PNTC][1] = dtdy;
|
||||
tCoords[numTcoords++] = VARYING_SLOT_PNTC;
|
||||
continue;
|
||||
}
|
||||
/* use vertex's texcoord/attrib */
|
||||
COPY_4V(span.attrStart[attr], vert->attrib[attr]);
|
||||
ASSIGN_4V(span.attrStepX[attr], 0, 0, 0, 0);
|
||||
ASSIGN_4V(span.attrStepY[attr], 0, 0, 0, 0);
|
||||
ATTRIB_LOOP_END;
|
||||
}
|
||||
|
||||
/* compute pos, bounds and render */
|
||||
{
|
||||
const GLfloat x = vert->attrib[VARYING_SLOT_POS][0];
|
||||
const GLfloat y = vert->attrib[VARYING_SLOT_POS][1];
|
||||
GLint iSize = (GLint) (size + 0.5F);
|
||||
GLint xmin, xmax, ymin, ymax, iy;
|
||||
GLint iRadius;
|
||||
GLfloat tcoord = t0;
|
||||
|
||||
iSize = MAX2(1, iSize);
|
||||
iRadius = iSize / 2;
|
||||
|
||||
if (iSize & 1) {
|
||||
/* odd size */
|
||||
xmin = (GLint) (x - iRadius);
|
||||
xmax = (GLint) (x + iRadius);
|
||||
ymin = (GLint) (y - iRadius);
|
||||
ymax = (GLint) (y + iRadius);
|
||||
}
|
||||
else {
|
||||
/* even size */
|
||||
/* 0.501 factor allows conformance to pass */
|
||||
xmin = (GLint) (x + 0.501F) - iRadius;
|
||||
xmax = xmin + iSize - 1;
|
||||
ymin = (GLint) (y + 0.501F) - iRadius;
|
||||
ymax = ymin + iSize - 1;
|
||||
}
|
||||
|
||||
/* render spans */
|
||||
for (iy = ymin; iy <= ymax; iy++) {
|
||||
GLuint i;
|
||||
/* setup texcoord T for this row */
|
||||
for (i = 0; i < numTcoords; i++) {
|
||||
span.attrStart[tCoords[i]][1] = tcoord;
|
||||
}
|
||||
|
||||
/* these might get changed by span clipping */
|
||||
span.x = xmin;
|
||||
span.y = iy;
|
||||
span.end = xmax - xmin + 1;
|
||||
|
||||
_swrast_write_rgba_span(ctx, &span);
|
||||
|
||||
tcoord += dtdy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Draw smooth/antialiased point. RGB or CI mode.
|
||||
*/
|
||||
static void
|
||||
smooth_point(struct gl_context *ctx, const SWvertex *vert)
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
SWspan span;
|
||||
GLfloat size, alphaAtten;
|
||||
|
||||
CULL_INVALID(vert);
|
||||
|
||||
/* z coord */
|
||||
if (ctx->DrawBuffer->Visual.depthBits <= 16)
|
||||
span.z = FloatToFixed(vert->attrib[VARYING_SLOT_POS][2] + 0.5F);
|
||||
else
|
||||
span.z = (GLuint) (vert->attrib[VARYING_SLOT_POS][2] + 0.5F);
|
||||
span.zStep = 0;
|
||||
|
||||
size = get_size(ctx, vert, GL_TRUE);
|
||||
|
||||
/* alpha attenuation / fade factor */
|
||||
if (_mesa_is_multisample_enabled(ctx)) {
|
||||
if (vert->pointSize >= ctx->Point.Threshold) {
|
||||
alphaAtten = 1.0F;
|
||||
}
|
||||
else {
|
||||
GLfloat dsize = vert->pointSize / ctx->Point.Threshold;
|
||||
alphaAtten = dsize * dsize;
|
||||
}
|
||||
}
|
||||
else {
|
||||
alphaAtten = 1.0;
|
||||
}
|
||||
(void) alphaAtten; /* not used */
|
||||
|
||||
/* span init */
|
||||
INIT_SPAN(span, GL_POINT);
|
||||
span.interpMask = SPAN_Z | SPAN_RGBA;
|
||||
span.arrayMask = SPAN_COVERAGE | SPAN_MASK;
|
||||
|
||||
span.facing = swrast->PointLineFacing;
|
||||
|
||||
span.red = ChanToFixed(vert->color[0]);
|
||||
span.green = ChanToFixed(vert->color[1]);
|
||||
span.blue = ChanToFixed(vert->color[2]);
|
||||
span.alpha = ChanToFixed(vert->color[3]);
|
||||
span.redStep = 0;
|
||||
span.greenStep = 0;
|
||||
span.blueStep = 0;
|
||||
span.alphaStep = 0;
|
||||
|
||||
/* need these for fragment programs */
|
||||
span.attrStart[VARYING_SLOT_POS][3] = 1.0F;
|
||||
span.attrStepX[VARYING_SLOT_POS][3] = 0.0F;
|
||||
span.attrStepY[VARYING_SLOT_POS][3] = 0.0F;
|
||||
|
||||
ATTRIB_LOOP_BEGIN
|
||||
COPY_4V(span.attrStart[attr], vert->attrib[attr]);
|
||||
ASSIGN_4V(span.attrStepX[attr], 0, 0, 0, 0);
|
||||
ASSIGN_4V(span.attrStepY[attr], 0, 0, 0, 0);
|
||||
ATTRIB_LOOP_END
|
||||
|
||||
/* compute pos, bounds and render */
|
||||
{
|
||||
const GLfloat x = vert->attrib[VARYING_SLOT_POS][0];
|
||||
const GLfloat y = vert->attrib[VARYING_SLOT_POS][1];
|
||||
const GLfloat radius = 0.5F * size;
|
||||
const GLfloat rmin = radius - 0.7071F; /* 0.7071 = sqrt(2)/2 */
|
||||
const GLfloat rmax = radius + 0.7071F;
|
||||
const GLfloat rmin2 = MAX2(0.0F, rmin * rmin);
|
||||
const GLfloat rmax2 = rmax * rmax;
|
||||
const GLfloat cscale = 1.0F / (rmax2 - rmin2);
|
||||
const GLint xmin = (GLint) (x - radius);
|
||||
const GLint xmax = (GLint) (x + radius);
|
||||
const GLint ymin = (GLint) (y - radius);
|
||||
const GLint ymax = (GLint) (y + radius);
|
||||
GLint ix, iy;
|
||||
|
||||
for (iy = ymin; iy <= ymax; iy++) {
|
||||
|
||||
/* these might get changed by span clipping */
|
||||
span.x = xmin;
|
||||
span.y = iy;
|
||||
span.end = xmax - xmin + 1;
|
||||
|
||||
/* compute coverage for each pixel in span */
|
||||
for (ix = xmin; ix <= xmax; ix++) {
|
||||
const GLfloat dx = ix - x + 0.5F;
|
||||
const GLfloat dy = iy - y + 0.5F;
|
||||
const GLfloat dist2 = dx * dx + dy * dy;
|
||||
GLfloat coverage;
|
||||
|
||||
if (dist2 < rmax2) {
|
||||
if (dist2 >= rmin2) {
|
||||
/* compute partial coverage */
|
||||
coverage = 1.0F - (dist2 - rmin2) * cscale;
|
||||
}
|
||||
else {
|
||||
/* full coverage */
|
||||
coverage = 1.0F;
|
||||
}
|
||||
span.array->mask[ix - xmin] = 1;
|
||||
}
|
||||
else {
|
||||
/* zero coverage - fragment outside the radius */
|
||||
coverage = 0.0;
|
||||
span.array->mask[ix - xmin] = 0;
|
||||
}
|
||||
span.array->coverage[ix - xmin] = coverage;
|
||||
}
|
||||
|
||||
/* render span */
|
||||
_swrast_write_rgba_span(ctx, &span);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Draw large (size >= 1) non-AA point. RGB or CI mode.
|
||||
*/
|
||||
static void
|
||||
large_point(struct gl_context *ctx, const SWvertex *vert)
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
SWspan span;
|
||||
GLfloat size;
|
||||
|
||||
CULL_INVALID(vert);
|
||||
|
||||
/* z coord */
|
||||
if (ctx->DrawBuffer->Visual.depthBits <= 16)
|
||||
span.z = FloatToFixed(vert->attrib[VARYING_SLOT_POS][2] + 0.5F);
|
||||
else
|
||||
span.z = (GLuint) (vert->attrib[VARYING_SLOT_POS][2] + 0.5F);
|
||||
span.zStep = 0;
|
||||
|
||||
size = get_size(ctx, vert, GL_FALSE);
|
||||
|
||||
/* span init */
|
||||
INIT_SPAN(span, GL_POINT);
|
||||
span.arrayMask = SPAN_XY;
|
||||
span.facing = swrast->PointLineFacing;
|
||||
|
||||
span.interpMask = SPAN_Z | SPAN_RGBA;
|
||||
span.red = ChanToFixed(vert->color[0]);
|
||||
span.green = ChanToFixed(vert->color[1]);
|
||||
span.blue = ChanToFixed(vert->color[2]);
|
||||
span.alpha = ChanToFixed(vert->color[3]);
|
||||
span.redStep = 0;
|
||||
span.greenStep = 0;
|
||||
span.blueStep = 0;
|
||||
span.alphaStep = 0;
|
||||
|
||||
/* need these for fragment programs */
|
||||
span.attrStart[VARYING_SLOT_POS][3] = 1.0F;
|
||||
span.attrStepX[VARYING_SLOT_POS][3] = 0.0F;
|
||||
span.attrStepY[VARYING_SLOT_POS][3] = 0.0F;
|
||||
|
||||
ATTRIB_LOOP_BEGIN
|
||||
COPY_4V(span.attrStart[attr], vert->attrib[attr]);
|
||||
ASSIGN_4V(span.attrStepX[attr], 0, 0, 0, 0);
|
||||
ASSIGN_4V(span.attrStepY[attr], 0, 0, 0, 0);
|
||||
ATTRIB_LOOP_END
|
||||
|
||||
/* compute pos, bounds and render */
|
||||
{
|
||||
const GLfloat x = vert->attrib[VARYING_SLOT_POS][0];
|
||||
const GLfloat y = vert->attrib[VARYING_SLOT_POS][1];
|
||||
GLint iSize = (GLint) (size + 0.5F);
|
||||
GLint xmin, xmax, ymin, ymax, ix, iy;
|
||||
GLint iRadius;
|
||||
|
||||
iSize = MAX2(1, iSize);
|
||||
iRadius = iSize / 2;
|
||||
|
||||
if (iSize & 1) {
|
||||
/* odd size */
|
||||
xmin = (GLint) (x - iRadius);
|
||||
xmax = (GLint) (x + iRadius);
|
||||
ymin = (GLint) (y - iRadius);
|
||||
ymax = (GLint) (y + iRadius);
|
||||
}
|
||||
else {
|
||||
/* even size */
|
||||
/* 0.501 factor allows conformance to pass */
|
||||
xmin = (GLint) (x + 0.501F) - iRadius;
|
||||
xmax = xmin + iSize - 1;
|
||||
ymin = (GLint) (y + 0.501F) - iRadius;
|
||||
ymax = ymin + iSize - 1;
|
||||
}
|
||||
|
||||
/* generate fragments */
|
||||
span.end = 0;
|
||||
for (iy = ymin; iy <= ymax; iy++) {
|
||||
for (ix = xmin; ix <= xmax; ix++) {
|
||||
span.array->x[span.end] = ix;
|
||||
span.array->y[span.end] = iy;
|
||||
span.end++;
|
||||
}
|
||||
}
|
||||
assert(span.end <= SWRAST_MAX_WIDTH);
|
||||
_swrast_write_rgba_span(ctx, &span);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Draw size=1, single-pixel point
|
||||
*/
|
||||
static void
|
||||
pixel_point(struct gl_context *ctx, const SWvertex *vert)
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
/*
|
||||
* Note that unlike the other functions, we put single-pixel points
|
||||
* into a special span array in order to render as many points as
|
||||
* possible with a single _swrast_write_rgba_span() call.
|
||||
*/
|
||||
SWspan *span = &(swrast->PointSpan);
|
||||
GLuint count;
|
||||
|
||||
CULL_INVALID(vert);
|
||||
|
||||
/* Span init */
|
||||
span->interpMask = 0;
|
||||
span->arrayMask = SPAN_XY | SPAN_Z;
|
||||
span->arrayMask |= SPAN_RGBA;
|
||||
/*span->arrayMask |= SPAN_LAMBDA;*/
|
||||
span->arrayAttribs = swrast->_ActiveAttribMask; /* we'll produce these vals */
|
||||
|
||||
/* need these for fragment programs */
|
||||
span->attrStart[VARYING_SLOT_POS][3] = 1.0F;
|
||||
span->attrStepX[VARYING_SLOT_POS][3] = 0.0F;
|
||||
span->attrStepY[VARYING_SLOT_POS][3] = 0.0F;
|
||||
|
||||
/* check if we need to flush */
|
||||
if (span->end >= SWRAST_MAX_WIDTH ||
|
||||
(swrast->_RasterMask & (BLEND_BIT | LOGIC_OP_BIT | MASKING_BIT)) ||
|
||||
span->facing != swrast->PointLineFacing) {
|
||||
if (span->end > 0) {
|
||||
_swrast_write_rgba_span(ctx, span);
|
||||
span->end = 0;
|
||||
}
|
||||
}
|
||||
|
||||
count = span->end;
|
||||
|
||||
span->facing = swrast->PointLineFacing;
|
||||
|
||||
/* fragment attributes */
|
||||
span->array->rgba[count][RCOMP] = vert->color[0];
|
||||
span->array->rgba[count][GCOMP] = vert->color[1];
|
||||
span->array->rgba[count][BCOMP] = vert->color[2];
|
||||
span->array->rgba[count][ACOMP] = vert->color[3];
|
||||
|
||||
ATTRIB_LOOP_BEGIN
|
||||
COPY_4V(span->array->attribs[attr][count], vert->attrib[attr]);
|
||||
ATTRIB_LOOP_END
|
||||
|
||||
/* fragment position */
|
||||
span->array->x[count] = (GLint) vert->attrib[VARYING_SLOT_POS][0];
|
||||
span->array->y[count] = (GLint) vert->attrib[VARYING_SLOT_POS][1];
|
||||
span->array->z[count] = (GLint) (vert->attrib[VARYING_SLOT_POS][2] + 0.5F);
|
||||
|
||||
span->end = count + 1;
|
||||
assert(span->end <= SWRAST_MAX_WIDTH);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add specular color to primary color, draw point, restore original
|
||||
* primary color.
|
||||
*/
|
||||
void
|
||||
_swrast_add_spec_terms_point(struct gl_context *ctx, const SWvertex *v0)
|
||||
{
|
||||
SWvertex *ncv0 = (SWvertex *) v0; /* cast away const */
|
||||
GLfloat rSum, gSum, bSum;
|
||||
GLchan cSave[4];
|
||||
|
||||
/* save */
|
||||
COPY_CHAN4(cSave, ncv0->color);
|
||||
/* sum */
|
||||
rSum = CHAN_TO_FLOAT(ncv0->color[0]) + ncv0->attrib[VARYING_SLOT_COL1][0];
|
||||
gSum = CHAN_TO_FLOAT(ncv0->color[1]) + ncv0->attrib[VARYING_SLOT_COL1][1];
|
||||
bSum = CHAN_TO_FLOAT(ncv0->color[2]) + ncv0->attrib[VARYING_SLOT_COL1][2];
|
||||
UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[0], rSum);
|
||||
UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[1], gSum);
|
||||
UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[2], bSum);
|
||||
/* draw */
|
||||
SWRAST_CONTEXT(ctx)->SpecPoint(ctx, ncv0);
|
||||
/* restore */
|
||||
COPY_CHAN4(ncv0->color, cSave);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Examine current state to determine which point drawing function to use.
|
||||
*/
|
||||
void
|
||||
_swrast_choose_point(struct gl_context *ctx)
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
const GLfloat size = CLAMP(ctx->Point.Size,
|
||||
ctx->Point.MinSize,
|
||||
ctx->Point.MaxSize);
|
||||
|
||||
if (ctx->RenderMode == GL_RENDER) {
|
||||
if (ctx->Point.PointSprite) {
|
||||
swrast->Point = sprite_point;
|
||||
}
|
||||
else if (ctx->Point.SmoothFlag) {
|
||||
swrast->Point = smooth_point;
|
||||
}
|
||||
else if (size > 1.0F ||
|
||||
ctx->Point._Attenuated ||
|
||||
ctx->VertexProgram.PointSizeEnabled) {
|
||||
swrast->Point = large_point;
|
||||
}
|
||||
else {
|
||||
swrast->Point = pixel_point;
|
||||
}
|
||||
}
|
||||
else if (ctx->RenderMode == GL_FEEDBACK) {
|
||||
swrast->Point = _swrast_feedback_point;
|
||||
}
|
||||
else {
|
||||
/* GL_SELECT mode */
|
||||
swrast->Point = _swrast_select_point;
|
||||
}
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
|
||||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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 S_POINTS_H
|
||||
#define S_POINTS_H
|
||||
|
||||
#include "swrast.h"
|
||||
|
||||
extern void
|
||||
_swrast_choose_point( struct gl_context *ctx );
|
||||
|
||||
extern void
|
||||
_swrast_add_spec_terms_point( struct gl_context *ctx,
|
||||
const SWvertex *v0 );
|
||||
|
||||
#endif
|
|
@ -1,642 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Functions for allocating/managing software-based renderbuffers.
|
||||
* Also, routines for reading/writing software-based renderbuffer data as
|
||||
* ubytes, ushorts, uints, etc.
|
||||
*/
|
||||
|
||||
|
||||
#include "main/glheader.h"
|
||||
|
||||
#include "main/context.h"
|
||||
#include "main/fbobject.h"
|
||||
#include "main/formats.h"
|
||||
#include "main/mtypes.h"
|
||||
#include "main/renderbuffer.h"
|
||||
#include "util/u_memory.h"
|
||||
#include "swrast/s_context.h"
|
||||
#include "swrast/s_renderbuffer.h"
|
||||
|
||||
|
||||
/**
|
||||
* This is a software fallback for the gl_renderbuffer->AllocStorage
|
||||
* function.
|
||||
* Device drivers will typically override this function for the buffers
|
||||
* which it manages (typically color buffers, Z and stencil).
|
||||
* Other buffers (like software accumulation and aux buffers) which the driver
|
||||
* doesn't manage can be handled with this function.
|
||||
*
|
||||
* This one multi-purpose function can allocate stencil, depth, accum, color
|
||||
* or color-index buffers!
|
||||
*/
|
||||
static GLboolean
|
||||
soft_renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
|
||||
GLenum internalFormat,
|
||||
GLuint width, GLuint height)
|
||||
{
|
||||
struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
|
||||
GLuint bpp;
|
||||
|
||||
switch (internalFormat) {
|
||||
case GL_RGB:
|
||||
case GL_R3_G3_B2:
|
||||
case GL_RGB4:
|
||||
case GL_RGB5:
|
||||
case GL_RGB8:
|
||||
case GL_RGB10:
|
||||
case GL_RGB12:
|
||||
case GL_RGB16:
|
||||
rb->Format = MESA_FORMAT_BGR_UNORM8;
|
||||
break;
|
||||
case GL_RGBA:
|
||||
case GL_RGBA2:
|
||||
case GL_RGBA4:
|
||||
case GL_RGB5_A1:
|
||||
case GL_RGBA8:
|
||||
case GL_RGB10_A2:
|
||||
case GL_RGBA12:
|
||||
#if UTIL_ARCH_LITTLE_ENDIAN
|
||||
rb->Format = MESA_FORMAT_R8G8B8A8_UNORM;
|
||||
#else
|
||||
rb->Format = MESA_FORMAT_A8B8G8R8_UNORM;
|
||||
#endif
|
||||
break;
|
||||
case GL_RGBA16:
|
||||
case GL_RGBA16_SNORM:
|
||||
/* for accum buffer */
|
||||
rb->Format = MESA_FORMAT_RGBA_SNORM16;
|
||||
break;
|
||||
case GL_STENCIL_INDEX:
|
||||
case GL_STENCIL_INDEX1_EXT:
|
||||
case GL_STENCIL_INDEX4_EXT:
|
||||
case GL_STENCIL_INDEX8_EXT:
|
||||
case GL_STENCIL_INDEX16_EXT:
|
||||
rb->Format = MESA_FORMAT_S_UINT8;
|
||||
break;
|
||||
case GL_DEPTH_COMPONENT:
|
||||
case GL_DEPTH_COMPONENT16:
|
||||
rb->Format = MESA_FORMAT_Z_UNORM16;
|
||||
break;
|
||||
case GL_DEPTH_COMPONENT24:
|
||||
rb->Format = MESA_FORMAT_Z24_UNORM_X8_UINT;
|
||||
break;
|
||||
case GL_DEPTH_COMPONENT32:
|
||||
rb->Format = MESA_FORMAT_Z_UNORM32;
|
||||
break;
|
||||
case GL_DEPTH_STENCIL_EXT:
|
||||
case GL_DEPTH24_STENCIL8_EXT:
|
||||
rb->Format = MESA_FORMAT_S8_UINT_Z24_UNORM;
|
||||
break;
|
||||
default:
|
||||
/* unsupported format */
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
bpp = _mesa_get_format_bytes(rb->Format);
|
||||
|
||||
/* free old buffer storage */
|
||||
free(srb->Buffer);
|
||||
srb->Buffer = NULL;
|
||||
|
||||
srb->RowStride = width * bpp;
|
||||
|
||||
if (width > 0 && height > 0) {
|
||||
/* allocate new buffer storage */
|
||||
srb->Buffer = malloc(srb->RowStride * height);
|
||||
|
||||
if (srb->Buffer == NULL) {
|
||||
rb->Width = 0;
|
||||
rb->Height = 0;
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY,
|
||||
"software renderbuffer allocation (%d x %d x %d)",
|
||||
width, height, bpp);
|
||||
return GL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
rb->Width = width;
|
||||
rb->Height = height;
|
||||
rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat);
|
||||
|
||||
if (rb->Name == 0 &&
|
||||
internalFormat == GL_RGBA16_SNORM &&
|
||||
rb->_BaseFormat == 0) {
|
||||
/* NOTE: This is a special case just for accumulation buffers.
|
||||
* This is a very limited use case- there's no snorm texturing or
|
||||
* rendering going on.
|
||||
*/
|
||||
rb->_BaseFormat = GL_RGBA;
|
||||
}
|
||||
else {
|
||||
/* the internalFormat should have been error checked long ago */
|
||||
assert(rb->_BaseFormat);
|
||||
}
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called via gl_renderbuffer::Delete()
|
||||
*/
|
||||
static void
|
||||
soft_renderbuffer_delete(struct gl_context *ctx, struct gl_renderbuffer *rb)
|
||||
{
|
||||
struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
|
||||
|
||||
free(srb->Buffer);
|
||||
srb->Buffer = NULL;
|
||||
_mesa_delete_renderbuffer(ctx, rb);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_swrast_map_soft_renderbuffer(struct gl_context *ctx,
|
||||
struct gl_renderbuffer *rb,
|
||||
GLuint x, GLuint y, GLuint w, GLuint h,
|
||||
GLbitfield mode,
|
||||
GLubyte **out_map,
|
||||
GLint *out_stride,
|
||||
bool flip_y)
|
||||
{
|
||||
struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
|
||||
GLubyte *map = srb->Buffer;
|
||||
int cpp = _mesa_get_format_bytes(rb->Format);
|
||||
int stride = rb->Width * cpp;
|
||||
|
||||
if (!map) {
|
||||
*out_map = NULL;
|
||||
*out_stride = 0;
|
||||
}
|
||||
|
||||
map += y * stride;
|
||||
map += x * cpp;
|
||||
|
||||
*out_map = map;
|
||||
*out_stride = stride;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_swrast_unmap_soft_renderbuffer(struct gl_context *ctx,
|
||||
struct gl_renderbuffer *rb)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Allocate a software-based renderbuffer. This is called via the
|
||||
* ctx->Driver.NewRenderbuffer() function when the user creates a new
|
||||
* renderbuffer.
|
||||
* This would not be used for hardware-based renderbuffers.
|
||||
*/
|
||||
struct gl_renderbuffer *
|
||||
_swrast_new_soft_renderbuffer(struct gl_context *ctx, GLuint name)
|
||||
{
|
||||
struct swrast_renderbuffer *srb = CALLOC_STRUCT(swrast_renderbuffer);
|
||||
if (srb) {
|
||||
_mesa_init_renderbuffer(&srb->Base, name);
|
||||
srb->Base.AllocStorage = soft_renderbuffer_storage;
|
||||
srb->Base.Delete = soft_renderbuffer_delete;
|
||||
}
|
||||
return &srb->Base;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add software-based color renderbuffers to the given framebuffer.
|
||||
* This is a helper routine for device drivers when creating a
|
||||
* window system framebuffer (not a user-created render/framebuffer).
|
||||
* Once this function is called, you can basically forget about this
|
||||
* renderbuffer; core Mesa will handle all the buffer management and
|
||||
* rendering!
|
||||
*/
|
||||
static GLboolean
|
||||
add_color_renderbuffers(struct gl_context *ctx, struct gl_framebuffer *fb,
|
||||
GLuint rgbBits, GLuint alphaBits,
|
||||
GLboolean frontLeft, GLboolean backLeft,
|
||||
GLboolean frontRight, GLboolean backRight)
|
||||
{
|
||||
gl_buffer_index b;
|
||||
|
||||
if (rgbBits > 16 || alphaBits > 16) {
|
||||
_mesa_problem(ctx,
|
||||
"Unsupported bit depth in add_color_renderbuffers");
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
assert(MAX_COLOR_ATTACHMENTS >= 4);
|
||||
|
||||
for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) {
|
||||
struct gl_renderbuffer *rb;
|
||||
|
||||
if (b == BUFFER_FRONT_LEFT && !frontLeft)
|
||||
continue;
|
||||
else if (b == BUFFER_BACK_LEFT && !backLeft)
|
||||
continue;
|
||||
else if (b == BUFFER_FRONT_RIGHT && !frontRight)
|
||||
continue;
|
||||
else if (b == BUFFER_BACK_RIGHT && !backRight)
|
||||
continue;
|
||||
|
||||
assert(fb->Attachment[b].Renderbuffer == NULL);
|
||||
|
||||
rb = ctx->Driver.NewRenderbuffer(ctx, 0);
|
||||
if (!rb) {
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating color buffer");
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
rb->InternalFormat = GL_RGBA;
|
||||
|
||||
rb->AllocStorage = soft_renderbuffer_storage;
|
||||
_mesa_attach_and_own_rb(fb, b, rb);
|
||||
}
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a software-based depth renderbuffer to the given framebuffer.
|
||||
* This is a helper routine for device drivers when creating a
|
||||
* window system framebuffer (not a user-created render/framebuffer).
|
||||
* Once this function is called, you can basically forget about this
|
||||
* renderbuffer; core Mesa will handle all the buffer management and
|
||||
* rendering!
|
||||
*/
|
||||
static GLboolean
|
||||
add_depth_renderbuffer(struct gl_context *ctx, struct gl_framebuffer *fb,
|
||||
GLuint depthBits)
|
||||
{
|
||||
struct gl_renderbuffer *rb;
|
||||
|
||||
if (depthBits > 32) {
|
||||
_mesa_problem(ctx,
|
||||
"Unsupported depthBits in add_depth_renderbuffer");
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
assert(fb->Attachment[BUFFER_DEPTH].Renderbuffer == NULL);
|
||||
|
||||
rb = _swrast_new_soft_renderbuffer(ctx, 0);
|
||||
if (!rb) {
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating depth buffer");
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
if (depthBits <= 16) {
|
||||
rb->InternalFormat = GL_DEPTH_COMPONENT16;
|
||||
}
|
||||
else if (depthBits <= 24) {
|
||||
rb->InternalFormat = GL_DEPTH_COMPONENT24;
|
||||
}
|
||||
else {
|
||||
rb->InternalFormat = GL_DEPTH_COMPONENT32;
|
||||
}
|
||||
|
||||
rb->AllocStorage = soft_renderbuffer_storage;
|
||||
_mesa_attach_and_own_rb(fb, BUFFER_DEPTH, rb);
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a software-based stencil renderbuffer to the given framebuffer.
|
||||
* This is a helper routine for device drivers when creating a
|
||||
* window system framebuffer (not a user-created render/framebuffer).
|
||||
* Once this function is called, you can basically forget about this
|
||||
* renderbuffer; core Mesa will handle all the buffer management and
|
||||
* rendering!
|
||||
*/
|
||||
static GLboolean
|
||||
add_stencil_renderbuffer(struct gl_context *ctx, struct gl_framebuffer *fb,
|
||||
GLuint stencilBits)
|
||||
{
|
||||
struct gl_renderbuffer *rb;
|
||||
|
||||
if (stencilBits > 16) {
|
||||
_mesa_problem(ctx,
|
||||
"Unsupported stencilBits in add_stencil_renderbuffer");
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
assert(fb->Attachment[BUFFER_STENCIL].Renderbuffer == NULL);
|
||||
|
||||
rb = _swrast_new_soft_renderbuffer(ctx, 0);
|
||||
if (!rb) {
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating stencil buffer");
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
assert(stencilBits <= 8);
|
||||
rb->InternalFormat = GL_STENCIL_INDEX8;
|
||||
|
||||
rb->AllocStorage = soft_renderbuffer_storage;
|
||||
_mesa_attach_and_own_rb(fb, BUFFER_STENCIL, rb);
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
static GLboolean
|
||||
add_depth_stencil_renderbuffer(struct gl_context *ctx,
|
||||
struct gl_framebuffer *fb)
|
||||
{
|
||||
struct gl_renderbuffer *rb;
|
||||
|
||||
assert(fb->Attachment[BUFFER_DEPTH].Renderbuffer == NULL);
|
||||
assert(fb->Attachment[BUFFER_STENCIL].Renderbuffer == NULL);
|
||||
|
||||
rb = _swrast_new_soft_renderbuffer(ctx, 0);
|
||||
if (!rb) {
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating depth+stencil buffer");
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
rb->InternalFormat = GL_DEPTH_STENCIL;
|
||||
|
||||
rb->AllocStorage = soft_renderbuffer_storage;
|
||||
_mesa_attach_and_own_rb(fb, BUFFER_DEPTH, rb);
|
||||
_mesa_attach_and_reference_rb(fb, BUFFER_STENCIL, rb);
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a software-based accumulation renderbuffer to the given framebuffer.
|
||||
* This is a helper routine for device drivers when creating a
|
||||
* window system framebuffer (not a user-created render/framebuffer).
|
||||
* Once this function is called, you can basically forget about this
|
||||
* renderbuffer; core Mesa will handle all the buffer management and
|
||||
* rendering!
|
||||
*/
|
||||
static GLboolean
|
||||
add_accum_renderbuffer(struct gl_context *ctx, struct gl_framebuffer *fb,
|
||||
GLuint redBits, GLuint greenBits,
|
||||
GLuint blueBits, GLuint alphaBits)
|
||||
{
|
||||
struct gl_renderbuffer *rb;
|
||||
|
||||
if (redBits > 16 || greenBits > 16 || blueBits > 16 || alphaBits > 16) {
|
||||
_mesa_problem(ctx,
|
||||
"Unsupported accumBits in add_accum_renderbuffer");
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
assert(fb->Attachment[BUFFER_ACCUM].Renderbuffer == NULL);
|
||||
|
||||
rb = _swrast_new_soft_renderbuffer(ctx, 0);
|
||||
if (!rb) {
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating accum buffer");
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
rb->InternalFormat = GL_RGBA16_SNORM;
|
||||
rb->AllocStorage = soft_renderbuffer_storage;
|
||||
_mesa_attach_and_own_rb(fb, BUFFER_ACCUM, rb);
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create/attach software-based renderbuffers to the given framebuffer.
|
||||
* This is a helper routine for device drivers. Drivers can just as well
|
||||
* call the individual _mesa_add_*_renderbuffer() routines directly.
|
||||
*/
|
||||
void
|
||||
_swrast_add_soft_renderbuffers(struct gl_framebuffer *fb,
|
||||
GLboolean color,
|
||||
GLboolean depth,
|
||||
GLboolean stencil,
|
||||
GLboolean accum,
|
||||
GLboolean alpha)
|
||||
{
|
||||
GLboolean frontLeft = GL_TRUE;
|
||||
GLboolean backLeft = fb->Visual.doubleBufferMode;
|
||||
GLboolean frontRight = fb->Visual.stereoMode;
|
||||
GLboolean backRight = fb->Visual.stereoMode && fb->Visual.doubleBufferMode;
|
||||
|
||||
if (color) {
|
||||
assert(fb->Visual.redBits == fb->Visual.greenBits);
|
||||
assert(fb->Visual.redBits == fb->Visual.blueBits);
|
||||
add_color_renderbuffers(NULL, fb,
|
||||
fb->Visual.redBits,
|
||||
fb->Visual.alphaBits,
|
||||
frontLeft, backLeft,
|
||||
frontRight, backRight);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* This is pretty much for debugging purposes only since there's a perf
|
||||
* hit for using combined depth/stencil in swrast.
|
||||
*/
|
||||
if (depth && fb->Visual.depthBits == 24 &&
|
||||
stencil && fb->Visual.stencilBits == 8) {
|
||||
/* use combined depth/stencil buffer */
|
||||
add_depth_stencil_renderbuffer(NULL, fb);
|
||||
}
|
||||
else
|
||||
#else
|
||||
(void) add_depth_stencil_renderbuffer;
|
||||
#endif
|
||||
{
|
||||
if (depth) {
|
||||
assert(fb->Visual.depthBits > 0);
|
||||
add_depth_renderbuffer(NULL, fb, fb->Visual.depthBits);
|
||||
}
|
||||
|
||||
if (stencil) {
|
||||
assert(fb->Visual.stencilBits > 0);
|
||||
add_stencil_renderbuffer(NULL, fb, fb->Visual.stencilBits);
|
||||
}
|
||||
}
|
||||
|
||||
if (accum) {
|
||||
assert(fb->Visual.accumRedBits > 0);
|
||||
assert(fb->Visual.accumGreenBits > 0);
|
||||
assert(fb->Visual.accumBlueBits > 0);
|
||||
add_accum_renderbuffer(NULL, fb,
|
||||
fb->Visual.accumRedBits,
|
||||
fb->Visual.accumGreenBits,
|
||||
fb->Visual.accumBlueBits,
|
||||
fb->Visual.accumAlphaBits);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
map_attachment(struct gl_context *ctx,
|
||||
struct gl_framebuffer *fb,
|
||||
gl_buffer_index buffer)
|
||||
{
|
||||
struct gl_texture_object *texObj = fb->Attachment[buffer].Texture;
|
||||
struct gl_renderbuffer *rb = fb->Attachment[buffer].Renderbuffer;
|
||||
struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
|
||||
|
||||
if (texObj) {
|
||||
/* map texture image (render to texture) */
|
||||
const GLuint level = fb->Attachment[buffer].TextureLevel;
|
||||
const GLuint face = fb->Attachment[buffer].CubeMapFace;
|
||||
const GLuint slice = fb->Attachment[buffer].Zoffset;
|
||||
struct gl_texture_image *texImage = texObj->Image[face][level];
|
||||
if (texImage) {
|
||||
ctx->Driver.MapTextureImage(ctx, texImage, slice,
|
||||
0, 0, texImage->Width, texImage->Height,
|
||||
GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
|
||||
&srb->Map, &srb->RowStride);
|
||||
}
|
||||
}
|
||||
else if (rb) {
|
||||
/* Map ordinary renderbuffer */
|
||||
ctx->Driver.MapRenderbuffer(ctx, rb,
|
||||
0, 0, rb->Width, rb->Height,
|
||||
GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
|
||||
&srb->Map, &srb->RowStride,
|
||||
fb->FlipY);
|
||||
}
|
||||
|
||||
assert(srb->Map);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
unmap_attachment(struct gl_context *ctx,
|
||||
struct gl_framebuffer *fb,
|
||||
gl_buffer_index buffer)
|
||||
{
|
||||
struct gl_texture_object *texObj = fb->Attachment[buffer].Texture;
|
||||
struct gl_renderbuffer *rb = fb->Attachment[buffer].Renderbuffer;
|
||||
struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
|
||||
|
||||
if (texObj) {
|
||||
/* unmap texture image (render to texture) */
|
||||
const GLuint level = fb->Attachment[buffer].TextureLevel;
|
||||
const GLuint face = fb->Attachment[buffer].CubeMapFace;
|
||||
const GLuint slice = fb->Attachment[buffer].Zoffset;
|
||||
struct gl_texture_image *texImage = texObj->Image[face][level];
|
||||
if (texImage) {
|
||||
ctx->Driver.UnmapTextureImage(ctx, texImage, slice);
|
||||
}
|
||||
}
|
||||
else if (rb) {
|
||||
/* unmap ordinary renderbuffer */
|
||||
ctx->Driver.UnmapRenderbuffer(ctx, rb);
|
||||
}
|
||||
|
||||
srb->Map = NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine what type to use (ubyte vs. float) for span colors for the
|
||||
* given renderbuffer.
|
||||
* See also _swrast_write_rgba_span().
|
||||
*/
|
||||
static void
|
||||
find_renderbuffer_colortype(struct gl_renderbuffer *rb)
|
||||
{
|
||||
struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
|
||||
GLuint rbMaxBits = _mesa_get_format_max_bits(rb->Format);
|
||||
GLenum rbDatatype = _mesa_get_format_datatype(rb->Format);
|
||||
|
||||
if (rbDatatype == GL_UNSIGNED_NORMALIZED && rbMaxBits <= 8) {
|
||||
/* the buffer's values fit in GLubyte values */
|
||||
srb->ColorType = GL_UNSIGNED_BYTE;
|
||||
}
|
||||
else {
|
||||
/* use floats otherwise */
|
||||
srb->ColorType = GL_FLOAT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Map the renderbuffers we'll use for tri/line/point rendering.
|
||||
*/
|
||||
void
|
||||
_swrast_map_renderbuffers(struct gl_context *ctx)
|
||||
{
|
||||
struct gl_framebuffer *fb = ctx->DrawBuffer;
|
||||
struct gl_renderbuffer *depthRb, *stencilRb;
|
||||
GLuint buf;
|
||||
|
||||
depthRb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
|
||||
if (depthRb) {
|
||||
/* map depth buffer */
|
||||
map_attachment(ctx, fb, BUFFER_DEPTH);
|
||||
}
|
||||
|
||||
stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
|
||||
if (stencilRb && stencilRb != depthRb) {
|
||||
/* map stencil buffer */
|
||||
map_attachment(ctx, fb, BUFFER_STENCIL);
|
||||
}
|
||||
|
||||
for (buf = 0; buf < fb->_NumColorDrawBuffers; buf++) {
|
||||
if (fb->_ColorDrawBufferIndexes[buf] != BUFFER_NONE) {
|
||||
map_attachment(ctx, fb, fb->_ColorDrawBufferIndexes[buf]);
|
||||
find_renderbuffer_colortype(fb->_ColorDrawBuffers[buf]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Unmap renderbuffers after rendering.
|
||||
*/
|
||||
void
|
||||
_swrast_unmap_renderbuffers(struct gl_context *ctx)
|
||||
{
|
||||
struct gl_framebuffer *fb = ctx->DrawBuffer;
|
||||
struct gl_renderbuffer *depthRb, *stencilRb;
|
||||
GLuint buf;
|
||||
|
||||
depthRb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
|
||||
if (depthRb) {
|
||||
/* map depth buffer */
|
||||
unmap_attachment(ctx, fb, BUFFER_DEPTH);
|
||||
}
|
||||
|
||||
stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
|
||||
if (stencilRb && stencilRb != depthRb) {
|
||||
/* map stencil buffer */
|
||||
unmap_attachment(ctx, fb, BUFFER_STENCIL);
|
||||
}
|
||||
|
||||
for (buf = 0; buf < fb->_NumColorDrawBuffers; buf++) {
|
||||
if (fb->_ColorDrawBufferIndexes[buf] != BUFFER_NONE) {
|
||||
unmap_attachment(ctx, fb, fb->_ColorDrawBufferIndexes[buf]);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* Copyright (C) 1999-2005 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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 S_RENDERBUFFER_H
|
||||
#define S_RENDERBUFFER_H
|
||||
|
||||
#include "main/glheader.h"
|
||||
|
||||
|
||||
struct gl_context;
|
||||
struct gl_framebuffer;
|
||||
struct gl_renderbuffer;
|
||||
|
||||
|
||||
extern struct gl_renderbuffer *
|
||||
_swrast_new_soft_renderbuffer(struct gl_context *ctx, GLuint name);
|
||||
|
||||
extern void
|
||||
_swrast_map_soft_renderbuffer(struct gl_context *ctx,
|
||||
struct gl_renderbuffer *rb,
|
||||
GLuint x, GLuint y, GLuint w, GLuint h,
|
||||
GLbitfield mode,
|
||||
GLubyte **out_map,
|
||||
GLint *out_stride,
|
||||
bool flip_y);
|
||||
|
||||
extern void
|
||||
_swrast_unmap_soft_renderbuffer(struct gl_context *ctx,
|
||||
struct gl_renderbuffer *rb);
|
||||
|
||||
extern void
|
||||
_swrast_set_renderbuffer_accessors(struct gl_renderbuffer *rb);
|
||||
|
||||
|
||||
extern void
|
||||
_swrast_add_soft_renderbuffers(struct gl_framebuffer *fb,
|
||||
GLboolean color,
|
||||
GLboolean depth,
|
||||
GLboolean stencil,
|
||||
GLboolean accum,
|
||||
GLboolean alpha);
|
||||
|
||||
|
||||
#endif /* S_RENDERBUFFER_H */
|
File diff suppressed because it is too large
Load Diff
|
@ -1,217 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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 S_SPAN_H
|
||||
#define S_SPAN_H
|
||||
|
||||
|
||||
#include "main/config.h"
|
||||
#include "main/glheader.h"
|
||||
#include "main/mtypes.h"
|
||||
#include "swrast/s_chan.h"
|
||||
#include "swrast/swrast.h"
|
||||
|
||||
|
||||
struct gl_context;
|
||||
struct gl_renderbuffer;
|
||||
|
||||
|
||||
/**
|
||||
* \defgroup SpanFlags
|
||||
* Special bitflags to describe span data.
|
||||
*
|
||||
* In general, the point/line/triangle functions interpolate/emit the
|
||||
* attributes specified by swrast->_ActiveAttribs (i.e. FRAT_BIT_* values).
|
||||
* Some things don't fit into that, though, so we have these flags.
|
||||
*/
|
||||
/*@{*/
|
||||
#define SPAN_RGBA 0x01 /**< interpMask and arrayMask */
|
||||
#define SPAN_Z 0x02 /**< interpMask and arrayMask */
|
||||
#define SPAN_FLAT 0x04 /**< interpMask: flat shading? */
|
||||
#define SPAN_XY 0x08 /**< array.x[], y[] valid? */
|
||||
#define SPAN_MASK 0x10 /**< was array.mask[] filled in by caller? */
|
||||
#define SPAN_LAMBDA 0x20 /**< array.lambda[] valid? */
|
||||
#define SPAN_COVERAGE 0x40 /**< array.coverage[] valid? */
|
||||
/*@}*/
|
||||
|
||||
|
||||
/**
|
||||
* \sw_span_arrays
|
||||
* \brief Arrays of fragment values.
|
||||
*
|
||||
* These will either be computed from the span x/xStep values or
|
||||
* filled in by glDraw/CopyPixels, etc.
|
||||
* These arrays are separated out of sw_span to conserve memory.
|
||||
*/
|
||||
typedef struct sw_span_arrays
|
||||
{
|
||||
/** Per-fragment attributes (indexed by VARYING_SLOT_* tokens) */
|
||||
/* XXX someday look at transposing first two indexes for better memory
|
||||
* access pattern.
|
||||
*/
|
||||
GLfloat attribs[VARYING_SLOT_MAX][SWRAST_MAX_WIDTH][4];
|
||||
|
||||
/** This mask indicates which fragments are alive or culled */
|
||||
GLubyte mask[SWRAST_MAX_WIDTH];
|
||||
|
||||
GLenum ChanType; /**< Color channel type, GL_UNSIGNED_BYTE, GL_FLOAT */
|
||||
|
||||
/** Attribute arrays that don't fit into attribs[] array above */
|
||||
/*@{*/
|
||||
GLubyte rgba8[SWRAST_MAX_WIDTH][4];
|
||||
GLushort rgba16[SWRAST_MAX_WIDTH][4];
|
||||
GLchan (*rgba)[4]; /** either == rgba8 or rgba16 */
|
||||
GLint x[SWRAST_MAX_WIDTH]; /**< fragment X coords */
|
||||
GLint y[SWRAST_MAX_WIDTH]; /**< fragment Y coords */
|
||||
GLuint z[SWRAST_MAX_WIDTH]; /**< fragment Z coords */
|
||||
GLuint index[SWRAST_MAX_WIDTH]; /**< Color indexes */
|
||||
GLfloat lambda[MAX_TEXTURE_COORD_UNITS][SWRAST_MAX_WIDTH]; /**< Texture LOD */
|
||||
GLfloat coverage[SWRAST_MAX_WIDTH]; /**< Fragment coverage for AA/smoothing */
|
||||
/*@}*/
|
||||
} SWspanarrays;
|
||||
|
||||
|
||||
/**
|
||||
* The SWspan structure describes the colors, Z, fogcoord, texcoords,
|
||||
* etc for either a horizontal run or an array of independent pixels.
|
||||
* We can either specify a base/step to indicate interpolated values, or
|
||||
* fill in explicit arrays of values. The interpMask and arrayMask bitfields
|
||||
* indicate which attributes are active interpolants or arrays, respectively.
|
||||
*
|
||||
* It would be interesting to experiment with multiprocessor rasterization
|
||||
* with this structure. The triangle rasterizer could simply emit a
|
||||
* stream of these structures which would be consumed by one or more
|
||||
* span-processing threads which could run in parallel.
|
||||
*/
|
||||
typedef struct sw_span
|
||||
{
|
||||
/** Coord of first fragment in horizontal span/run */
|
||||
GLint x, y;
|
||||
|
||||
/** Number of fragments in the span */
|
||||
GLuint end;
|
||||
|
||||
/** for clipping left edge of spans */
|
||||
GLuint leftClip;
|
||||
|
||||
/** This flag indicates that mask[] array is effectively filled with ones */
|
||||
GLboolean writeAll;
|
||||
|
||||
/** either GL_POLYGON, GL_LINE, GL_POLYGON, GL_BITMAP */
|
||||
GLenum primitive;
|
||||
|
||||
/** 0 = front-facing span, 1 = back-facing span (for two-sided stencil) */
|
||||
GLuint facing;
|
||||
|
||||
/**
|
||||
* This bitmask (of \link SpanFlags SPAN_* flags\endlink) indicates
|
||||
* which of the attrStart/StepX/StepY variables are relevant.
|
||||
*/
|
||||
GLbitfield interpMask;
|
||||
|
||||
/** Fragment attribute interpolants */
|
||||
GLfloat attrStart[VARYING_SLOT_MAX][4]; /**< initial value */
|
||||
GLfloat attrStepX[VARYING_SLOT_MAX][4]; /**< dvalue/dx */
|
||||
GLfloat attrStepY[VARYING_SLOT_MAX][4]; /**< dvalue/dy */
|
||||
|
||||
/* XXX the rest of these will go away eventually... */
|
||||
|
||||
/* For horizontal spans, step is the partial derivative wrt X.
|
||||
* For lines, step is the delta from one fragment to the next.
|
||||
*/
|
||||
GLfixed red, redStep;
|
||||
GLfixed green, greenStep;
|
||||
GLfixed blue, blueStep;
|
||||
GLfixed alpha, alphaStep;
|
||||
GLfixed index, indexStep;
|
||||
GLfixed z, zStep; /**< XXX z should probably be GLuint */
|
||||
GLfixed intTex[2], intTexStep[2]; /**< (s,t) for unit[0] only */
|
||||
|
||||
/**
|
||||
* This bitmask (of \link SpanFlags SPAN_* flags\endlink) indicates
|
||||
* which of the fragment arrays in the span_arrays struct are relevant.
|
||||
*/
|
||||
GLbitfield arrayMask;
|
||||
|
||||
/** Mask of VARYING_BIT_x bits */
|
||||
GLbitfield64 arrayAttribs;
|
||||
|
||||
/**
|
||||
* We store the arrays of fragment values in a separate struct so
|
||||
* that we can allocate sw_span structs on the stack without using
|
||||
* a lot of memory. The span_arrays struct is about 1.4MB while the
|
||||
* sw_span struct is only about 512 bytes.
|
||||
*/
|
||||
SWspanarrays *array;
|
||||
} SWspan;
|
||||
|
||||
|
||||
|
||||
#define INIT_SPAN(S, PRIMITIVE) \
|
||||
do { \
|
||||
(S).primitive = (PRIMITIVE); \
|
||||
(S).interpMask = 0x0; \
|
||||
(S).arrayMask = 0x0; \
|
||||
(S).arrayAttribs = 0x0; \
|
||||
(S).end = 0; \
|
||||
(S).leftClip = 0; \
|
||||
(S).facing = 0; \
|
||||
(S).array = SWRAST_CONTEXT(ctx)->SpanArrays; \
|
||||
} while (0)
|
||||
|
||||
|
||||
|
||||
extern void
|
||||
_swrast_span_default_attribs(struct gl_context *ctx, SWspan *span);
|
||||
|
||||
extern void
|
||||
_swrast_span_interpolate_z( const struct gl_context *ctx, SWspan *span );
|
||||
|
||||
extern GLfloat
|
||||
_swrast_compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
|
||||
GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
|
||||
GLfloat s, GLfloat t, GLfloat q, GLfloat invQ);
|
||||
|
||||
|
||||
extern void
|
||||
_swrast_write_rgba_span( struct gl_context *ctx, SWspan *span);
|
||||
|
||||
|
||||
extern void
|
||||
_swrast_read_rgba_span(struct gl_context *ctx, struct gl_renderbuffer *rb,
|
||||
GLuint n, GLint x, GLint y, GLvoid *rgba);
|
||||
|
||||
extern void
|
||||
_swrast_put_row(struct gl_context *ctx, struct gl_renderbuffer *rb,
|
||||
GLenum datatype,
|
||||
GLuint count, GLint x, GLint y,
|
||||
const void *values, const GLubyte *mask);
|
||||
|
||||
extern void *
|
||||
_swrast_get_dest_rgba(struct gl_context *ctx, struct gl_renderbuffer *rb,
|
||||
SWspan *span);
|
||||
|
||||
#endif
|
|
@ -1,710 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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/context.h"
|
||||
|
||||
#include "main/format_pack.h"
|
||||
#include "main/format_unpack.h"
|
||||
#include "main/stencil.h"
|
||||
|
||||
#include "s_context.h"
|
||||
#include "s_depth.h"
|
||||
#include "s_stencil.h"
|
||||
#include "s_span.h"
|
||||
|
||||
|
||||
|
||||
/* Stencil Logic:
|
||||
|
||||
IF stencil test fails THEN
|
||||
Apply fail-op to stencil value
|
||||
Don't write the pixel (RGBA,Z)
|
||||
ELSE
|
||||
IF doing depth test && depth test fails THEN
|
||||
Apply zfail-op to stencil value
|
||||
Write RGBA and Z to appropriate buffers
|
||||
ELSE
|
||||
Apply zpass-op to stencil value
|
||||
ENDIF
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Compute/return the offset of the stencil value in a pixel.
|
||||
* For example, if the format is Z24+S8, the position of the stencil bits
|
||||
* within the 4-byte pixel will be either 0 or 3.
|
||||
*/
|
||||
static GLint
|
||||
get_stencil_offset(mesa_format format)
|
||||
{
|
||||
const GLubyte one = 1;
|
||||
GLubyte pixel[MAX_PIXEL_BYTES];
|
||||
GLint bpp = _mesa_get_format_bytes(format);
|
||||
GLint i;
|
||||
|
||||
assert(_mesa_get_format_bits(format, GL_STENCIL_BITS) == 8);
|
||||
memset(pixel, 0, sizeof(pixel));
|
||||
_mesa_pack_ubyte_stencil_row(format, 1, &one, pixel);
|
||||
|
||||
for (i = 0; i < bpp; i++) {
|
||||
if (pixel[i])
|
||||
return i;
|
||||
}
|
||||
|
||||
_mesa_problem(NULL, "get_stencil_offset() failed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/** Clamp the stencil value to [0, 255] */
|
||||
static inline GLubyte
|
||||
clamp(GLint val)
|
||||
{
|
||||
if (val < 0)
|
||||
return 0;
|
||||
else if (val > 255)
|
||||
return 255;
|
||||
else
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
#define STENCIL_OP(NEW_VAL) \
|
||||
if (invmask == 0) { \
|
||||
for (i = j = 0; i < n; i++, j += stride) { \
|
||||
if (mask[i]) { \
|
||||
GLubyte s = stencil[j]; \
|
||||
(void) s; \
|
||||
stencil[j] = (GLubyte) (NEW_VAL); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
else { \
|
||||
for (i = j = 0; i < n; i++, j += stride) { \
|
||||
if (mask[i]) { \
|
||||
GLubyte s = stencil[j]; \
|
||||
stencil[j] = (GLubyte) ((invmask & s) | (wrtmask & (NEW_VAL))); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Apply the given stencil operator to the array of stencil values.
|
||||
* Don't touch stencil[i] if mask[i] is zero.
|
||||
* @param n number of stencil values
|
||||
* @param oper the stencil buffer operator
|
||||
* @param face 0 or 1 for front or back face operation
|
||||
* @param stencil array of stencil values (in/out)
|
||||
* @param mask array [n] of flag: 1=apply operator, 0=don't apply operator
|
||||
* @param stride stride between stencil values
|
||||
*/
|
||||
static void
|
||||
apply_stencil_op(const struct gl_context *ctx, GLenum oper, GLuint face,
|
||||
GLuint n, GLubyte stencil[], const GLubyte mask[],
|
||||
GLint stride)
|
||||
{
|
||||
const GLubyte ref = _mesa_get_stencil_ref(ctx, face);
|
||||
const GLubyte wrtmask = ctx->Stencil.WriteMask[face];
|
||||
const GLubyte invmask = (GLubyte) (~wrtmask);
|
||||
GLuint i, j;
|
||||
|
||||
switch (oper) {
|
||||
case GL_KEEP:
|
||||
/* do nothing */
|
||||
break;
|
||||
case GL_ZERO:
|
||||
/* replace stencil buf values with zero */
|
||||
STENCIL_OP(0);
|
||||
break;
|
||||
case GL_REPLACE:
|
||||
/* replace stencil buf values with ref value */
|
||||
STENCIL_OP(ref);
|
||||
break;
|
||||
case GL_INCR:
|
||||
/* increment stencil buf values, with clamping */
|
||||
STENCIL_OP(clamp(s + 1));
|
||||
break;
|
||||
case GL_DECR:
|
||||
/* increment stencil buf values, with clamping */
|
||||
STENCIL_OP(clamp(s - 1));
|
||||
break;
|
||||
case GL_INCR_WRAP_EXT:
|
||||
/* increment stencil buf values, without clamping */
|
||||
STENCIL_OP(s + 1);
|
||||
break;
|
||||
case GL_DECR_WRAP_EXT:
|
||||
/* increment stencil buf values, without clamping */
|
||||
STENCIL_OP(s - 1);
|
||||
break;
|
||||
case GL_INVERT:
|
||||
/* replace stencil buf values with inverted value */
|
||||
STENCIL_OP(~s);
|
||||
break;
|
||||
default:
|
||||
_mesa_problem(ctx, "Bad stencil op in apply_stencil_op");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define STENCIL_TEST(FUNC) \
|
||||
for (i = j = 0; i < n; i++, j += stride) { \
|
||||
if (mask[i]) { \
|
||||
s = (GLubyte) (stencil[j] & valueMask); \
|
||||
if (FUNC) { \
|
||||
/* stencil pass */ \
|
||||
fail[i] = 0; \
|
||||
} \
|
||||
else { \
|
||||
/* stencil fail */ \
|
||||
fail[i] = 1; \
|
||||
mask[i] = 0; \
|
||||
} \
|
||||
} \
|
||||
else { \
|
||||
fail[i] = 0; \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Apply stencil test to an array of stencil values (before depth buffering).
|
||||
* For the values that fail, we'll apply the GL_STENCIL_FAIL operator to
|
||||
* the stencil values.
|
||||
*
|
||||
* @param face 0 or 1 for front or back-face polygons
|
||||
* @param n number of pixels in the array
|
||||
* @param stencil array of [n] stencil values (in/out)
|
||||
* @param mask array [n] of flag: 0=skip the pixel, 1=stencil the pixel,
|
||||
* values are set to zero where the stencil test fails.
|
||||
* @param stride stride between stencil values
|
||||
* @return GL_FALSE = all pixels failed, GL_TRUE = zero or more pixels passed.
|
||||
*/
|
||||
static GLboolean
|
||||
do_stencil_test(struct gl_context *ctx, GLuint face, GLuint n,
|
||||
GLubyte stencil[], GLubyte mask[], GLint stride)
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
GLubyte *fail = swrast->stencil_temp.buf2;
|
||||
GLboolean allfail = GL_FALSE;
|
||||
GLuint i, j;
|
||||
const GLuint valueMask = ctx->Stencil.ValueMask[face];
|
||||
const GLubyte ref = (GLubyte) (_mesa_get_stencil_ref(ctx, face) & valueMask);
|
||||
GLubyte s;
|
||||
|
||||
/*
|
||||
* Perform stencil test. The results of this operation are stored
|
||||
* in the fail[] array:
|
||||
* IF fail[i] is non-zero THEN
|
||||
* the stencil fail operator is to be applied
|
||||
* ELSE
|
||||
* the stencil fail operator is not to be applied
|
||||
* ENDIF
|
||||
*/
|
||||
switch (ctx->Stencil.Function[face]) {
|
||||
case GL_NEVER:
|
||||
STENCIL_TEST(0);
|
||||
allfail = GL_TRUE;
|
||||
break;
|
||||
case GL_LESS:
|
||||
STENCIL_TEST(ref < s);
|
||||
break;
|
||||
case GL_LEQUAL:
|
||||
STENCIL_TEST(ref <= s);
|
||||
break;
|
||||
case GL_GREATER:
|
||||
STENCIL_TEST(ref > s);
|
||||
break;
|
||||
case GL_GEQUAL:
|
||||
STENCIL_TEST(ref >= s);
|
||||
break;
|
||||
case GL_EQUAL:
|
||||
STENCIL_TEST(ref == s);
|
||||
break;
|
||||
case GL_NOTEQUAL:
|
||||
STENCIL_TEST(ref != s);
|
||||
break;
|
||||
case GL_ALWAYS:
|
||||
STENCIL_TEST(1);
|
||||
break;
|
||||
default:
|
||||
_mesa_problem(ctx, "Bad stencil func in gl_stencil_span");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ctx->Stencil.FailFunc[face] != GL_KEEP) {
|
||||
apply_stencil_op(ctx, ctx->Stencil.FailFunc[face], face, n, stencil,
|
||||
fail, stride);
|
||||
}
|
||||
|
||||
return !allfail;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compute the zpass/zfail masks by comparing the pre- and post-depth test
|
||||
* masks.
|
||||
*/
|
||||
static inline void
|
||||
compute_pass_fail_masks(GLuint n, const GLubyte origMask[],
|
||||
const GLubyte newMask[],
|
||||
GLubyte passMask[], GLubyte failMask[])
|
||||
{
|
||||
GLuint i;
|
||||
for (i = 0; i < n; i++) {
|
||||
assert(newMask[i] == 0 || newMask[i] == 1);
|
||||
passMask[i] = origMask[i] & newMask[i];
|
||||
failMask[i] = origMask[i] & (newMask[i] ^ 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get 8-bit stencil values from random locations in the stencil buffer.
|
||||
*/
|
||||
static void
|
||||
get_s8_values(struct gl_context *ctx, struct gl_renderbuffer *rb,
|
||||
GLuint count, const GLint x[], const GLint y[],
|
||||
GLubyte stencil[])
|
||||
{
|
||||
struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
|
||||
const GLint w = rb->Width, h = rb->Height;
|
||||
const GLubyte *map = _swrast_pixel_address(rb, 0, 0);
|
||||
GLuint i;
|
||||
|
||||
if (rb->Format == MESA_FORMAT_S_UINT8) {
|
||||
const GLint rowStride = srb->RowStride;
|
||||
for (i = 0; i < count; i++) {
|
||||
if (x[i] >= 0 && y[i] >= 0 && x[i] < w && y[i] < h) {
|
||||
stencil[i] = *(map + y[i] * rowStride + x[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
const GLint bpp = _mesa_get_format_bytes(rb->Format);
|
||||
const GLint rowStride = srb->RowStride;
|
||||
for (i = 0; i < count; i++) {
|
||||
if (x[i] >= 0 && y[i] >= 0 && x[i] < w && y[i] < h) {
|
||||
const GLubyte *src = map + y[i] * rowStride + x[i] * bpp;
|
||||
_mesa_unpack_ubyte_stencil_row(rb->Format, 1, src, &stencil[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
** Pack ubyte stencil pixels
|
||||
**/
|
||||
|
||||
static void
|
||||
pack_ubyte_stencil_Z24_S8(const uint8_t *src, void *dst)
|
||||
{
|
||||
/* don't disturb the Z values */
|
||||
uint32_t *d = ((uint32_t *) dst);
|
||||
uint32_t s = *src;
|
||||
uint32_t z = *d & 0xffffff00;
|
||||
*d = z | s;
|
||||
}
|
||||
|
||||
static void
|
||||
pack_ubyte_stencil_S8_Z24(const uint8_t *src, void *dst)
|
||||
{
|
||||
/* don't disturb the Z values */
|
||||
uint32_t *d = ((uint32_t *) dst);
|
||||
uint32_t s = *src << 24;
|
||||
uint32_t z = *d & 0xffffff;
|
||||
*d = s | z;
|
||||
}
|
||||
|
||||
static void
|
||||
pack_ubyte_stencil_S8(const uint8_t *src, void *dst)
|
||||
{
|
||||
uint8_t *d = (uint8_t *) dst;
|
||||
*d = *src;
|
||||
}
|
||||
|
||||
static void
|
||||
pack_ubyte_stencil_Z32_FLOAT_X24S8(const uint8_t *src, void *dst)
|
||||
{
|
||||
float *d = ((float *) dst);
|
||||
d[1] = *src;
|
||||
}
|
||||
|
||||
/** Pack a uint8_t stencil value to dest address */
|
||||
typedef void (*mesa_pack_ubyte_stencil_func)(const uint8_t *src, void *dst);
|
||||
|
||||
static mesa_pack_ubyte_stencil_func
|
||||
get_pack_ubyte_stencil_func(mesa_format format)
|
||||
{
|
||||
switch (format) {
|
||||
case MESA_FORMAT_S8_UINT_Z24_UNORM:
|
||||
return pack_ubyte_stencil_Z24_S8;
|
||||
case MESA_FORMAT_Z24_UNORM_S8_UINT:
|
||||
return pack_ubyte_stencil_S8_Z24;
|
||||
case MESA_FORMAT_S_UINT8:
|
||||
return pack_ubyte_stencil_S8;
|
||||
case MESA_FORMAT_Z32_FLOAT_S8X24_UINT:
|
||||
return pack_ubyte_stencil_Z32_FLOAT_X24S8;
|
||||
default:
|
||||
unreachable("unexpected format in get_pack_ubyte_stencil_func()");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Put 8-bit stencil values at random locations into the stencil buffer.
|
||||
*/
|
||||
static void
|
||||
put_s8_values(struct gl_context *ctx, struct gl_renderbuffer *rb,
|
||||
GLuint count, const GLint x[], const GLint y[],
|
||||
const GLubyte stencil[])
|
||||
{
|
||||
const GLint w = rb->Width, h = rb->Height;
|
||||
mesa_pack_ubyte_stencil_func pack_stencil =
|
||||
get_pack_ubyte_stencil_func(rb->Format);
|
||||
GLuint i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (x[i] >= 0 && y[i] >= 0 && x[i] < w && y[i] < h) {
|
||||
GLubyte *dst = _swrast_pixel_address(rb, x[i], y[i]);
|
||||
pack_stencil(&stencil[i], dst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* /return GL_TRUE = one or more fragments passed,
|
||||
* GL_FALSE = all fragments failed.
|
||||
*/
|
||||
GLboolean
|
||||
_swrast_stencil_and_ztest_span(struct gl_context *ctx, SWspan *span)
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
struct gl_framebuffer *fb = ctx->DrawBuffer;
|
||||
struct gl_renderbuffer *rb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
|
||||
const GLint stencilOffset = get_stencil_offset(rb->Format);
|
||||
const GLint stencilStride = _mesa_get_format_bytes(rb->Format);
|
||||
const GLuint face = (span->facing == 0) ? 0 : ctx->Stencil._BackFace;
|
||||
const GLuint count = span->end;
|
||||
GLubyte *mask = span->array->mask;
|
||||
GLubyte *stencilTemp = swrast->stencil_temp.buf1;
|
||||
GLubyte *stencilBuf;
|
||||
|
||||
if (span->arrayMask & SPAN_XY) {
|
||||
/* read stencil values from random locations */
|
||||
get_s8_values(ctx, rb, count, span->array->x, span->array->y,
|
||||
stencilTemp);
|
||||
stencilBuf = stencilTemp;
|
||||
}
|
||||
else {
|
||||
/* Processing a horizontal run of pixels. Since stencil is always
|
||||
* 8 bits for all MESA_FORMATs, we just need to use the right offset
|
||||
* and stride to access them.
|
||||
*/
|
||||
stencilBuf = _swrast_pixel_address(rb, span->x, span->y) + stencilOffset;
|
||||
}
|
||||
|
||||
/*
|
||||
* Apply the stencil test to the fragments.
|
||||
* failMask[i] is 1 if the stencil test failed.
|
||||
*/
|
||||
if (!do_stencil_test(ctx, face, count, stencilBuf, mask, stencilStride)) {
|
||||
/* all fragments failed the stencil test, we're done. */
|
||||
span->writeAll = GL_FALSE;
|
||||
if (span->arrayMask & SPAN_XY) {
|
||||
/* need to write the updated stencil values back to the buffer */
|
||||
put_s8_values(ctx, rb, count, span->array->x, span->array->y,
|
||||
stencilTemp);
|
||||
}
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Some fragments passed the stencil test, apply depth test to them
|
||||
* and apply Zpass and Zfail stencil ops.
|
||||
*/
|
||||
if (ctx->Depth.Test == GL_FALSE ||
|
||||
ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer == NULL) {
|
||||
/*
|
||||
* No depth buffer, just apply zpass stencil function to active pixels.
|
||||
*/
|
||||
apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face, count,
|
||||
stencilBuf, mask, stencilStride);
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* Perform depth buffering, then apply zpass or zfail stencil function.
|
||||
*/
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
GLubyte *passMask = swrast->stencil_temp.buf2;
|
||||
GLubyte *failMask = swrast->stencil_temp.buf3;
|
||||
GLubyte *origMask = swrast->stencil_temp.buf4;
|
||||
|
||||
/* save the current mask bits */
|
||||
memcpy(origMask, mask, count * sizeof(GLubyte));
|
||||
|
||||
/* apply the depth test */
|
||||
_swrast_depth_test_span(ctx, span);
|
||||
|
||||
compute_pass_fail_masks(count, origMask, mask, passMask, failMask);
|
||||
|
||||
/* apply the pass and fail operations */
|
||||
if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
|
||||
apply_stencil_op(ctx, ctx->Stencil.ZFailFunc[face], face,
|
||||
count, stencilBuf, failMask, stencilStride);
|
||||
}
|
||||
if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
|
||||
apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face,
|
||||
count, stencilBuf, passMask, stencilStride);
|
||||
}
|
||||
}
|
||||
|
||||
/* Write updated stencil values back into hardware stencil buffer */
|
||||
if (span->arrayMask & SPAN_XY) {
|
||||
put_s8_values(ctx, rb, count, span->array->x, span->array->y,
|
||||
stencilBuf);
|
||||
}
|
||||
|
||||
span->writeAll = GL_FALSE;
|
||||
|
||||
return GL_TRUE; /* one or more fragments passed both tests */
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Return a span of stencil values from the stencil buffer.
|
||||
* Used for glRead/CopyPixels
|
||||
* Input: n - how many pixels
|
||||
* x,y - location of first pixel
|
||||
* Output: stencil - the array of stencil values
|
||||
*/
|
||||
void
|
||||
_swrast_read_stencil_span(struct gl_context *ctx, struct gl_renderbuffer *rb,
|
||||
GLint n, GLint x, GLint y, GLubyte stencil[])
|
||||
{
|
||||
GLubyte *src;
|
||||
|
||||
if (y < 0 || y >= (GLint) rb->Height ||
|
||||
x + n <= 0 || x >= (GLint) rb->Width) {
|
||||
/* span is completely outside framebuffer */
|
||||
return; /* undefined values OK */
|
||||
}
|
||||
|
||||
if (x < 0) {
|
||||
GLint dx = -x;
|
||||
x = 0;
|
||||
n -= dx;
|
||||
stencil += dx;
|
||||
}
|
||||
if (x + n > (GLint) rb->Width) {
|
||||
GLint dx = x + n - rb->Width;
|
||||
n -= dx;
|
||||
}
|
||||
if (n <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
src = _swrast_pixel_address(rb, x, y);
|
||||
_mesa_unpack_ubyte_stencil_row(rb->Format, n, src, stencil);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Write a span of stencil values to the stencil buffer. This function
|
||||
* applies the stencil write mask when needed.
|
||||
* Used for glDraw/CopyPixels
|
||||
* Input: n - how many pixels
|
||||
* x, y - location of first pixel
|
||||
* stencil - the array of stencil values
|
||||
*/
|
||||
void
|
||||
_swrast_write_stencil_span(struct gl_context *ctx, GLint n, GLint x, GLint y,
|
||||
const GLubyte stencil[] )
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
struct gl_framebuffer *fb = ctx->DrawBuffer;
|
||||
struct gl_renderbuffer *rb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
|
||||
const GLuint stencilMax = (1 << fb->Visual.stencilBits) - 1;
|
||||
const GLuint stencilMask = ctx->Stencil.WriteMask[0];
|
||||
GLubyte *stencilBuf;
|
||||
|
||||
if (y < 0 || y >= (GLint) rb->Height ||
|
||||
x + n <= 0 || x >= (GLint) rb->Width) {
|
||||
/* span is completely outside framebuffer */
|
||||
return; /* undefined values OK */
|
||||
}
|
||||
if (x < 0) {
|
||||
GLint dx = -x;
|
||||
x = 0;
|
||||
n -= dx;
|
||||
stencil += dx;
|
||||
}
|
||||
if (x + n > (GLint) rb->Width) {
|
||||
GLint dx = x + n - rb->Width;
|
||||
n -= dx;
|
||||
}
|
||||
if (n <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
stencilBuf = _swrast_pixel_address(rb, x, y);
|
||||
|
||||
if ((stencilMask & stencilMax) != stencilMax) {
|
||||
/* need to apply writemask */
|
||||
GLubyte *destVals = swrast->stencil_temp.buf1;
|
||||
GLubyte *newVals = swrast->stencil_temp.buf2;
|
||||
GLint i;
|
||||
|
||||
_mesa_unpack_ubyte_stencil_row(rb->Format, n, stencilBuf, destVals);
|
||||
for (i = 0; i < n; i++) {
|
||||
newVals[i]
|
||||
= (stencil[i] & stencilMask) | (destVals[i] & ~stencilMask);
|
||||
}
|
||||
_mesa_pack_ubyte_stencil_row(rb->Format, n, newVals, stencilBuf);
|
||||
}
|
||||
else {
|
||||
_mesa_pack_ubyte_stencil_row(rb->Format, n, stencil, stencilBuf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Clear the stencil buffer. If the buffer is a combined
|
||||
* depth+stencil buffer, only the stencil bits will be touched.
|
||||
*/
|
||||
void
|
||||
_swrast_clear_stencil_buffer(struct gl_context *ctx)
|
||||
{
|
||||
struct gl_renderbuffer *rb =
|
||||
ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
|
||||
const GLubyte stencilBits = ctx->DrawBuffer->Visual.stencilBits;
|
||||
const GLuint writeMask = ctx->Stencil.WriteMask[0];
|
||||
const GLuint stencilMax = (1 << stencilBits) - 1;
|
||||
GLint x, y, width, height;
|
||||
GLubyte *map;
|
||||
GLint rowStride, i, j;
|
||||
GLbitfield mapMode;
|
||||
|
||||
if (!rb || writeMask == 0)
|
||||
return;
|
||||
|
||||
/* compute region to clear */
|
||||
x = ctx->DrawBuffer->_Xmin;
|
||||
y = ctx->DrawBuffer->_Ymin;
|
||||
width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
|
||||
height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
|
||||
|
||||
mapMode = GL_MAP_WRITE_BIT;
|
||||
if ((writeMask & stencilMax) != stencilMax) {
|
||||
/* need to mask stencil values */
|
||||
mapMode |= GL_MAP_READ_BIT;
|
||||
}
|
||||
else if (_mesa_get_format_bits(rb->Format, GL_DEPTH_BITS) > 0) {
|
||||
/* combined depth+stencil, need to mask Z values */
|
||||
mapMode |= GL_MAP_READ_BIT;
|
||||
}
|
||||
|
||||
ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height,
|
||||
mapMode, &map, &rowStride,
|
||||
ctx->DrawBuffer->FlipY);
|
||||
if (!map) {
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glClear(stencil)");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (rb->Format) {
|
||||
case MESA_FORMAT_S_UINT8:
|
||||
{
|
||||
GLubyte clear = ctx->Stencil.Clear & writeMask & 0xff;
|
||||
GLubyte mask = (~writeMask) & 0xff;
|
||||
if (mask != 0) {
|
||||
/* masked clear */
|
||||
for (i = 0; i < height; i++) {
|
||||
GLubyte *row = map;
|
||||
for (j = 0; j < width; j++) {
|
||||
row[j] = (row[j] & mask) | clear;
|
||||
}
|
||||
map += rowStride;
|
||||
}
|
||||
}
|
||||
else if (rowStride == width) {
|
||||
/* clear whole buffer */
|
||||
memset(map, clear, width * height);
|
||||
}
|
||||
else {
|
||||
/* clear scissored */
|
||||
for (i = 0; i < height; i++) {
|
||||
memset(map, clear, width);
|
||||
map += rowStride;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MESA_FORMAT_Z24_UNORM_S8_UINT:
|
||||
{
|
||||
GLuint clear = (ctx->Stencil.Clear & writeMask & 0xff) << 24;
|
||||
GLuint mask = (((~writeMask) & 0xff) << 24) | 0xffffff;
|
||||
for (i = 0; i < height; i++) {
|
||||
GLuint *row = (GLuint *) map;
|
||||
for (j = 0; j < width; j++) {
|
||||
row[j] = (row[j] & mask) | clear;
|
||||
}
|
||||
map += rowStride;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MESA_FORMAT_S8_UINT_Z24_UNORM:
|
||||
{
|
||||
GLuint clear = ctx->Stencil.Clear & writeMask & 0xff;
|
||||
GLuint mask = 0xffffff00 | ((~writeMask) & 0xff);
|
||||
for (i = 0; i < height; i++) {
|
||||
GLuint *row = (GLuint *) map;
|
||||
for (j = 0; j < width; j++) {
|
||||
row[j] = (row[j] & mask) | clear;
|
||||
}
|
||||
map += rowStride;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
_mesa_problem(ctx, "Unexpected stencil buffer format %s"
|
||||
" in _swrast_clear_stencil_buffer()",
|
||||
_mesa_get_format_name(rb->Format));
|
||||
}
|
||||
|
||||
ctx->Driver.UnmapRenderbuffer(ctx, rb);
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* Copyright (C) 1999-2005 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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 S_STENCIL_H
|
||||
#define S_STENCIL_H
|
||||
|
||||
|
||||
#include "main/mtypes.h"
|
||||
#include "s_span.h"
|
||||
|
||||
|
||||
|
||||
extern GLboolean
|
||||
_swrast_stencil_and_ztest_span(struct gl_context *ctx, SWspan *span);
|
||||
|
||||
|
||||
extern void
|
||||
_swrast_read_stencil_span(struct gl_context *ctx, struct gl_renderbuffer *rb,
|
||||
GLint n, GLint x, GLint y, GLubyte stencil[]);
|
||||
|
||||
|
||||
extern void
|
||||
_swrast_write_stencil_span( struct gl_context *ctx, GLint n, GLint x, GLint y,
|
||||
const GLubyte stencil[] );
|
||||
|
||||
|
||||
extern void
|
||||
_swrast_clear_stencil_buffer(struct gl_context *ctx);
|
||||
|
||||
|
||||
#endif
|
|
@ -1,721 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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/context.h"
|
||||
|
||||
#include "main/macros.h"
|
||||
#include "main/pixeltransfer.h"
|
||||
#include "main/samplerobj.h"
|
||||
#include "program/prog_instruction.h"
|
||||
|
||||
#include "s_context.h"
|
||||
#include "s_texcombine.h"
|
||||
|
||||
|
||||
/**
|
||||
* Pointer to array of float[4]
|
||||
* This type makes the code below more concise and avoids a lot of casting.
|
||||
*/
|
||||
typedef float (*float4_array)[4];
|
||||
|
||||
|
||||
/**
|
||||
* Return array of texels for given unit.
|
||||
*/
|
||||
static inline float4_array
|
||||
get_texel_array(SWcontext *swrast, GLuint unit)
|
||||
{
|
||||
#ifdef _OPENMP
|
||||
return (float4_array) (swrast->TexelBuffer + unit * SWRAST_MAX_WIDTH * 4 * omp_get_num_threads() + (SWRAST_MAX_WIDTH * 4 * omp_get_thread_num()));
|
||||
#else
|
||||
return (float4_array) (swrast->TexelBuffer + unit * SWRAST_MAX_WIDTH * 4);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Do texture application for:
|
||||
* GL_EXT_texture_env_combine
|
||||
* GL_ARB_texture_env_combine
|
||||
* GL_EXT_texture_env_dot3
|
||||
* GL_ARB_texture_env_dot3
|
||||
* GL_ATI_texture_env_combine3
|
||||
* GL_NV_texture_env_combine4
|
||||
* conventional GL texture env modes
|
||||
*
|
||||
* \param ctx rendering context
|
||||
* \param unit the texture combiner unit
|
||||
* \param primary_rgba incoming fragment color array
|
||||
* \param texelBuffer pointer to texel colors for all texture units
|
||||
*
|
||||
* \param span two fields are used in this function:
|
||||
* span->end: number of fragments to process
|
||||
* span->array->rgba: incoming/result fragment colors
|
||||
*/
|
||||
static void
|
||||
texture_combine( struct gl_context *ctx, GLuint unit,
|
||||
const float4_array primary_rgba,
|
||||
const GLfloat *texelBuffer,
|
||||
SWspan *span )
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
const struct gl_fixedfunc_texture_unit *textureUnit =
|
||||
&ctx->Texture.FixedFuncUnit[unit];
|
||||
const struct gl_tex_env_combine_state *combine = textureUnit->_CurrentCombine;
|
||||
float4_array argRGB[MAX_COMBINER_TERMS];
|
||||
float4_array argA[MAX_COMBINER_TERMS];
|
||||
const GLfloat scaleRGB = (GLfloat) (1 << combine->ScaleShiftRGB);
|
||||
const GLfloat scaleA = (GLfloat) (1 << combine->ScaleShiftA);
|
||||
const GLuint numArgsRGB = combine->_NumArgsRGB;
|
||||
const GLuint numArgsA = combine->_NumArgsA;
|
||||
float4_array ccolor[4], rgba;
|
||||
GLuint i, term;
|
||||
GLuint n = span->end;
|
||||
GLchan (*rgbaChan)[4] = span->array->rgba;
|
||||
|
||||
/* alloc temp pixel buffers */
|
||||
rgba = malloc(4 * n * sizeof(GLfloat));
|
||||
if (!rgba) {
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "texture_combine");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < numArgsRGB || i < numArgsA; i++) {
|
||||
ccolor[i] = malloc(4 * n * sizeof(GLfloat));
|
||||
if (!ccolor[i]) {
|
||||
while (i) {
|
||||
free(ccolor[i]);
|
||||
i--;
|
||||
}
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "texture_combine");
|
||||
free(rgba);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
rgba[i][RCOMP] = CHAN_TO_FLOAT(rgbaChan[i][RCOMP]);
|
||||
rgba[i][GCOMP] = CHAN_TO_FLOAT(rgbaChan[i][GCOMP]);
|
||||
rgba[i][BCOMP] = CHAN_TO_FLOAT(rgbaChan[i][BCOMP]);
|
||||
rgba[i][ACOMP] = CHAN_TO_FLOAT(rgbaChan[i][ACOMP]);
|
||||
}
|
||||
|
||||
/*
|
||||
printf("modeRGB 0x%x modeA 0x%x srcRGB1 0x%x srcA1 0x%x srcRGB2 0x%x srcA2 0x%x\n",
|
||||
combine->ModeRGB,
|
||||
combine->ModeA,
|
||||
combine->SourceRGB[0],
|
||||
combine->SourceA[0],
|
||||
combine->SourceRGB[1],
|
||||
combine->SourceA[1]);
|
||||
*/
|
||||
|
||||
/*
|
||||
* Do operand setup for up to 4 operands. Loop over the terms.
|
||||
*/
|
||||
for (term = 0; term < numArgsRGB; term++) {
|
||||
const GLenum srcRGB = combine->SourceRGB[term];
|
||||
const GLenum operandRGB = combine->OperandRGB[term];
|
||||
|
||||
switch (srcRGB) {
|
||||
case GL_TEXTURE:
|
||||
argRGB[term] = get_texel_array(swrast, unit);
|
||||
break;
|
||||
case GL_PRIMARY_COLOR:
|
||||
argRGB[term] = primary_rgba;
|
||||
break;
|
||||
case GL_PREVIOUS:
|
||||
argRGB[term] = rgba;
|
||||
break;
|
||||
case GL_CONSTANT:
|
||||
{
|
||||
float4_array c = ccolor[term];
|
||||
GLfloat red = textureUnit->EnvColor[0];
|
||||
GLfloat green = textureUnit->EnvColor[1];
|
||||
GLfloat blue = textureUnit->EnvColor[2];
|
||||
GLfloat alpha = textureUnit->EnvColor[3];
|
||||
for (i = 0; i < n; i++) {
|
||||
ASSIGN_4V(c[i], red, green, blue, alpha);
|
||||
}
|
||||
argRGB[term] = ccolor[term];
|
||||
}
|
||||
break;
|
||||
/* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
|
||||
*/
|
||||
case GL_ZERO:
|
||||
{
|
||||
float4_array c = ccolor[term];
|
||||
for (i = 0; i < n; i++) {
|
||||
ASSIGN_4V(c[i], 0.0F, 0.0F, 0.0F, 0.0F);
|
||||
}
|
||||
argRGB[term] = ccolor[term];
|
||||
}
|
||||
break;
|
||||
case GL_ONE:
|
||||
{
|
||||
float4_array c = ccolor[term];
|
||||
for (i = 0; i < n; i++) {
|
||||
ASSIGN_4V(c[i], 1.0F, 1.0F, 1.0F, 1.0F);
|
||||
}
|
||||
argRGB[term] = ccolor[term];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* ARB_texture_env_crossbar source */
|
||||
{
|
||||
const GLuint srcUnit = srcRGB - GL_TEXTURE0;
|
||||
assert(srcUnit < ctx->Const.MaxTextureUnits);
|
||||
if (!ctx->Texture.Unit[srcUnit]._Current)
|
||||
goto end;
|
||||
argRGB[term] = get_texel_array(swrast, srcUnit);
|
||||
}
|
||||
}
|
||||
|
||||
if (operandRGB != GL_SRC_COLOR) {
|
||||
float4_array src = argRGB[term];
|
||||
float4_array dst = ccolor[term];
|
||||
|
||||
/* point to new arg[term] storage */
|
||||
argRGB[term] = ccolor[term];
|
||||
|
||||
switch (operandRGB) {
|
||||
case GL_ONE_MINUS_SRC_COLOR:
|
||||
for (i = 0; i < n; i++) {
|
||||
dst[i][RCOMP] = 1.0F - src[i][RCOMP];
|
||||
dst[i][GCOMP] = 1.0F - src[i][GCOMP];
|
||||
dst[i][BCOMP] = 1.0F - src[i][BCOMP];
|
||||
}
|
||||
break;
|
||||
case GL_SRC_ALPHA:
|
||||
for (i = 0; i < n; i++) {
|
||||
dst[i][RCOMP] =
|
||||
dst[i][GCOMP] =
|
||||
dst[i][BCOMP] = src[i][ACOMP];
|
||||
}
|
||||
break;
|
||||
case GL_ONE_MINUS_SRC_ALPHA:
|
||||
for (i = 0; i < n; i++) {
|
||||
dst[i][RCOMP] =
|
||||
dst[i][GCOMP] =
|
||||
dst[i][BCOMP] = 1.0F - src[i][ACOMP];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
_mesa_problem(ctx, "Bad operandRGB");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up the argA[term] pointers
|
||||
*/
|
||||
for (term = 0; term < numArgsA; term++) {
|
||||
const GLenum srcA = combine->SourceA[term];
|
||||
const GLenum operandA = combine->OperandA[term];
|
||||
|
||||
switch (srcA) {
|
||||
case GL_TEXTURE:
|
||||
argA[term] = get_texel_array(swrast, unit);
|
||||
break;
|
||||
case GL_PRIMARY_COLOR:
|
||||
argA[term] = primary_rgba;
|
||||
break;
|
||||
case GL_PREVIOUS:
|
||||
argA[term] = rgba;
|
||||
break;
|
||||
case GL_CONSTANT:
|
||||
{
|
||||
float4_array c = ccolor[term];
|
||||
GLfloat alpha = textureUnit->EnvColor[3];
|
||||
for (i = 0; i < n; i++)
|
||||
c[i][ACOMP] = alpha;
|
||||
argA[term] = ccolor[term];
|
||||
}
|
||||
break;
|
||||
/* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
|
||||
*/
|
||||
case GL_ZERO:
|
||||
{
|
||||
float4_array c = ccolor[term];
|
||||
for (i = 0; i < n; i++)
|
||||
c[i][ACOMP] = 0.0F;
|
||||
argA[term] = ccolor[term];
|
||||
}
|
||||
break;
|
||||
case GL_ONE:
|
||||
{
|
||||
float4_array c = ccolor[term];
|
||||
for (i = 0; i < n; i++)
|
||||
c[i][ACOMP] = 1.0F;
|
||||
argA[term] = ccolor[term];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* ARB_texture_env_crossbar source */
|
||||
{
|
||||
const GLuint srcUnit = srcA - GL_TEXTURE0;
|
||||
assert(srcUnit < ctx->Const.MaxTextureUnits);
|
||||
if (!ctx->Texture.Unit[srcUnit]._Current)
|
||||
goto end;
|
||||
argA[term] = get_texel_array(swrast, srcUnit);
|
||||
}
|
||||
}
|
||||
|
||||
if (operandA == GL_ONE_MINUS_SRC_ALPHA) {
|
||||
float4_array src = argA[term];
|
||||
float4_array dst = ccolor[term];
|
||||
argA[term] = ccolor[term];
|
||||
for (i = 0; i < n; i++) {
|
||||
dst[i][ACOMP] = 1.0F - src[i][ACOMP];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* RGB channel combine */
|
||||
{
|
||||
float4_array arg0 = argRGB[0];
|
||||
float4_array arg1 = argRGB[1];
|
||||
float4_array arg2 = argRGB[2];
|
||||
float4_array arg3 = argRGB[3];
|
||||
|
||||
switch (combine->ModeRGB) {
|
||||
case GL_REPLACE:
|
||||
for (i = 0; i < n; i++) {
|
||||
rgba[i][RCOMP] = arg0[i][RCOMP] * scaleRGB;
|
||||
rgba[i][GCOMP] = arg0[i][GCOMP] * scaleRGB;
|
||||
rgba[i][BCOMP] = arg0[i][BCOMP] * scaleRGB;
|
||||
}
|
||||
break;
|
||||
case GL_MODULATE:
|
||||
for (i = 0; i < n; i++) {
|
||||
rgba[i][RCOMP] = arg0[i][RCOMP] * arg1[i][RCOMP] * scaleRGB;
|
||||
rgba[i][GCOMP] = arg0[i][GCOMP] * arg1[i][GCOMP] * scaleRGB;
|
||||
rgba[i][BCOMP] = arg0[i][BCOMP] * arg1[i][BCOMP] * scaleRGB;
|
||||
}
|
||||
break;
|
||||
case GL_ADD:
|
||||
if (textureUnit->EnvMode == GL_COMBINE4_NV) {
|
||||
/* (a * b) + (c * d) */
|
||||
for (i = 0; i < n; i++) {
|
||||
rgba[i][RCOMP] = (arg0[i][RCOMP] * arg1[i][RCOMP] +
|
||||
arg2[i][RCOMP] * arg3[i][RCOMP]) * scaleRGB;
|
||||
rgba[i][GCOMP] = (arg0[i][GCOMP] * arg1[i][GCOMP] +
|
||||
arg2[i][GCOMP] * arg3[i][GCOMP]) * scaleRGB;
|
||||
rgba[i][BCOMP] = (arg0[i][BCOMP] * arg1[i][BCOMP] +
|
||||
arg2[i][BCOMP] * arg3[i][BCOMP]) * scaleRGB;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* 2-term addition */
|
||||
for (i = 0; i < n; i++) {
|
||||
rgba[i][RCOMP] = (arg0[i][RCOMP] + arg1[i][RCOMP]) * scaleRGB;
|
||||
rgba[i][GCOMP] = (arg0[i][GCOMP] + arg1[i][GCOMP]) * scaleRGB;
|
||||
rgba[i][BCOMP] = (arg0[i][BCOMP] + arg1[i][BCOMP]) * scaleRGB;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GL_ADD_SIGNED:
|
||||
if (textureUnit->EnvMode == GL_COMBINE4_NV) {
|
||||
/* (a * b) + (c * d) - 0.5 */
|
||||
for (i = 0; i < n; i++) {
|
||||
rgba[i][RCOMP] = (arg0[i][RCOMP] * arg1[i][RCOMP] +
|
||||
arg2[i][RCOMP] * arg3[i][RCOMP] - 0.5F) * scaleRGB;
|
||||
rgba[i][GCOMP] = (arg0[i][GCOMP] * arg1[i][GCOMP] +
|
||||
arg2[i][GCOMP] * arg3[i][GCOMP] - 0.5F) * scaleRGB;
|
||||
rgba[i][BCOMP] = (arg0[i][BCOMP] * arg1[i][BCOMP] +
|
||||
arg2[i][BCOMP] * arg3[i][BCOMP] - 0.5F) * scaleRGB;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (i = 0; i < n; i++) {
|
||||
rgba[i][RCOMP] = (arg0[i][RCOMP] + arg1[i][RCOMP] - 0.5F) * scaleRGB;
|
||||
rgba[i][GCOMP] = (arg0[i][GCOMP] + arg1[i][GCOMP] - 0.5F) * scaleRGB;
|
||||
rgba[i][BCOMP] = (arg0[i][BCOMP] + arg1[i][BCOMP] - 0.5F) * scaleRGB;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GL_INTERPOLATE:
|
||||
for (i = 0; i < n; i++) {
|
||||
rgba[i][RCOMP] = (arg0[i][RCOMP] * arg2[i][RCOMP] +
|
||||
arg1[i][RCOMP] * (1.0F - arg2[i][RCOMP])) * scaleRGB;
|
||||
rgba[i][GCOMP] = (arg0[i][GCOMP] * arg2[i][GCOMP] +
|
||||
arg1[i][GCOMP] * (1.0F - arg2[i][GCOMP])) * scaleRGB;
|
||||
rgba[i][BCOMP] = (arg0[i][BCOMP] * arg2[i][BCOMP] +
|
||||
arg1[i][BCOMP] * (1.0F - arg2[i][BCOMP])) * scaleRGB;
|
||||
}
|
||||
break;
|
||||
case GL_SUBTRACT:
|
||||
for (i = 0; i < n; i++) {
|
||||
rgba[i][RCOMP] = (arg0[i][RCOMP] - arg1[i][RCOMP]) * scaleRGB;
|
||||
rgba[i][GCOMP] = (arg0[i][GCOMP] - arg1[i][GCOMP]) * scaleRGB;
|
||||
rgba[i][BCOMP] = (arg0[i][BCOMP] - arg1[i][BCOMP]) * scaleRGB;
|
||||
}
|
||||
break;
|
||||
case GL_DOT3_RGB_EXT:
|
||||
case GL_DOT3_RGBA_EXT:
|
||||
/* Do not scale the result by 1 2 or 4 */
|
||||
for (i = 0; i < n; i++) {
|
||||
GLfloat dot = ((arg0[i][RCOMP] - 0.5F) * (arg1[i][RCOMP] - 0.5F) +
|
||||
(arg0[i][GCOMP] - 0.5F) * (arg1[i][GCOMP] - 0.5F) +
|
||||
(arg0[i][BCOMP] - 0.5F) * (arg1[i][BCOMP] - 0.5F))
|
||||
* 4.0F;
|
||||
dot = CLAMP(dot, 0.0F, 1.0F);
|
||||
rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = dot;
|
||||
}
|
||||
break;
|
||||
case GL_DOT3_RGB:
|
||||
case GL_DOT3_RGBA:
|
||||
/* DO scale the result by 1 2 or 4 */
|
||||
for (i = 0; i < n; i++) {
|
||||
GLfloat dot = ((arg0[i][RCOMP] - 0.5F) * (arg1[i][RCOMP] - 0.5F) +
|
||||
(arg0[i][GCOMP] - 0.5F) * (arg1[i][GCOMP] - 0.5F) +
|
||||
(arg0[i][BCOMP] - 0.5F) * (arg1[i][BCOMP] - 0.5F))
|
||||
* 4.0F * scaleRGB;
|
||||
dot = CLAMP(dot, 0.0F, 1.0F);
|
||||
rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = dot;
|
||||
}
|
||||
break;
|
||||
case GL_MODULATE_ADD_ATI:
|
||||
for (i = 0; i < n; i++) {
|
||||
rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) +
|
||||
arg1[i][RCOMP]) * scaleRGB;
|
||||
rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) +
|
||||
arg1[i][GCOMP]) * scaleRGB;
|
||||
rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) +
|
||||
arg1[i][BCOMP]) * scaleRGB;
|
||||
}
|
||||
break;
|
||||
case GL_MODULATE_SIGNED_ADD_ATI:
|
||||
for (i = 0; i < n; i++) {
|
||||
rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) +
|
||||
arg1[i][RCOMP] - 0.5F) * scaleRGB;
|
||||
rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) +
|
||||
arg1[i][GCOMP] - 0.5F) * scaleRGB;
|
||||
rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) +
|
||||
arg1[i][BCOMP] - 0.5F) * scaleRGB;
|
||||
}
|
||||
break;
|
||||
case GL_MODULATE_SUBTRACT_ATI:
|
||||
for (i = 0; i < n; i++) {
|
||||
rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) -
|
||||
arg1[i][RCOMP]) * scaleRGB;
|
||||
rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) -
|
||||
arg1[i][GCOMP]) * scaleRGB;
|
||||
rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) -
|
||||
arg1[i][BCOMP]) * scaleRGB;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
_mesa_problem(ctx, "invalid combine mode");
|
||||
}
|
||||
}
|
||||
|
||||
/* Alpha channel combine */
|
||||
{
|
||||
float4_array arg0 = argA[0];
|
||||
float4_array arg1 = argA[1];
|
||||
float4_array arg2 = argA[2];
|
||||
float4_array arg3 = argA[3];
|
||||
|
||||
switch (combine->ModeA) {
|
||||
case GL_REPLACE:
|
||||
for (i = 0; i < n; i++) {
|
||||
rgba[i][ACOMP] = arg0[i][ACOMP] * scaleA;
|
||||
}
|
||||
break;
|
||||
case GL_MODULATE:
|
||||
for (i = 0; i < n; i++) {
|
||||
rgba[i][ACOMP] = arg0[i][ACOMP] * arg1[i][ACOMP] * scaleA;
|
||||
}
|
||||
break;
|
||||
case GL_ADD:
|
||||
if (textureUnit->EnvMode == GL_COMBINE4_NV) {
|
||||
/* (a * b) + (c * d) */
|
||||
for (i = 0; i < n; i++) {
|
||||
rgba[i][ACOMP] = (arg0[i][ACOMP] * arg1[i][ACOMP] +
|
||||
arg2[i][ACOMP] * arg3[i][ACOMP]) * scaleA;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* two-term add */
|
||||
for (i = 0; i < n; i++) {
|
||||
rgba[i][ACOMP] = (arg0[i][ACOMP] + arg1[i][ACOMP]) * scaleA;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GL_ADD_SIGNED:
|
||||
if (textureUnit->EnvMode == GL_COMBINE4_NV) {
|
||||
/* (a * b) + (c * d) - 0.5 */
|
||||
for (i = 0; i < n; i++) {
|
||||
rgba[i][ACOMP] = (arg0[i][ACOMP] * arg1[i][ACOMP] +
|
||||
arg2[i][ACOMP] * arg3[i][ACOMP] -
|
||||
0.5F) * scaleA;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* a + b - 0.5 */
|
||||
for (i = 0; i < n; i++) {
|
||||
rgba[i][ACOMP] = (arg0[i][ACOMP] + arg1[i][ACOMP] - 0.5F) * scaleA;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GL_INTERPOLATE:
|
||||
for (i = 0; i < n; i++) {
|
||||
rgba[i][ACOMP] = (arg0[i][ACOMP] * arg2[i][ACOMP] +
|
||||
arg1[i][ACOMP] * (1.0F - arg2[i][ACOMP]))
|
||||
* scaleA;
|
||||
}
|
||||
break;
|
||||
case GL_SUBTRACT:
|
||||
for (i = 0; i < n; i++) {
|
||||
rgba[i][ACOMP] = (arg0[i][ACOMP] - arg1[i][ACOMP]) * scaleA;
|
||||
}
|
||||
break;
|
||||
case GL_MODULATE_ADD_ATI:
|
||||
for (i = 0; i < n; i++) {
|
||||
rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP])
|
||||
+ arg1[i][ACOMP]) * scaleA;
|
||||
}
|
||||
break;
|
||||
case GL_MODULATE_SIGNED_ADD_ATI:
|
||||
for (i = 0; i < n; i++) {
|
||||
rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP]) +
|
||||
arg1[i][ACOMP] - 0.5F) * scaleA;
|
||||
}
|
||||
break;
|
||||
case GL_MODULATE_SUBTRACT_ATI:
|
||||
for (i = 0; i < n; i++) {
|
||||
rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP])
|
||||
- arg1[i][ACOMP]) * scaleA;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
_mesa_problem(ctx, "invalid combine mode");
|
||||
}
|
||||
}
|
||||
|
||||
/* Fix the alpha component for GL_DOT3_RGBA_EXT/ARB combining.
|
||||
* This is kind of a kludge. It would have been better if the spec
|
||||
* were written such that the GL_COMBINE_ALPHA value could be set to
|
||||
* GL_DOT3.
|
||||
*/
|
||||
if (combine->ModeRGB == GL_DOT3_RGBA_EXT ||
|
||||
combine->ModeRGB == GL_DOT3_RGBA) {
|
||||
for (i = 0; i < n; i++) {
|
||||
rgba[i][ACOMP] = rgba[i][RCOMP];
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][RCOMP], rgba[i][RCOMP]);
|
||||
UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][GCOMP], rgba[i][GCOMP]);
|
||||
UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][BCOMP], rgba[i][BCOMP]);
|
||||
UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][ACOMP], rgba[i][ACOMP]);
|
||||
}
|
||||
/* The span->array->rgba values are of CHAN type so set
|
||||
* span->array->ChanType field accordingly.
|
||||
*/
|
||||
span->array->ChanType = CHAN_TYPE;
|
||||
|
||||
end:
|
||||
for (i = 0; i < numArgsRGB || i < numArgsA; i++) {
|
||||
free(ccolor[i]);
|
||||
}
|
||||
free(rgba);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Apply X/Y/Z/W/0/1 swizzle to an array of colors/texels.
|
||||
* See GL_EXT_texture_swizzle.
|
||||
*/
|
||||
static void
|
||||
swizzle_texels(GLuint swizzle, GLuint count, float4_array texels)
|
||||
{
|
||||
const GLuint swzR = GET_SWZ(swizzle, 0);
|
||||
const GLuint swzG = GET_SWZ(swizzle, 1);
|
||||
const GLuint swzB = GET_SWZ(swizzle, 2);
|
||||
const GLuint swzA = GET_SWZ(swizzle, 3);
|
||||
GLfloat vector[6];
|
||||
GLuint i;
|
||||
|
||||
vector[SWIZZLE_ZERO] = 0;
|
||||
vector[SWIZZLE_ONE] = 1.0F;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
vector[SWIZZLE_X] = texels[i][0];
|
||||
vector[SWIZZLE_Y] = texels[i][1];
|
||||
vector[SWIZZLE_Z] = texels[i][2];
|
||||
vector[SWIZZLE_W] = texels[i][3];
|
||||
texels[i][RCOMP] = vector[swzR];
|
||||
texels[i][GCOMP] = vector[swzG];
|
||||
texels[i][BCOMP] = vector[swzB];
|
||||
texels[i][ACOMP] = vector[swzA];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Apply texture mapping to a span of fragments.
|
||||
*/
|
||||
void
|
||||
_swrast_texture_span( struct gl_context *ctx, SWspan *span )
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
float4_array primary_rgba;
|
||||
GLuint unit;
|
||||
|
||||
if (!swrast->TexelBuffer) {
|
||||
#ifdef _OPENMP
|
||||
const GLint maxThreads = omp_get_max_threads();
|
||||
|
||||
/* TexelBuffer memory allocation needs to be done in a critical section
|
||||
* as this code runs in a parallel loop.
|
||||
* When entering the section, first check if TexelBuffer has been
|
||||
* initialized already by another thread while this thread was waiting.
|
||||
*/
|
||||
#pragma omp critical
|
||||
if (!swrast->TexelBuffer) {
|
||||
#else
|
||||
const GLint maxThreads = 1;
|
||||
#endif
|
||||
|
||||
/* TexelBuffer is also global and normally shared by all SWspan
|
||||
* instances; when running with multiple threads, create one per
|
||||
* thread.
|
||||
*/
|
||||
swrast->TexelBuffer =
|
||||
malloc(ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits * maxThreads *
|
||||
SWRAST_MAX_WIDTH * 4 * sizeof(GLfloat));
|
||||
#ifdef _OPENMP
|
||||
} /* critical section */
|
||||
#endif
|
||||
|
||||
if (!swrast->TexelBuffer) {
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "texture_combine");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
primary_rgba = malloc(span->end * 4 * sizeof(GLfloat));
|
||||
|
||||
if (!primary_rgba) {
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "texture_span");
|
||||
return;
|
||||
}
|
||||
|
||||
assert(span->end <= SWRAST_MAX_WIDTH);
|
||||
|
||||
/*
|
||||
* Save copy of the incoming fragment colors (the GL_PRIMARY_COLOR)
|
||||
*/
|
||||
if (swrast->_TextureCombinePrimary) {
|
||||
GLuint i;
|
||||
for (i = 0; i < span->end; i++) {
|
||||
primary_rgba[i][RCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][RCOMP]);
|
||||
primary_rgba[i][GCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][GCOMP]);
|
||||
primary_rgba[i][BCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][BCOMP]);
|
||||
primary_rgba[i][ACOMP] = CHAN_TO_FLOAT(span->array->rgba[i][ACOMP]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Must do all texture sampling before combining in order to
|
||||
* accommodate GL_ARB_texture_env_crossbar.
|
||||
*/
|
||||
for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
|
||||
const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
|
||||
if (texUnit->_Current) {
|
||||
const GLfloat (*texcoords)[4] = (const GLfloat (*)[4])
|
||||
span->array->attribs[VARYING_SLOT_TEX0 + unit];
|
||||
const struct gl_texture_object *curObj = texUnit->_Current;
|
||||
const struct gl_sampler_object *samp = _mesa_get_samplerobj(ctx, unit);
|
||||
GLfloat *lambda = span->array->lambda[unit];
|
||||
float4_array texels = get_texel_array(swrast, unit);
|
||||
|
||||
/* adjust texture lod (lambda) */
|
||||
if (span->arrayMask & SPAN_LAMBDA) {
|
||||
if (texUnit->LodBias + samp->Attrib.LodBias != 0.0F) {
|
||||
/* apply LOD bias, but don't clamp yet */
|
||||
const GLfloat bias = CLAMP(texUnit->LodBias + samp->Attrib.LodBias,
|
||||
-ctx->Const.MaxTextureLodBias,
|
||||
ctx->Const.MaxTextureLodBias);
|
||||
GLuint i;
|
||||
for (i = 0; i < span->end; i++) {
|
||||
lambda[i] += bias;
|
||||
}
|
||||
}
|
||||
|
||||
if (samp->Attrib.MinLod != -1000.0F ||
|
||||
samp->Attrib.MaxLod != 1000.0F) {
|
||||
/* apply LOD clamping to lambda */
|
||||
const GLfloat min = samp->Attrib.MinLod;
|
||||
const GLfloat max = samp->Attrib.MaxLod;
|
||||
GLuint i;
|
||||
for (i = 0; i < span->end; i++) {
|
||||
GLfloat l = lambda[i];
|
||||
lambda[i] = CLAMP(l, min, max);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (samp->Attrib.MaxAnisotropy > 1.0F &&
|
||||
samp->Attrib.MinFilter == GL_LINEAR_MIPMAP_LINEAR) {
|
||||
/* sample_lambda_2d_aniso is beeing used as texture_sample_func,
|
||||
* it requires the current SWspan *span as an additional parameter.
|
||||
* In order to keep the same function signature, the unused lambda
|
||||
* parameter will be modified to actually contain the SWspan pointer.
|
||||
* This is a Hack. To make it right, the texture_sample_func
|
||||
* signature and all implementing functions need to be modified.
|
||||
*/
|
||||
/* "hide" SWspan struct; cast to (GLfloat *) to suppress warning */
|
||||
lambda = (GLfloat *)span;
|
||||
}
|
||||
|
||||
/* Sample the texture (span->end = number of fragments) */
|
||||
swrast->TextureSample[unit]( ctx, samp,
|
||||
ctx->Texture.Unit[unit]._Current,
|
||||
span->end, texcoords, lambda, texels );
|
||||
|
||||
/* GL_EXT_texture_swizzle */
|
||||
if (curObj->Attrib._Swizzle != SWIZZLE_NOOP) {
|
||||
swizzle_texels(curObj->Attrib._Swizzle, span->end, texels);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* OK, now apply the texture (aka texture combine/blend).
|
||||
* We modify the span->color.rgba values.
|
||||
*/
|
||||
for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
|
||||
if (ctx->Texture.Unit[unit]._Current)
|
||||
texture_combine(ctx, unit, primary_rgba, swrast->TexelBuffer, span);
|
||||
}
|
||||
|
||||
free(primary_rgba);
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* Copyright (C) 1999-2005 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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 S_TEXCOMBINE_H
|
||||
#define S_TEXCOMBINE_H
|
||||
|
||||
|
||||
#include "s_span.h"
|
||||
|
||||
struct gl_context;
|
||||
|
||||
extern void
|
||||
_swrast_texture_span( struct gl_context *ctx, SWspan *span );
|
||||
|
||||
#endif
|
|
@ -1,368 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
|
||||
* Copyright (c) 2009 VMware, Inc.
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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 s_texfetch.c
|
||||
*
|
||||
* Texel fetch/store functions
|
||||
*
|
||||
* \author Gareth Hughes
|
||||
*/
|
||||
|
||||
|
||||
#include "main/errors.h"
|
||||
#include "main/macros.h"
|
||||
#include "main/texcompress.h"
|
||||
#include "main/texcompress_fxt1.h"
|
||||
#include "main/texcompress_s3tc.h"
|
||||
#include "main/texcompress_rgtc.h"
|
||||
#include "main/texcompress_etc.h"
|
||||
#include "main/teximage.h"
|
||||
#include "main/samplerobj.h"
|
||||
#include "s_context.h"
|
||||
#include "s_texfetch.h"
|
||||
#include "util/format_rgb9e5.h"
|
||||
#include "util/format_r11g11b10f.h"
|
||||
#include "util/format_srgb.h"
|
||||
|
||||
|
||||
/* Texel fetch routines for all supported formats
|
||||
*/
|
||||
#define DIM 1
|
||||
#include "s_texfetch_tmp.h"
|
||||
|
||||
#define DIM 2
|
||||
#include "s_texfetch_tmp.h"
|
||||
|
||||
#define DIM 3
|
||||
#include "s_texfetch_tmp.h"
|
||||
|
||||
|
||||
/**
|
||||
* All compressed texture texel fetching is done though this function.
|
||||
* Basically just call a core-Mesa texel fetch function.
|
||||
*/
|
||||
static void
|
||||
fetch_compressed(const struct swrast_texture_image *swImage,
|
||||
GLint i, GLint j, GLint k, GLfloat *texel)
|
||||
{
|
||||
/* The FetchCompressedTexel function takes an integer pixel rowstride,
|
||||
* while the image's rowstride is bytes per row of blocks.
|
||||
*/
|
||||
GLuint bw, bh;
|
||||
GLuint texelBytes = _mesa_get_format_bytes(swImage->Base.TexFormat);
|
||||
_mesa_get_format_block_size(swImage->Base.TexFormat, &bw, &bh);
|
||||
assert(swImage->RowStride * bw % texelBytes == 0);
|
||||
|
||||
swImage->FetchCompressedTexel(swImage->ImageSlices[k],
|
||||
swImage->RowStride * bw / texelBytes,
|
||||
i, j, texel);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Null texel fetch function.
|
||||
*
|
||||
* Have to have this so the FetchTexel function pointer is never NULL.
|
||||
*/
|
||||
static void fetch_null_texelf( const struct swrast_texture_image *texImage,
|
||||
GLint i, GLint j, GLint k, GLfloat *texel )
|
||||
{
|
||||
(void) texImage; (void) i; (void) j; (void) k;
|
||||
texel[RCOMP] = 0.0;
|
||||
texel[GCOMP] = 0.0;
|
||||
texel[BCOMP] = 0.0;
|
||||
texel[ACOMP] = 0.0;
|
||||
_mesa_warning(NULL, "fetch_null_texelf() called!");
|
||||
}
|
||||
|
||||
|
||||
#define FETCH_FUNCS(NAME) \
|
||||
[MESA_FORMAT_ ## NAME] = { \
|
||||
fetch_texel_1d_ ## NAME, \
|
||||
fetch_texel_2d_ ## NAME, \
|
||||
fetch_texel_3d_ ## NAME, \
|
||||
}
|
||||
|
||||
#define FETCH_COMPRESSED(NAME) \
|
||||
[MESA_FORMAT_ ## NAME] = { \
|
||||
fetch_compressed, \
|
||||
fetch_compressed, \
|
||||
fetch_compressed \
|
||||
}
|
||||
|
||||
/**
|
||||
* Table to map MESA_FORMAT_ to texel fetch/store funcs.
|
||||
*/
|
||||
static struct {
|
||||
FetchTexelFunc Fetch1D;
|
||||
FetchTexelFunc Fetch2D;
|
||||
FetchTexelFunc Fetch3D;
|
||||
}
|
||||
texfetch_funcs[] =
|
||||
{
|
||||
/* Packed unorm formats */
|
||||
FETCH_FUNCS(A8B8G8R8_UNORM),
|
||||
FETCH_FUNCS(X8B8G8R8_UNORM),
|
||||
FETCH_FUNCS(R8G8B8A8_UNORM),
|
||||
FETCH_FUNCS(R8G8B8X8_UNORM),
|
||||
FETCH_FUNCS(B8G8R8A8_UNORM),
|
||||
FETCH_FUNCS(B8G8R8X8_UNORM),
|
||||
FETCH_FUNCS(A8R8G8B8_UNORM),
|
||||
FETCH_FUNCS(X8R8G8B8_UNORM),
|
||||
FETCH_FUNCS(B5G6R5_UNORM),
|
||||
FETCH_FUNCS(R5G6B5_UNORM),
|
||||
FETCH_FUNCS(B4G4R4A4_UNORM),
|
||||
FETCH_FUNCS(A4R4G4B4_UNORM),
|
||||
FETCH_FUNCS(A1B5G5R5_UNORM),
|
||||
FETCH_FUNCS(B5G5R5A1_UNORM),
|
||||
FETCH_FUNCS(A1R5G5B5_UNORM),
|
||||
FETCH_FUNCS(L4A4_UNORM),
|
||||
FETCH_FUNCS(B2G3R3_UNORM),
|
||||
FETCH_FUNCS(B10G10R10A2_UNORM),
|
||||
FETCH_FUNCS(R10G10B10A2_UNORM),
|
||||
|
||||
FETCH_FUNCS(S8_UINT_Z24_UNORM),
|
||||
[MESA_FORMAT_X8_UINT_Z24_UNORM] = {
|
||||
fetch_texel_1d_S8_UINT_Z24_UNORM,
|
||||
fetch_texel_2d_S8_UINT_Z24_UNORM,
|
||||
fetch_texel_3d_S8_UINT_Z24_UNORM
|
||||
},
|
||||
FETCH_FUNCS(Z24_UNORM_S8_UINT),
|
||||
[MESA_FORMAT_Z24_UNORM_X8_UINT] = {
|
||||
fetch_texel_1d_Z24_UNORM_S8_UINT,
|
||||
fetch_texel_2d_Z24_UNORM_S8_UINT,
|
||||
fetch_texel_3d_Z24_UNORM_S8_UINT
|
||||
},
|
||||
|
||||
FETCH_FUNCS(YCBCR),
|
||||
FETCH_FUNCS(YCBCR_REV),
|
||||
|
||||
/* Array unorm formats */
|
||||
FETCH_FUNCS(A_UNORM8),
|
||||
FETCH_FUNCS(A_UNORM16),
|
||||
FETCH_FUNCS(L_UNORM8),
|
||||
FETCH_FUNCS(L_UNORM16),
|
||||
FETCH_FUNCS(LA_UNORM8),
|
||||
FETCH_FUNCS(LA_UNORM16),
|
||||
FETCH_FUNCS(I_UNORM8),
|
||||
FETCH_FUNCS(I_UNORM16),
|
||||
FETCH_FUNCS(R_UNORM8),
|
||||
FETCH_FUNCS(R_UNORM16),
|
||||
FETCH_FUNCS(RG_UNORM8),
|
||||
FETCH_FUNCS(RG_UNORM16),
|
||||
FETCH_FUNCS(BGR_UNORM8),
|
||||
FETCH_FUNCS(RGB_UNORM8),
|
||||
FETCH_FUNCS(RGBA_UNORM16),
|
||||
FETCH_FUNCS(RGBX_UNORM16),
|
||||
FETCH_FUNCS(Z_UNORM16),
|
||||
FETCH_FUNCS(Z_UNORM32),
|
||||
|
||||
/* Packed signed/normalized formats */
|
||||
FETCH_FUNCS(A8B8G8R8_SNORM),
|
||||
FETCH_FUNCS(X8B8G8R8_SNORM),
|
||||
FETCH_FUNCS(R8G8B8A8_SNORM),
|
||||
|
||||
/* Array signed/normalized formats */
|
||||
FETCH_FUNCS(A_SNORM8),
|
||||
FETCH_FUNCS(A_SNORM16),
|
||||
FETCH_FUNCS(L_SNORM8),
|
||||
FETCH_FUNCS(L_SNORM16),
|
||||
FETCH_FUNCS(LA_SNORM8),
|
||||
FETCH_FUNCS(LA_SNORM16),
|
||||
FETCH_FUNCS(I_SNORM8),
|
||||
FETCH_FUNCS(I_SNORM16),
|
||||
FETCH_FUNCS(R_SNORM8),
|
||||
FETCH_FUNCS(R_SNORM16),
|
||||
FETCH_FUNCS(RG_SNORM8),
|
||||
FETCH_FUNCS(RG_SNORM16),
|
||||
FETCH_FUNCS(RGB_SNORM16),
|
||||
FETCH_FUNCS(RGBA_SNORM16),
|
||||
|
||||
/* Packed sRGB formats */
|
||||
FETCH_FUNCS(A8B8G8R8_SRGB),
|
||||
FETCH_FUNCS(B8G8R8A8_SRGB),
|
||||
FETCH_FUNCS(A8R8G8B8_SRGB),
|
||||
FETCH_FUNCS(R8G8B8A8_SRGB),
|
||||
FETCH_FUNCS(R8G8B8X8_SRGB),
|
||||
FETCH_FUNCS(X8B8G8R8_SRGB),
|
||||
|
||||
/* Array sRGB formats */
|
||||
FETCH_FUNCS(R_SRGB8),
|
||||
FETCH_FUNCS(L_SRGB8),
|
||||
FETCH_FUNCS(LA_SRGB8),
|
||||
FETCH_FUNCS(BGR_SRGB8),
|
||||
|
||||
/* Packed float formats */
|
||||
FETCH_FUNCS(R9G9B9E5_FLOAT),
|
||||
FETCH_FUNCS(R11G11B10_FLOAT),
|
||||
FETCH_FUNCS(Z32_FLOAT_S8X24_UINT),
|
||||
|
||||
/* Array float formats */
|
||||
FETCH_FUNCS(A_FLOAT16),
|
||||
FETCH_FUNCS(A_FLOAT32),
|
||||
FETCH_FUNCS(L_FLOAT16),
|
||||
FETCH_FUNCS(L_FLOAT32),
|
||||
FETCH_FUNCS(LA_FLOAT16),
|
||||
FETCH_FUNCS(LA_FLOAT32),
|
||||
FETCH_FUNCS(I_FLOAT16),
|
||||
FETCH_FUNCS(I_FLOAT32),
|
||||
FETCH_FUNCS(R_FLOAT16),
|
||||
FETCH_FUNCS(R_FLOAT32),
|
||||
FETCH_FUNCS(RG_FLOAT16),
|
||||
FETCH_FUNCS(RG_FLOAT32),
|
||||
FETCH_FUNCS(RGB_FLOAT16),
|
||||
FETCH_FUNCS(RGB_FLOAT32),
|
||||
FETCH_FUNCS(RGBA_FLOAT16),
|
||||
FETCH_FUNCS(RGBA_FLOAT32),
|
||||
FETCH_FUNCS(RGBX_FLOAT16),
|
||||
FETCH_FUNCS(RGBX_FLOAT32),
|
||||
[MESA_FORMAT_Z_FLOAT32] = {
|
||||
fetch_texel_1d_R_FLOAT32, /* Reuse the R32F functions. */
|
||||
fetch_texel_2d_R_FLOAT32,
|
||||
fetch_texel_3d_R_FLOAT32
|
||||
},
|
||||
|
||||
/* Packed signed/unsigned non-normalized integer formats */
|
||||
|
||||
/* Array signed/unsigned non-normalized integer formats */
|
||||
FETCH_FUNCS(RGBA_UINT16),
|
||||
FETCH_FUNCS(RGBA_UINT32),
|
||||
FETCH_FUNCS(RGBA_SINT8),
|
||||
FETCH_FUNCS(RGBA_SINT16),
|
||||
FETCH_FUNCS(RGBA_SINT32),
|
||||
|
||||
/* DXT compressed formats */
|
||||
FETCH_COMPRESSED(RGB_DXT1),
|
||||
FETCH_COMPRESSED(RGBA_DXT1),
|
||||
FETCH_COMPRESSED(RGBA_DXT3),
|
||||
FETCH_COMPRESSED(RGBA_DXT5),
|
||||
|
||||
/* DXT sRGB compressed formats */
|
||||
FETCH_COMPRESSED(SRGB_DXT1),
|
||||
FETCH_COMPRESSED(SRGBA_DXT1),
|
||||
FETCH_COMPRESSED(SRGBA_DXT3),
|
||||
FETCH_COMPRESSED(SRGBA_DXT5),
|
||||
|
||||
/* FXT1 compressed formats */
|
||||
FETCH_COMPRESSED(RGB_FXT1),
|
||||
FETCH_COMPRESSED(RGBA_FXT1),
|
||||
|
||||
/* RGTC compressed formats */
|
||||
FETCH_COMPRESSED(R_RGTC1_UNORM),
|
||||
FETCH_COMPRESSED(R_RGTC1_SNORM),
|
||||
FETCH_COMPRESSED(RG_RGTC2_UNORM),
|
||||
FETCH_COMPRESSED(RG_RGTC2_SNORM),
|
||||
|
||||
/* LATC1/2 compressed formats */
|
||||
FETCH_COMPRESSED(L_LATC1_UNORM),
|
||||
FETCH_COMPRESSED(L_LATC1_SNORM),
|
||||
FETCH_COMPRESSED(LA_LATC2_UNORM),
|
||||
FETCH_COMPRESSED(LA_LATC2_SNORM),
|
||||
|
||||
/* ETC1/2 compressed formats */
|
||||
FETCH_COMPRESSED(ETC1_RGB8),
|
||||
FETCH_COMPRESSED(ETC2_RGB8),
|
||||
FETCH_COMPRESSED(ETC2_SRGB8),
|
||||
FETCH_COMPRESSED(ETC2_RGBA8_EAC),
|
||||
FETCH_COMPRESSED(ETC2_SRGB8_ALPHA8_EAC),
|
||||
FETCH_COMPRESSED(ETC2_R11_EAC),
|
||||
FETCH_COMPRESSED(ETC2_RG11_EAC),
|
||||
FETCH_COMPRESSED(ETC2_SIGNED_R11_EAC),
|
||||
FETCH_COMPRESSED(ETC2_SIGNED_RG11_EAC),
|
||||
FETCH_COMPRESSED(ETC2_RGB8_PUNCHTHROUGH_ALPHA1),
|
||||
FETCH_COMPRESSED(ETC2_SRGB8_PUNCHTHROUGH_ALPHA1),
|
||||
FETCH_COMPRESSED(BPTC_RGBA_UNORM),
|
||||
FETCH_COMPRESSED(BPTC_SRGB_ALPHA_UNORM),
|
||||
FETCH_COMPRESSED(BPTC_RGB_SIGNED_FLOAT),
|
||||
FETCH_COMPRESSED(BPTC_RGB_UNSIGNED_FLOAT),
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the texture image's FetchTexel methods.
|
||||
*/
|
||||
static void
|
||||
set_fetch_functions(const struct gl_sampler_object *samp,
|
||||
struct swrast_texture_image *texImage, GLuint dims)
|
||||
{
|
||||
mesa_format format = texImage->Base.TexFormat;
|
||||
|
||||
if (samp->Attrib.sRGBDecode == GL_SKIP_DECODE_EXT)
|
||||
format = _mesa_get_srgb_format_linear(format);
|
||||
|
||||
texImage->FetchTexel = NULL;
|
||||
|
||||
if (format < ARRAY_SIZE(texfetch_funcs)) {
|
||||
switch (dims) {
|
||||
case 1:
|
||||
texImage->FetchTexel = texfetch_funcs[format].Fetch1D;
|
||||
break;
|
||||
case 2:
|
||||
texImage->FetchTexel = texfetch_funcs[format].Fetch2D;
|
||||
break;
|
||||
case 3:
|
||||
texImage->FetchTexel = texfetch_funcs[format].Fetch3D;
|
||||
break;
|
||||
default:
|
||||
assert(!"Bad dims in set_fetch_functions()");
|
||||
}
|
||||
}
|
||||
|
||||
if (!texImage->FetchTexel)
|
||||
texImage->FetchTexel = fetch_null_texelf;
|
||||
|
||||
texImage->FetchCompressedTexel = _mesa_get_compressed_fetch_func(format);
|
||||
|
||||
assert(texImage->FetchTexel);
|
||||
}
|
||||
|
||||
void
|
||||
_mesa_update_fetch_functions(struct gl_context *ctx, GLuint unit)
|
||||
{
|
||||
struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current;
|
||||
struct gl_sampler_object *samp;
|
||||
GLuint face, i;
|
||||
GLuint dims;
|
||||
|
||||
if (!texObj)
|
||||
return;
|
||||
|
||||
samp = _mesa_get_samplerobj(ctx, unit);
|
||||
|
||||
dims = _mesa_get_texture_dimensions(texObj->Target);
|
||||
|
||||
for (face = 0; face < 6; face++) {
|
||||
for (i = 0; i < MAX_TEXTURE_LEVELS; i++) {
|
||||
if (texObj->Image[face][i]) {
|
||||
set_fetch_functions(samp,
|
||||
swrast_texture_image(texObj->Image[face][i]),
|
||||
dims);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
|
||||
* Copyright (c) 2009 VMware, Inc.
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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 S_TEXFETCH_H
|
||||
#define S_TEXFETCH_H
|
||||
|
||||
#include "swrast/s_context.h"
|
||||
|
||||
void
|
||||
_mesa_update_fetch_functions(struct gl_context *ctx, GLuint unit);
|
||||
|
||||
#endif /* S_TEXFETCH_H */
|
|
@ -1,190 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
|
||||
* Copyright (c) 2008-2009 VMware, Inc.
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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 texfetch_tmp.h
|
||||
* Texel fetch functions template.
|
||||
*
|
||||
* This template file is used by texfetch.c to generate texel fetch functions
|
||||
* for 1-D, 2-D and 3-D texture images.
|
||||
*
|
||||
* It should be expanded by defining \p DIM as the number texture dimensions
|
||||
* (1, 2 or 3). According to the value of \p DIM a series of macros is defined
|
||||
* for the texel lookup in the gl_texture_image::Data.
|
||||
*
|
||||
* \author Gareth Hughes
|
||||
* \author Brian Paul
|
||||
*/
|
||||
|
||||
#include <format_unpack.h>
|
||||
|
||||
#if DIM == 1
|
||||
|
||||
#define TEXEL_ADDR( type, image, i, j, k, size ) \
|
||||
((void) (j), (void) (k), ((type *)(image)->ImageSlices[0] + (i) * (size)))
|
||||
|
||||
#define FETCH(x) fetch_texel_1d_##x
|
||||
|
||||
#elif DIM == 2
|
||||
|
||||
#define TEXEL_ADDR( type, image, i, j, k, size ) \
|
||||
((void) (k), \
|
||||
((type *)((GLubyte *) (image)->ImageSlices[0] + (image)->RowStride * (j)) + \
|
||||
(i) * (size)))
|
||||
|
||||
#define FETCH(x) fetch_texel_2d_##x
|
||||
|
||||
#elif DIM == 3
|
||||
|
||||
#define TEXEL_ADDR( type, image, i, j, k, size ) \
|
||||
((type *)((GLubyte *) (image)->ImageSlices[k] + \
|
||||
(image)->RowStride * (j)) + (i) * (size))
|
||||
|
||||
#define FETCH(x) fetch_texel_3d_##x
|
||||
|
||||
#else
|
||||
#error illegal number of texture dimensions
|
||||
#endif
|
||||
|
||||
#define FETCH_Z(x, type, size) \
|
||||
static void \
|
||||
FETCH(x) (const struct swrast_texture_image *texImage, \
|
||||
GLint i, GLint j, GLint k, GLfloat *texel) \
|
||||
{ \
|
||||
const type *src = TEXEL_ADDR(type, texImage, i, j, k, size); \
|
||||
_mesa_unpack_float_z_row(MESA_FORMAT_##x, 1, src, texel); \
|
||||
}
|
||||
|
||||
#define FETCH_RGBA(x, type, size) \
|
||||
static void \
|
||||
FETCH(x) (const struct swrast_texture_image *texImage, \
|
||||
GLint i, GLint j, GLint k, GLfloat *texel) \
|
||||
{ \
|
||||
const type *src = TEXEL_ADDR(type, texImage, i, j, k, size); \
|
||||
_mesa_unpack_rgba_row(MESA_FORMAT_##x, 1, src, (GLvoid *)texel); \
|
||||
}
|
||||
|
||||
FETCH_Z(Z_UNORM32, GLuint, 1)
|
||||
FETCH_Z(Z_UNORM16, GLushort, 1)
|
||||
FETCH_Z(S8_UINT_Z24_UNORM, GLuint, 1) /* only return Z, not stencil data */
|
||||
FETCH_Z(Z24_UNORM_S8_UINT, GLuint, 1) /* only return Z, not stencil data */
|
||||
FETCH_Z(Z32_FLOAT_S8X24_UINT, GLfloat, 2)
|
||||
|
||||
FETCH_RGBA(RGBA_FLOAT32, GLfloat, 4)
|
||||
FETCH_RGBA(RGBA_FLOAT16, GLhalfARB, 4)
|
||||
FETCH_RGBA(RGB_FLOAT32, GLfloat, 3)
|
||||
FETCH_RGBA(RGB_FLOAT16, GLhalfARB, 3)
|
||||
FETCH_RGBA(A_FLOAT32, GLfloat, 1)
|
||||
FETCH_RGBA(A_FLOAT16, GLhalfARB, 1)
|
||||
FETCH_RGBA(L_FLOAT32, GLfloat, 1)
|
||||
FETCH_RGBA(L_FLOAT16, GLhalfARB, 1)
|
||||
FETCH_RGBA(LA_FLOAT32, GLfloat, 2)
|
||||
FETCH_RGBA(LA_FLOAT16, GLhalfARB, 2)
|
||||
FETCH_RGBA(I_FLOAT32, GLfloat, 1)
|
||||
FETCH_RGBA(I_FLOAT16, GLhalfARB, 1)
|
||||
FETCH_RGBA(R_FLOAT32, GLfloat, 1)
|
||||
FETCH_RGBA(R_FLOAT16, GLhalfARB, 1)
|
||||
FETCH_RGBA(RG_FLOAT32, GLfloat, 2)
|
||||
FETCH_RGBA(RG_FLOAT16, GLhalfARB, 2)
|
||||
FETCH_RGBA(A8B8G8R8_UNORM, GLuint, 1)
|
||||
FETCH_RGBA(R8G8B8A8_UNORM, GLuint, 1)
|
||||
FETCH_RGBA(B8G8R8A8_UNORM, GLuint, 1)
|
||||
FETCH_RGBA(A8R8G8B8_UNORM, GLuint, 1)
|
||||
FETCH_RGBA(X8B8G8R8_UNORM, GLuint, 1)
|
||||
FETCH_RGBA(R8G8B8X8_UNORM, GLuint, 1)
|
||||
FETCH_RGBA(B8G8R8X8_UNORM, GLuint, 1)
|
||||
FETCH_RGBA(X8R8G8B8_UNORM, GLuint, 1)
|
||||
FETCH_RGBA(BGR_UNORM8, GLubyte, 3)
|
||||
FETCH_RGBA(RGB_UNORM8, GLubyte, 3)
|
||||
FETCH_RGBA(B5G6R5_UNORM, GLushort, 1)
|
||||
FETCH_RGBA(R5G6B5_UNORM, GLushort, 1)
|
||||
FETCH_RGBA(B4G4R4A4_UNORM, GLushort, 1)
|
||||
FETCH_RGBA(A4R4G4B4_UNORM, GLushort, 1)
|
||||
FETCH_RGBA(A1B5G5R5_UNORM, GLushort, 1)
|
||||
FETCH_RGBA(B5G5R5A1_UNORM, GLushort, 1)
|
||||
FETCH_RGBA(A1R5G5B5_UNORM, GLushort, 1)
|
||||
FETCH_RGBA(B10G10R10A2_UNORM, GLuint, 1)
|
||||
FETCH_RGBA(R10G10B10A2_UNORM, GLuint, 1)
|
||||
FETCH_RGBA(RG_UNORM8, GLubyte, 2)
|
||||
FETCH_RGBA(L4A4_UNORM, GLubyte, 1)
|
||||
FETCH_RGBA(R_UNORM8, GLubyte, 1)
|
||||
FETCH_RGBA(R_UNORM16, GLushort, 1)
|
||||
FETCH_RGBA(LA_UNORM8, GLubyte, 2)
|
||||
FETCH_RGBA(RG_UNORM16, GLushort, 2)
|
||||
FETCH_RGBA(B2G3R3_UNORM, GLubyte, 1)
|
||||
FETCH_RGBA(A_UNORM8, GLubyte, 1)
|
||||
FETCH_RGBA(A_UNORM16, GLushort, 1)
|
||||
FETCH_RGBA(L_UNORM8, GLubyte, 1)
|
||||
FETCH_RGBA(L_UNORM16, GLushort, 1)
|
||||
FETCH_RGBA(LA_UNORM16, GLushort, 2)
|
||||
FETCH_RGBA(I_UNORM8, GLubyte, 1)
|
||||
FETCH_RGBA(I_UNORM16, GLushort, 1)
|
||||
FETCH_RGBA(BGR_SRGB8, GLubyte, 3)
|
||||
FETCH_RGBA(A8B8G8R8_SRGB, GLuint, 1)
|
||||
FETCH_RGBA(B8G8R8A8_SRGB, GLuint, 1)
|
||||
FETCH_RGBA(A8R8G8B8_SRGB, GLuint, 1)
|
||||
FETCH_RGBA(R8G8B8A8_SRGB, GLuint, 1)
|
||||
FETCH_RGBA(R8G8B8X8_SRGB, GLuint, 1)
|
||||
FETCH_RGBA(X8B8G8R8_SRGB, GLuint, 1)
|
||||
FETCH_RGBA(R_SRGB8, GLubyte, 1)
|
||||
FETCH_RGBA(L_SRGB8, GLubyte, 1)
|
||||
FETCH_RGBA(LA_SRGB8, GLubyte, 2)
|
||||
FETCH_RGBA(RGBA_SINT8, GLbyte, 4)
|
||||
FETCH_RGBA(RGBA_SINT16, GLshort, 4)
|
||||
FETCH_RGBA(RGBA_SINT32, GLint, 4)
|
||||
FETCH_RGBA(RGBA_UINT16, GLushort, 4)
|
||||
FETCH_RGBA(RGBA_UINT32, GLuint, 4)
|
||||
FETCH_RGBA(R_SNORM8, GLbyte, 1)
|
||||
FETCH_RGBA(A_SNORM8, GLbyte, 1)
|
||||
FETCH_RGBA(L_SNORM8, GLbyte, 1)
|
||||
FETCH_RGBA(I_SNORM8, GLbyte, 1)
|
||||
FETCH_RGBA(LA_SNORM8, GLbyte, 2)
|
||||
FETCH_RGBA(RG_SNORM8, GLbyte, 2)
|
||||
FETCH_RGBA(X8B8G8R8_SNORM, GLint, 1)
|
||||
FETCH_RGBA(A8B8G8R8_SNORM, GLint, 1)
|
||||
FETCH_RGBA(R8G8B8A8_SNORM, GLint, 1)
|
||||
FETCH_RGBA(R_SNORM16, GLshort, 1)
|
||||
FETCH_RGBA(A_SNORM16, GLshort, 1)
|
||||
FETCH_RGBA(L_SNORM16, GLshort, 1)
|
||||
FETCH_RGBA(I_SNORM16, GLshort, 1)
|
||||
FETCH_RGBA(RG_SNORM16, GLshort, 2)
|
||||
FETCH_RGBA(LA_SNORM16, GLshort, 2)
|
||||
FETCH_RGBA(RGB_SNORM16, GLshort, 3)
|
||||
FETCH_RGBA(RGBA_SNORM16, GLshort, 4)
|
||||
FETCH_RGBA(RGBA_UNORM16, GLushort, 4)
|
||||
FETCH_RGBA(RGBX_UNORM16, GLushort, 4)
|
||||
FETCH_RGBA(RGBX_FLOAT16, GLhalfARB, 4)
|
||||
FETCH_RGBA(RGBX_FLOAT32, GLfloat, 4)
|
||||
FETCH_RGBA(YCBCR, GLushort, 1) /* Fetch texel from 1D, 2D or 3D ycbcr texture, returning RGBA. */
|
||||
FETCH_RGBA(YCBCR_REV, GLushort, 1) /* Fetch texel from 1D, 2D or 3D ycbcr texture, returning RGBA. */
|
||||
FETCH_RGBA(R9G9B9E5_FLOAT, GLuint, 1)
|
||||
FETCH_RGBA(R11G11B10_FLOAT, GLuint, 1)
|
||||
|
||||
#undef TEXEL_ADDR
|
||||
#undef DIM
|
||||
#undef FETCH
|
||||
#undef FETCH_Z
|
||||
#undef FETCH_RGBA
|
File diff suppressed because it is too large
Load Diff
|
@ -1,42 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* Copyright (C) 1999-2005 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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 S_TEXFILTER_H
|
||||
#define S_TEXFILTER_H
|
||||
|
||||
|
||||
#include "s_context.h"
|
||||
|
||||
struct gl_context;
|
||||
struct gl_texture_object;
|
||||
|
||||
|
||||
extern texture_sample_func
|
||||
_swrast_choose_texture_sample_func( struct gl_context *ctx,
|
||||
const struct gl_texture_object *tObj,
|
||||
const struct gl_sampler_object *sampler);
|
||||
|
||||
|
||||
#endif
|
|
@ -1,102 +0,0 @@
|
|||
|
||||
#include "main/context.h"
|
||||
#include "main/fbobject.h"
|
||||
#include "main/macros.h"
|
||||
#include "main/teximage.h"
|
||||
#include "main/renderbuffer.h"
|
||||
#include "swrast/swrast.h"
|
||||
#include "swrast/s_context.h"
|
||||
#include "swrast/s_texfetch.h"
|
||||
|
||||
|
||||
/*
|
||||
* Render-to-texture code for GL_EXT_framebuffer_object
|
||||
*/
|
||||
|
||||
|
||||
static void
|
||||
delete_texture_wrapper(struct gl_context *ctx, struct gl_renderbuffer *rb)
|
||||
{
|
||||
assert(rb->RefCount == 0);
|
||||
free(rb);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the renderbuffer wrapper for rendering to a texture.
|
||||
* For example, update the width, height of the RB based on the texture size,
|
||||
* update the internal format info, etc.
|
||||
*/
|
||||
static void
|
||||
update_wrapper(struct gl_context *ctx, struct gl_renderbuffer_attachment *att)
|
||||
{
|
||||
struct gl_renderbuffer *rb = att->Renderbuffer;
|
||||
struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
|
||||
struct swrast_texture_image *swImage;
|
||||
mesa_format format;
|
||||
GLuint zOffset;
|
||||
|
||||
(void) ctx;
|
||||
|
||||
swImage = swrast_texture_image(rb->TexImage);
|
||||
assert(swImage);
|
||||
|
||||
format = swImage->Base.TexFormat;
|
||||
|
||||
if (att->Texture->Target == GL_TEXTURE_1D_ARRAY_EXT) {
|
||||
zOffset = 0;
|
||||
}
|
||||
else {
|
||||
zOffset = att->Zoffset;
|
||||
}
|
||||
|
||||
/* Want to store linear values, not sRGB */
|
||||
rb->Format = _mesa_get_srgb_format_linear(format);
|
||||
|
||||
srb->Buffer = swImage->ImageSlices[zOffset];
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Called when rendering to a texture image begins, or when changing
|
||||
* the dest mipmap level, cube face, etc.
|
||||
* This is a fallback routine for software render-to-texture.
|
||||
*
|
||||
* Called via the glRenderbufferTexture1D/2D/3D() functions
|
||||
* and elsewhere (such as glTexImage2D).
|
||||
*
|
||||
* The image we're rendering into is
|
||||
* att->Texture->Image[att->CubeMapFace][att->TextureLevel];
|
||||
* It'll never be NULL.
|
||||
*
|
||||
* \param fb the framebuffer object the texture is being bound to
|
||||
* \param att the fb attachment point of the texture
|
||||
*
|
||||
* \sa _mesa_FramebufferRenderbuffer_sw
|
||||
*/
|
||||
void
|
||||
_swrast_render_texture(struct gl_context *ctx,
|
||||
struct gl_framebuffer *fb,
|
||||
struct gl_renderbuffer_attachment *att)
|
||||
{
|
||||
struct gl_renderbuffer *rb = att->Renderbuffer;
|
||||
(void) fb;
|
||||
|
||||
/* plug in our texture_renderbuffer-specific functions */
|
||||
rb->Delete = delete_texture_wrapper;
|
||||
|
||||
update_wrapper(ctx, att);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_swrast_finish_render_texture(struct gl_context *ctx,
|
||||
struct gl_renderbuffer *rb)
|
||||
{
|
||||
/* do nothing */
|
||||
/* The renderbuffer texture wrapper will get deleted by the
|
||||
* normal mechanism for deleting renderbuffers.
|
||||
*/
|
||||
(void) ctx;
|
||||
(void) rb;
|
||||
}
|
|
@ -1,388 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* Copyright (C) 2011 VMware, Inc.
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Functions for mapping/unmapping texture images.
|
||||
*/
|
||||
|
||||
|
||||
#include "main/context.h"
|
||||
#include "main/fbobject.h"
|
||||
#include "main/teximage.h"
|
||||
#include "main/texobj.h"
|
||||
#include "util/u_memory.h"
|
||||
#include "util/u_math.h"
|
||||
#include "swrast/swrast.h"
|
||||
#include "swrast/s_context.h"
|
||||
|
||||
|
||||
/**
|
||||
* Allocate a new swrast_texture_image (a subclass of gl_texture_image).
|
||||
* Called via ctx->Driver.NewTextureImage().
|
||||
*/
|
||||
struct gl_texture_image *
|
||||
_swrast_new_texture_image( struct gl_context *ctx )
|
||||
{
|
||||
(void) ctx;
|
||||
return (struct gl_texture_image *) CALLOC_STRUCT(swrast_texture_image);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Free a swrast_texture_image (a subclass of gl_texture_image).
|
||||
* Called via ctx->Driver.DeleteTextureImage().
|
||||
*/
|
||||
void
|
||||
_swrast_delete_texture_image(struct gl_context *ctx,
|
||||
struct gl_texture_image *texImage)
|
||||
{
|
||||
/* Nothing special for the subclass yet */
|
||||
_mesa_delete_texture_image(ctx, texImage);
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
texture_slices(const struct gl_texture_image *texImage)
|
||||
{
|
||||
if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY)
|
||||
return texImage->Height;
|
||||
else
|
||||
return texImage->Depth;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
_swrast_teximage_slice_height(struct gl_texture_image *texImage)
|
||||
{
|
||||
/* For 1D array textures, the slices are all 1 pixel high, and Height is
|
||||
* the number of slices.
|
||||
*/
|
||||
if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY)
|
||||
return 1;
|
||||
else
|
||||
return texImage->Height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called via ctx->Driver.AllocTextureImageBuffer()
|
||||
*/
|
||||
GLboolean
|
||||
_swrast_alloc_texture_image_buffer(struct gl_context *ctx,
|
||||
struct gl_texture_image *texImage)
|
||||
{
|
||||
struct swrast_texture_image *swImg = swrast_texture_image(texImage);
|
||||
GLuint bytesPerSlice;
|
||||
GLuint slices = texture_slices(texImage);
|
||||
GLuint i;
|
||||
|
||||
if (!_swrast_init_texture_image(texImage))
|
||||
return GL_FALSE;
|
||||
|
||||
bytesPerSlice = _mesa_format_image_size(texImage->TexFormat, texImage->Width,
|
||||
_swrast_teximage_slice_height(texImage), 1);
|
||||
|
||||
assert(!swImg->Buffer);
|
||||
swImg->Buffer = align_malloc(bytesPerSlice * slices, 512);
|
||||
if (!swImg->Buffer)
|
||||
return GL_FALSE;
|
||||
|
||||
/* RowStride and ImageSlices[] describe how to address texels in 'Data' */
|
||||
swImg->RowStride = _mesa_format_row_stride(texImage->TexFormat,
|
||||
texImage->Width);
|
||||
|
||||
for (i = 0; i < slices; i++) {
|
||||
swImg->ImageSlices[i] = swImg->Buffer + bytesPerSlice * i;
|
||||
}
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Code that overrides ctx->Driver.AllocTextureImageBuffer may use this to
|
||||
* initialize the fields of swrast_texture_image without allocating the image
|
||||
* buffer or initializing RowStride or the contents of ImageSlices.
|
||||
*
|
||||
* Returns GL_TRUE on success, GL_FALSE on memory allocation failure.
|
||||
*/
|
||||
GLboolean
|
||||
_swrast_init_texture_image(struct gl_texture_image *texImage)
|
||||
{
|
||||
struct swrast_texture_image *swImg = swrast_texture_image(texImage);
|
||||
|
||||
if ((texImage->Width == 1 || util_is_power_of_two_or_zero(texImage->Width2)) &&
|
||||
(texImage->Height == 1 || util_is_power_of_two_or_zero(texImage->Height2)) &&
|
||||
(texImage->Depth == 1 || util_is_power_of_two_or_zero(texImage->Depth2)))
|
||||
swImg->_IsPowerOfTwo = GL_TRUE;
|
||||
else
|
||||
swImg->_IsPowerOfTwo = GL_FALSE;
|
||||
|
||||
/* Compute Width/Height/DepthScale for mipmap lod computation */
|
||||
if (texImage->TexObject->Target == GL_TEXTURE_RECTANGLE_NV) {
|
||||
/* scale = 1.0 since texture coords directly map to texels */
|
||||
swImg->WidthScale = 1.0;
|
||||
swImg->HeightScale = 1.0;
|
||||
swImg->DepthScale = 1.0;
|
||||
}
|
||||
else {
|
||||
swImg->WidthScale = (GLfloat) texImage->Width;
|
||||
swImg->HeightScale = (GLfloat) texImage->Height;
|
||||
swImg->DepthScale = (GLfloat) texImage->Depth;
|
||||
}
|
||||
|
||||
assert(!swImg->ImageSlices);
|
||||
swImg->ImageSlices = calloc(texture_slices(texImage), sizeof(void *));
|
||||
if (!swImg->ImageSlices)
|
||||
return GL_FALSE;
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called via ctx->Driver.FreeTextureImageBuffer()
|
||||
*/
|
||||
void
|
||||
_swrast_free_texture_image_buffer(struct gl_context *ctx,
|
||||
struct gl_texture_image *texImage)
|
||||
{
|
||||
struct swrast_texture_image *swImage = swrast_texture_image(texImage);
|
||||
|
||||
align_free(swImage->Buffer);
|
||||
swImage->Buffer = NULL;
|
||||
|
||||
free(swImage->ImageSlices);
|
||||
swImage->ImageSlices = NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Error checking for debugging only.
|
||||
*/
|
||||
static void
|
||||
check_map_teximage(const struct gl_texture_image *texImage,
|
||||
GLuint slice, GLuint x, GLuint y, GLuint w, GLuint h)
|
||||
{
|
||||
|
||||
if (texImage->TexObject->Target == GL_TEXTURE_1D)
|
||||
assert(y == 0 && h == 1);
|
||||
|
||||
assert(x < texImage->Width || texImage->Width == 0);
|
||||
assert(y < texImage->Height || texImage->Height == 0);
|
||||
assert(x + w <= texImage->Width);
|
||||
assert(y + h <= texImage->Height);
|
||||
assert(slice < texture_slices(texImage));
|
||||
}
|
||||
|
||||
/**
|
||||
* Map a 2D slice of a texture image into user space.
|
||||
* (x,y,w,h) defines a region of interest (ROI). Reading/writing texels
|
||||
* outside of the ROI is undefined.
|
||||
*
|
||||
* \param texImage the texture image
|
||||
* \param slice the 3D image slice or array texture slice
|
||||
* \param x, y, w, h region of interest
|
||||
* \param mode bitmask of GL_MAP_READ_BIT, GL_MAP_WRITE_BIT
|
||||
* \param mapOut returns start of mapping of region of interest
|
||||
* \param rowStrideOut returns row stride (in bytes)
|
||||
*/
|
||||
void
|
||||
_swrast_map_teximage(struct gl_context *ctx,
|
||||
struct gl_texture_image *texImage,
|
||||
GLuint slice,
|
||||
GLuint x, GLuint y, GLuint w, GLuint h,
|
||||
GLbitfield mode,
|
||||
GLubyte **mapOut,
|
||||
GLint *rowStrideOut)
|
||||
{
|
||||
struct swrast_texture_image *swImage = swrast_texture_image(texImage);
|
||||
GLubyte *map;
|
||||
GLint stride, texelSize;
|
||||
GLuint bw, bh;
|
||||
|
||||
check_map_teximage(texImage, slice, x, y, w, h);
|
||||
|
||||
if (!swImage->Buffer) {
|
||||
/* Either glTexImage was called with a NULL <pixels> argument or
|
||||
* we ran out of memory when allocating texture memory,
|
||||
*/
|
||||
*mapOut = NULL;
|
||||
*rowStrideOut = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
texelSize = _mesa_get_format_bytes(texImage->TexFormat);
|
||||
stride = _mesa_format_row_stride(texImage->TexFormat, texImage->Width);
|
||||
_mesa_get_format_block_size(texImage->TexFormat, &bw, &bh);
|
||||
|
||||
assert(x % bw == 0);
|
||||
assert(y % bh == 0);
|
||||
|
||||
/* This function can only be used with a swrast-allocated buffer, in which
|
||||
* case ImageSlices is populated with pointers into Buffer.
|
||||
*/
|
||||
assert(swImage->Buffer);
|
||||
assert(swImage->Buffer == swImage->ImageSlices[0]);
|
||||
|
||||
map = swImage->ImageSlices[slice];
|
||||
|
||||
/* apply x/y offset to map address */
|
||||
map += stride * (y / bh) + texelSize * (x / bw);
|
||||
|
||||
*mapOut = map;
|
||||
*rowStrideOut = stride;
|
||||
}
|
||||
|
||||
void
|
||||
_swrast_unmap_teximage(struct gl_context *ctx,
|
||||
struct gl_texture_image *texImage,
|
||||
GLuint slice)
|
||||
{
|
||||
/* nop */
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_swrast_map_texture(struct gl_context *ctx, struct gl_texture_object *texObj)
|
||||
{
|
||||
const GLuint faces = _mesa_num_tex_faces(texObj->Target);
|
||||
GLuint face, level;
|
||||
|
||||
for (face = 0; face < faces; face++) {
|
||||
for (level = texObj->Attrib.BaseLevel; level < MAX_TEXTURE_LEVELS; level++) {
|
||||
struct gl_texture_image *texImage = texObj->Image[face][level];
|
||||
struct swrast_texture_image *swImage = swrast_texture_image(texImage);
|
||||
unsigned int i, slices;
|
||||
|
||||
if (!texImage)
|
||||
continue;
|
||||
|
||||
/* In the case of a swrast-allocated texture buffer, the ImageSlices
|
||||
* and RowStride are always available.
|
||||
*/
|
||||
if (swImage->Buffer) {
|
||||
assert(swImage->ImageSlices[0] == swImage->Buffer);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!swImage->ImageSlices) {
|
||||
swImage->ImageSlices =
|
||||
calloc(texture_slices(texImage), sizeof(void *));
|
||||
if (!swImage->ImageSlices)
|
||||
continue;
|
||||
}
|
||||
|
||||
slices = texture_slices(texImage);
|
||||
|
||||
for (i = 0; i < slices; i++) {
|
||||
GLubyte *map;
|
||||
GLint rowStride;
|
||||
|
||||
if (swImage->ImageSlices[i])
|
||||
continue;
|
||||
|
||||
ctx->Driver.MapTextureImage(ctx, texImage, i,
|
||||
0, 0,
|
||||
texImage->Width, texImage->Height,
|
||||
GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
|
||||
&map, &rowStride);
|
||||
|
||||
swImage->ImageSlices[i] = map;
|
||||
/* A swrast-using driver has to return the same rowstride for
|
||||
* every slice of the same texture, since we don't track them
|
||||
* separately.
|
||||
*/
|
||||
if (i == 0)
|
||||
swImage->RowStride = rowStride;
|
||||
else
|
||||
assert(swImage->RowStride == rowStride);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_swrast_unmap_texture(struct gl_context *ctx, struct gl_texture_object *texObj)
|
||||
{
|
||||
const GLuint faces = _mesa_num_tex_faces(texObj->Target);
|
||||
GLuint face, level;
|
||||
|
||||
for (face = 0; face < faces; face++) {
|
||||
for (level = texObj->Attrib.BaseLevel; level < MAX_TEXTURE_LEVELS; level++) {
|
||||
struct gl_texture_image *texImage = texObj->Image[face][level];
|
||||
struct swrast_texture_image *swImage = swrast_texture_image(texImage);
|
||||
unsigned int i, slices;
|
||||
|
||||
if (!texImage)
|
||||
continue;
|
||||
|
||||
if (swImage->Buffer)
|
||||
return;
|
||||
|
||||
if (!swImage->ImageSlices)
|
||||
continue;
|
||||
|
||||
slices = texture_slices(texImage);
|
||||
|
||||
for (i = 0; i < slices; i++) {
|
||||
if (swImage->ImageSlices[i]) {
|
||||
ctx->Driver.UnmapTextureImage(ctx, texImage, i);
|
||||
swImage->ImageSlices[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Map all textures for reading prior to software rendering.
|
||||
*/
|
||||
void
|
||||
_swrast_map_textures(struct gl_context *ctx)
|
||||
{
|
||||
int unit;
|
||||
|
||||
for (unit = 0; unit <= ctx->Texture._MaxEnabledTexImageUnit; unit++) {
|
||||
struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current;
|
||||
|
||||
if (texObj)
|
||||
_swrast_map_texture(ctx, texObj);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Unmap all textures for reading prior to software rendering.
|
||||
*/
|
||||
void
|
||||
_swrast_unmap_textures(struct gl_context *ctx)
|
||||
{
|
||||
int unit;
|
||||
for (unit = 0; unit <= ctx->Texture._MaxEnabledTexImageUnit; unit++) {
|
||||
struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current;
|
||||
|
||||
if (texObj)
|
||||
_swrast_unmap_texture(ctx, texObj);
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,50 +0,0 @@
|
|||
|
||||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* Copyright (C) 1999-2003 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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 S_TRIANGLES_H
|
||||
#define S_TRIANGLES_H
|
||||
|
||||
|
||||
#include "swrast.h"
|
||||
|
||||
|
||||
extern GLboolean
|
||||
_swrast_culltriangle( struct gl_context *ctx,
|
||||
const SWvertex *v0,
|
||||
const SWvertex *v1,
|
||||
const SWvertex *v2);
|
||||
|
||||
extern void
|
||||
_swrast_choose_triangle( struct gl_context *ctx );
|
||||
|
||||
extern void
|
||||
_swrast_add_spec_terms_triangle( struct gl_context *ctx,
|
||||
const SWvertex *v0,
|
||||
const SWvertex *v1,
|
||||
const SWvertex *v2 );
|
||||
|
||||
|
||||
#endif
|
|
@ -1,935 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Triangle Rasterizer Template
|
||||
*
|
||||
* This file is #include'd to generate custom triangle rasterizers.
|
||||
*
|
||||
* The following macros may be defined to indicate what auxillary information
|
||||
* must be interpolated across the triangle:
|
||||
* INTERP_Z - if defined, interpolate integer Z values
|
||||
* INTERP_RGB - if defined, interpolate integer RGB values
|
||||
* INTERP_ALPHA - if defined, interpolate integer Alpha values
|
||||
* INTERP_INT_TEX - if defined, interpolate integer ST texcoords
|
||||
* (fast, simple 2-D texture mapping, without
|
||||
* perspective correction)
|
||||
* INTERP_ATTRIBS - if defined, interpolate arbitrary attribs (texcoords,
|
||||
* varying vars, etc) This also causes W to be
|
||||
* computed for perspective correction).
|
||||
*
|
||||
* When one can directly address pixels in the color buffer the following
|
||||
* macros can be defined and used to compute pixel addresses during
|
||||
* rasterization (see pRow):
|
||||
* PIXEL_TYPE - the datatype of a pixel (GLubyte, GLushort, GLuint)
|
||||
* BYTES_PER_ROW - number of bytes per row in the color buffer
|
||||
* PIXEL_ADDRESS(X,Y) - returns the address of pixel at (X,Y) where
|
||||
* Y==0 at bottom of screen and increases upward.
|
||||
*
|
||||
* Similarly, for direct depth buffer access, this type is used for depth
|
||||
* buffer addressing (see zRow):
|
||||
* DEPTH_TYPE - either GLushort or GLuint
|
||||
*
|
||||
* Optionally, one may provide one-time setup code per triangle:
|
||||
* SETUP_CODE - code which is to be executed once per triangle
|
||||
*
|
||||
* The following macro MUST be defined:
|
||||
* RENDER_SPAN(span) - code to write a span of pixels.
|
||||
*
|
||||
* This code was designed for the origin to be in the lower-left corner.
|
||||
*
|
||||
* Inspired by triangle rasterizer code written by Allen Akin. Thanks Allen!
|
||||
*
|
||||
*
|
||||
* Some notes on rasterization accuracy:
|
||||
*
|
||||
* This code uses fixed point arithmetic (the GLfixed type) to iterate
|
||||
* over the triangle edges and interpolate ancillary data (such as Z,
|
||||
* color, secondary color, etc). The number of fractional bits in
|
||||
* GLfixed and the value of SUB_PIXEL_BITS has a direct bearing on the
|
||||
* accuracy of rasterization.
|
||||
*
|
||||
* If SUB_PIXEL_BITS=4 then we'll snap the vertices to the nearest
|
||||
* 1/16 of a pixel. If we're walking up a long, nearly vertical edge
|
||||
* (dx=1/16, dy=1024) we'll need 4 + 10 = 14 fractional bits in
|
||||
* GLfixed to walk the edge without error. If the maximum viewport
|
||||
* height is 4K pixels, then we'll need 4 + 12 = 16 fractional bits.
|
||||
*
|
||||
* Historically, Mesa has used 11 fractional bits in GLfixed, snaps
|
||||
* vertices to 1/16 pixel and allowed a maximum viewport height of 2K
|
||||
* pixels. 11 fractional bits is actually insufficient for accurately
|
||||
* rasterizing some triangles. More recently, the maximum viewport
|
||||
* height was increased to 4K pixels. Thus, Mesa should be using 16
|
||||
* fractional bits in GLfixed. Unfortunately, there may be some issues
|
||||
* with setting FIXED_FRAC_BITS=16, such as multiplication overflow.
|
||||
* This will have to be examined in some detail...
|
||||
*
|
||||
* For now, if you find rasterization errors, particularly with tall,
|
||||
* sliver triangles, try increasing FIXED_FRAC_BITS and/or decreasing
|
||||
* SUB_PIXEL_BITS.
|
||||
*/
|
||||
|
||||
#include "util/u_math.h"
|
||||
|
||||
#ifndef MAX_GLUINT
|
||||
#define MAX_GLUINT 0xffffffffu
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Some code we unfortunately need to prevent negative interpolated colors.
|
||||
*/
|
||||
#ifndef CLAMP_INTERPOLANT
|
||||
#define CLAMP_INTERPOLANT(CHANNEL, CHANNELSTEP, LEN) \
|
||||
do { \
|
||||
GLfixed endVal = span.CHANNEL + (LEN) * span.CHANNELSTEP; \
|
||||
if (endVal < 0) { \
|
||||
span.CHANNEL -= endVal; \
|
||||
} \
|
||||
if (span.CHANNEL < 0) { \
|
||||
span.CHANNEL = 0; \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
|
||||
static void NAME(struct gl_context *ctx, const SWvertex *v0,
|
||||
const SWvertex *v1,
|
||||
const SWvertex *v2 )
|
||||
{
|
||||
typedef struct {
|
||||
const SWvertex *v0, *v1; /* Y(v0) < Y(v1) */
|
||||
GLfloat dx; /* X(v1) - X(v0) */
|
||||
GLfloat dy; /* Y(v1) - Y(v0) */
|
||||
GLfloat dxdy; /* dx/dy */
|
||||
GLfixed fdxdy; /* dx/dy in fixed-point */
|
||||
GLfloat adjy; /* adjust from v[0]->fy to fsy, scaled */
|
||||
GLfixed fsx; /* first sample point x coord */
|
||||
GLfixed fsy;
|
||||
GLfixed fx0; /* fixed pt X of lower endpoint */
|
||||
GLint lines; /* number of lines to be sampled on this edge */
|
||||
} EdgeT;
|
||||
|
||||
const SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
#ifdef INTERP_Z
|
||||
const GLint depthBits = ctx->DrawBuffer->Visual.depthBits;
|
||||
const GLint fixedToDepthShift = depthBits <= 16 ? FIXED_SHIFT : 0;
|
||||
const GLfloat maxDepth = ctx->DrawBuffer->_DepthMaxF;
|
||||
#define FixedToDepth(F) ((F) >> fixedToDepthShift)
|
||||
#endif
|
||||
EdgeT eMaj, eTop, eBot;
|
||||
GLfloat oneOverArea;
|
||||
const SWvertex *vMin, *vMid, *vMax; /* Y(vMin)<=Y(vMid)<=Y(vMax) */
|
||||
GLfloat bf = SWRAST_CONTEXT(ctx)->_BackfaceSign;
|
||||
const GLint snapMask = ~((FIXED_ONE / (1 << SUB_PIXEL_BITS)) - 1); /* for x/y coord snapping */
|
||||
GLfixed vMin_fx, vMin_fy, vMid_fx, vMid_fy, vMax_fx, vMax_fy;
|
||||
|
||||
SWspan span;
|
||||
|
||||
(void) swrast;
|
||||
|
||||
INIT_SPAN(span, GL_POLYGON);
|
||||
span.y = 0; /* silence warnings */
|
||||
|
||||
#ifdef INTERP_Z
|
||||
(void) fixedToDepthShift;
|
||||
#endif
|
||||
|
||||
/*
|
||||
printf("%s()\n", __func__);
|
||||
printf(" %g, %g, %g\n",
|
||||
v0->attrib[VARYING_SLOT_POS][0],
|
||||
v0->attrib[VARYING_SLOT_POS][1],
|
||||
v0->attrib[VARYING_SLOT_POS][2]);
|
||||
printf(" %g, %g, %g\n",
|
||||
v1->attrib[VARYING_SLOT_POS][0],
|
||||
v1->attrib[VARYING_SLOT_POS][1],
|
||||
v1->attrib[VARYING_SLOT_POS][2]);
|
||||
printf(" %g, %g, %g\n",
|
||||
v2->attrib[VARYING_SLOT_POS][0],
|
||||
v2->attrib[VARYING_SLOT_POS][1],
|
||||
v2->attrib[VARYING_SLOT_POS][2]);
|
||||
*/
|
||||
|
||||
/* Compute fixed point x,y coords w/ half-pixel offsets and snapping.
|
||||
* And find the order of the 3 vertices along the Y axis.
|
||||
*/
|
||||
{
|
||||
const GLfixed fy0 = FloatToFixed(v0->attrib[VARYING_SLOT_POS][1] - 0.5F) & snapMask;
|
||||
const GLfixed fy1 = FloatToFixed(v1->attrib[VARYING_SLOT_POS][1] - 0.5F) & snapMask;
|
||||
const GLfixed fy2 = FloatToFixed(v2->attrib[VARYING_SLOT_POS][1] - 0.5F) & snapMask;
|
||||
if (fy0 <= fy1) {
|
||||
if (fy1 <= fy2) {
|
||||
/* y0 <= y1 <= y2 */
|
||||
vMin = v0; vMid = v1; vMax = v2;
|
||||
vMin_fy = fy0; vMid_fy = fy1; vMax_fy = fy2;
|
||||
}
|
||||
else if (fy2 <= fy0) {
|
||||
/* y2 <= y0 <= y1 */
|
||||
vMin = v2; vMid = v0; vMax = v1;
|
||||
vMin_fy = fy2; vMid_fy = fy0; vMax_fy = fy1;
|
||||
}
|
||||
else {
|
||||
/* y0 <= y2 <= y1 */
|
||||
vMin = v0; vMid = v2; vMax = v1;
|
||||
vMin_fy = fy0; vMid_fy = fy2; vMax_fy = fy1;
|
||||
bf = -bf;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (fy0 <= fy2) {
|
||||
/* y1 <= y0 <= y2 */
|
||||
vMin = v1; vMid = v0; vMax = v2;
|
||||
vMin_fy = fy1; vMid_fy = fy0; vMax_fy = fy2;
|
||||
bf = -bf;
|
||||
}
|
||||
else if (fy2 <= fy1) {
|
||||
/* y2 <= y1 <= y0 */
|
||||
vMin = v2; vMid = v1; vMax = v0;
|
||||
vMin_fy = fy2; vMid_fy = fy1; vMax_fy = fy0;
|
||||
bf = -bf;
|
||||
}
|
||||
else {
|
||||
/* y1 <= y2 <= y0 */
|
||||
vMin = v1; vMid = v2; vMax = v0;
|
||||
vMin_fy = fy1; vMid_fy = fy2; vMax_fy = fy0;
|
||||
}
|
||||
}
|
||||
|
||||
/* fixed point X coords */
|
||||
vMin_fx = FloatToFixed(vMin->attrib[VARYING_SLOT_POS][0] + 0.5F) & snapMask;
|
||||
vMid_fx = FloatToFixed(vMid->attrib[VARYING_SLOT_POS][0] + 0.5F) & snapMask;
|
||||
vMax_fx = FloatToFixed(vMax->attrib[VARYING_SLOT_POS][0] + 0.5F) & snapMask;
|
||||
}
|
||||
|
||||
/* vertex/edge relationship */
|
||||
eMaj.v0 = vMin; eMaj.v1 = vMax; /*TODO: .v1's not needed */
|
||||
eTop.v0 = vMid; eTop.v1 = vMax;
|
||||
eBot.v0 = vMin; eBot.v1 = vMid;
|
||||
|
||||
/* compute deltas for each edge: vertex[upper] - vertex[lower] */
|
||||
eMaj.dx = FixedToFloat(vMax_fx - vMin_fx);
|
||||
eMaj.dy = FixedToFloat(vMax_fy - vMin_fy);
|
||||
eTop.dx = FixedToFloat(vMax_fx - vMid_fx);
|
||||
eTop.dy = FixedToFloat(vMax_fy - vMid_fy);
|
||||
eBot.dx = FixedToFloat(vMid_fx - vMin_fx);
|
||||
eBot.dy = FixedToFloat(vMid_fy - vMin_fy);
|
||||
|
||||
/* compute area, oneOverArea and perform backface culling */
|
||||
{
|
||||
const GLfloat area = eMaj.dx * eBot.dy - eBot.dx * eMaj.dy;
|
||||
|
||||
if (util_is_inf_or_nan(area) || area == 0.0F)
|
||||
return;
|
||||
|
||||
if (area * bf * swrast->_BackfaceCullSign < 0.0F)
|
||||
return;
|
||||
|
||||
oneOverArea = 1.0F / area;
|
||||
|
||||
/* 0 = front, 1 = back */
|
||||
span.facing = oneOverArea * bf > 0.0F;
|
||||
}
|
||||
|
||||
/* Edge setup. For a triangle strip these could be reused... */
|
||||
{
|
||||
eMaj.fsy = FixedCeil(vMin_fy);
|
||||
eMaj.lines = FixedToInt(FixedCeil(vMax_fy - eMaj.fsy));
|
||||
if (eMaj.lines > 0) {
|
||||
eMaj.dxdy = eMaj.dx / eMaj.dy;
|
||||
eMaj.fdxdy = SignedFloatToFixed(eMaj.dxdy);
|
||||
eMaj.adjy = (GLfloat) (eMaj.fsy - vMin_fy); /* SCALED! */
|
||||
eMaj.fx0 = vMin_fx;
|
||||
eMaj.fsx = eMaj.fx0 + (GLfixed) (eMaj.adjy * eMaj.dxdy);
|
||||
}
|
||||
else {
|
||||
return; /*CULLED*/
|
||||
}
|
||||
|
||||
eTop.fsy = FixedCeil(vMid_fy);
|
||||
eTop.lines = FixedToInt(FixedCeil(vMax_fy - eTop.fsy));
|
||||
if (eTop.lines > 0) {
|
||||
eTop.dxdy = eTop.dx / eTop.dy;
|
||||
eTop.fdxdy = SignedFloatToFixed(eTop.dxdy);
|
||||
eTop.adjy = (GLfloat) (eTop.fsy - vMid_fy); /* SCALED! */
|
||||
eTop.fx0 = vMid_fx;
|
||||
eTop.fsx = eTop.fx0 + (GLfixed) (eTop.adjy * eTop.dxdy);
|
||||
}
|
||||
|
||||
eBot.fsy = FixedCeil(vMin_fy);
|
||||
eBot.lines = FixedToInt(FixedCeil(vMid_fy - eBot.fsy));
|
||||
if (eBot.lines > 0) {
|
||||
eBot.dxdy = eBot.dx / eBot.dy;
|
||||
eBot.fdxdy = SignedFloatToFixed(eBot.dxdy);
|
||||
eBot.adjy = (GLfloat) (eBot.fsy - vMin_fy); /* SCALED! */
|
||||
eBot.fx0 = vMin_fx;
|
||||
eBot.fsx = eBot.fx0 + (GLfixed) (eBot.adjy * eBot.dxdy);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Conceptually, we view a triangle as two subtriangles
|
||||
* separated by a perfectly horizontal line. The edge that is
|
||||
* intersected by this line is one with maximal absolute dy; we
|
||||
* call it a ``major'' edge. The other two edges are the
|
||||
* ``top'' edge (for the upper subtriangle) and the ``bottom''
|
||||
* edge (for the lower subtriangle). If either of these two
|
||||
* edges is horizontal or very close to horizontal, the
|
||||
* corresponding subtriangle might cover zero sample points;
|
||||
* we take care to handle such cases, for performance as well
|
||||
* as correctness.
|
||||
*
|
||||
* By stepping rasterization parameters along the major edge,
|
||||
* we can avoid recomputing them at the discontinuity where
|
||||
* the top and bottom edges meet. However, this forces us to
|
||||
* be able to scan both left-to-right and right-to-left.
|
||||
* Also, we must determine whether the major edge is at the
|
||||
* left or right side of the triangle. We do this by
|
||||
* computing the magnitude of the cross-product of the major
|
||||
* and top edges. Since this magnitude depends on the sine of
|
||||
* the angle between the two edges, its sign tells us whether
|
||||
* we turn to the left or to the right when travelling along
|
||||
* the major edge to the top edge, and from this we infer
|
||||
* whether the major edge is on the left or the right.
|
||||
*
|
||||
* Serendipitously, this cross-product magnitude is also a
|
||||
* value we need to compute the iteration parameter
|
||||
* derivatives for the triangle, and it can be used to perform
|
||||
* backface culling because its sign tells us whether the
|
||||
* triangle is clockwise or counterclockwise. In this code we
|
||||
* refer to it as ``area'' because it's also proportional to
|
||||
* the pixel area of the triangle.
|
||||
*/
|
||||
|
||||
{
|
||||
GLint scan_from_left_to_right; /* true if scanning left-to-right */
|
||||
|
||||
/*
|
||||
* Execute user-supplied setup code
|
||||
*/
|
||||
#ifdef SETUP_CODE
|
||||
SETUP_CODE
|
||||
#endif
|
||||
|
||||
scan_from_left_to_right = (oneOverArea < 0.0F);
|
||||
|
||||
|
||||
/* compute d?/dx and d?/dy derivatives */
|
||||
#ifdef INTERP_Z
|
||||
span.interpMask |= SPAN_Z;
|
||||
{
|
||||
GLfloat eMaj_dz = vMax->attrib[VARYING_SLOT_POS][2] - vMin->attrib[VARYING_SLOT_POS][2];
|
||||
GLfloat eBot_dz = vMid->attrib[VARYING_SLOT_POS][2] - vMin->attrib[VARYING_SLOT_POS][2];
|
||||
span.attrStepX[VARYING_SLOT_POS][2] = oneOverArea * (eMaj_dz * eBot.dy - eMaj.dy * eBot_dz);
|
||||
if (span.attrStepX[VARYING_SLOT_POS][2] > maxDepth ||
|
||||
span.attrStepX[VARYING_SLOT_POS][2] < -maxDepth) {
|
||||
/* probably a sliver triangle */
|
||||
span.attrStepX[VARYING_SLOT_POS][2] = 0.0;
|
||||
span.attrStepY[VARYING_SLOT_POS][2] = 0.0;
|
||||
}
|
||||
else {
|
||||
span.attrStepY[VARYING_SLOT_POS][2] = oneOverArea * (eMaj.dx * eBot_dz - eMaj_dz * eBot.dx);
|
||||
}
|
||||
if (depthBits <= 16)
|
||||
span.zStep = SignedFloatToFixed(span.attrStepX[VARYING_SLOT_POS][2]);
|
||||
else
|
||||
span.zStep = (GLint) span.attrStepX[VARYING_SLOT_POS][2];
|
||||
}
|
||||
#endif
|
||||
#ifdef INTERP_RGB
|
||||
span.interpMask |= SPAN_RGBA;
|
||||
if (ctx->Light.ShadeModel == GL_SMOOTH) {
|
||||
GLfloat eMaj_dr = (GLfloat) (vMax->color[RCOMP] - vMin->color[RCOMP]);
|
||||
GLfloat eBot_dr = (GLfloat) (vMid->color[RCOMP] - vMin->color[RCOMP]);
|
||||
GLfloat eMaj_dg = (GLfloat) (vMax->color[GCOMP] - vMin->color[GCOMP]);
|
||||
GLfloat eBot_dg = (GLfloat) (vMid->color[GCOMP] - vMin->color[GCOMP]);
|
||||
GLfloat eMaj_db = (GLfloat) (vMax->color[BCOMP] - vMin->color[BCOMP]);
|
||||
GLfloat eBot_db = (GLfloat) (vMid->color[BCOMP] - vMin->color[BCOMP]);
|
||||
# ifdef INTERP_ALPHA
|
||||
GLfloat eMaj_da = (GLfloat) (vMax->color[ACOMP] - vMin->color[ACOMP]);
|
||||
GLfloat eBot_da = (GLfloat) (vMid->color[ACOMP] - vMin->color[ACOMP]);
|
||||
# endif
|
||||
span.attrStepX[VARYING_SLOT_COL0][0] = oneOverArea * (eMaj_dr * eBot.dy - eMaj.dy * eBot_dr);
|
||||
span.attrStepY[VARYING_SLOT_COL0][0] = oneOverArea * (eMaj.dx * eBot_dr - eMaj_dr * eBot.dx);
|
||||
span.attrStepX[VARYING_SLOT_COL0][1] = oneOverArea * (eMaj_dg * eBot.dy - eMaj.dy * eBot_dg);
|
||||
span.attrStepY[VARYING_SLOT_COL0][1] = oneOverArea * (eMaj.dx * eBot_dg - eMaj_dg * eBot.dx);
|
||||
span.attrStepX[VARYING_SLOT_COL0][2] = oneOverArea * (eMaj_db * eBot.dy - eMaj.dy * eBot_db);
|
||||
span.attrStepY[VARYING_SLOT_COL0][2] = oneOverArea * (eMaj.dx * eBot_db - eMaj_db * eBot.dx);
|
||||
span.redStep = SignedFloatToFixed(span.attrStepX[VARYING_SLOT_COL0][0]);
|
||||
span.greenStep = SignedFloatToFixed(span.attrStepX[VARYING_SLOT_COL0][1]);
|
||||
span.blueStep = SignedFloatToFixed(span.attrStepX[VARYING_SLOT_COL0][2]);
|
||||
# ifdef INTERP_ALPHA
|
||||
span.attrStepX[VARYING_SLOT_COL0][3] = oneOverArea * (eMaj_da * eBot.dy - eMaj.dy * eBot_da);
|
||||
span.attrStepY[VARYING_SLOT_COL0][3] = oneOverArea * (eMaj.dx * eBot_da - eMaj_da * eBot.dx);
|
||||
span.alphaStep = SignedFloatToFixed(span.attrStepX[VARYING_SLOT_COL0][3]);
|
||||
# endif /* INTERP_ALPHA */
|
||||
}
|
||||
else {
|
||||
assert(ctx->Light.ShadeModel == GL_FLAT);
|
||||
span.interpMask |= SPAN_FLAT;
|
||||
span.attrStepX[VARYING_SLOT_COL0][0] = span.attrStepY[VARYING_SLOT_COL0][0] = 0.0F;
|
||||
span.attrStepX[VARYING_SLOT_COL0][1] = span.attrStepY[VARYING_SLOT_COL0][1] = 0.0F;
|
||||
span.attrStepX[VARYING_SLOT_COL0][2] = span.attrStepY[VARYING_SLOT_COL0][2] = 0.0F;
|
||||
span.redStep = 0;
|
||||
span.greenStep = 0;
|
||||
span.blueStep = 0;
|
||||
# ifdef INTERP_ALPHA
|
||||
span.attrStepX[VARYING_SLOT_COL0][3] = span.attrStepY[VARYING_SLOT_COL0][3] = 0.0F;
|
||||
span.alphaStep = 0;
|
||||
# endif
|
||||
}
|
||||
#endif /* INTERP_RGB */
|
||||
#ifdef INTERP_INT_TEX
|
||||
{
|
||||
GLfloat eMaj_ds = (vMax->attrib[VARYING_SLOT_TEX0][0] - vMin->attrib[VARYING_SLOT_TEX0][0]) * S_SCALE;
|
||||
GLfloat eBot_ds = (vMid->attrib[VARYING_SLOT_TEX0][0] - vMin->attrib[VARYING_SLOT_TEX0][0]) * S_SCALE;
|
||||
GLfloat eMaj_dt = (vMax->attrib[VARYING_SLOT_TEX0][1] - vMin->attrib[VARYING_SLOT_TEX0][1]) * T_SCALE;
|
||||
GLfloat eBot_dt = (vMid->attrib[VARYING_SLOT_TEX0][1] - vMin->attrib[VARYING_SLOT_TEX0][1]) * T_SCALE;
|
||||
span.attrStepX[VARYING_SLOT_TEX0][0] = oneOverArea * (eMaj_ds * eBot.dy - eMaj.dy * eBot_ds);
|
||||
span.attrStepY[VARYING_SLOT_TEX0][0] = oneOverArea * (eMaj.dx * eBot_ds - eMaj_ds * eBot.dx);
|
||||
span.attrStepX[VARYING_SLOT_TEX0][1] = oneOverArea * (eMaj_dt * eBot.dy - eMaj.dy * eBot_dt);
|
||||
span.attrStepY[VARYING_SLOT_TEX0][1] = oneOverArea * (eMaj.dx * eBot_dt - eMaj_dt * eBot.dx);
|
||||
span.intTexStep[0] = SignedFloatToFixed(span.attrStepX[VARYING_SLOT_TEX0][0]);
|
||||
span.intTexStep[1] = SignedFloatToFixed(span.attrStepX[VARYING_SLOT_TEX0][1]);
|
||||
}
|
||||
#endif
|
||||
#ifdef INTERP_ATTRIBS
|
||||
{
|
||||
/* attrib[VARYING_SLOT_POS][3] is 1/W */
|
||||
const GLfloat wMax = vMax->attrib[VARYING_SLOT_POS][3];
|
||||
const GLfloat wMin = vMin->attrib[VARYING_SLOT_POS][3];
|
||||
const GLfloat wMid = vMid->attrib[VARYING_SLOT_POS][3];
|
||||
{
|
||||
const GLfloat eMaj_dw = wMax - wMin;
|
||||
const GLfloat eBot_dw = wMid - wMin;
|
||||
span.attrStepX[VARYING_SLOT_POS][3] = oneOverArea * (eMaj_dw * eBot.dy - eMaj.dy * eBot_dw);
|
||||
span.attrStepY[VARYING_SLOT_POS][3] = oneOverArea * (eMaj.dx * eBot_dw - eMaj_dw * eBot.dx);
|
||||
}
|
||||
ATTRIB_LOOP_BEGIN
|
||||
if (swrast->_InterpMode[attr] == GL_FLAT) {
|
||||
ASSIGN_4V(span.attrStepX[attr], 0.0, 0.0, 0.0, 0.0);
|
||||
ASSIGN_4V(span.attrStepY[attr], 0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
else {
|
||||
GLuint c;
|
||||
for (c = 0; c < 4; c++) {
|
||||
GLfloat eMaj_da = vMax->attrib[attr][c] * wMax - vMin->attrib[attr][c] * wMin;
|
||||
GLfloat eBot_da = vMid->attrib[attr][c] * wMid - vMin->attrib[attr][c] * wMin;
|
||||
span.attrStepX[attr][c] = oneOverArea * (eMaj_da * eBot.dy - eMaj.dy * eBot_da);
|
||||
span.attrStepY[attr][c] = oneOverArea * (eMaj.dx * eBot_da - eMaj_da * eBot.dx);
|
||||
}
|
||||
}
|
||||
ATTRIB_LOOP_END
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We always sample at pixel centers. However, we avoid
|
||||
* explicit half-pixel offsets in this code by incorporating
|
||||
* the proper offset in each of x and y during the
|
||||
* transformation to window coordinates.
|
||||
*
|
||||
* We also apply the usual rasterization rules to prevent
|
||||
* cracks and overlaps. A pixel is considered inside a
|
||||
* subtriangle if it meets all of four conditions: it is on or
|
||||
* to the right of the left edge, strictly to the left of the
|
||||
* right edge, on or below the top edge, and strictly above
|
||||
* the bottom edge. (Some edges may be degenerate.)
|
||||
*
|
||||
* The following discussion assumes left-to-right scanning
|
||||
* (that is, the major edge is on the left); the right-to-left
|
||||
* case is a straightforward variation.
|
||||
*
|
||||
* We start by finding the half-integral y coordinate that is
|
||||
* at or below the top of the triangle. This gives us the
|
||||
* first scan line that could possibly contain pixels that are
|
||||
* inside the triangle.
|
||||
*
|
||||
* Next we creep down the major edge until we reach that y,
|
||||
* and compute the corresponding x coordinate on the edge.
|
||||
* Then we find the half-integral x that lies on or just
|
||||
* inside the edge. This is the first pixel that might lie in
|
||||
* the interior of the triangle. (We won't know for sure
|
||||
* until we check the other edges.)
|
||||
*
|
||||
* As we rasterize the triangle, we'll step down the major
|
||||
* edge. For each step in y, we'll move an integer number
|
||||
* of steps in x. There are two possible x step sizes, which
|
||||
* we'll call the ``inner'' step (guaranteed to land on the
|
||||
* edge or inside it) and the ``outer'' step (guaranteed to
|
||||
* land on the edge or outside it). The inner and outer steps
|
||||
* differ by one. During rasterization we maintain an error
|
||||
* term that indicates our distance from the true edge, and
|
||||
* select either the inner step or the outer step, whichever
|
||||
* gets us to the first pixel that falls inside the triangle.
|
||||
*
|
||||
* All parameters (z, red, etc.) as well as the buffer
|
||||
* addresses for color and z have inner and outer step values,
|
||||
* so that we can increment them appropriately. This method
|
||||
* eliminates the need to adjust parameters by creeping a
|
||||
* sub-pixel amount into the triangle at each scanline.
|
||||
*/
|
||||
|
||||
{
|
||||
GLint subTriangle;
|
||||
GLfixed fxLeftEdge = 0, fxRightEdge = 0;
|
||||
GLfixed fdxLeftEdge = 0, fdxRightEdge = 0;
|
||||
GLfixed fError = 0, fdError = 0;
|
||||
#ifdef PIXEL_ADDRESS
|
||||
PIXEL_TYPE *pRow = NULL;
|
||||
GLint dPRowOuter = 0, dPRowInner; /* offset in bytes */
|
||||
#endif
|
||||
#ifdef INTERP_Z
|
||||
# ifdef DEPTH_TYPE
|
||||
struct gl_renderbuffer *zrb
|
||||
= ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
|
||||
DEPTH_TYPE *zRow = NULL;
|
||||
GLint dZRowOuter = 0, dZRowInner; /* offset in bytes */
|
||||
# endif
|
||||
GLuint zLeft = 0;
|
||||
GLfixed fdzOuter = 0, fdzInner;
|
||||
#endif
|
||||
#ifdef INTERP_RGB
|
||||
GLint rLeft = 0, fdrOuter = 0, fdrInner;
|
||||
GLint gLeft = 0, fdgOuter = 0, fdgInner;
|
||||
GLint bLeft = 0, fdbOuter = 0, fdbInner;
|
||||
#endif
|
||||
#ifdef INTERP_ALPHA
|
||||
GLint aLeft = 0, fdaOuter = 0, fdaInner;
|
||||
#endif
|
||||
#ifdef INTERP_INT_TEX
|
||||
GLfixed sLeft=0, dsOuter=0, dsInner;
|
||||
GLfixed tLeft=0, dtOuter=0, dtInner;
|
||||
#endif
|
||||
#ifdef INTERP_ATTRIBS
|
||||
GLfloat wLeft = 0, dwOuter = 0, dwInner;
|
||||
GLfloat attrLeft[VARYING_SLOT_MAX][4];
|
||||
GLfloat daOuter[VARYING_SLOT_MAX][4], daInner[VARYING_SLOT_MAX][4];
|
||||
#endif
|
||||
|
||||
for (subTriangle=0; subTriangle<=1; subTriangle++) {
|
||||
EdgeT *eLeft, *eRight;
|
||||
int setupLeft, setupRight;
|
||||
int lines;
|
||||
|
||||
if (subTriangle==0) {
|
||||
/* bottom half */
|
||||
if (scan_from_left_to_right) {
|
||||
eLeft = &eMaj;
|
||||
eRight = &eBot;
|
||||
lines = eRight->lines;
|
||||
setupLeft = 1;
|
||||
setupRight = 1;
|
||||
}
|
||||
else {
|
||||
eLeft = &eBot;
|
||||
eRight = &eMaj;
|
||||
lines = eLeft->lines;
|
||||
setupLeft = 1;
|
||||
setupRight = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* top half */
|
||||
if (scan_from_left_to_right) {
|
||||
eLeft = &eMaj;
|
||||
eRight = &eTop;
|
||||
lines = eRight->lines;
|
||||
setupLeft = 0;
|
||||
setupRight = 1;
|
||||
}
|
||||
else {
|
||||
eLeft = &eTop;
|
||||
eRight = &eMaj;
|
||||
lines = eLeft->lines;
|
||||
setupLeft = 1;
|
||||
setupRight = 0;
|
||||
}
|
||||
if (lines == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
if (setupLeft && eLeft->lines > 0) {
|
||||
const SWvertex *vLower = eLeft->v0;
|
||||
const GLfixed fsy = eLeft->fsy;
|
||||
const GLfixed fsx = eLeft->fsx; /* no fractional part */
|
||||
const GLfixed fx = FixedCeil(fsx); /* no fractional part */
|
||||
const GLfixed adjx = (GLfixed) (fx - eLeft->fx0); /* SCALED! */
|
||||
const GLfixed adjy = (GLfixed) eLeft->adjy; /* SCALED! */
|
||||
GLint idxOuter;
|
||||
GLfloat dxOuter;
|
||||
GLfixed fdxOuter;
|
||||
|
||||
fError = fx - fsx - FIXED_ONE;
|
||||
fxLeftEdge = fsx - FIXED_EPSILON;
|
||||
fdxLeftEdge = eLeft->fdxdy;
|
||||
fdxOuter = FixedFloor(fdxLeftEdge - FIXED_EPSILON);
|
||||
fdError = fdxOuter - fdxLeftEdge + FIXED_ONE;
|
||||
idxOuter = FixedToInt(fdxOuter);
|
||||
dxOuter = (GLfloat) idxOuter;
|
||||
span.y = FixedToInt(fsy);
|
||||
|
||||
/* silence warnings on some compilers */
|
||||
(void) dxOuter;
|
||||
(void) adjx;
|
||||
(void) adjy;
|
||||
(void) vLower;
|
||||
|
||||
#ifdef PIXEL_ADDRESS
|
||||
{
|
||||
pRow = (PIXEL_TYPE *) PIXEL_ADDRESS(FixedToInt(fxLeftEdge), span.y);
|
||||
dPRowOuter = -((int)BYTES_PER_ROW) + idxOuter * sizeof(PIXEL_TYPE);
|
||||
/* negative because Y=0 at bottom and increases upward */
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* Now we need the set of parameter (z, color, etc.) values at
|
||||
* the point (fx, fsy). This gives us properly-sampled parameter
|
||||
* values that we can step from pixel to pixel. Furthermore,
|
||||
* although we might have intermediate results that overflow
|
||||
* the normal parameter range when we step temporarily outside
|
||||
* the triangle, we shouldn't overflow or underflow for any
|
||||
* pixel that's actually inside the triangle.
|
||||
*/
|
||||
|
||||
#ifdef INTERP_Z
|
||||
{
|
||||
GLfloat z0 = vLower->attrib[VARYING_SLOT_POS][2];
|
||||
if (depthBits <= 16) {
|
||||
/* interpolate fixed-pt values */
|
||||
GLfloat tmp = (z0 * FIXED_SCALE
|
||||
+ span.attrStepX[VARYING_SLOT_POS][2] * adjx
|
||||
+ span.attrStepY[VARYING_SLOT_POS][2] * adjy) + FIXED_HALF;
|
||||
if (tmp < MAX_GLUINT / 2)
|
||||
zLeft = (GLfixed) tmp;
|
||||
else
|
||||
zLeft = MAX_GLUINT / 2;
|
||||
fdzOuter = SignedFloatToFixed(span.attrStepY[VARYING_SLOT_POS][2] +
|
||||
dxOuter * span.attrStepX[VARYING_SLOT_POS][2]);
|
||||
}
|
||||
else {
|
||||
/* interpolate depth values w/out scaling */
|
||||
zLeft = (GLuint) (z0 + span.attrStepX[VARYING_SLOT_POS][2] * FixedToFloat(adjx)
|
||||
+ span.attrStepY[VARYING_SLOT_POS][2] * FixedToFloat(adjy));
|
||||
fdzOuter = (GLint) (span.attrStepY[VARYING_SLOT_POS][2] +
|
||||
dxOuter * span.attrStepX[VARYING_SLOT_POS][2]);
|
||||
}
|
||||
# ifdef DEPTH_TYPE
|
||||
zRow = (DEPTH_TYPE *)
|
||||
_swrast_pixel_address(zrb, FixedToInt(fxLeftEdge), span.y);
|
||||
dZRowOuter = (ctx->DrawBuffer->Width + idxOuter) * sizeof(DEPTH_TYPE);
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
#ifdef INTERP_RGB
|
||||
if (ctx->Light.ShadeModel == GL_SMOOTH) {
|
||||
rLeft = (GLint)(ChanToFixed(vLower->color[RCOMP])
|
||||
+ span.attrStepX[VARYING_SLOT_COL0][0] * adjx
|
||||
+ span.attrStepY[VARYING_SLOT_COL0][0] * adjy) + FIXED_HALF;
|
||||
gLeft = (GLint)(ChanToFixed(vLower->color[GCOMP])
|
||||
+ span.attrStepX[VARYING_SLOT_COL0][1] * adjx
|
||||
+ span.attrStepY[VARYING_SLOT_COL0][1] * adjy) + FIXED_HALF;
|
||||
bLeft = (GLint)(ChanToFixed(vLower->color[BCOMP])
|
||||
+ span.attrStepX[VARYING_SLOT_COL0][2] * adjx
|
||||
+ span.attrStepY[VARYING_SLOT_COL0][2] * adjy) + FIXED_HALF;
|
||||
fdrOuter = SignedFloatToFixed(span.attrStepY[VARYING_SLOT_COL0][0]
|
||||
+ dxOuter * span.attrStepX[VARYING_SLOT_COL0][0]);
|
||||
fdgOuter = SignedFloatToFixed(span.attrStepY[VARYING_SLOT_COL0][1]
|
||||
+ dxOuter * span.attrStepX[VARYING_SLOT_COL0][1]);
|
||||
fdbOuter = SignedFloatToFixed(span.attrStepY[VARYING_SLOT_COL0][2]
|
||||
+ dxOuter * span.attrStepX[VARYING_SLOT_COL0][2]);
|
||||
# ifdef INTERP_ALPHA
|
||||
aLeft = (GLint)(ChanToFixed(vLower->color[ACOMP])
|
||||
+ span.attrStepX[VARYING_SLOT_COL0][3] * adjx
|
||||
+ span.attrStepY[VARYING_SLOT_COL0][3] * adjy) + FIXED_HALF;
|
||||
fdaOuter = SignedFloatToFixed(span.attrStepY[VARYING_SLOT_COL0][3]
|
||||
+ dxOuter * span.attrStepX[VARYING_SLOT_COL0][3]);
|
||||
# endif
|
||||
}
|
||||
else {
|
||||
assert(ctx->Light.ShadeModel == GL_FLAT);
|
||||
rLeft = ChanToFixed(v2->color[RCOMP]);
|
||||
gLeft = ChanToFixed(v2->color[GCOMP]);
|
||||
bLeft = ChanToFixed(v2->color[BCOMP]);
|
||||
fdrOuter = fdgOuter = fdbOuter = 0;
|
||||
# ifdef INTERP_ALPHA
|
||||
aLeft = ChanToFixed(v2->color[ACOMP]);
|
||||
fdaOuter = 0;
|
||||
# endif
|
||||
}
|
||||
#endif /* INTERP_RGB */
|
||||
|
||||
|
||||
#ifdef INTERP_INT_TEX
|
||||
{
|
||||
GLfloat s0, t0;
|
||||
s0 = vLower->attrib[VARYING_SLOT_TEX0][0] * S_SCALE;
|
||||
sLeft = (GLfixed)(s0 * FIXED_SCALE + span.attrStepX[VARYING_SLOT_TEX0][0] * adjx
|
||||
+ span.attrStepY[VARYING_SLOT_TEX0][0] * adjy) + FIXED_HALF;
|
||||
dsOuter = SignedFloatToFixed(span.attrStepY[VARYING_SLOT_TEX0][0]
|
||||
+ dxOuter * span.attrStepX[VARYING_SLOT_TEX0][0]);
|
||||
|
||||
t0 = vLower->attrib[VARYING_SLOT_TEX0][1] * T_SCALE;
|
||||
tLeft = (GLfixed)(t0 * FIXED_SCALE + span.attrStepX[VARYING_SLOT_TEX0][1] * adjx
|
||||
+ span.attrStepY[VARYING_SLOT_TEX0][1] * adjy) + FIXED_HALF;
|
||||
dtOuter = SignedFloatToFixed(span.attrStepY[VARYING_SLOT_TEX0][1]
|
||||
+ dxOuter * span.attrStepX[VARYING_SLOT_TEX0][1]);
|
||||
}
|
||||
#endif
|
||||
#ifdef INTERP_ATTRIBS
|
||||
{
|
||||
const GLuint attr = VARYING_SLOT_POS;
|
||||
wLeft = vLower->attrib[VARYING_SLOT_POS][3]
|
||||
+ (span.attrStepX[attr][3] * adjx
|
||||
+ span.attrStepY[attr][3] * adjy) * (1.0F/FIXED_SCALE);
|
||||
dwOuter = span.attrStepY[attr][3] + dxOuter * span.attrStepX[attr][3];
|
||||
}
|
||||
ATTRIB_LOOP_BEGIN
|
||||
const GLfloat invW = vLower->attrib[VARYING_SLOT_POS][3];
|
||||
if (swrast->_InterpMode[attr] == GL_FLAT) {
|
||||
GLuint c;
|
||||
for (c = 0; c < 4; c++) {
|
||||
attrLeft[attr][c] = v2->attrib[attr][c] * invW;
|
||||
daOuter[attr][c] = 0.0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
GLuint c;
|
||||
for (c = 0; c < 4; c++) {
|
||||
const GLfloat a = vLower->attrib[attr][c] * invW;
|
||||
attrLeft[attr][c] = a + ( span.attrStepX[attr][c] * adjx
|
||||
+ span.attrStepY[attr][c] * adjy) * (1.0F/FIXED_SCALE);
|
||||
daOuter[attr][c] = span.attrStepY[attr][c] + dxOuter * span.attrStepX[attr][c];
|
||||
}
|
||||
}
|
||||
ATTRIB_LOOP_END
|
||||
#endif
|
||||
} /*if setupLeft*/
|
||||
|
||||
|
||||
if (setupRight && eRight->lines>0) {
|
||||
fxRightEdge = eRight->fsx - FIXED_EPSILON;
|
||||
fdxRightEdge = eRight->fdxdy;
|
||||
}
|
||||
|
||||
if (lines==0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
/* Rasterize setup */
|
||||
#ifdef PIXEL_ADDRESS
|
||||
dPRowInner = dPRowOuter + sizeof(PIXEL_TYPE);
|
||||
#endif
|
||||
#ifdef INTERP_Z
|
||||
# ifdef DEPTH_TYPE
|
||||
dZRowInner = dZRowOuter + sizeof(DEPTH_TYPE);
|
||||
# endif
|
||||
fdzInner = fdzOuter + span.zStep;
|
||||
#endif
|
||||
#ifdef INTERP_RGB
|
||||
fdrInner = fdrOuter + span.redStep;
|
||||
fdgInner = fdgOuter + span.greenStep;
|
||||
fdbInner = fdbOuter + span.blueStep;
|
||||
#endif
|
||||
#ifdef INTERP_ALPHA
|
||||
fdaInner = fdaOuter + span.alphaStep;
|
||||
#endif
|
||||
#ifdef INTERP_INT_TEX
|
||||
dsInner = dsOuter + span.intTexStep[0];
|
||||
dtInner = dtOuter + span.intTexStep[1];
|
||||
#endif
|
||||
#ifdef INTERP_ATTRIBS
|
||||
dwInner = dwOuter + span.attrStepX[VARYING_SLOT_POS][3];
|
||||
ATTRIB_LOOP_BEGIN
|
||||
GLuint c;
|
||||
for (c = 0; c < 4; c++) {
|
||||
daInner[attr][c] = daOuter[attr][c] + span.attrStepX[attr][c];
|
||||
}
|
||||
ATTRIB_LOOP_END
|
||||
#endif
|
||||
|
||||
while (lines > 0) {
|
||||
/* initialize the span interpolants to the leftmost value */
|
||||
/* ff = fixed-pt fragment */
|
||||
const GLint right = FixedToInt(fxRightEdge);
|
||||
span.x = FixedToInt(fxLeftEdge);
|
||||
if (right <= span.x)
|
||||
span.end = 0;
|
||||
else
|
||||
span.end = right - span.x;
|
||||
|
||||
#ifdef INTERP_Z
|
||||
span.z = zLeft;
|
||||
#endif
|
||||
#ifdef INTERP_RGB
|
||||
span.red = rLeft;
|
||||
span.green = gLeft;
|
||||
span.blue = bLeft;
|
||||
#endif
|
||||
#ifdef INTERP_ALPHA
|
||||
span.alpha = aLeft;
|
||||
#endif
|
||||
#ifdef INTERP_INT_TEX
|
||||
span.intTex[0] = sLeft;
|
||||
span.intTex[1] = tLeft;
|
||||
#endif
|
||||
|
||||
#ifdef INTERP_ATTRIBS
|
||||
span.attrStart[VARYING_SLOT_POS][3] = wLeft;
|
||||
ATTRIB_LOOP_BEGIN
|
||||
GLuint c;
|
||||
for (c = 0; c < 4; c++) {
|
||||
span.attrStart[attr][c] = attrLeft[attr][c];
|
||||
}
|
||||
ATTRIB_LOOP_END
|
||||
#endif
|
||||
|
||||
/* This is where we actually generate fragments */
|
||||
/* XXX the test for span.y > 0 _shouldn't_ be needed but
|
||||
* it fixes a problem on 64-bit Opterons (bug 4842).
|
||||
*/
|
||||
if (span.end > 0 && span.y >= 0) {
|
||||
const GLint len = span.end - 1;
|
||||
(void) len;
|
||||
#ifdef INTERP_RGB
|
||||
CLAMP_INTERPOLANT(red, redStep, len);
|
||||
CLAMP_INTERPOLANT(green, greenStep, len);
|
||||
CLAMP_INTERPOLANT(blue, blueStep, len);
|
||||
#endif
|
||||
#ifdef INTERP_ALPHA
|
||||
CLAMP_INTERPOLANT(alpha, alphaStep, len);
|
||||
#endif
|
||||
{
|
||||
RENDER_SPAN( span );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Advance to the next scan line. Compute the
|
||||
* new edge coordinates, and adjust the
|
||||
* pixel-center x coordinate so that it stays
|
||||
* on or inside the major edge.
|
||||
*/
|
||||
span.y++;
|
||||
lines--;
|
||||
|
||||
fxLeftEdge += fdxLeftEdge;
|
||||
fxRightEdge += fdxRightEdge;
|
||||
|
||||
fError += fdError;
|
||||
if (fError >= 0) {
|
||||
fError -= FIXED_ONE;
|
||||
|
||||
#ifdef PIXEL_ADDRESS
|
||||
pRow = (PIXEL_TYPE *) ((GLubyte *) pRow + dPRowOuter);
|
||||
#endif
|
||||
#ifdef INTERP_Z
|
||||
# ifdef DEPTH_TYPE
|
||||
zRow = (DEPTH_TYPE *) ((GLubyte *) zRow + dZRowOuter);
|
||||
# endif
|
||||
zLeft += fdzOuter;
|
||||
#endif
|
||||
#ifdef INTERP_RGB
|
||||
rLeft += fdrOuter;
|
||||
gLeft += fdgOuter;
|
||||
bLeft += fdbOuter;
|
||||
#endif
|
||||
#ifdef INTERP_ALPHA
|
||||
aLeft += fdaOuter;
|
||||
#endif
|
||||
#ifdef INTERP_INT_TEX
|
||||
sLeft += dsOuter;
|
||||
tLeft += dtOuter;
|
||||
#endif
|
||||
#ifdef INTERP_ATTRIBS
|
||||
wLeft += dwOuter;
|
||||
ATTRIB_LOOP_BEGIN
|
||||
GLuint c;
|
||||
for (c = 0; c < 4; c++) {
|
||||
attrLeft[attr][c] += daOuter[attr][c];
|
||||
}
|
||||
ATTRIB_LOOP_END
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
#ifdef PIXEL_ADDRESS
|
||||
pRow = (PIXEL_TYPE *) ((GLubyte *) pRow + dPRowInner);
|
||||
#endif
|
||||
#ifdef INTERP_Z
|
||||
# ifdef DEPTH_TYPE
|
||||
zRow = (DEPTH_TYPE *) ((GLubyte *) zRow + dZRowInner);
|
||||
# endif
|
||||
zLeft += fdzInner;
|
||||
#endif
|
||||
#ifdef INTERP_RGB
|
||||
rLeft += fdrInner;
|
||||
gLeft += fdgInner;
|
||||
bLeft += fdbInner;
|
||||
#endif
|
||||
#ifdef INTERP_ALPHA
|
||||
aLeft += fdaInner;
|
||||
#endif
|
||||
#ifdef INTERP_INT_TEX
|
||||
sLeft += dsInner;
|
||||
tLeft += dtInner;
|
||||
#endif
|
||||
#ifdef INTERP_ATTRIBS
|
||||
wLeft += dwInner;
|
||||
ATTRIB_LOOP_BEGIN
|
||||
GLuint c;
|
||||
for (c = 0; c < 4; c++) {
|
||||
attrLeft[attr][c] += daInner[attr][c];
|
||||
}
|
||||
ATTRIB_LOOP_END
|
||||
#endif
|
||||
}
|
||||
} /*while lines>0*/
|
||||
|
||||
} /* for subTriangle */
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#undef SETUP_CODE
|
||||
#undef RENDER_SPAN
|
||||
|
||||
#undef PIXEL_TYPE
|
||||
#undef BYTES_PER_ROW
|
||||
#undef PIXEL_ADDRESS
|
||||
#undef DEPTH_TYPE
|
||||
|
||||
#undef INTERP_Z
|
||||
#undef INTERP_RGB
|
||||
#undef INTERP_ALPHA
|
||||
#undef INTERP_INT_TEX
|
||||
#undef INTERP_ATTRIBS
|
||||
|
||||
#undef S_SCALE
|
||||
#undef T_SCALE
|
||||
|
||||
#undef FixedToDepth
|
||||
|
||||
#undef NAME
|
|
@ -1,442 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* Copyright (C) 1999-2008 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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/errors.h"
|
||||
#include "main/glheader.h"
|
||||
#include "main/macros.h"
|
||||
|
||||
#include "main/format_pack.h"
|
||||
|
||||
#include "s_context.h"
|
||||
#include "s_span.h"
|
||||
#include "s_stencil.h"
|
||||
#include "s_zoom.h"
|
||||
|
||||
|
||||
/**
|
||||
* Compute the bounds of the region resulting from zooming a pixel span.
|
||||
* The resulting region will be entirely inside the window/scissor bounds
|
||||
* so no additional clipping is needed.
|
||||
* \param imageX, imageY position of the mage being drawn (gl WindowPos)
|
||||
* \param spanX, spanY position of span being drawing
|
||||
* \param width number of pixels in span
|
||||
* \param x0, x1 returned X bounds of zoomed region [x0, x1)
|
||||
* \param y0, y1 returned Y bounds of zoomed region [y0, y1)
|
||||
* \return GL_TRUE if any zoomed pixels visible, GL_FALSE if totally clipped
|
||||
*/
|
||||
static GLboolean
|
||||
compute_zoomed_bounds(struct gl_context *ctx, GLint imageX, GLint imageY,
|
||||
GLint spanX, GLint spanY, GLint width,
|
||||
GLint *x0, GLint *x1, GLint *y0, GLint *y1)
|
||||
{
|
||||
const struct gl_framebuffer *fb = ctx->DrawBuffer;
|
||||
GLint c0, c1, r0, r1;
|
||||
|
||||
assert(spanX >= imageX);
|
||||
assert(spanY >= imageY);
|
||||
|
||||
/*
|
||||
* Compute destination columns: [c0, c1)
|
||||
*/
|
||||
c0 = imageX + (GLint) ((spanX - imageX) * ctx->Pixel.ZoomX);
|
||||
c1 = imageX + (GLint) ((spanX + width - imageX) * ctx->Pixel.ZoomX);
|
||||
if (c1 < c0) {
|
||||
/* swap */
|
||||
GLint tmp = c1;
|
||||
c1 = c0;
|
||||
c0 = tmp;
|
||||
}
|
||||
c0 = CLAMP(c0, fb->_Xmin, fb->_Xmax);
|
||||
c1 = CLAMP(c1, fb->_Xmin, fb->_Xmax);
|
||||
if (c0 == c1) {
|
||||
return GL_FALSE; /* no width */
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute destination rows: [r0, r1)
|
||||
*/
|
||||
r0 = imageY + (GLint) ((spanY - imageY) * ctx->Pixel.ZoomY);
|
||||
r1 = imageY + (GLint) ((spanY + 1 - imageY) * ctx->Pixel.ZoomY);
|
||||
if (r1 < r0) {
|
||||
/* swap */
|
||||
GLint tmp = r1;
|
||||
r1 = r0;
|
||||
r0 = tmp;
|
||||
}
|
||||
r0 = CLAMP(r0, fb->_Ymin, fb->_Ymax);
|
||||
r1 = CLAMP(r1, fb->_Ymin, fb->_Ymax);
|
||||
if (r0 == r1) {
|
||||
return GL_FALSE; /* no height */
|
||||
}
|
||||
|
||||
*x0 = c0;
|
||||
*x1 = c1;
|
||||
*y0 = r0;
|
||||
*y1 = r1;
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a zoomed x image coordinate back to an unzoomed x coord.
|
||||
* 'zx' is screen position of a pixel in the zoomed image, who's left edge
|
||||
* is at 'imageX'.
|
||||
* return corresponding x coord in the original, unzoomed image.
|
||||
* This can use this for unzooming X or Y values.
|
||||
*/
|
||||
static inline GLint
|
||||
unzoom_x(GLfloat zoomX, GLint imageX, GLint zx)
|
||||
{
|
||||
/*
|
||||
zx = imageX + (x - imageX) * zoomX;
|
||||
zx - imageX = (x - imageX) * zoomX;
|
||||
(zx - imageX) / zoomX = x - imageX;
|
||||
*/
|
||||
GLint x;
|
||||
if (zoomX < 0.0F)
|
||||
zx++;
|
||||
x = imageX + (GLint) ((zx - imageX) / zoomX);
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Helper function called from _swrast_write_zoomed_rgba/rgb/
|
||||
* index/depth_span().
|
||||
*/
|
||||
static void
|
||||
zoom_span( struct gl_context *ctx, GLint imgX, GLint imgY, const SWspan *span,
|
||||
const GLvoid *src, GLenum format )
|
||||
{
|
||||
SWcontext *swrast = SWRAST_CONTEXT(ctx);
|
||||
SWspan zoomed;
|
||||
GLint x0, x1, y0, y1;
|
||||
GLint zoomedWidth;
|
||||
|
||||
if (!compute_zoomed_bounds(ctx, imgX, imgY, span->x, span->y, span->end,
|
||||
&x0, &x1, &y0, &y1)) {
|
||||
return; /* totally clipped */
|
||||
}
|
||||
|
||||
if (!swrast->ZoomedArrays) {
|
||||
/* allocate on demand */
|
||||
swrast->ZoomedArrays = (SWspanarrays *) calloc(1, sizeof(SWspanarrays));
|
||||
if (!swrast->ZoomedArrays)
|
||||
return;
|
||||
}
|
||||
|
||||
zoomedWidth = x1 - x0;
|
||||
assert(zoomedWidth > 0);
|
||||
assert(zoomedWidth <= SWRAST_MAX_WIDTH);
|
||||
|
||||
/* no pixel arrays! must be horizontal spans. */
|
||||
assert((span->arrayMask & SPAN_XY) == 0);
|
||||
assert(span->primitive == GL_BITMAP);
|
||||
|
||||
INIT_SPAN(zoomed, GL_BITMAP);
|
||||
zoomed.x = x0;
|
||||
zoomed.end = zoomedWidth;
|
||||
zoomed.array = swrast->ZoomedArrays;
|
||||
zoomed.array->ChanType = span->array->ChanType;
|
||||
if (zoomed.array->ChanType == GL_UNSIGNED_BYTE)
|
||||
zoomed.array->rgba = (GLchan (*)[4]) zoomed.array->rgba8;
|
||||
else if (zoomed.array->ChanType == GL_UNSIGNED_SHORT)
|
||||
zoomed.array->rgba = (GLchan (*)[4]) zoomed.array->rgba16;
|
||||
else
|
||||
zoomed.array->rgba = (GLchan (*)[4]) zoomed.array->attribs[VARYING_SLOT_COL0];
|
||||
|
||||
COPY_4V(zoomed.attrStart[VARYING_SLOT_POS], span->attrStart[VARYING_SLOT_POS]);
|
||||
COPY_4V(zoomed.attrStepX[VARYING_SLOT_POS], span->attrStepX[VARYING_SLOT_POS]);
|
||||
COPY_4V(zoomed.attrStepY[VARYING_SLOT_POS], span->attrStepY[VARYING_SLOT_POS]);
|
||||
|
||||
zoomed.attrStart[VARYING_SLOT_FOGC][0] = span->attrStart[VARYING_SLOT_FOGC][0];
|
||||
zoomed.attrStepX[VARYING_SLOT_FOGC][0] = span->attrStepX[VARYING_SLOT_FOGC][0];
|
||||
zoomed.attrStepY[VARYING_SLOT_FOGC][0] = span->attrStepY[VARYING_SLOT_FOGC][0];
|
||||
|
||||
if (format == GL_RGBA || format == GL_RGB) {
|
||||
/* copy Z info */
|
||||
zoomed.z = span->z;
|
||||
zoomed.zStep = span->zStep;
|
||||
/* we'll generate an array of colorss */
|
||||
zoomed.interpMask = span->interpMask & ~SPAN_RGBA;
|
||||
zoomed.arrayMask |= SPAN_RGBA;
|
||||
zoomed.arrayAttribs |= VARYING_BIT_COL0; /* we'll produce these values */
|
||||
assert(span->arrayMask & SPAN_RGBA);
|
||||
}
|
||||
else if (format == GL_DEPTH_COMPONENT) {
|
||||
/* Copy color info */
|
||||
zoomed.red = span->red;
|
||||
zoomed.green = span->green;
|
||||
zoomed.blue = span->blue;
|
||||
zoomed.alpha = span->alpha;
|
||||
zoomed.redStep = span->redStep;
|
||||
zoomed.greenStep = span->greenStep;
|
||||
zoomed.blueStep = span->blueStep;
|
||||
zoomed.alphaStep = span->alphaStep;
|
||||
/* we'll generate an array of depth values */
|
||||
zoomed.interpMask = span->interpMask & ~SPAN_Z;
|
||||
zoomed.arrayMask |= SPAN_Z;
|
||||
assert(span->arrayMask & SPAN_Z);
|
||||
}
|
||||
else {
|
||||
_mesa_problem(ctx, "Bad format in zoom_span");
|
||||
return;
|
||||
}
|
||||
|
||||
/* zoom the span horizontally */
|
||||
if (format == GL_RGBA) {
|
||||
if (zoomed.array->ChanType == GL_UNSIGNED_BYTE) {
|
||||
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) src;
|
||||
GLint i;
|
||||
for (i = 0; i < zoomedWidth; i++) {
|
||||
GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
|
||||
assert(j >= 0);
|
||||
assert(j < (GLint) span->end);
|
||||
COPY_4UBV(zoomed.array->rgba8[i], rgba[j]);
|
||||
}
|
||||
}
|
||||
else if (zoomed.array->ChanType == GL_UNSIGNED_SHORT) {
|
||||
const GLushort (*rgba)[4] = (const GLushort (*)[4]) src;
|
||||
GLint i;
|
||||
for (i = 0; i < zoomedWidth; i++) {
|
||||
GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
|
||||
assert(j >= 0);
|
||||
assert(j < (GLint) span->end);
|
||||
COPY_4V(zoomed.array->rgba16[i], rgba[j]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
const GLfloat (*rgba)[4] = (const GLfloat (*)[4]) src;
|
||||
GLint i;
|
||||
for (i = 0; i < zoomedWidth; i++) {
|
||||
GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
|
||||
assert(j >= 0);
|
||||
assert(j < (GLint) span->end);
|
||||
COPY_4V(zoomed.array->attribs[VARYING_SLOT_COL0][i], rgba[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (format == GL_RGB) {
|
||||
if (zoomed.array->ChanType == GL_UNSIGNED_BYTE) {
|
||||
const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) src;
|
||||
GLint i;
|
||||
for (i = 0; i < zoomedWidth; i++) {
|
||||
GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
|
||||
assert(j >= 0);
|
||||
assert(j < (GLint) span->end);
|
||||
zoomed.array->rgba8[i][0] = rgb[j][0];
|
||||
zoomed.array->rgba8[i][1] = rgb[j][1];
|
||||
zoomed.array->rgba8[i][2] = rgb[j][2];
|
||||
zoomed.array->rgba8[i][3] = 0xff;
|
||||
}
|
||||
}
|
||||
else if (zoomed.array->ChanType == GL_UNSIGNED_SHORT) {
|
||||
const GLushort (*rgb)[3] = (const GLushort (*)[3]) src;
|
||||
GLint i;
|
||||
for (i = 0; i < zoomedWidth; i++) {
|
||||
GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
|
||||
assert(j >= 0);
|
||||
assert(j < (GLint) span->end);
|
||||
zoomed.array->rgba16[i][0] = rgb[j][0];
|
||||
zoomed.array->rgba16[i][1] = rgb[j][1];
|
||||
zoomed.array->rgba16[i][2] = rgb[j][2];
|
||||
zoomed.array->rgba16[i][3] = 0xffff;
|
||||
}
|
||||
}
|
||||
else {
|
||||
const GLfloat (*rgb)[3] = (const GLfloat (*)[3]) src;
|
||||
GLint i;
|
||||
for (i = 0; i < zoomedWidth; i++) {
|
||||
GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
|
||||
assert(j >= 0);
|
||||
assert(j < (GLint) span->end);
|
||||
zoomed.array->attribs[VARYING_SLOT_COL0][i][0] = rgb[j][0];
|
||||
zoomed.array->attribs[VARYING_SLOT_COL0][i][1] = rgb[j][1];
|
||||
zoomed.array->attribs[VARYING_SLOT_COL0][i][2] = rgb[j][2];
|
||||
zoomed.array->attribs[VARYING_SLOT_COL0][i][3] = 1.0F;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (format == GL_DEPTH_COMPONENT) {
|
||||
const GLuint *zValues = (const GLuint *) src;
|
||||
GLint i;
|
||||
for (i = 0; i < zoomedWidth; i++) {
|
||||
GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
|
||||
assert(j >= 0);
|
||||
assert(j < (GLint) span->end);
|
||||
zoomed.array->z[i] = zValues[j];
|
||||
}
|
||||
/* Now, fall into the RGB path below */
|
||||
format = GL_RGBA;
|
||||
}
|
||||
|
||||
/* write the span in rows [r0, r1) */
|
||||
if (format == GL_RGBA || format == GL_RGB) {
|
||||
/* Writing the span may modify the colors, so make a backup now if we're
|
||||
* going to call _swrast_write_zoomed_span() more than once.
|
||||
* Also, clipping may change the span end value, so store it as well.
|
||||
*/
|
||||
const GLint end = zoomed.end; /* save */
|
||||
void *rgbaSave;
|
||||
const GLint pixelSize =
|
||||
(zoomed.array->ChanType == GL_UNSIGNED_BYTE) ? 4 * sizeof(GLubyte) :
|
||||
((zoomed.array->ChanType == GL_UNSIGNED_SHORT) ? 4 * sizeof(GLushort)
|
||||
: 4 * sizeof(GLfloat));
|
||||
|
||||
rgbaSave = malloc(zoomed.end * pixelSize);
|
||||
if (!rgbaSave) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (y1 - y0 > 1) {
|
||||
memcpy(rgbaSave, zoomed.array->rgba, zoomed.end * pixelSize);
|
||||
}
|
||||
for (zoomed.y = y0; zoomed.y < y1; zoomed.y++) {
|
||||
_swrast_write_rgba_span(ctx, &zoomed);
|
||||
zoomed.end = end; /* restore */
|
||||
if (y1 - y0 > 1) {
|
||||
/* restore the colors */
|
||||
memcpy(zoomed.array->rgba, rgbaSave, zoomed.end * pixelSize);
|
||||
}
|
||||
}
|
||||
|
||||
free(rgbaSave);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_swrast_write_zoomed_rgba_span(struct gl_context *ctx, GLint imgX, GLint imgY,
|
||||
const SWspan *span, const GLvoid *rgba)
|
||||
{
|
||||
zoom_span(ctx, imgX, imgY, span, rgba, GL_RGBA);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_swrast_write_zoomed_rgb_span(struct gl_context *ctx, GLint imgX, GLint imgY,
|
||||
const SWspan *span, const GLvoid *rgb)
|
||||
{
|
||||
zoom_span(ctx, imgX, imgY, span, rgb, GL_RGB);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_swrast_write_zoomed_depth_span(struct gl_context *ctx, GLint imgX, GLint imgY,
|
||||
const SWspan *span)
|
||||
{
|
||||
zoom_span(ctx, imgX, imgY, span,
|
||||
(const GLvoid *) span->array->z, GL_DEPTH_COMPONENT);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Zoom/write stencil values.
|
||||
* No per-fragment operations are applied.
|
||||
*/
|
||||
void
|
||||
_swrast_write_zoomed_stencil_span(struct gl_context *ctx, GLint imgX, GLint imgY,
|
||||
GLint width, GLint spanX, GLint spanY,
|
||||
const GLubyte stencil[])
|
||||
{
|
||||
GLubyte *zoomedVals;
|
||||
GLint x0, x1, y0, y1, y;
|
||||
GLint i, zoomedWidth;
|
||||
|
||||
if (!compute_zoomed_bounds(ctx, imgX, imgY, spanX, spanY, width,
|
||||
&x0, &x1, &y0, &y1)) {
|
||||
return; /* totally clipped */
|
||||
}
|
||||
|
||||
zoomedWidth = x1 - x0;
|
||||
assert(zoomedWidth > 0);
|
||||
assert(zoomedWidth <= SWRAST_MAX_WIDTH);
|
||||
|
||||
zoomedVals = malloc(zoomedWidth * sizeof(GLubyte));
|
||||
if (!zoomedVals)
|
||||
return;
|
||||
|
||||
/* zoom the span horizontally */
|
||||
for (i = 0; i < zoomedWidth; i++) {
|
||||
GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - spanX;
|
||||
assert(j >= 0);
|
||||
assert(j < width);
|
||||
zoomedVals[i] = stencil[j];
|
||||
}
|
||||
|
||||
/* write the zoomed spans */
|
||||
for (y = y0; y < y1; y++) {
|
||||
_swrast_write_stencil_span(ctx, zoomedWidth, x0, y, zoomedVals);
|
||||
}
|
||||
|
||||
free(zoomedVals);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Zoom/write 32-bit Z values.
|
||||
* No per-fragment operations are applied.
|
||||
*/
|
||||
void
|
||||
_swrast_write_zoomed_z_span(struct gl_context *ctx, GLint imgX, GLint imgY,
|
||||
GLint width, GLint spanX, GLint spanY,
|
||||
const GLuint *zVals)
|
||||
{
|
||||
struct gl_renderbuffer *rb =
|
||||
ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
|
||||
GLuint *zoomedVals;
|
||||
GLint x0, x1, y0, y1, y;
|
||||
GLint i, zoomedWidth;
|
||||
|
||||
if (!compute_zoomed_bounds(ctx, imgX, imgY, spanX, spanY, width,
|
||||
&x0, &x1, &y0, &y1)) {
|
||||
return; /* totally clipped */
|
||||
}
|
||||
|
||||
zoomedWidth = x1 - x0;
|
||||
assert(zoomedWidth > 0);
|
||||
assert(zoomedWidth <= SWRAST_MAX_WIDTH);
|
||||
|
||||
zoomedVals = malloc(zoomedWidth * sizeof(GLuint));
|
||||
if (!zoomedVals)
|
||||
return;
|
||||
|
||||
/* zoom the span horizontally */
|
||||
for (i = 0; i < zoomedWidth; i++) {
|
||||
GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - spanX;
|
||||
assert(j >= 0);
|
||||
assert(j < width);
|
||||
zoomedVals[i] = zVals[j];
|
||||
}
|
||||
|
||||
/* write the zoomed spans */
|
||||
for (y = y0; y < y1; y++) {
|
||||
GLubyte *dst = _swrast_pixel_address(rb, x0, y);
|
||||
_mesa_pack_uint_z_row(rb->Format, zoomedWidth, zoomedVals, dst);
|
||||
}
|
||||
|
||||
free(zoomedVals);
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* Copyright (C) 1999-2005 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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 S_ZOOM_H
|
||||
#define S_ZOOM_H
|
||||
|
||||
#include "main/mtypes.h"
|
||||
#include "s_span.h"
|
||||
|
||||
|
||||
extern void
|
||||
_swrast_write_zoomed_rgba_span(struct gl_context *ctx, GLint imgX, GLint imgY,
|
||||
const SWspan *span, const GLvoid *rgba);
|
||||
|
||||
extern void
|
||||
_swrast_write_zoomed_rgb_span(struct gl_context *ctx, GLint imgX, GLint imgY,
|
||||
const SWspan *span, const GLvoid *rgb);
|
||||
|
||||
extern void
|
||||
_swrast_write_zoomed_depth_span(struct gl_context *ctx, GLint imgX, GLint imgY,
|
||||
const SWspan *span);
|
||||
|
||||
|
||||
extern void
|
||||
_swrast_write_zoomed_stencil_span(struct gl_context *ctx, GLint imgX, GLint imgY,
|
||||
GLint width, GLint spanX, GLint spanY,
|
||||
const GLubyte stencil[]);
|
||||
|
||||
extern void
|
||||
_swrast_write_zoomed_z_span(struct gl_context *ctx, GLint imgX, GLint imgY,
|
||||
GLint width, GLint spanX, GLint spanY,
|
||||
const GLuint *zVals);
|
||||
|
||||
|
||||
#endif
|
|
@ -1,301 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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 swrast/swrast.h
|
||||
* \brief Public interface to the software rasterization functions.
|
||||
* \author Keith Whitwell <keithw@vmware.com>
|
||||
*/
|
||||
|
||||
#ifndef SWRAST_H
|
||||
#define SWRAST_H
|
||||
|
||||
#include "main/mtypes.h"
|
||||
#include "swrast/s_chan.h"
|
||||
|
||||
|
||||
/**
|
||||
* If non-zero use GLdouble for walking triangle edges, for better accuracy.
|
||||
*/
|
||||
#define TRIANGLE_WALK_DOUBLE 0
|
||||
|
||||
|
||||
/**
|
||||
* Bits per depth buffer value (max is 32).
|
||||
*/
|
||||
#ifndef DEFAULT_SOFTWARE_DEPTH_BITS
|
||||
#define DEFAULT_SOFTWARE_DEPTH_BITS 16
|
||||
#endif
|
||||
/** Depth buffer data type */
|
||||
#if DEFAULT_SOFTWARE_DEPTH_BITS <= 16
|
||||
#define DEFAULT_SOFTWARE_DEPTH_TYPE GLushort
|
||||
#else
|
||||
#define DEFAULT_SOFTWARE_DEPTH_TYPE GLuint
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Max image/surface/texture size.
|
||||
*/
|
||||
#define SWRAST_MAX_WIDTH 16384
|
||||
#define SWRAST_MAX_HEIGHT 16384
|
||||
|
||||
|
||||
/**
|
||||
* \struct SWvertex
|
||||
* \brief Data-structure to handle vertices in the software rasterizer.
|
||||
*
|
||||
* The software rasterizer now uses this format for vertices. Thus a
|
||||
* 'RasterSetup' stage or other translation is required between the
|
||||
* tnl module and the swrast rasterization functions. This serves to
|
||||
* isolate the swrast module from the internals of the tnl module, and
|
||||
* improve its usefulness as a fallback mechanism for hardware
|
||||
* drivers.
|
||||
*
|
||||
* wpos = attr[VARYING_SLOT_POS] and MUST BE THE FIRST values in the
|
||||
* vertex because of the tnl clipping code.
|
||||
|
||||
* wpos[0] and [1] are the screen-coords of SWvertex.
|
||||
* wpos[2] is the z-buffer coord (if 16-bit Z buffer, in range [0,65535]).
|
||||
* wpos[3] is 1/w where w is the clip-space W coord. This is the value
|
||||
* that clip{XYZ} were multiplied by to get ndc{XYZ}.
|
||||
*
|
||||
* Full software drivers:
|
||||
* - Register the rastersetup and triangle functions from
|
||||
* utils/software_helper.
|
||||
* - On statechange, update the rasterization pointers in that module.
|
||||
*
|
||||
* Rasterization hardware drivers:
|
||||
* - Keep native rastersetup.
|
||||
* - Implement native twoside,offset and unfilled triangle setup.
|
||||
* - Implement a translator from native vertices to swrast vertices.
|
||||
* - On partial fallback (mix of accelerated and unaccelerated
|
||||
* prims), call a pass-through function which translates native
|
||||
* vertices to SWvertices and calls the appropriate swrast function.
|
||||
* - On total fallback (vertex format insufficient for state or all
|
||||
* primitives unaccelerated), hook in swrast_setup instead.
|
||||
*/
|
||||
typedef struct {
|
||||
GLfloat attrib[VARYING_SLOT_MAX][4];
|
||||
GLchan color[4]; /** integer color */
|
||||
GLfloat pointSize;
|
||||
} SWvertex;
|
||||
|
||||
|
||||
#define VARYING_SLOT_CI VARYING_SLOT_COL0
|
||||
|
||||
|
||||
struct swrast_device_driver;
|
||||
|
||||
|
||||
/* These are the public-access functions exported from swrast.
|
||||
*/
|
||||
|
||||
extern GLboolean
|
||||
_swrast_CreateContext( struct gl_context *ctx );
|
||||
|
||||
extern void
|
||||
_swrast_DestroyContext( struct gl_context *ctx );
|
||||
|
||||
/* Get a (non-const) reference to the device driver struct for swrast.
|
||||
*/
|
||||
extern struct swrast_device_driver *
|
||||
_swrast_GetDeviceDriverReference( struct gl_context *ctx );
|
||||
|
||||
extern void
|
||||
_swrast_Bitmap( struct gl_context *ctx,
|
||||
GLint px, GLint py,
|
||||
GLsizei width, GLsizei height,
|
||||
const struct gl_pixelstore_attrib *unpack,
|
||||
const GLubyte *bitmap );
|
||||
|
||||
extern void
|
||||
_swrast_CopyPixels(struct gl_context *ctx,
|
||||
GLint srcx, GLint srcy,
|
||||
GLint destx, GLint desty,
|
||||
GLsizei width, GLsizei height,
|
||||
GLenum type);
|
||||
|
||||
extern GLboolean
|
||||
swrast_fast_copy_pixels(struct gl_context *ctx,
|
||||
struct gl_framebuffer *srcFb,
|
||||
struct gl_framebuffer *dstFb,
|
||||
GLint srcX, GLint srcY, GLsizei width, GLsizei height,
|
||||
GLint dstX, GLint dstY, GLenum type);
|
||||
|
||||
extern void
|
||||
_swrast_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
|
||||
_swrast_BlitFramebuffer(struct gl_context *ctx,
|
||||
struct gl_framebuffer *readFb,
|
||||
struct gl_framebuffer *drawFb,
|
||||
GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
|
||||
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
|
||||
GLbitfield mask, GLenum filter);
|
||||
|
||||
extern void
|
||||
_swrast_Clear(struct gl_context *ctx, GLbitfield buffers);
|
||||
|
||||
|
||||
|
||||
/* Reset the stipple counter
|
||||
*/
|
||||
extern void
|
||||
_swrast_ResetLineStipple( struct gl_context *ctx );
|
||||
|
||||
/**
|
||||
* Indicates front/back facing for subsequent points/lines when drawing
|
||||
* unfilled polygons. Needed for two-side stencil.
|
||||
*/
|
||||
extern void
|
||||
_swrast_SetFacing(struct gl_context *ctx, GLuint facing);
|
||||
|
||||
/* These will always render the correct point/line/triangle for the
|
||||
* current state.
|
||||
*
|
||||
* For flatshaded primitives, the provoking vertex is the final one.
|
||||
*/
|
||||
extern void
|
||||
_swrast_Point( struct gl_context *ctx, const SWvertex *v );
|
||||
|
||||
extern void
|
||||
_swrast_Line( struct gl_context *ctx, const SWvertex *v0, const SWvertex *v1 );
|
||||
|
||||
extern void
|
||||
_swrast_Triangle( struct gl_context *ctx, const SWvertex *v0,
|
||||
const SWvertex *v1, const SWvertex *v2 );
|
||||
|
||||
extern void
|
||||
_swrast_Quad( struct gl_context *ctx,
|
||||
const SWvertex *v0, const SWvertex *v1,
|
||||
const SWvertex *v2, const SWvertex *v3);
|
||||
|
||||
extern void
|
||||
_swrast_flush( struct gl_context *ctx );
|
||||
|
||||
extern void
|
||||
_swrast_render_primitive( struct gl_context *ctx, GLenum mode );
|
||||
|
||||
extern void
|
||||
_swrast_render_start( struct gl_context *ctx );
|
||||
|
||||
extern void
|
||||
_swrast_render_finish( struct gl_context *ctx );
|
||||
|
||||
extern struct gl_texture_image *
|
||||
_swrast_new_texture_image( struct gl_context *ctx );
|
||||
|
||||
extern void
|
||||
_swrast_delete_texture_image(struct gl_context *ctx,
|
||||
struct gl_texture_image *texImage);
|
||||
|
||||
extern GLboolean
|
||||
_swrast_alloc_texture_image_buffer(struct gl_context *ctx,
|
||||
struct gl_texture_image *texImage);
|
||||
|
||||
extern GLboolean
|
||||
_swrast_init_texture_image(struct gl_texture_image *texImage);
|
||||
|
||||
extern void
|
||||
_swrast_free_texture_image_buffer(struct gl_context *ctx,
|
||||
struct gl_texture_image *texImage);
|
||||
|
||||
extern void
|
||||
_swrast_map_teximage(struct gl_context *ctx,
|
||||
struct gl_texture_image *texImage,
|
||||
GLuint slice,
|
||||
GLuint x, GLuint y, GLuint w, GLuint h,
|
||||
GLbitfield mode,
|
||||
GLubyte **mapOut,
|
||||
GLint *rowStrideOut);
|
||||
|
||||
extern void
|
||||
_swrast_unmap_teximage(struct gl_context *ctx,
|
||||
struct gl_texture_image *texImage,
|
||||
GLuint slice);
|
||||
|
||||
/* Tell the software rasterizer about core state changes.
|
||||
*/
|
||||
extern void
|
||||
_swrast_InvalidateState( struct gl_context *ctx, GLbitfield new_state );
|
||||
|
||||
/* Configure software rasterizer to match hardware rasterizer characteristics:
|
||||
*/
|
||||
extern void
|
||||
_swrast_allow_vertex_fog( struct gl_context *ctx, GLboolean value );
|
||||
|
||||
extern void
|
||||
_swrast_allow_pixel_fog( struct gl_context *ctx, GLboolean value );
|
||||
|
||||
/* Debug:
|
||||
*/
|
||||
extern void
|
||||
_swrast_print_vertex( struct gl_context *ctx, const SWvertex *v );
|
||||
|
||||
|
||||
|
||||
extern void
|
||||
_swrast_eject_texture_images(struct gl_context *ctx);
|
||||
|
||||
|
||||
extern void
|
||||
_swrast_render_texture(struct gl_context *ctx,
|
||||
struct gl_framebuffer *fb,
|
||||
struct gl_renderbuffer_attachment *att);
|
||||
|
||||
extern void
|
||||
_swrast_finish_render_texture(struct gl_context *ctx,
|
||||
struct gl_renderbuffer *rb);
|
||||
|
||||
|
||||
/**
|
||||
* The driver interface for the software rasterizer.
|
||||
* XXX this may go away.
|
||||
* We may move these functions to ctx->Driver.RenderStart, RenderEnd.
|
||||
*/
|
||||
struct swrast_device_driver {
|
||||
/*
|
||||
* These are called before and after accessing renderbuffers during
|
||||
* software rasterization.
|
||||
*
|
||||
* These are a suitable place for grabbing/releasing hardware locks.
|
||||
*
|
||||
* NOTE: The swrast triangle/line/point routines *DO NOT* call
|
||||
* these functions. Locking in that case must be organized by the
|
||||
* driver by other mechanisms.
|
||||
*/
|
||||
void (*SpanRenderStart)(struct gl_context *ctx);
|
||||
void (*SpanRenderFinish)(struct gl_context *ctx);
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -1,65 +0,0 @@
|
|||
INTRODUCTION
|
||||
|
||||
A helper module which provides glue to bind the software rasterizer to
|
||||
the software t&l module. The main task of this module is to build
|
||||
swrast vertices from the t&l vertex_buffer structs, and to use them to
|
||||
perform triangle setup functions not implemented in the software
|
||||
rasterizer.
|
||||
|
||||
The module implements a full set of functions to plug into the
|
||||
t_vb_render.c driver interface (tnl->Driver.Render.*).
|
||||
|
||||
There are strong advantages to decoupling the software rasterizer from
|
||||
the t&l module, primarily allowing hardware drivers better control
|
||||
over fallbacks, the removal of implicit knowledge about the software
|
||||
rasterizer in the t&l module, allowing the two modules to evolve
|
||||
independently and allowing either to be substituted with equivalent
|
||||
functionality from another codebase.
|
||||
|
||||
This module implements triangle/quad setup for offset, unfilled and
|
||||
twoside-lit triangles. The software rasterizer doesn't handle these
|
||||
primitives directly.
|
||||
|
||||
Hardware rasterization drivers typically use this module in situations
|
||||
where no hardware rasterization is possible, ie during total
|
||||
fallbacks.
|
||||
|
||||
STATE
|
||||
|
||||
To create and destroy the module:
|
||||
|
||||
GLboolean _swsetup_CreateContext( struct gl_context *ctx );
|
||||
void _swsetup_DestroyContext( struct gl_context *ctx );
|
||||
|
||||
The module is not active by default, and must be installed by calling
|
||||
_swrast_Wakeup(). This function installs internal swrast_setup
|
||||
functions into all the tnl->Driver.Render driver hooks, thus taking
|
||||
over the task of rasterization entirely:
|
||||
|
||||
void _swrast_Wakeup( struct gl_context *ctx );
|
||||
|
||||
|
||||
This module tracks state changes internally and maintains derived
|
||||
values based on the current state. For this to work, the driver
|
||||
ensure the following funciton is called whenever the state changes and
|
||||
the swsetup module is 'awake':
|
||||
|
||||
void _swsetup_InvalidateState( struct gl_context *ctx, GLuint new_state );
|
||||
|
||||
There is no explicit call to put the swsetup module to sleep. Simply
|
||||
install other function pointers into all the tnl->Driver.Render.*
|
||||
hooks, and (optionally) cease calling _swsetup_InvalidateState().
|
||||
|
||||
DRIVER INTERFACE
|
||||
|
||||
The module offers a minimal driver interface:
|
||||
|
||||
void (*Start)( struct gl_context *ctx );
|
||||
void (*Finish)( struct gl_context *ctx );
|
||||
|
||||
These are called before and after the completion of all swrast drawing
|
||||
activity. As swrast doesn't call callbacks during triangle, line or
|
||||
point rasterization, these are necessary to provide locking hooks for
|
||||
some drivers. They may otherwise be left null.
|
||||
|
||||
|
|
@ -1,305 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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@vmware.com>
|
||||
*/
|
||||
|
||||
#include "main/glheader.h"
|
||||
|
||||
#include "main/macros.h"
|
||||
#include "main/state.h"
|
||||
#include "tnl/tnl.h"
|
||||
#include "tnl/t_context.h"
|
||||
#include "tnl/t_pipeline.h"
|
||||
#include "tnl/t_vertex.h"
|
||||
#include "swrast_setup.h"
|
||||
#include "ss_context.h"
|
||||
#include "ss_triangle.h"
|
||||
|
||||
|
||||
/* Need to check lighting state and vertex program state to know
|
||||
* if two-sided lighting is in effect.
|
||||
*/
|
||||
#define _SWSETUP_NEW_RENDERINDEX (_NEW_POLYGON|_NEW_LIGHT|_NEW_PROGRAM)
|
||||
|
||||
|
||||
#define VARYING_EMIT_STYLE EMIT_4F
|
||||
|
||||
|
||||
GLboolean
|
||||
_swsetup_CreateContext( struct gl_context *ctx )
|
||||
{
|
||||
SScontext *swsetup = calloc(1, sizeof(SScontext));
|
||||
|
||||
if (!swsetup)
|
||||
return GL_FALSE;
|
||||
|
||||
ctx->swsetup_context = swsetup;
|
||||
|
||||
swsetup->NewState = ~0;
|
||||
_swsetup_trifuncs_init( ctx );
|
||||
|
||||
_tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12,
|
||||
sizeof(SWvertex) );
|
||||
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
_swsetup_DestroyContext( struct gl_context *ctx )
|
||||
{
|
||||
SScontext *swsetup = SWSETUP_CONTEXT(ctx);
|
||||
|
||||
if (swsetup) {
|
||||
free(swsetup);
|
||||
ctx->swsetup_context = 0;
|
||||
}
|
||||
|
||||
_tnl_free_vertices( ctx );
|
||||
}
|
||||
|
||||
static void
|
||||
_swsetup_RenderPrimitive( struct gl_context *ctx, GLenum mode )
|
||||
{
|
||||
SWSETUP_CONTEXT(ctx)->render_prim = mode;
|
||||
_swrast_render_primitive( ctx, mode );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helper macros for setup_vertex_format()
|
||||
*/
|
||||
#define SWZ ((SWvertex *)0)
|
||||
#define SWOffset(MEMBER) (((char *)&(SWZ->MEMBER)) - ((char *)SWZ))
|
||||
|
||||
#define EMIT_ATTR( ATTR, STYLE, MEMBER ) \
|
||||
do { \
|
||||
map[e].attrib = (ATTR); \
|
||||
map[e].format = (STYLE); \
|
||||
map[e].offset = SWOffset(MEMBER); \
|
||||
e++; \
|
||||
} while (0)
|
||||
|
||||
|
||||
/**
|
||||
* Tell the tnl module how to build SWvertex objects for swrast.
|
||||
* We'll build the map[] array with that info and pass it to
|
||||
* _tnl_install_attrs().
|
||||
*/
|
||||
static void
|
||||
setup_vertex_format(struct gl_context *ctx)
|
||||
{
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
SScontext *swsetup = SWSETUP_CONTEXT(ctx);
|
||||
GLboolean intColors = !ctx->FragmentProgram._Current
|
||||
&& !_mesa_ati_fragment_shader_enabled(ctx)
|
||||
&& ctx->RenderMode == GL_RENDER
|
||||
&& CHAN_TYPE != GL_FLOAT;
|
||||
|
||||
if (intColors != swsetup->intColors ||
|
||||
tnl->render_inputs_bitset != swsetup->last_index_bitset) {
|
||||
GLbitfield64 index_bitset = tnl->render_inputs_bitset;
|
||||
struct tnl_attr_map map[_TNL_ATTRIB_MAX];
|
||||
unsigned int i, e = 0;
|
||||
|
||||
swsetup->intColors = intColors;
|
||||
|
||||
EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, attrib[VARYING_SLOT_POS] );
|
||||
|
||||
if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_COLOR0)) {
|
||||
if (swsetup->intColors)
|
||||
EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4CHAN_4F_RGBA, color );
|
||||
else
|
||||
EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4F, attrib[VARYING_SLOT_COL0]);
|
||||
}
|
||||
|
||||
if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_COLOR1)) {
|
||||
EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_4F, attrib[VARYING_SLOT_COL1]);
|
||||
}
|
||||
|
||||
if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_FOG)) {
|
||||
const GLint emit = ctx->FragmentProgram._Current ? EMIT_4F : EMIT_1F;
|
||||
EMIT_ATTR( _TNL_ATTRIB_FOG, emit, attrib[VARYING_SLOT_FOGC]);
|
||||
}
|
||||
|
||||
if (index_bitset & BITFIELD64_RANGE(_TNL_ATTRIB_TEX0, _TNL_NUM_TEX))
|
||||
{
|
||||
for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++) {
|
||||
if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_TEX(i))) {
|
||||
EMIT_ATTR( _TNL_ATTRIB_TEX(i), EMIT_4F,
|
||||
attrib[VARYING_SLOT_TEX0 + i] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* shader varying vars */
|
||||
if (index_bitset & BITFIELD64_RANGE(_TNL_ATTRIB_GENERIC0, _TNL_NUM_GENERIC)) {
|
||||
for (i = 0; i < ctx->Const.MaxVarying; i++) {
|
||||
if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_GENERIC(i))) {
|
||||
EMIT_ATTR( _TNL_ATTRIB_GENERIC(i), VARYING_EMIT_STYLE,
|
||||
attrib[VARYING_SLOT_VAR0 + i] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_POINTSIZE))
|
||||
EMIT_ATTR( _TNL_ATTRIB_POINTSIZE, EMIT_1F, pointSize );
|
||||
|
||||
_tnl_install_attrs( ctx, map, e,
|
||||
tnl->_WindowMap.m,
|
||||
sizeof(SWvertex) );
|
||||
|
||||
swsetup->last_index_bitset = index_bitset;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Prepare to render a vertex buffer.
|
||||
* Called via tnl->Driver.Render.Start.
|
||||
*/
|
||||
static void
|
||||
_swsetup_RenderStart( struct gl_context *ctx )
|
||||
{
|
||||
SScontext *swsetup = SWSETUP_CONTEXT(ctx);
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
struct vertex_buffer *VB = &tnl->vb;
|
||||
|
||||
if (swsetup->NewState & _SWSETUP_NEW_RENDERINDEX) {
|
||||
_swsetup_choose_trifuncs(ctx);
|
||||
}
|
||||
|
||||
if (swsetup->NewState & _NEW_PROGRAM) {
|
||||
swsetup->last_index_bitset = 0;
|
||||
}
|
||||
|
||||
swsetup->NewState = 0;
|
||||
|
||||
/* This will change if drawing unfilled tris */
|
||||
_swrast_SetFacing(ctx, 0);
|
||||
|
||||
_swrast_render_start(ctx);
|
||||
|
||||
/* Important */
|
||||
VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr;
|
||||
|
||||
setup_vertex_format(ctx);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* We patch this function into tnl->Driver.Render.Finish.
|
||||
* It's called when we finish rendering a vertex buffer.
|
||||
*/
|
||||
static void
|
||||
_swsetup_RenderFinish( struct gl_context *ctx )
|
||||
{
|
||||
_swrast_render_finish( ctx );
|
||||
}
|
||||
|
||||
void
|
||||
_swsetup_InvalidateState( struct gl_context *ctx, GLuint new_state )
|
||||
{
|
||||
SScontext *swsetup = SWSETUP_CONTEXT(ctx);
|
||||
swsetup->NewState |= new_state;
|
||||
_tnl_invalidate_vertex_state( ctx, new_state );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_swsetup_Wakeup( struct gl_context *ctx )
|
||||
{
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
SScontext *swsetup = SWSETUP_CONTEXT(ctx);
|
||||
|
||||
tnl->Driver.Render.Start = _swsetup_RenderStart;
|
||||
tnl->Driver.Render.Finish = _swsetup_RenderFinish;
|
||||
tnl->Driver.Render.PrimitiveNotify = _swsetup_RenderPrimitive;
|
||||
tnl->Driver.Render.Interp = _tnl_interp;
|
||||
tnl->Driver.Render.CopyPV = _tnl_copy_pv;
|
||||
tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon; /* new */
|
||||
tnl->Driver.Render.ClippedLine = _tnl_RenderClippedLine; /* new */
|
||||
/* points */
|
||||
/* line */
|
||||
/* triangle */
|
||||
/* quad */
|
||||
tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
|
||||
tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
|
||||
tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple;
|
||||
tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
|
||||
tnl->Driver.Render.Multipass = 0;
|
||||
|
||||
_tnl_invalidate_vertices( ctx, ~0 );
|
||||
_tnl_need_projected_coords( ctx, GL_TRUE );
|
||||
_swsetup_InvalidateState( ctx, ~0 );
|
||||
|
||||
swsetup->verts = (SWvertex *)tnl->clipspace.vertex_buf;
|
||||
swsetup->last_index_bitset = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Populate a swrast SWvertex from an attrib-style vertex.
|
||||
*/
|
||||
void
|
||||
_swsetup_Translate( struct gl_context *ctx, const void *vertex, SWvertex *dest )
|
||||
{
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
const GLfloat *m = tnl->_WindowMap.m;
|
||||
GLfloat tmp[4];
|
||||
GLuint i;
|
||||
|
||||
_tnl_get_attr( ctx, vertex, _TNL_ATTRIB_POS, tmp );
|
||||
|
||||
dest->attrib[VARYING_SLOT_POS][0] = m[0] * tmp[0] + m[12];
|
||||
dest->attrib[VARYING_SLOT_POS][1] = m[5] * tmp[1] + m[13];
|
||||
dest->attrib[VARYING_SLOT_POS][2] = m[10] * tmp[2] + m[14];
|
||||
dest->attrib[VARYING_SLOT_POS][3] = tmp[3];
|
||||
|
||||
/** XXX try to limit these loops someday */
|
||||
for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++)
|
||||
_tnl_get_attr( ctx, vertex, _TNL_ATTRIB_TEX0 + i,
|
||||
dest->attrib[VARYING_SLOT_TEX0 + i] );
|
||||
|
||||
for (i = 0 ; i < ctx->Const.MaxVarying ; i++)
|
||||
_tnl_get_attr( ctx, vertex, _TNL_ATTRIB_GENERIC0 + i,
|
||||
dest->attrib[VARYING_SLOT_VAR0 + i] );
|
||||
|
||||
_tnl_get_attr( ctx, vertex, _TNL_ATTRIB_COLOR0,
|
||||
dest->attrib[VARYING_SLOT_COL0] );
|
||||
|
||||
UNCLAMPED_FLOAT_TO_RGBA_CHAN(dest->color, dest->attrib[VARYING_SLOT_COL0]);
|
||||
|
||||
_tnl_get_attr( ctx, vertex, _TNL_ATTRIB_COLOR1,
|
||||
dest->attrib[VARYING_SLOT_COL1]);
|
||||
|
||||
_tnl_get_attr( ctx, vertex, _TNL_ATTRIB_FOG, tmp );
|
||||
dest->attrib[VARYING_SLOT_FOGC][0] = tmp[0];
|
||||
|
||||
/* XXX See _tnl_get_attr about pointsize ... */
|
||||
_tnl_get_attr( ctx, vertex, _TNL_ATTRIB_POINTSIZE, tmp );
|
||||
dest->pointSize = tmp[0];
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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@vmware.com>
|
||||
*/
|
||||
|
||||
#ifndef SS_CONTEXT_H
|
||||
#define SS_CONTEXT_H
|
||||
|
||||
#include "main/glheader.h"
|
||||
#include "swrast/swrast.h"
|
||||
#include "tnl/t_context.h"
|
||||
|
||||
typedef struct {
|
||||
GLuint NewState;
|
||||
GLenum render_prim;
|
||||
GLbitfield64 last_index_bitset;
|
||||
SWvertex *verts;
|
||||
GLboolean intColors;
|
||||
} SScontext;
|
||||
|
||||
#define SWSETUP_CONTEXT(ctx) ((SScontext *)ctx->swsetup_context)
|
||||
|
||||
#endif
|
|
@ -1,267 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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@vmware.com>
|
||||
*/
|
||||
|
||||
#include "c99_math.h"
|
||||
#include "main/glheader.h"
|
||||
#include "main/macros.h"
|
||||
#include "main/mtypes.h"
|
||||
#include "main/stencil.h"
|
||||
#include "main/state.h"
|
||||
|
||||
#include "tnl/t_context.h"
|
||||
|
||||
#include "ss_triangle.h"
|
||||
#include "ss_context.h"
|
||||
|
||||
#define SS_OFFSET_BIT 0x1
|
||||
#define SS_TWOSIDE_BIT 0x2
|
||||
#define SS_UNFILLED_BIT 0x4
|
||||
#define SS_MAX_TRIFUNC 0x8
|
||||
|
||||
static tnl_triangle_func tri_tab[SS_MAX_TRIFUNC];
|
||||
static tnl_quad_func quad_tab[SS_MAX_TRIFUNC];
|
||||
|
||||
|
||||
/*
|
||||
* Render a triangle respecting edge flags.
|
||||
*/
|
||||
typedef void (* swsetup_edge_render_prim_tri)(struct gl_context *ctx,
|
||||
const GLubyte *ef,
|
||||
GLuint e0,
|
||||
GLuint e1,
|
||||
GLuint e2,
|
||||
const SWvertex *v0,
|
||||
const SWvertex *v1,
|
||||
const SWvertex *v2);
|
||||
|
||||
/*
|
||||
* Render a triangle using lines and respecting edge flags.
|
||||
*/
|
||||
static void
|
||||
_swsetup_edge_render_line_tri(struct gl_context *ctx,
|
||||
const GLubyte *ef,
|
||||
GLuint e0,
|
||||
GLuint e1,
|
||||
GLuint e2,
|
||||
const SWvertex *v0,
|
||||
const SWvertex *v1,
|
||||
const SWvertex *v2)
|
||||
{
|
||||
SScontext *swsetup = SWSETUP_CONTEXT(ctx);
|
||||
|
||||
if (swsetup->render_prim == GL_POLYGON) {
|
||||
if (ef[e2]) _swrast_Line( ctx, v2, v0 );
|
||||
if (ef[e0]) _swrast_Line( ctx, v0, v1 );
|
||||
if (ef[e1]) _swrast_Line( ctx, v1, v2 );
|
||||
} else {
|
||||
if (ef[e0]) _swrast_Line( ctx, v0, v1 );
|
||||
if (ef[e1]) _swrast_Line( ctx, v1, v2 );
|
||||
if (ef[e2]) _swrast_Line( ctx, v2, v0 );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Render a triangle using points and respecting edge flags.
|
||||
*/
|
||||
static void
|
||||
_swsetup_edge_render_point_tri(struct gl_context *ctx,
|
||||
const GLubyte *ef,
|
||||
GLuint e0,
|
||||
GLuint e1,
|
||||
GLuint e2,
|
||||
const SWvertex *v0,
|
||||
const SWvertex *v1,
|
||||
const SWvertex *v2)
|
||||
{
|
||||
if (ef[e0]) _swrast_Point( ctx, v0 );
|
||||
if (ef[e1]) _swrast_Point( ctx, v1 );
|
||||
if (ef[e2]) _swrast_Point( ctx, v2 );
|
||||
|
||||
_swrast_flush(ctx);
|
||||
}
|
||||
|
||||
/*
|
||||
* Render a triangle respecting cull and shade model.
|
||||
*/
|
||||
static void _swsetup_render_tri(struct gl_context *ctx,
|
||||
GLuint e0,
|
||||
GLuint e1,
|
||||
GLuint e2,
|
||||
GLuint facing,
|
||||
swsetup_edge_render_prim_tri render)
|
||||
{
|
||||
SScontext *swsetup = SWSETUP_CONTEXT(ctx);
|
||||
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
|
||||
GLubyte *ef = VB->EdgeFlag;
|
||||
SWvertex *verts = swsetup->verts;
|
||||
SWvertex *v0 = &verts[e0];
|
||||
SWvertex *v1 = &verts[e1];
|
||||
SWvertex *v2 = &verts[e2];
|
||||
|
||||
/* cull testing */
|
||||
if (ctx->Polygon.CullFlag) {
|
||||
if (facing == 1 && ctx->Polygon.CullFaceMode != GL_FRONT)
|
||||
return;
|
||||
if (facing == 0 && ctx->Polygon.CullFaceMode != GL_BACK)
|
||||
return;
|
||||
}
|
||||
|
||||
_swrast_SetFacing(ctx, facing);
|
||||
|
||||
if (ctx->Light.ShadeModel == GL_FLAT) {
|
||||
GLchan c[2][4];
|
||||
GLfloat s[2][4];
|
||||
|
||||
/* save colors/indexes for v0, v1 vertices */
|
||||
COPY_CHAN4(c[0], v0->color);
|
||||
COPY_CHAN4(c[1], v1->color);
|
||||
COPY_4V(s[0], v0->attrib[VARYING_SLOT_COL1]);
|
||||
COPY_4V(s[1], v1->attrib[VARYING_SLOT_COL1]);
|
||||
|
||||
/* copy v2 color/indexes to v0, v1 indexes */
|
||||
COPY_CHAN4(v0->color, v2->color);
|
||||
COPY_CHAN4(v1->color, v2->color);
|
||||
COPY_4V(v0->attrib[VARYING_SLOT_COL1], v2->attrib[VARYING_SLOT_COL1]);
|
||||
COPY_4V(v1->attrib[VARYING_SLOT_COL1], v2->attrib[VARYING_SLOT_COL1]);
|
||||
|
||||
render(ctx, ef, e0, e1, e2, v0, v1, v2);
|
||||
|
||||
COPY_CHAN4(v0->color, c[0]);
|
||||
COPY_CHAN4(v1->color, c[1]);
|
||||
COPY_4V(v0->attrib[VARYING_SLOT_COL1], s[0]);
|
||||
COPY_4V(v1->attrib[VARYING_SLOT_COL1], s[1]);
|
||||
}
|
||||
else {
|
||||
render(ctx, ef, e0, e1, e2, v0, v1, v2);
|
||||
}
|
||||
}
|
||||
|
||||
#define SS_COLOR(a,b) UNCLAMPED_FLOAT_TO_RGBA_CHAN(a,b)
|
||||
#define SS_SPEC(a,b) COPY_4V(a,b)
|
||||
#define SS_IND(a,b) (a = b)
|
||||
|
||||
#define IND (0)
|
||||
#define TAG(x) x##_rgba
|
||||
#include "ss_tritmp.h"
|
||||
|
||||
#define IND (SS_OFFSET_BIT)
|
||||
#define TAG(x) x##_offset_rgba
|
||||
#include "ss_tritmp.h"
|
||||
|
||||
#define IND (SS_TWOSIDE_BIT)
|
||||
#define TAG(x) x##_twoside_rgba
|
||||
#include "ss_tritmp.h"
|
||||
|
||||
#define IND (SS_OFFSET_BIT|SS_TWOSIDE_BIT)
|
||||
#define TAG(x) x##_offset_twoside_rgba
|
||||
#include "ss_tritmp.h"
|
||||
|
||||
#define IND (SS_UNFILLED_BIT)
|
||||
#define TAG(x) x##_unfilled_rgba
|
||||
#include "ss_tritmp.h"
|
||||
|
||||
#define IND (SS_OFFSET_BIT|SS_UNFILLED_BIT)
|
||||
#define TAG(x) x##_offset_unfilled_rgba
|
||||
#include "ss_tritmp.h"
|
||||
|
||||
#define IND (SS_TWOSIDE_BIT|SS_UNFILLED_BIT)
|
||||
#define TAG(x) x##_twoside_unfilled_rgba
|
||||
#include "ss_tritmp.h"
|
||||
|
||||
#define IND (SS_OFFSET_BIT|SS_TWOSIDE_BIT|SS_UNFILLED_BIT)
|
||||
#define TAG(x) x##_offset_twoside_unfilled_rgba
|
||||
#include "ss_tritmp.h"
|
||||
|
||||
|
||||
void _swsetup_trifuncs_init( struct gl_context *ctx )
|
||||
{
|
||||
(void) ctx;
|
||||
|
||||
init_rgba();
|
||||
init_offset_rgba();
|
||||
init_twoside_rgba();
|
||||
init_offset_twoside_rgba();
|
||||
init_unfilled_rgba();
|
||||
init_offset_unfilled_rgba();
|
||||
init_twoside_unfilled_rgba();
|
||||
init_offset_twoside_unfilled_rgba();
|
||||
}
|
||||
|
||||
|
||||
static void swsetup_points( struct gl_context *ctx, GLuint first, GLuint last )
|
||||
{
|
||||
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
|
||||
SWvertex *verts = SWSETUP_CONTEXT(ctx)->verts;
|
||||
GLuint i;
|
||||
|
||||
if (VB->Elts) {
|
||||
for (i = first; i < last; i++)
|
||||
if (VB->ClipMask[VB->Elts[i]] == 0)
|
||||
_swrast_Point( ctx, &verts[VB->Elts[i]] );
|
||||
}
|
||||
else {
|
||||
for (i = first; i < last; i++)
|
||||
if (VB->ClipMask[i] == 0)
|
||||
_swrast_Point( ctx, &verts[i] );
|
||||
}
|
||||
}
|
||||
|
||||
static void swsetup_line( struct gl_context *ctx, GLuint v0, GLuint v1 )
|
||||
{
|
||||
SWvertex *verts = SWSETUP_CONTEXT(ctx)->verts;
|
||||
_swrast_Line( ctx, &verts[v0], &verts[v1] );
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _swsetup_choose_trifuncs( struct gl_context *ctx )
|
||||
{
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
GLuint ind = 0;
|
||||
|
||||
if (ctx->Polygon.OffsetPoint ||
|
||||
ctx->Polygon.OffsetLine ||
|
||||
ctx->Polygon.OffsetFill)
|
||||
ind |= SS_OFFSET_BIT;
|
||||
|
||||
if ((ctx->Light.Enabled && ctx->Light.Model.TwoSide) ||
|
||||
(ctx->VertexProgram._Current && ctx->VertexProgram.TwoSideEnabled))
|
||||
ind |= SS_TWOSIDE_BIT;
|
||||
|
||||
/* We piggyback the two-sided stencil front/back determination on the
|
||||
* unfilled triangle path.
|
||||
*/
|
||||
if (ctx->Polygon.FrontMode != GL_FILL ||
|
||||
ctx->Polygon.BackMode != GL_FILL ||
|
||||
(ctx->Stencil.Enabled && _mesa_stencil_is_two_sided(ctx)))
|
||||
ind |= SS_UNFILLED_BIT;
|
||||
|
||||
tnl->Driver.Render.Triangle = tri_tab[ind];
|
||||
tnl->Driver.Render.Quad = quad_tab[ind];
|
||||
tnl->Driver.Render.Line = swsetup_line;
|
||||
tnl->Driver.Render.Points = swsetup_points;
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
|
||||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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@vmware.com>
|
||||
*/
|
||||
|
||||
#ifndef SS_TRIANGLE_H
|
||||
#define SS_TRIANGLE_H
|
||||
|
||||
struct gl_context;
|
||||
|
||||
|
||||
void _swsetup_trifuncs_init( struct gl_context *ctx );
|
||||
void _swsetup_choose_trifuncs( struct gl_context *ctx );
|
||||
|
||||
#endif
|
|
@ -1,248 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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@vmware.com>
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* This is where we handle assigning vertex colors based on front/back
|
||||
* facing, compute polygon offset and handle glPolygonMode().
|
||||
*/
|
||||
static void TAG(triangle)(struct gl_context *ctx, GLuint e0, GLuint e1, GLuint e2 )
|
||||
{
|
||||
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
|
||||
SScontext *swsetup = SWSETUP_CONTEXT(ctx);
|
||||
SWvertex *verts = SWSETUP_CONTEXT(ctx)->verts;
|
||||
SWvertex *v[3];
|
||||
GLfloat z[3];
|
||||
GLfloat offset, oz0, oz1, oz2;
|
||||
GLenum mode = GL_FILL;
|
||||
GLuint facing = 0;
|
||||
GLchan saved_color[3][4] = { { 0 } };
|
||||
GLfloat saved_col0[3][4] = { { 0 } };
|
||||
GLfloat saved_spec[3][4] = { { 0 } };
|
||||
|
||||
v[0] = &verts[e0];
|
||||
v[1] = &verts[e1];
|
||||
v[2] = &verts[e2];
|
||||
|
||||
if (IND & (SS_TWOSIDE_BIT | SS_OFFSET_BIT | SS_UNFILLED_BIT))
|
||||
{
|
||||
GLfloat ex = v[0]->attrib[VARYING_SLOT_POS][0] - v[2]->attrib[VARYING_SLOT_POS][0];
|
||||
GLfloat ey = v[0]->attrib[VARYING_SLOT_POS][1] - v[2]->attrib[VARYING_SLOT_POS][1];
|
||||
GLfloat fx = v[1]->attrib[VARYING_SLOT_POS][0] - v[2]->attrib[VARYING_SLOT_POS][0];
|
||||
GLfloat fy = v[1]->attrib[VARYING_SLOT_POS][1] - v[2]->attrib[VARYING_SLOT_POS][1];
|
||||
GLfloat cc = ex*fy - ey*fx;
|
||||
|
||||
if (IND & (SS_TWOSIDE_BIT | SS_UNFILLED_BIT))
|
||||
{
|
||||
facing = (cc < 0.0F) ^ _mesa_polygon_get_front_bit(ctx);
|
||||
|
||||
if (IND & SS_UNFILLED_BIT)
|
||||
mode = facing ? ctx->Polygon.BackMode : ctx->Polygon.FrontMode;
|
||||
|
||||
if (facing == 1) {
|
||||
if (IND & SS_TWOSIDE_BIT) {
|
||||
if (VB->BackfaceColorPtr) {
|
||||
GLfloat (*vbcolor)[4] = VB->BackfaceColorPtr->data;
|
||||
|
||||
if (swsetup->intColors) {
|
||||
COPY_CHAN4(saved_color[0], v[0]->color);
|
||||
COPY_CHAN4(saved_color[1], v[1]->color);
|
||||
COPY_CHAN4(saved_color[2], v[2]->color);
|
||||
}
|
||||
else {
|
||||
COPY_4V(saved_col0[0], v[0]->attrib[VARYING_SLOT_COL0]);
|
||||
COPY_4V(saved_col0[1], v[1]->attrib[VARYING_SLOT_COL0]);
|
||||
COPY_4V(saved_col0[2], v[2]->attrib[VARYING_SLOT_COL0]);
|
||||
}
|
||||
|
||||
if (VB->BackfaceColorPtr->stride) {
|
||||
if (swsetup->intColors) {
|
||||
SS_COLOR(v[0]->color, vbcolor[e0]);
|
||||
SS_COLOR(v[1]->color, vbcolor[e1]);
|
||||
SS_COLOR(v[2]->color, vbcolor[e2]);
|
||||
}
|
||||
else {
|
||||
COPY_4V(v[0]->attrib[VARYING_SLOT_COL0], vbcolor[e0]);
|
||||
COPY_4V(v[1]->attrib[VARYING_SLOT_COL0], vbcolor[e1]);
|
||||
COPY_4V(v[2]->attrib[VARYING_SLOT_COL0], vbcolor[e2]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* flat shade */
|
||||
if (swsetup->intColors) {
|
||||
SS_COLOR(v[0]->color, vbcolor[0]);
|
||||
SS_COLOR(v[1]->color, vbcolor[0]);
|
||||
SS_COLOR(v[2]->color, vbcolor[0]);
|
||||
}
|
||||
else {
|
||||
COPY_4V(v[0]->attrib[VARYING_SLOT_COL0], vbcolor[0]);
|
||||
COPY_4V(v[1]->attrib[VARYING_SLOT_COL0], vbcolor[0]);
|
||||
COPY_4V(v[2]->attrib[VARYING_SLOT_COL0], vbcolor[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (VB->BackfaceSecondaryColorPtr) {
|
||||
GLfloat (*vbspec)[4] = VB->BackfaceSecondaryColorPtr->data;
|
||||
|
||||
COPY_4V(saved_spec[0], v[0]->attrib[VARYING_SLOT_COL1]);
|
||||
COPY_4V(saved_spec[1], v[1]->attrib[VARYING_SLOT_COL1]);
|
||||
COPY_4V(saved_spec[2], v[2]->attrib[VARYING_SLOT_COL1]);
|
||||
|
||||
if (VB->BackfaceSecondaryColorPtr->stride) {
|
||||
SS_SPEC(v[0]->attrib[VARYING_SLOT_COL1], vbspec[e0]);
|
||||
SS_SPEC(v[1]->attrib[VARYING_SLOT_COL1], vbspec[e1]);
|
||||
SS_SPEC(v[2]->attrib[VARYING_SLOT_COL1], vbspec[e2]);
|
||||
}
|
||||
else {
|
||||
SS_SPEC(v[0]->attrib[VARYING_SLOT_COL1], vbspec[0]);
|
||||
SS_SPEC(v[1]->attrib[VARYING_SLOT_COL1], vbspec[0]);
|
||||
SS_SPEC(v[2]->attrib[VARYING_SLOT_COL1], vbspec[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (IND & SS_OFFSET_BIT) {
|
||||
const GLfloat max = ctx->DrawBuffer->_DepthMaxF;
|
||||
/* save original Z values (restored later) */
|
||||
z[0] = v[0]->attrib[VARYING_SLOT_POS][2];
|
||||
z[1] = v[1]->attrib[VARYING_SLOT_POS][2];
|
||||
z[2] = v[2]->attrib[VARYING_SLOT_POS][2];
|
||||
/* Note that Z values are already scaled to [0,65535] (for example)
|
||||
* so no MRD value is used here.
|
||||
*/
|
||||
offset = ctx->Polygon.OffsetUnits;
|
||||
if (cc * cc > 1e-16F) {
|
||||
const GLfloat ez = z[0] - z[2];
|
||||
const GLfloat fz = z[1] - z[2];
|
||||
const GLfloat oneOverArea = 1.0F / cc;
|
||||
const GLfloat dzdx = fabsf((ey * fz - ez * fy) * oneOverArea);
|
||||
const GLfloat dzdy = fabsf((ez * fx - ex * fz) * oneOverArea);
|
||||
offset += MAX2(dzdx, dzdy) * ctx->Polygon.OffsetFactor;
|
||||
}
|
||||
/* new Z values */
|
||||
oz0 = CLAMP(v[0]->attrib[VARYING_SLOT_POS][2] + offset, 0.0F, max);
|
||||
oz1 = CLAMP(v[1]->attrib[VARYING_SLOT_POS][2] + offset, 0.0F, max);
|
||||
oz2 = CLAMP(v[2]->attrib[VARYING_SLOT_POS][2] + offset, 0.0F, max);
|
||||
}
|
||||
}
|
||||
|
||||
if (mode == GL_POINT) {
|
||||
if ((IND & SS_OFFSET_BIT) && ctx->Polygon.OffsetPoint) {
|
||||
v[0]->attrib[VARYING_SLOT_POS][2] = oz0;
|
||||
v[1]->attrib[VARYING_SLOT_POS][2] = oz1;
|
||||
v[2]->attrib[VARYING_SLOT_POS][2] = oz2;
|
||||
}
|
||||
_swsetup_render_tri(ctx, e0, e1, e2, facing, _swsetup_edge_render_point_tri);
|
||||
} else if (mode == GL_LINE) {
|
||||
if ((IND & SS_OFFSET_BIT) && ctx->Polygon.OffsetLine) {
|
||||
v[0]->attrib[VARYING_SLOT_POS][2] = oz0;
|
||||
v[1]->attrib[VARYING_SLOT_POS][2] = oz1;
|
||||
v[2]->attrib[VARYING_SLOT_POS][2] = oz2;
|
||||
}
|
||||
_swsetup_render_tri(ctx, e0, e1, e2, facing, _swsetup_edge_render_line_tri);
|
||||
} else {
|
||||
if ((IND & SS_OFFSET_BIT) && ctx->Polygon.OffsetFill) {
|
||||
v[0]->attrib[VARYING_SLOT_POS][2] = oz0;
|
||||
v[1]->attrib[VARYING_SLOT_POS][2] = oz1;
|
||||
v[2]->attrib[VARYING_SLOT_POS][2] = oz2;
|
||||
}
|
||||
_swrast_Triangle( ctx, v[0], v[1], v[2] );
|
||||
}
|
||||
|
||||
/*
|
||||
* Restore original vertex colors, etc.
|
||||
*/
|
||||
if (IND & SS_OFFSET_BIT) {
|
||||
v[0]->attrib[VARYING_SLOT_POS][2] = z[0];
|
||||
v[1]->attrib[VARYING_SLOT_POS][2] = z[1];
|
||||
v[2]->attrib[VARYING_SLOT_POS][2] = z[2];
|
||||
}
|
||||
|
||||
if (IND & SS_TWOSIDE_BIT) {
|
||||
if (facing == 1) {
|
||||
if (VB->BackfaceColorPtr) {
|
||||
if (swsetup->intColors) {
|
||||
COPY_CHAN4(v[0]->color, saved_color[0]);
|
||||
COPY_CHAN4(v[1]->color, saved_color[1]);
|
||||
COPY_CHAN4(v[2]->color, saved_color[2]);
|
||||
}
|
||||
else {
|
||||
COPY_4V(v[0]->attrib[VARYING_SLOT_COL0], saved_col0[0]);
|
||||
COPY_4V(v[1]->attrib[VARYING_SLOT_COL0], saved_col0[1]);
|
||||
COPY_4V(v[2]->attrib[VARYING_SLOT_COL0], saved_col0[2]);
|
||||
}
|
||||
}
|
||||
|
||||
if (VB->BackfaceSecondaryColorPtr) {
|
||||
COPY_4V(v[0]->attrib[VARYING_SLOT_COL1], saved_spec[0]);
|
||||
COPY_4V(v[1]->attrib[VARYING_SLOT_COL1], saved_spec[1]);
|
||||
COPY_4V(v[2]->attrib[VARYING_SLOT_COL1], saved_spec[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Need to fixup edgeflags when decomposing to triangles:
|
||||
*/
|
||||
static void TAG(quadfunc)( struct gl_context *ctx, GLuint v0,
|
||||
GLuint v1, GLuint v2, GLuint v3 )
|
||||
{
|
||||
if (IND & SS_UNFILLED_BIT) {
|
||||
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
|
||||
if (VB->EdgeFlag) { /* XXX this test shouldn't be needed (bug 12614) */
|
||||
GLubyte ef1 = VB->EdgeFlag[v1];
|
||||
GLubyte ef3 = VB->EdgeFlag[v3];
|
||||
VB->EdgeFlag[v1] = 0;
|
||||
TAG(triangle)( ctx, v0, v1, v3 );
|
||||
VB->EdgeFlag[v1] = ef1;
|
||||
VB->EdgeFlag[v3] = 0;
|
||||
TAG(triangle)( ctx, v1, v2, v3 );
|
||||
VB->EdgeFlag[v3] = ef3;
|
||||
}
|
||||
} else {
|
||||
TAG(triangle)( ctx, v0, v1, v3 );
|
||||
TAG(triangle)( ctx, v1, v2, v3 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void TAG(init)( void )
|
||||
{
|
||||
tri_tab[IND] = TAG(triangle);
|
||||
quad_tab[IND] = TAG(quadfunc);
|
||||
}
|
||||
|
||||
|
||||
#undef IND
|
||||
#undef TAG
|
|
@ -1,37 +0,0 @@
|
|||
|
||||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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@vmware.com>
|
||||
*/
|
||||
|
||||
#ifndef SS_VB_H
|
||||
#define SS_VB_H
|
||||
|
||||
struct gl_context;
|
||||
|
||||
void _swsetup_vb_init( struct gl_context *ctx );
|
||||
void _swsetup_choose_rastersetup_func( struct gl_context *ctx );
|
||||
|
||||
#endif
|
|
@ -1,61 +0,0 @@
|
|||
|
||||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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@vmware.com>
|
||||
*/
|
||||
|
||||
/* Public interface to the swrast_setup module. This module provides
|
||||
* an implementation of the driver interface to t_vb_render.c, and uses
|
||||
* the software rasterizer (swrast) to perform actual rasterization.
|
||||
*
|
||||
* The internals of the implementation are private, but can be hooked
|
||||
* into tnl at any time (except between RenderStart/RenderEnd) by
|
||||
* calling _swsetup_Wakeup().
|
||||
*/
|
||||
|
||||
#ifndef SWRAST_SETUP_H
|
||||
#define SWRAST_SETUP_H
|
||||
|
||||
#include "swrast/swrast.h"
|
||||
|
||||
extern GLboolean
|
||||
_swsetup_CreateContext( struct gl_context *ctx );
|
||||
|
||||
extern void
|
||||
_swsetup_DestroyContext( struct gl_context *ctx );
|
||||
|
||||
extern void
|
||||
_swsetup_InvalidateState( struct gl_context *ctx, GLuint new_state );
|
||||
|
||||
extern void
|
||||
_swsetup_Wakeup( struct gl_context *ctx );
|
||||
|
||||
/* Helper function to translate a hardware vertex (as understood by
|
||||
* the tnl/t_vertex.c code) to a swrast vertex.
|
||||
*/
|
||||
extern void
|
||||
_swsetup_Translate( struct gl_context *ctx, const void *vertex, SWvertex *dest );
|
||||
|
||||
#endif
|
|
@ -1,100 +0,0 @@
|
|||
INTRODUCTION
|
||||
|
||||
A generic, configurable software implementation of GL transformation &
|
||||
lighting.
|
||||
|
||||
This module provides an implementation of the routines required by the
|
||||
'vtxfmt' mechanism of core mesa for tnl functionality in all
|
||||
combinations of compile and execute modes.
|
||||
|
||||
Most current drivers use the tnl module exclusively to provide this
|
||||
functionality.
|
||||
|
||||
|
||||
STATE
|
||||
|
||||
To create and destroy the module:
|
||||
|
||||
GLboolean _tnl_CreateContext( struct gl_context *ctx );
|
||||
void _tnl_DestroyContext( struct gl_context *ctx );
|
||||
|
||||
The module is not active by default, and must be installed by calling
|
||||
_tnl_Wakeup(). This function installs internal tnl functions into all
|
||||
the vtxfmt dispatch hooks, thus taking over the task of transformation
|
||||
and lighting entirely:
|
||||
|
||||
void _tnl_wakeup_exec( struct gl_context *ctx );
|
||||
void _tnl_wakeup_save_exec( struct gl_context *ctx );
|
||||
|
||||
|
||||
This module tracks state changes internally and maintains derived
|
||||
values based on the current state. For this to work, the driver
|
||||
ensure the following funciton is called whenever the state changes and
|
||||
the swsetup module is 'awake':
|
||||
|
||||
void _tnl_InvalidateState( struct gl_context *ctx, GLuint new_state );
|
||||
|
||||
There is no explicit call to put the tnl module to sleep. Simply
|
||||
install other function pointers into all the vtxfmt dispatch slots,
|
||||
and (optionally) cease calling _tnl_InvalidateState().
|
||||
|
||||
CUSTOMIZATION
|
||||
|
||||
The module provides customizability through several mechanisms. The
|
||||
most important is by allowing drivers to specify the pipeline through
|
||||
which vertex data is passed, including its eventual transfer to
|
||||
rasterization hardware (or software).
|
||||
|
||||
The default pipeline is specified in t_pipeline.c, and is usually a
|
||||
starting point for driver pipelines. Some drivers will remove a stage
|
||||
where hardware provides support for the implemented operation (for
|
||||
instance fog where per-pixel hardware fog is available),
|
||||
or add stages to shortcircuit latter operations (for
|
||||
example taking advantage of hardware support for strips and other
|
||||
higher-level primitives (for example the radeon driver).
|
||||
|
||||
In addition, the following functions provide further tweaks:
|
||||
|
||||
extern void
|
||||
_tnl_need_projected_coords( struct gl_context *ctx, GLboolean flag );
|
||||
|
||||
- Direct the default vertex transformation stage to
|
||||
produce/not produce projected clip coordinates.
|
||||
|
||||
extern void
|
||||
_tnl_need_dlist_loopback( struct gl_context *ctx, GLboolean flag );
|
||||
|
||||
- Direct the display list component of the tnl module to
|
||||
replay display lists as 'glVertex' type calls, rather than
|
||||
passing the display list data directly into the tnl pipeline
|
||||
mechanism.
|
||||
|
||||
This allows display lists to be replayed by the tnl module
|
||||
even when the module is not strictly active.
|
||||
|
||||
|
||||
extern void
|
||||
_tnl_need_dlist_norm_lengths( struct gl_context *ctx, GLboolean flag );
|
||||
|
||||
- Direct the display list component to enable/disable caching
|
||||
1/length values for display list normals. Doing so is
|
||||
ususally helpful when lighting is performed in software, but
|
||||
wasteful otherwise.
|
||||
|
||||
|
||||
DRIVER INTERFACE
|
||||
|
||||
The module itself offers a minimal driver interface:
|
||||
|
||||
void (*RunPipeline)( struct gl_context *ctx );
|
||||
|
||||
Normally this is set to _tnl_RunPipeline(), however the driver can use
|
||||
this hook to wrap checks or other code around this call.
|
||||
|
||||
In addition, the driver interface for the default render pipeline
|
||||
stage is housed in the tnl context struct (this could be cleaner).
|
||||
|
||||
|
||||
RENDER DRIVER INTERFACE
|
||||
|
||||
See t_context.h for the definition and explanation of this.
|
|
@ -1,253 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* Copyright (C) 1999-2008 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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@vmware.com>
|
||||
*/
|
||||
|
||||
|
||||
#include "main/glheader.h"
|
||||
|
||||
#include "main/context.h"
|
||||
#include "main/macros.h"
|
||||
#include "main/mtypes.h"
|
||||
#include "main/light.h"
|
||||
#include "math/m_translate.h"
|
||||
#include "math/m_xform.h"
|
||||
#include "main/state.h"
|
||||
#include "main/viewport.h"
|
||||
#include "util/simple_list.h"
|
||||
#include "util/u_memory.h"
|
||||
|
||||
#include "tnl.h"
|
||||
#include "t_context.h"
|
||||
#include "t_pipeline.h"
|
||||
|
||||
#include "vbo/vbo.h"
|
||||
|
||||
GLboolean
|
||||
_tnl_CreateContext( struct gl_context *ctx )
|
||||
{
|
||||
TNLcontext *tnl;
|
||||
GLuint i;
|
||||
|
||||
/* Create the TNLcontext structure
|
||||
*/
|
||||
ctx->swtnl_context = tnl = calloc(1, sizeof(TNLcontext));
|
||||
|
||||
if (!tnl) {
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
/* Initialize the VB.
|
||||
*/
|
||||
tnl->vb.Size = ctx->Const.MaxArrayLockSize + MAX_CLIPPED_VERTICES;
|
||||
|
||||
|
||||
/* Initialize tnl state.
|
||||
*/
|
||||
if (ctx->VertexProgram._MaintainTnlProgram) {
|
||||
_tnl_install_pipeline( ctx, _tnl_vp_pipeline );
|
||||
} else {
|
||||
_tnl_install_pipeline( ctx, _tnl_default_pipeline );
|
||||
}
|
||||
|
||||
_math_matrix_ctr(&tnl->_WindowMap);
|
||||
|
||||
tnl->NeedNdcCoords = GL_TRUE;
|
||||
tnl->AllowVertexFog = GL_TRUE;
|
||||
tnl->AllowPixelFog = GL_TRUE;
|
||||
|
||||
/* Set a few default values in the driver struct.
|
||||
*/
|
||||
tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
|
||||
tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
|
||||
tnl->Driver.NotifyMaterialChange = _tnl_validate_shine_tables;
|
||||
|
||||
tnl->nr_blocks = 0;
|
||||
|
||||
/* Lighting miscellaneous */
|
||||
tnl->_ShineTabList = MALLOC_STRUCT( tnl_shine_tab );
|
||||
make_empty_list( tnl->_ShineTabList );
|
||||
/* Allocate 10 (arbitrary) shininess lookup tables */
|
||||
for (i = 0 ; i < 10 ; i++) {
|
||||
struct tnl_shine_tab *s = MALLOC_STRUCT( tnl_shine_tab );
|
||||
s->shininess = -1;
|
||||
s->refcount = 0;
|
||||
insert_at_tail( tnl->_ShineTabList, s );
|
||||
}
|
||||
|
||||
_math_init_transformation();
|
||||
_math_init_translate();
|
||||
|
||||
/* Keep our list of tnl_vertex_array inputs */
|
||||
_tnl_init_inputs(&tnl->draw_arrays);
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_tnl_DestroyContext( struct gl_context *ctx )
|
||||
{
|
||||
struct tnl_shine_tab *s, *tmps;
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
|
||||
/* Free lighting shininess exponentiation table */
|
||||
foreach_s( s, tmps, tnl->_ShineTabList ) {
|
||||
free( s );
|
||||
}
|
||||
free( tnl->_ShineTabList );
|
||||
|
||||
_tnl_destroy_pipeline( ctx );
|
||||
|
||||
free(tnl);
|
||||
ctx->swtnl_context = NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_tnl_InvalidateState( struct gl_context *ctx, GLuint new_state )
|
||||
{
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
const struct gl_program *vp = ctx->VertexProgram._Current;
|
||||
const struct gl_program *fp = ctx->FragmentProgram._Current;
|
||||
GLuint i;
|
||||
|
||||
if (new_state & (_NEW_LIGHT_CONSTANTS | _NEW_MATERIAL))
|
||||
_mesa_update_light_materials(ctx);
|
||||
|
||||
if (new_state & (_NEW_HINT | _NEW_PROGRAM)) {
|
||||
assert(tnl->AllowVertexFog || tnl->AllowPixelFog);
|
||||
tnl->_DoVertexFog = ((tnl->AllowVertexFog && (ctx->Hint.Fog != GL_NICEST))
|
||||
|| !tnl->AllowPixelFog) && !fp;
|
||||
}
|
||||
|
||||
tnl->pipeline.new_state |= new_state;
|
||||
|
||||
/* Calculate tnl->render_inputs. This bitmask indicates which vertex
|
||||
* attributes need to be emitted to the rasterizer.
|
||||
*/
|
||||
tnl->render_inputs_bitset = BITFIELD64_BIT(_TNL_ATTRIB_POS);
|
||||
|
||||
if (!fp || (fp->info.inputs_read & VARYING_BIT_COL0)) {
|
||||
tnl->render_inputs_bitset |= BITFIELD64_BIT(_TNL_ATTRIB_COLOR0);
|
||||
}
|
||||
|
||||
if (_mesa_need_secondary_color(ctx))
|
||||
tnl->render_inputs_bitset |= BITFIELD64_BIT(_TNL_ATTRIB_COLOR1);
|
||||
|
||||
for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
|
||||
if (ctx->Texture._EnabledCoordUnits & (1 << i) ||
|
||||
(fp && fp->info.inputs_read & VARYING_BIT_TEX(i)) ||
|
||||
_mesa_ati_fragment_shader_enabled(ctx)) {
|
||||
tnl->render_inputs_bitset |= BITFIELD64_BIT(_TNL_ATTRIB_TEX(i));
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->Fog.Enabled
|
||||
|| (fp != NULL && (fp->info.inputs_read & VARYING_BIT_FOGC) != 0)) {
|
||||
/* Either fixed-function fog or a fragment program needs fog coord.
|
||||
*/
|
||||
tnl->render_inputs_bitset |= BITFIELD64_BIT(_TNL_ATTRIB_FOG);
|
||||
}
|
||||
|
||||
if (ctx->Polygon.FrontMode != GL_FILL ||
|
||||
ctx->Polygon.BackMode != GL_FILL)
|
||||
tnl->render_inputs_bitset |= BITFIELD64_BIT(_TNL_ATTRIB_EDGEFLAG);
|
||||
|
||||
if (ctx->RenderMode == GL_FEEDBACK)
|
||||
tnl->render_inputs_bitset |= BITFIELD64_BIT(_TNL_ATTRIB_TEX0);
|
||||
|
||||
if (ctx->Point._Attenuated || ctx->VertexProgram.PointSizeEnabled)
|
||||
tnl->render_inputs_bitset |= BITFIELD64_BIT(_TNL_ATTRIB_POINTSIZE);
|
||||
|
||||
/* check for varying vars which are written by the vertex program */
|
||||
if (vp) {
|
||||
GLuint i;
|
||||
for (i = 0; i < MAX_VARYING; i++) {
|
||||
if (vp->info.outputs_written &
|
||||
BITFIELD64_BIT(VARYING_SLOT_VAR0 + i)) {
|
||||
tnl->render_inputs_bitset |= BITFIELD64_BIT(_TNL_ATTRIB_GENERIC(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (new_state & (_NEW_VIEWPORT | _NEW_BUFFERS)) {
|
||||
float scale[3], translate[3];
|
||||
_mesa_get_viewport_xform(ctx, 0, scale, translate);
|
||||
_math_matrix_viewport(&tnl->_WindowMap, scale, translate,
|
||||
ctx->DrawBuffer->_DepthMaxF);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_tnl_wakeup( struct gl_context *ctx )
|
||||
{
|
||||
/* Assume we haven't been getting state updates either:
|
||||
*/
|
||||
_tnl_InvalidateState( ctx, ~0 );
|
||||
|
||||
#if 0
|
||||
if (ctx->Light.ColorMaterialEnabled) {
|
||||
_mesa_update_color_material( ctx,
|
||||
ctx->Current.Attrib[VERT_ATTRIB_COLOR0] );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Drivers call this function to tell the TCL module whether or not
|
||||
* it wants Normalized Device Coords (NDC) computed. I.e. whether
|
||||
* we should "Divide-by-W". Software renders will want that.
|
||||
*/
|
||||
void
|
||||
_tnl_need_projected_coords( struct gl_context *ctx, GLboolean mode )
|
||||
{
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
tnl->NeedNdcCoords = mode;
|
||||
}
|
||||
|
||||
void
|
||||
_tnl_allow_vertex_fog( struct gl_context *ctx, GLboolean value )
|
||||
{
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
tnl->AllowVertexFog = value;
|
||||
tnl->_DoVertexFog = ((tnl->AllowVertexFog && (ctx->Hint.Fog != GL_NICEST))
|
||||
|| !tnl->AllowPixelFog) && !ctx->FragmentProgram._Current;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
_tnl_allow_pixel_fog( struct gl_context *ctx, GLboolean value )
|
||||
{
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
tnl->AllowPixelFog = value;
|
||||
tnl->_DoVertexFog = ((tnl->AllowVertexFog && (ctx->Hint.Fog != GL_NICEST))
|
||||
|| !tnl->AllowPixelFog) && !ctx->FragmentProgram._Current;
|
||||
}
|
||||
|
|
@ -1,594 +0,0 @@
|
|||
/*
|
||||
* mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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 t_context.h
|
||||
* \brief TnL module datatypes and definitions.
|
||||
* \author Keith Whitwell
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* \mainpage The TNL-module
|
||||
*
|
||||
* TNL stands for "transform and lighting", i.e. this module implements
|
||||
* a pipeline that receives as input a buffer of vertices and does all
|
||||
* necessary transformations (rotations, clipping, vertex shader etc.)
|
||||
* and passes then the output to the rasterizer.
|
||||
*
|
||||
* The tnl_pipeline contains the array of all stages, which should be
|
||||
* applied. Each stage is a black-box, which is described by an
|
||||
* tnl_pipeline_stage. The function ::_tnl_run_pipeline applies all the
|
||||
* stages to the vertex_buffer TNLcontext::vb, where the vertex data
|
||||
* is stored. The last stage in the pipeline is the rasterizer.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _T_CONTEXT_H
|
||||
#define _T_CONTEXT_H
|
||||
|
||||
#include "main/glheader.h"
|
||||
|
||||
#include "main/mtypes.h"
|
||||
|
||||
#include "math/m_vector.h"
|
||||
|
||||
#include "vbo/vbo.h"
|
||||
|
||||
#include "tnl.h"
|
||||
|
||||
#define MAX_PIPELINE_STAGES 30
|
||||
|
||||
/*
|
||||
* Note: The first attributes match the VERT_ATTRIB_* definitions
|
||||
* in mtypes.h. However, the tnl module has additional attributes
|
||||
* for materials, color indexes, edge flags, etc.
|
||||
*/
|
||||
/* Although it's nice to use these as bit indexes in a DWORD flag, we
|
||||
* could manage without if necessary. Another limit currently is the
|
||||
* number of bits allocated for these numbers in places like vertex
|
||||
* program instruction formats and register layouts.
|
||||
*/
|
||||
/* The bit space exhaustion is a fact now, done by _TNL_ATTRIB_ATTRIBUTE* for
|
||||
* GLSL vertex shader which cannot be aliased with conventional vertex attribs.
|
||||
* Compacting _TNL_ATTRIB_MAT_* attribs would not work, they would not give
|
||||
* as many free bits (11 plus already 1 free bit) as _TNL_ATTRIB_ATTRIBUTE*
|
||||
* attribs want (16).
|
||||
*/
|
||||
enum {
|
||||
_TNL_ATTRIB_POS,
|
||||
_TNL_ATTRIB_NORMAL,
|
||||
_TNL_ATTRIB_COLOR0,
|
||||
_TNL_ATTRIB_COLOR1,
|
||||
_TNL_ATTRIB_FOG,
|
||||
_TNL_ATTRIB_COLOR_INDEX,
|
||||
_TNL_ATTRIB_TEX0,
|
||||
_TNL_ATTRIB_TEX1,
|
||||
_TNL_ATTRIB_TEX2,
|
||||
_TNL_ATTRIB_TEX3,
|
||||
_TNL_ATTRIB_TEX4,
|
||||
_TNL_ATTRIB_TEX5,
|
||||
_TNL_ATTRIB_TEX6,
|
||||
_TNL_ATTRIB_TEX7,
|
||||
|
||||
/* This is really a VARYING_SLOT, not an attrib. Need to fix
|
||||
* tnl to understand the difference.
|
||||
*/
|
||||
_TNL_ATTRIB_POINTSIZE,
|
||||
|
||||
_TNL_ATTRIB_GENERIC0, /* doesn't really exist! */
|
||||
_TNL_ATTRIB_GENERIC1,
|
||||
_TNL_ATTRIB_GENERIC2,
|
||||
_TNL_ATTRIB_GENERIC3,
|
||||
_TNL_ATTRIB_GENERIC4,
|
||||
_TNL_ATTRIB_GENERIC5,
|
||||
_TNL_ATTRIB_GENERIC6,
|
||||
_TNL_ATTRIB_GENERIC7,
|
||||
_TNL_ATTRIB_GENERIC8,
|
||||
_TNL_ATTRIB_GENERIC9,
|
||||
_TNL_ATTRIB_GENERIC10,
|
||||
_TNL_ATTRIB_GENERIC11,
|
||||
_TNL_ATTRIB_GENERIC12,
|
||||
_TNL_ATTRIB_GENERIC13,
|
||||
_TNL_ATTRIB_GENERIC14,
|
||||
_TNL_ATTRIB_GENERIC15,
|
||||
_TNL_ATTRIB_EDGEFLAG,
|
||||
|
||||
_TNL_ATTRIB_MAX,
|
||||
|
||||
/* These alias with the generics, but they are not active
|
||||
* concurrently, so it's not a problem. The TNL module
|
||||
* doesn't have to do anything about this as this is how they
|
||||
* are passed into the _draw_prims callback.
|
||||
*
|
||||
* When we generate fixed-function replacement programs (in
|
||||
* t_vp_build.c currently), they refer to the appropriate
|
||||
* generic attribute in order to pick up per-vertex material
|
||||
* data.
|
||||
*/
|
||||
_TNL_ATTRIB_MAT_FRONT_AMBIENT=VERT_ATTRIB_MAT(MAT_ATTRIB_FRONT_AMBIENT),
|
||||
_TNL_ATTRIB_MAT_BACK_AMBIENT,
|
||||
_TNL_ATTRIB_MAT_FRONT_DIFFUSE,
|
||||
_TNL_ATTRIB_MAT_BACK_DIFFUSE,
|
||||
_TNL_ATTRIB_MAT_FRONT_SPECULAR,
|
||||
_TNL_ATTRIB_MAT_BACK_SPECULAR,
|
||||
_TNL_ATTRIB_MAT_FRONT_EMISSION,
|
||||
_TNL_ATTRIB_MAT_BACK_EMISSION,
|
||||
_TNL_ATTRIB_MAT_FRONT_SHININESS,
|
||||
_TNL_ATTRIB_MAT_BACK_SHININESS,
|
||||
_TNL_ATTRIB_MAT_FRONT_INDEXES,
|
||||
_TNL_ATTRIB_MAT_BACK_INDEXES,
|
||||
};
|
||||
|
||||
#define _TNL_ATTRIB_TEX(u) (_TNL_ATTRIB_TEX0 + (u))
|
||||
#define _TNL_ATTRIB_GENERIC(n) (_TNL_ATTRIB_GENERIC0 + (n))
|
||||
|
||||
/* special index used for handing invalid glVertexAttribute() indices */
|
||||
#define _TNL_ATTRIB_ERROR (_TNL_ATTRIB_GENERIC15 + 1)
|
||||
|
||||
/**
|
||||
* Handy attribute ranges:
|
||||
*/
|
||||
#define _TNL_FIRST_PROG _TNL_ATTRIB_NORMAL
|
||||
#define _TNL_LAST_PROG _TNL_ATTRIB_TEX7
|
||||
|
||||
#define _TNL_FIRST_TEX _TNL_ATTRIB_TEX0
|
||||
#define _TNL_LAST_TEX _TNL_ATTRIB_TEX7
|
||||
|
||||
#define _TNL_FIRST_GENERIC _TNL_ATTRIB_GENERIC0
|
||||
#define _TNL_LAST_GENERIC _TNL_ATTRIB_GENERIC15
|
||||
|
||||
#define _TNL_FIRST_MAT _TNL_ATTRIB_MAT_FRONT_AMBIENT /* GENERIC4 */
|
||||
#define _TNL_LAST_MAT _TNL_ATTRIB_MAT_BACK_INDEXES /* GENERIC15 */
|
||||
|
||||
/* Number of available texture attributes */
|
||||
#define _TNL_NUM_TEX 8
|
||||
|
||||
/* Number of available generic attributes */
|
||||
#define _TNL_NUM_GENERIC 16
|
||||
|
||||
/* Number of attributes used for evaluators */
|
||||
#define _TNL_NUM_EVAL 16
|
||||
|
||||
|
||||
#define PRIM_BEGIN 0x10
|
||||
#define PRIM_END 0x20
|
||||
#define PRIM_MODE_MASK 0x0f
|
||||
|
||||
static inline GLuint _tnl_translate_prim( const struct _mesa_prim *prim )
|
||||
{
|
||||
GLuint flag;
|
||||
flag = prim->mode;
|
||||
if (prim->begin) flag |= PRIM_BEGIN;
|
||||
if (prim->end) flag |= PRIM_END;
|
||||
return flag;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Contains the current state of a running pipeline.
|
||||
*/
|
||||
struct vertex_buffer
|
||||
{
|
||||
GLuint Size; /**< Max vertices per vertex buffer, constant */
|
||||
|
||||
/* Constant over the pipeline.
|
||||
*/
|
||||
GLuint Count; /**< Number of vertices currently in buffer */
|
||||
|
||||
/* Pointers to current data. Most of the data is in AttribPtr -- all of
|
||||
* it that is one of VERT_ATTRIB_X. For things only produced by TNL,
|
||||
* such as backface color or eye-space coordinates, they are stored
|
||||
* here.
|
||||
*/
|
||||
GLuint *Elts;
|
||||
GLvector4f *EyePtr; /* _TNL_BIT_POS */
|
||||
GLvector4f *ClipPtr; /* _TNL_BIT_POS */
|
||||
GLvector4f *NdcPtr; /* _TNL_BIT_POS */
|
||||
GLubyte ClipOrMask; /* _TNL_BIT_POS */
|
||||
GLubyte ClipAndMask; /* _TNL_BIT_POS */
|
||||
GLubyte *ClipMask; /* _TNL_BIT_POS */
|
||||
GLfloat *NormalLengthPtr; /* _TNL_BIT_NORMAL */
|
||||
GLboolean *EdgeFlag; /* _TNL_BIT_EDGEFLAG */
|
||||
GLvector4f *BackfaceIndexPtr;
|
||||
GLvector4f *BackfaceColorPtr;
|
||||
GLvector4f *BackfaceSecondaryColorPtr;
|
||||
|
||||
const struct _mesa_prim *Primitive;
|
||||
GLuint PrimitiveCount;
|
||||
|
||||
/* Inputs to the vertex program stage */
|
||||
GLvector4f *AttribPtr[_TNL_ATTRIB_MAX];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Describes an individual operation on the pipeline.
|
||||
*/
|
||||
struct tnl_pipeline_stage
|
||||
{
|
||||
const char *name;
|
||||
|
||||
/* Private data for the pipeline stage:
|
||||
*/
|
||||
void *privatePtr;
|
||||
|
||||
/* Allocate private data
|
||||
*/
|
||||
GLboolean (*create)( struct gl_context *ctx, struct tnl_pipeline_stage * );
|
||||
|
||||
/* Free private data.
|
||||
*/
|
||||
void (*destroy)( struct tnl_pipeline_stage * );
|
||||
|
||||
/* Called on any statechange or input array size change or
|
||||
* input array change to/from zero stride.
|
||||
*/
|
||||
void (*validate)( struct gl_context *ctx, struct tnl_pipeline_stage * );
|
||||
|
||||
/* Called from _tnl_run_pipeline(). The stage.changed_inputs value
|
||||
* encodes all inputs to thee struct which have changed. If
|
||||
* non-zero, recompute all affected outputs of the stage, otherwise
|
||||
* execute any 'sideeffects' of the stage.
|
||||
*
|
||||
* Return value: GL_TRUE - keep going
|
||||
* GL_FALSE - finished pipeline
|
||||
*/
|
||||
GLboolean (*run)( struct gl_context *ctx, struct tnl_pipeline_stage * );
|
||||
};
|
||||
|
||||
|
||||
|
||||
/** Contains the array of all pipeline stages.
|
||||
* The default values are defined at the end of t_pipeline.c
|
||||
*/
|
||||
struct tnl_pipeline {
|
||||
|
||||
GLuint last_attrib_stride[_TNL_ATTRIB_MAX];
|
||||
GLuint last_attrib_size[_TNL_ATTRIB_MAX];
|
||||
GLuint input_changes;
|
||||
GLuint new_state;
|
||||
|
||||
struct tnl_pipeline_stage stages[MAX_PIPELINE_STAGES+1];
|
||||
GLuint nr_stages;
|
||||
};
|
||||
|
||||
struct tnl_clipspace;
|
||||
struct tnl_clipspace_attr;
|
||||
|
||||
typedef void (*tnl_extract_func)( const struct tnl_clipspace_attr *a,
|
||||
GLfloat *out,
|
||||
const GLubyte *v );
|
||||
|
||||
typedef void (*tnl_insert_func)( const struct tnl_clipspace_attr *a,
|
||||
GLubyte *v,
|
||||
const GLfloat *in );
|
||||
|
||||
typedef void (*tnl_emit_func)( struct gl_context *ctx,
|
||||
GLuint count,
|
||||
GLubyte *dest );
|
||||
|
||||
|
||||
/**
|
||||
* Describes how to convert/move a vertex attribute from a vertex array
|
||||
* to a vertex structure.
|
||||
*/
|
||||
struct tnl_clipspace_attr
|
||||
{
|
||||
GLuint attrib; /* which vertex attrib (0=position, etc) */
|
||||
GLuint format;
|
||||
GLuint vertoffset; /* position of the attrib in the vertex struct */
|
||||
GLuint vertattrsize; /* size of the attribute in bytes */
|
||||
GLubyte *inputptr;
|
||||
GLuint inputstride;
|
||||
GLuint inputsize;
|
||||
const tnl_insert_func *insert;
|
||||
tnl_insert_func emit;
|
||||
tnl_extract_func extract;
|
||||
const GLfloat *vp; /* NDC->Viewport mapping matrix */
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
typedef void (*tnl_points_func)( struct gl_context *ctx, GLuint first, GLuint last );
|
||||
typedef void (*tnl_line_func)( struct gl_context *ctx, GLuint v1, GLuint v2 );
|
||||
typedef void (*tnl_triangle_func)( struct gl_context *ctx,
|
||||
GLuint v1, GLuint v2, GLuint v3 );
|
||||
typedef void (*tnl_quad_func)( struct gl_context *ctx, GLuint v1, GLuint v2,
|
||||
GLuint v3, GLuint v4 );
|
||||
typedef void (*tnl_render_func)( struct gl_context *ctx, GLuint start, GLuint count,
|
||||
GLuint flags );
|
||||
typedef void (*tnl_interp_func)( struct gl_context *ctx,
|
||||
GLfloat t, GLuint dst, GLuint out, GLuint in,
|
||||
GLboolean force_boundary );
|
||||
typedef void (*tnl_copy_pv_func)( struct gl_context *ctx, GLuint dst, GLuint src );
|
||||
typedef void (*tnl_setup_func)( struct gl_context *ctx,
|
||||
GLuint start, GLuint end,
|
||||
GLuint new_inputs);
|
||||
|
||||
|
||||
struct tnl_attr_type {
|
||||
GLuint format;
|
||||
GLuint size;
|
||||
GLuint stride;
|
||||
GLuint offset;
|
||||
};
|
||||
|
||||
struct tnl_clipspace_fastpath {
|
||||
GLuint vertex_size;
|
||||
GLuint attr_count;
|
||||
GLboolean match_strides;
|
||||
|
||||
struct tnl_attr_type *attr;
|
||||
|
||||
tnl_emit_func func;
|
||||
struct tnl_clipspace_fastpath *next;
|
||||
};
|
||||
|
||||
/**
|
||||
* Used to describe conversion of vertex arrays to vertex structures.
|
||||
* I.e. Structure of arrays to arrays of structs.
|
||||
*/
|
||||
struct tnl_clipspace
|
||||
{
|
||||
GLboolean need_extras;
|
||||
|
||||
GLuint new_inputs;
|
||||
|
||||
GLubyte *vertex_buf;
|
||||
GLuint vertex_size;
|
||||
GLuint max_vertex_size;
|
||||
|
||||
struct tnl_clipspace_attr attr[_TNL_ATTRIB_MAX];
|
||||
GLuint attr_count;
|
||||
|
||||
tnl_emit_func emit;
|
||||
tnl_interp_func interp;
|
||||
tnl_copy_pv_func copy_pv;
|
||||
|
||||
/* Parameters and constants for codegen:
|
||||
*/
|
||||
GLboolean need_viewport;
|
||||
GLfloat vp_scale[4];
|
||||
GLfloat vp_xlate[4];
|
||||
GLfloat chan_scale[4];
|
||||
GLfloat identity[4];
|
||||
|
||||
struct tnl_clipspace_fastpath *fastpath;
|
||||
|
||||
void (*codegen_emit)( struct gl_context *ctx );
|
||||
};
|
||||
|
||||
|
||||
#define SHINE_TABLE_SIZE 256 /**< Material shininess lookup table sizes */
|
||||
|
||||
/**
|
||||
* Material shininess lookup table.
|
||||
*/
|
||||
struct tnl_shine_tab
|
||||
{
|
||||
struct tnl_shine_tab *next, *prev;
|
||||
GLfloat tab[SHINE_TABLE_SIZE+1];
|
||||
GLfloat shininess;
|
||||
GLuint refcount;
|
||||
};
|
||||
|
||||
|
||||
struct tnl_device_driver
|
||||
{
|
||||
/***
|
||||
*** TNL Pipeline
|
||||
***/
|
||||
|
||||
void (*RunPipeline)(struct gl_context *ctx);
|
||||
/* Replaces PipelineStart/PipelineFinish -- intended to allow
|
||||
* drivers to wrap _tnl_run_pipeline() with code to validate state
|
||||
* and grab/release hardware locks.
|
||||
*/
|
||||
|
||||
void (*NotifyMaterialChange)(struct gl_context *ctx);
|
||||
/* Alert tnl-aware drivers of changes to material.
|
||||
*/
|
||||
|
||||
/***
|
||||
*** Rendering -- These functions called only from t_vb_render.c
|
||||
***/
|
||||
struct
|
||||
{
|
||||
void (*Start)(struct gl_context *ctx);
|
||||
void (*Finish)(struct gl_context *ctx);
|
||||
/* Called before and after all rendering operations, including DrawPixels,
|
||||
* ReadPixels, Bitmap, span functions, and CopyTexImage, etc commands.
|
||||
* These are a suitable place for grabbing/releasing hardware locks.
|
||||
*/
|
||||
|
||||
void (*PrimitiveNotify)(struct gl_context *ctx, GLenum mode);
|
||||
/* Called between RenderStart() and RenderFinish() to indicate the
|
||||
* type of primitive we're about to draw. Mode will be one of the
|
||||
* modes accepted by glBegin().
|
||||
*/
|
||||
|
||||
tnl_interp_func Interp;
|
||||
/* The interp function is called by the clipping routines when we need
|
||||
* to generate an interpolated vertex. All pertinant vertex ancilliary
|
||||
* data should be computed by interpolating between the 'in' and 'out'
|
||||
* vertices.
|
||||
*/
|
||||
|
||||
tnl_copy_pv_func CopyPV;
|
||||
/* The copy function is used to make a copy of a vertex. All pertinant
|
||||
* vertex attributes should be copied.
|
||||
*/
|
||||
|
||||
void (*ClippedPolygon)( struct gl_context *ctx, const GLuint *elts, GLuint n );
|
||||
/* Render a polygon with <n> vertices whose indexes are in the <elts>
|
||||
* array.
|
||||
*/
|
||||
|
||||
void (*ClippedLine)( struct gl_context *ctx, GLuint v0, GLuint v1 );
|
||||
/* Render a line between the two vertices given by indexes v0 and v1. */
|
||||
|
||||
tnl_points_func Points; /* must now respect vb->elts */
|
||||
tnl_line_func Line;
|
||||
tnl_triangle_func Triangle;
|
||||
tnl_quad_func Quad;
|
||||
/* These functions are called in order to render points, lines,
|
||||
* triangles and quads. These are only called via the T&L module.
|
||||
*/
|
||||
|
||||
tnl_render_func *PrimTabVerts;
|
||||
tnl_render_func *PrimTabElts;
|
||||
/* Render whole unclipped primitives (points, lines, linestrips,
|
||||
* lineloops, etc). The tables are indexed by the GL enum of the
|
||||
* primitive to be rendered. RenderTabVerts is used for non-indexed
|
||||
* arrays of vertices. RenderTabElts is used for indexed arrays of
|
||||
* vertices.
|
||||
*/
|
||||
|
||||
void (*ResetLineStipple)( struct gl_context *ctx );
|
||||
/* Reset the hardware's line stipple counter.
|
||||
*/
|
||||
|
||||
tnl_setup_func BuildVertices;
|
||||
/* This function is called whenever new vertices are required for
|
||||
* rendering. The vertices in question are those n such that start
|
||||
* <= n < end. The new_inputs parameter indicates those fields of
|
||||
* the vertex which need to be updated, if only a partial repair of
|
||||
* the vertex is required.
|
||||
*
|
||||
* This function is called only from _tnl_render_stage in tnl/t_render.c.
|
||||
*/
|
||||
|
||||
|
||||
GLboolean (*Multipass)( struct gl_context *ctx, GLuint passno );
|
||||
/* Driver may request additional render passes by returning GL_TRUE
|
||||
* when this function is called. This function will be called
|
||||
* after the first pass, and passes will be made until the function
|
||||
* returns GL_FALSE. If no function is registered, only one pass
|
||||
* is made.
|
||||
*
|
||||
* This function will be first invoked with passno == 1.
|
||||
*/
|
||||
} Render;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Utility that tracks and updates the current array entries.
|
||||
*/
|
||||
struct tnl_inputs
|
||||
{
|
||||
/**
|
||||
* Array of inputs to be set to the _DrawArrays pointer.
|
||||
* The array contains pointers into the _DrawVAO and to the vbo modules
|
||||
* current values. The array of pointers is updated incrementally
|
||||
* based on the current and vertex_processing_mode values below.
|
||||
*/
|
||||
struct tnl_vertex_array inputs[VERT_ATTRIB_MAX];
|
||||
/** Those VERT_BIT_'s where the inputs array point to current values. */
|
||||
GLbitfield current;
|
||||
/** Store which aliasing current values - generics or materials - are set. */
|
||||
gl_vertex_processing_mode vertex_processing_mode;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Initialize inputs.
|
||||
*/
|
||||
void
|
||||
_tnl_init_inputs(struct tnl_inputs *inputs);
|
||||
|
||||
|
||||
/**
|
||||
* Update the tnl_vertex_array array inside the tnl_inputs structure
|
||||
* provided the current _VPMode, the provided vao and
|
||||
* the vao's enabled arrays filtered by the filter bitmask.
|
||||
*/
|
||||
void
|
||||
_tnl_update_inputs(struct gl_context *ctx, struct tnl_inputs *inputs);
|
||||
|
||||
|
||||
/**
|
||||
* Context state for T&L context.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/* Driver interface.
|
||||
*/
|
||||
struct tnl_device_driver Driver;
|
||||
|
||||
/* Pipeline
|
||||
*/
|
||||
struct tnl_pipeline pipeline;
|
||||
struct vertex_buffer vb;
|
||||
|
||||
/* Clipspace/ndc/window vertex managment:
|
||||
*/
|
||||
struct tnl_clipspace clipspace;
|
||||
GLmatrix _WindowMap;
|
||||
|
||||
/* Probably need a better configuration mechanism:
|
||||
*/
|
||||
GLboolean NeedNdcCoords;
|
||||
GLboolean AllowVertexFog;
|
||||
GLboolean AllowPixelFog;
|
||||
GLboolean _DoVertexFog; /* eval fog function at each vertex? */
|
||||
|
||||
GLbitfield64 render_inputs_bitset;
|
||||
|
||||
GLvector4f tmp_inputs[VERT_ATTRIB_MAX];
|
||||
|
||||
/* Temp storage for t_draw.c:
|
||||
*/
|
||||
GLubyte *block[VERT_ATTRIB_MAX];
|
||||
GLuint nr_blocks;
|
||||
|
||||
GLuint CurInstance;
|
||||
|
||||
struct tnl_shine_tab *_ShineTable[2]; /**< Active shine tables */
|
||||
struct tnl_shine_tab *_ShineTabList; /**< MRU list of inactive shine tables */
|
||||
/**@}*/
|
||||
|
||||
/* The list of tnl_vertex_array inputs. */
|
||||
struct tnl_inputs draw_arrays;
|
||||
} TNLcontext;
|
||||
|
||||
|
||||
|
||||
#define TNL_CONTEXT(ctx) ((TNLcontext *)((ctx)->swtnl_context))
|
||||
|
||||
|
||||
#define TYPE_IDX(t) ((t) & 0xf)
|
||||
#define MAX_TYPES TYPE_IDX(GL_DOUBLE)+1 /* 0xa + 1 */
|
||||
|
||||
|
||||
extern void
|
||||
tnl_clip_prepare(struct gl_context *ctx);
|
||||
|
||||
|
||||
#endif
|
|
@ -1,657 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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@vmware.com>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "main/glheader.h"
|
||||
#include "main/arrayobj.h"
|
||||
#include "main/bufferobj.h"
|
||||
#include "main/condrender.h"
|
||||
#include "main/context.h"
|
||||
|
||||
#include "main/mtypes.h"
|
||||
#include "main/macros.h"
|
||||
#include "main/enums.h"
|
||||
#include "main/varray.h"
|
||||
#include "util/half_float.h"
|
||||
|
||||
#include "t_context.h"
|
||||
#include "t_rebase.h"
|
||||
#include "tnl.h"
|
||||
|
||||
|
||||
static GLubyte *get_space(struct gl_context *ctx, GLuint bytes)
|
||||
{
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
GLubyte *space = malloc(bytes);
|
||||
|
||||
tnl->block[tnl->nr_blocks++] = space;
|
||||
return space;
|
||||
}
|
||||
|
||||
|
||||
static void free_space(struct gl_context *ctx)
|
||||
{
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
|
||||
for (GLuint i = 0; i < tnl->nr_blocks; i++)
|
||||
free(tnl->block[i]);
|
||||
|
||||
tnl->nr_blocks = 0;
|
||||
}
|
||||
|
||||
|
||||
/* Convert the incoming array to GLfloats. Understands the
|
||||
* array->Normalized flag and selects the correct conversion method.
|
||||
*/
|
||||
#define CONVERT( TYPE, MACRO ) do { \
|
||||
GLuint i, j; \
|
||||
if (attrib->Format.Normalized) { \
|
||||
for (i = 0; i < count; i++) { \
|
||||
const TYPE *in = (TYPE *)ptr; \
|
||||
for (j = 0; j < sz; j++) { \
|
||||
*fptr++ = MACRO(*in); \
|
||||
in++; \
|
||||
} \
|
||||
ptr += binding->Stride; \
|
||||
} \
|
||||
} else { \
|
||||
for (i = 0; i < count; i++) { \
|
||||
const TYPE *in = (TYPE *)ptr; \
|
||||
for (j = 0; j < sz; j++) { \
|
||||
*fptr++ = (GLfloat)(*in); \
|
||||
in++; \
|
||||
} \
|
||||
ptr += binding->Stride; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
/**
|
||||
* Convert array of BGRA/GLubyte[4] values to RGBA/float[4]
|
||||
* \param ptr input/ubyte array
|
||||
* \param fptr output/float array
|
||||
*/
|
||||
static void
|
||||
convert_bgra_to_float(const struct gl_vertex_buffer_binding *binding,
|
||||
const struct gl_array_attributes *attrib,
|
||||
const GLubyte *ptr, GLfloat *fptr,
|
||||
GLuint count)
|
||||
{
|
||||
GLuint i;
|
||||
assert(attrib->Format.Normalized);
|
||||
assert(attrib->Format.Size == 4);
|
||||
for (i = 0; i < count; i++) {
|
||||
const GLubyte *in = (GLubyte *) ptr; /* in is in BGRA order */
|
||||
*fptr++ = UBYTE_TO_FLOAT(in[2]); /* red */
|
||||
*fptr++ = UBYTE_TO_FLOAT(in[1]); /* green */
|
||||
*fptr++ = UBYTE_TO_FLOAT(in[0]); /* blue */
|
||||
*fptr++ = UBYTE_TO_FLOAT(in[3]); /* alpha */
|
||||
ptr += binding->Stride;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
convert_half_to_float(const struct gl_vertex_buffer_binding *binding,
|
||||
const GLubyte *ptr, GLfloat *fptr,
|
||||
GLuint count, GLuint sz)
|
||||
{
|
||||
GLuint i, j;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
GLhalfARB *in = (GLhalfARB *)ptr;
|
||||
|
||||
for (j = 0; j < sz; j++)
|
||||
*fptr++ = _mesa_half_to_float(in[j]);
|
||||
|
||||
ptr += binding->Stride;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Convert fixed-point to floating-point.
|
||||
*
|
||||
* In OpenGL, a fixed-point number is a "signed 2's complement 16.16 scaled
|
||||
* integer" (Table 2.2 of the OpenGL ES 2.0 spec).
|
||||
*
|
||||
* If the buffer has the \c normalized flag set, the formula
|
||||
* \code normalize(x) := (2*x + 1) / (2^16 - 1) \endcode
|
||||
* is used to map the fixed-point numbers into the range [-1, 1].
|
||||
*/
|
||||
static void
|
||||
convert_fixed_to_float(const struct gl_vertex_buffer_binding *binding,
|
||||
const struct gl_array_attributes *attrib,
|
||||
const GLubyte *ptr, GLfloat *fptr,
|
||||
GLuint count)
|
||||
{
|
||||
GLuint i;
|
||||
GLint j;
|
||||
const GLint size = attrib->Format.Size;
|
||||
|
||||
if (attrib->Format.Normalized) {
|
||||
for (i = 0; i < count; ++i) {
|
||||
const GLfixed *in = (GLfixed *) ptr;
|
||||
for (j = 0; j < size; ++j) {
|
||||
*fptr++ = (GLfloat) (2 * in[j] + 1) / (GLfloat) ((1 << 16) - 1);
|
||||
}
|
||||
ptr += binding->Stride;
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < count; ++i) {
|
||||
const GLfixed *in = (GLfixed *) ptr;
|
||||
for (j = 0; j < size; ++j) {
|
||||
*fptr++ = in[j] / (GLfloat) (1 << 16);
|
||||
}
|
||||
ptr += binding->Stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Adjust pointer to point at first requested element, convert to
|
||||
* floating point, populate VB->AttribPtr[].
|
||||
*/
|
||||
static void _tnl_import_array(struct gl_context *ctx,
|
||||
GLuint attr,
|
||||
GLuint count,
|
||||
const struct gl_vertex_buffer_binding *binding,
|
||||
const struct gl_array_attributes *attrib,
|
||||
const GLubyte *ptr)
|
||||
{
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
struct vertex_buffer *VB = &tnl->vb;
|
||||
GLuint stride = binding->Stride;
|
||||
|
||||
if (attrib->Format.Type != GL_FLOAT) {
|
||||
const GLuint sz = attrib->Format.Size;
|
||||
GLubyte *buf = get_space(ctx, count * sz * sizeof(GLfloat));
|
||||
GLfloat *fptr = (GLfloat *)buf;
|
||||
|
||||
switch (attrib->Format.Type) {
|
||||
case GL_BYTE:
|
||||
CONVERT(GLbyte, BYTE_TO_FLOAT);
|
||||
break;
|
||||
case GL_UNSIGNED_BYTE:
|
||||
if (attrib->Format.Format == GL_BGRA) {
|
||||
/* See GL_EXT_vertex_array_bgra */
|
||||
convert_bgra_to_float(binding, attrib, ptr, fptr, count);
|
||||
}
|
||||
else {
|
||||
CONVERT(GLubyte, UBYTE_TO_FLOAT);
|
||||
}
|
||||
break;
|
||||
case GL_SHORT:
|
||||
CONVERT(GLshort, SHORT_TO_FLOAT);
|
||||
break;
|
||||
case GL_UNSIGNED_SHORT:
|
||||
CONVERT(GLushort, USHORT_TO_FLOAT);
|
||||
break;
|
||||
case GL_INT:
|
||||
CONVERT(GLint, INT_TO_FLOAT);
|
||||
break;
|
||||
case GL_UNSIGNED_INT:
|
||||
CONVERT(GLuint, UINT_TO_FLOAT);
|
||||
break;
|
||||
case GL_DOUBLE:
|
||||
CONVERT(GLdouble, (GLfloat));
|
||||
break;
|
||||
case GL_HALF_FLOAT:
|
||||
convert_half_to_float(binding, ptr, fptr, count, sz);
|
||||
break;
|
||||
case GL_FIXED:
|
||||
convert_fixed_to_float(binding, attrib, ptr, fptr, count);
|
||||
break;
|
||||
default:
|
||||
unreachable("Invalid type.");
|
||||
}
|
||||
|
||||
ptr = buf;
|
||||
stride = sz * sizeof(GLfloat);
|
||||
}
|
||||
|
||||
VB->AttribPtr[attr] = &tnl->tmp_inputs[attr];
|
||||
VB->AttribPtr[attr]->data = (GLfloat (*)[4])ptr;
|
||||
VB->AttribPtr[attr]->start = (GLfloat *)ptr;
|
||||
VB->AttribPtr[attr]->count = count;
|
||||
VB->AttribPtr[attr]->stride = stride;
|
||||
VB->AttribPtr[attr]->size = attrib->Format.Size;
|
||||
|
||||
/* This should die, but so should the whole GLvector4f concept:
|
||||
*/
|
||||
VB->AttribPtr[attr]->flags = (((1<<attrib->Format.Size)-1) |
|
||||
VEC_NOT_WRITEABLE |
|
||||
(stride == 4*sizeof(GLfloat) ? 0 : VEC_BAD_STRIDE));
|
||||
|
||||
VB->AttribPtr[attr]->storage = NULL;
|
||||
}
|
||||
|
||||
#define CLIPVERTS ((6 + MAX_CLIP_PLANES) * 2)
|
||||
|
||||
|
||||
static GLboolean *_tnl_import_edgeflag(struct gl_context *ctx,
|
||||
const GLvector4f *input,
|
||||
GLuint count)
|
||||
{
|
||||
const GLubyte *ptr = (const GLubyte *)input->data;
|
||||
const GLuint stride = input->stride;
|
||||
GLboolean *space = (GLboolean *)get_space(ctx, count + CLIPVERTS);
|
||||
GLboolean *bptr = space;
|
||||
|
||||
for (GLuint i = 0; i < count; i++) {
|
||||
*bptr++ = ((GLfloat *)ptr)[0] == 1.0F;
|
||||
ptr += stride;
|
||||
}
|
||||
|
||||
return space;
|
||||
}
|
||||
|
||||
|
||||
static void bind_inputs(struct gl_context *ctx,
|
||||
const struct tnl_vertex_array *inputs,
|
||||
GLint count,
|
||||
struct gl_buffer_object **bo,
|
||||
GLuint *nr_bo)
|
||||
{
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
struct vertex_buffer *VB = &tnl->vb;
|
||||
|
||||
/* Map all the VBOs
|
||||
*/
|
||||
for (unsigned i = 0; i < VERT_ATTRIB_MAX; i++) {
|
||||
const struct tnl_vertex_array *array = &inputs[i];
|
||||
const struct gl_vertex_buffer_binding *binding = array->BufferBinding;
|
||||
const struct gl_array_attributes *attrib = array->VertexAttrib;
|
||||
const void *ptr;
|
||||
|
||||
if (binding->BufferObj) {
|
||||
if (!binding->BufferObj->Mappings[MAP_INTERNAL].Pointer) {
|
||||
bo[*nr_bo] = binding->BufferObj;
|
||||
(*nr_bo)++;
|
||||
ctx->Driver.MapBufferRange(ctx, 0, binding->BufferObj->Size,
|
||||
GL_MAP_READ_BIT,
|
||||
binding->BufferObj,
|
||||
MAP_INTERNAL);
|
||||
|
||||
assert(binding->BufferObj->Mappings[MAP_INTERNAL].Pointer);
|
||||
}
|
||||
|
||||
ptr = ADD_POINTERS(binding->BufferObj->Mappings[MAP_INTERNAL].Pointer,
|
||||
binding->Offset + attrib->RelativeOffset);
|
||||
} else
|
||||
ptr = attrib->Ptr;
|
||||
|
||||
/* Just make sure the array is floating point, otherwise convert to
|
||||
* temporary storage.
|
||||
*
|
||||
* XXX: remove the GLvector4f type at some stage and just use
|
||||
* client arrays.
|
||||
*/
|
||||
_tnl_import_array(ctx, i, count, binding, attrib, ptr);
|
||||
}
|
||||
|
||||
/* We process only the vertices between min & max index:
|
||||
*/
|
||||
VB->Count = count;
|
||||
|
||||
/* These should perhaps be part of _TNL_ATTRIB_* */
|
||||
VB->BackfaceColorPtr = NULL;
|
||||
VB->BackfaceIndexPtr = NULL;
|
||||
VB->BackfaceSecondaryColorPtr = NULL;
|
||||
|
||||
/* Clipping and drawing code still requires this to be a packed
|
||||
* array of ubytes which can be written into. TODO: Fix and
|
||||
* remove.
|
||||
*/
|
||||
if (ctx->Polygon.FrontMode != GL_FILL ||
|
||||
ctx->Polygon.BackMode != GL_FILL) {
|
||||
VB->EdgeFlag = _tnl_import_edgeflag(ctx,
|
||||
VB->AttribPtr[_TNL_ATTRIB_EDGEFLAG],
|
||||
VB->Count);
|
||||
} else {
|
||||
/* the data previously pointed to by EdgeFlag may have been freed */
|
||||
VB->EdgeFlag = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Translate indices to GLuints and store in VB->Elts.
|
||||
*/
|
||||
static void bind_indices(struct gl_context *ctx,
|
||||
unsigned start,
|
||||
const struct _mesa_index_buffer *ib,
|
||||
struct gl_buffer_object **bo,
|
||||
GLuint *nr_bo)
|
||||
{
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
struct vertex_buffer *VB = &tnl->vb;
|
||||
GLuint i;
|
||||
const void *ptr;
|
||||
|
||||
if (!ib) {
|
||||
VB->Elts = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ib->obj) {
|
||||
if (!_mesa_bufferobj_mapped(ib->obj, MAP_INTERNAL)) {
|
||||
/* if the buffer object isn't mapped yet, map it now */
|
||||
bo[*nr_bo] = ib->obj;
|
||||
(*nr_bo)++;
|
||||
ptr = ctx->Driver.MapBufferRange(ctx, (GLsizeiptr) ib->ptr,
|
||||
ib->count << ib->index_size_shift,
|
||||
GL_MAP_READ_BIT, ib->obj,
|
||||
MAP_INTERNAL);
|
||||
assert(ib->obj->Mappings[MAP_INTERNAL].Pointer);
|
||||
} else {
|
||||
/* user-space elements, or buffer already mapped */
|
||||
ptr = ADD_POINTERS(ib->obj->Mappings[MAP_INTERNAL].Pointer, ib->ptr);
|
||||
}
|
||||
} else
|
||||
ptr = ib->ptr;
|
||||
|
||||
if (ib->index_size_shift == 2 && VB->Primitive[0].basevertex == 0) {
|
||||
VB->Elts = (GLuint *) ptr;
|
||||
}
|
||||
else {
|
||||
GLuint *elts = (GLuint *)get_space(ctx, (start + ib->count) * sizeof(GLuint));
|
||||
VB->Elts = elts;
|
||||
|
||||
elts += start;
|
||||
|
||||
if (ib->index_size_shift == 2) {
|
||||
const GLuint *in = (GLuint *)ptr + start;
|
||||
for (i = 0; i < ib->count; i++)
|
||||
*elts++ = (GLuint)(*in++) + VB->Primitive[0].basevertex;
|
||||
}
|
||||
else if (ib->index_size_shift == 1) {
|
||||
const GLushort *in = (GLushort *)ptr + start;
|
||||
for (i = 0; i < ib->count; i++)
|
||||
*elts++ = (GLuint)(*in++) + VB->Primitive[0].basevertex;
|
||||
}
|
||||
else {
|
||||
const GLubyte *in = (GLubyte *)ptr + start;
|
||||
for (i = 0; i < ib->count; i++)
|
||||
*elts++ = (GLuint)(*in++) + VB->Primitive[0].basevertex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void bind_prims(struct gl_context *ctx,
|
||||
const struct _mesa_prim *prim,
|
||||
GLuint nr_prims)
|
||||
{
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
struct vertex_buffer *VB = &tnl->vb;
|
||||
|
||||
VB->Primitive = prim;
|
||||
VB->PrimitiveCount = nr_prims;
|
||||
}
|
||||
|
||||
static void unmap_vbos(struct gl_context *ctx,
|
||||
struct gl_buffer_object **bo,
|
||||
GLuint nr_bo)
|
||||
{
|
||||
for (GLuint i = 0; i < nr_bo; i++) {
|
||||
ctx->Driver.UnmapBuffer(ctx, bo[i], MAP_INTERNAL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* This is the main workhorse doing all the rendering work.
|
||||
*/
|
||||
void _tnl_draw_prims(struct gl_context *ctx,
|
||||
const struct tnl_vertex_array *arrays,
|
||||
const struct _mesa_prim *prim,
|
||||
GLuint nr_prims,
|
||||
const struct _mesa_index_buffer *ib,
|
||||
GLboolean index_bounds_valid,
|
||||
GLuint min_index,
|
||||
GLuint max_index,
|
||||
GLuint num_instances,
|
||||
GLuint base_instance)
|
||||
{
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
const GLuint TEST_SPLIT = 0;
|
||||
const GLint max = TEST_SPLIT ? 8 : tnl->vb.Size - MAX_CLIPPED_VERTICES;
|
||||
GLint max_basevertex = prim->basevertex;
|
||||
GLuint i;
|
||||
|
||||
if (!index_bounds_valid)
|
||||
vbo_get_minmax_indices(ctx, prim, ib, &min_index, &max_index, nr_prims,
|
||||
false, 0);
|
||||
|
||||
/* Mesa core state should have been validated already */
|
||||
assert(ctx->NewState == 0x0);
|
||||
|
||||
if (!_mesa_check_conditional_render(ctx))
|
||||
return; /* don't draw */
|
||||
|
||||
for (i = 1; i < nr_prims; i++)
|
||||
max_basevertex = MAX2(max_basevertex, prim[i].basevertex);
|
||||
|
||||
if (0) {
|
||||
printf("%s %d..%d\n", __func__, min_index, max_index);
|
||||
for (i = 0; i < nr_prims; i++)
|
||||
printf("prim %d: %s start %d count %d\n", i,
|
||||
_mesa_enum_to_string(prim[i].mode),
|
||||
prim[i].start,
|
||||
prim[i].count);
|
||||
}
|
||||
|
||||
if (min_index) {
|
||||
/* We always translate away calls with min_index != 0.
|
||||
*/
|
||||
t_rebase_prims(ctx, arrays, prim, nr_prims, ib,
|
||||
min_index, max_index, num_instances, base_instance,
|
||||
_tnl_draw_prims);
|
||||
return;
|
||||
}
|
||||
else if ((GLint)max_index + max_basevertex > max) {
|
||||
/* The software TNL pipeline has a fixed amount of storage for
|
||||
* vertices and it is necessary to split incoming drawing commands
|
||||
* if they exceed that limit.
|
||||
*/
|
||||
struct split_limits limits;
|
||||
limits.max_verts = max;
|
||||
limits.max_vb_size = ~0;
|
||||
limits.max_indices = ~0;
|
||||
|
||||
/* This will split the buffers one way or another and
|
||||
* recursively call back into this function.
|
||||
*/
|
||||
_tnl_split_prims(ctx, arrays, prim, nr_prims, ib,
|
||||
0, max_index + prim->basevertex,
|
||||
num_instances, base_instance,
|
||||
_tnl_draw_prims,
|
||||
&limits);
|
||||
}
|
||||
else {
|
||||
/* May need to map a vertex buffer object for every attribute plus
|
||||
* one for the index buffer.
|
||||
*/
|
||||
struct gl_buffer_object *bo[VERT_ATTRIB_MAX + 1];
|
||||
GLuint nr_bo;
|
||||
GLuint inst;
|
||||
|
||||
assert(num_instances > 0);
|
||||
|
||||
for (i = 0; i < nr_prims;) {
|
||||
GLuint this_nr_prims;
|
||||
|
||||
/* Our SW TNL pipeline doesn't handle basevertex yet, so bind_indices
|
||||
* will rebase the elements to the basevertex, and we'll only
|
||||
* emit strings of prims with the same basevertex in one draw call.
|
||||
*/
|
||||
for (this_nr_prims = 1; i + this_nr_prims < nr_prims;
|
||||
this_nr_prims++) {
|
||||
if (prim[i].basevertex != prim[i + this_nr_prims].basevertex ||
|
||||
prim[i].start != prim[i + this_nr_prims].start)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Binding inputs may imply mapping some vertex buffer objects.
|
||||
* They will need to be unmapped below.
|
||||
*/
|
||||
for (inst = 0; inst < num_instances; inst++) {
|
||||
nr_bo = 0;
|
||||
|
||||
bind_prims(ctx, &prim[i], this_nr_prims);
|
||||
bind_inputs(ctx, arrays, max_index + prim[i].basevertex + 1,
|
||||
bo, &nr_bo);
|
||||
bind_indices(ctx, prim[i].start, ib, bo, &nr_bo);
|
||||
|
||||
tnl->CurInstance = inst;
|
||||
TNL_CONTEXT(ctx)->Driver.RunPipeline(ctx);
|
||||
|
||||
unmap_vbos(ctx, bo, nr_bo);
|
||||
free_space(ctx);
|
||||
}
|
||||
|
||||
i += this_nr_prims;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_tnl_init_inputs(struct tnl_inputs *inputs)
|
||||
{
|
||||
inputs->current = 0;
|
||||
inputs->vertex_processing_mode = VP_MODE_FF;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update the tnl_inputs's arrays to point to the vao->_VertexArray arrays
|
||||
* according to the 'enable' bitmask.
|
||||
* \param enable bitfield of VERT_BIT_x flags.
|
||||
*/
|
||||
static inline void
|
||||
update_vao_inputs(struct gl_context *ctx,
|
||||
struct tnl_inputs *inputs, GLbitfield enable)
|
||||
{
|
||||
const struct gl_vertex_array_object *vao = ctx->Array._DrawVAO;
|
||||
|
||||
/* Make sure we process only arrays enabled in the VAO */
|
||||
assert((enable & ~vao->_EnabledWithMapMode) == 0);
|
||||
|
||||
/* Fill in the client arrays from the VAO */
|
||||
const struct gl_vertex_buffer_binding *bindings = &vao->BufferBinding[0];
|
||||
while (enable) {
|
||||
const int attr = u_bit_scan(&enable);
|
||||
struct tnl_vertex_array *input = &inputs->inputs[attr];
|
||||
const struct gl_array_attributes *attrib;
|
||||
attrib = _mesa_draw_array_attrib(vao, attr);
|
||||
input->VertexAttrib = attrib;
|
||||
input->BufferBinding = &bindings[attrib->BufferBindingIndex];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update the tnl_inputs's arrays to point to the vbo->currval arrays
|
||||
* according to the 'current' bitmask.
|
||||
* \param current bitfield of VERT_BIT_x flags.
|
||||
*/
|
||||
static inline void
|
||||
update_current_inputs(struct gl_context *ctx,
|
||||
struct tnl_inputs *inputs, GLbitfield current)
|
||||
{
|
||||
gl_vertex_processing_mode mode = ctx->VertexProgram._VPMode;
|
||||
|
||||
/* All previously non current array pointers need update. */
|
||||
GLbitfield mask = current & ~inputs->current;
|
||||
/* On mode change, the slots aliasing with materials need update too */
|
||||
if (mode != inputs->vertex_processing_mode)
|
||||
mask |= current & VERT_BIT_MAT_ALL;
|
||||
|
||||
while (mask) {
|
||||
const int attr = u_bit_scan(&mask);
|
||||
struct tnl_vertex_array *input = &inputs->inputs[attr];
|
||||
input->VertexAttrib = _vbo_current_attrib(ctx, attr);
|
||||
input->BufferBinding = _vbo_current_binding(ctx);
|
||||
}
|
||||
|
||||
inputs->current = current;
|
||||
inputs->vertex_processing_mode = mode;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update the tnl_inputs's arrays to point to the vao->_VertexArray and
|
||||
* vbo->currval arrays according to Array._DrawVAO and
|
||||
* Array._DrawVAOEnableAttribs.
|
||||
*/
|
||||
void
|
||||
_tnl_update_inputs(struct gl_context *ctx, struct tnl_inputs *inputs)
|
||||
{
|
||||
const GLbitfield enable = ctx->Array._DrawVAOEnabledAttribs;
|
||||
|
||||
/* Update array input pointers */
|
||||
update_vao_inputs(ctx, inputs, enable);
|
||||
|
||||
/* The rest must be current inputs. */
|
||||
update_current_inputs(ctx, inputs, ~enable & VERT_BIT_ALL);
|
||||
}
|
||||
|
||||
|
||||
const struct tnl_vertex_array *
|
||||
_tnl_bind_inputs(struct gl_context *ctx)
|
||||
{
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
_tnl_update_inputs(ctx, &tnl->draw_arrays);
|
||||
return tnl->draw_arrays.inputs;
|
||||
}
|
||||
|
||||
|
||||
/* This is the main entrypoint into the slimmed-down software tnl
|
||||
* module. In a regular swtnl driver, this can be plugged straight
|
||||
* into the ctx->Driver.Draw() callback.
|
||||
*/
|
||||
void
|
||||
_tnl_draw(struct gl_context *ctx,
|
||||
const struct _mesa_prim *prim, unsigned nr_prims,
|
||||
const struct _mesa_index_buffer *ib,
|
||||
bool index_bounds_valid, bool primitive_restart,
|
||||
unsigned restart_index, unsigned min_index, unsigned max_index,
|
||||
unsigned num_instances, unsigned base_instance)
|
||||
{
|
||||
/* Update TNLcontext::draw_arrays and return that pointer.
|
||||
*/
|
||||
const struct tnl_vertex_array* arrays = _tnl_bind_inputs(ctx);
|
||||
|
||||
_tnl_draw_prims(ctx, arrays, prim, nr_prims, ib,
|
||||
index_bounds_valid, min_index, max_index,
|
||||
num_instances, base_instance);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_tnl_init_driver_draw_function(struct dd_function_table *functions)
|
||||
{
|
||||
functions->Draw = _tnl_draw;
|
||||
}
|
|
@ -1,300 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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@vmware.com>
|
||||
*/
|
||||
|
||||
#include "main/glheader.h"
|
||||
#include "main/context.h"
|
||||
|
||||
#include "main/mtypes.h"
|
||||
|
||||
#include "t_context.h"
|
||||
#include "t_pipeline.h"
|
||||
#include "t_vp_build.h"
|
||||
#include "t_vertex.h"
|
||||
|
||||
void _tnl_install_pipeline( struct gl_context *ctx,
|
||||
const struct tnl_pipeline_stage **stages )
|
||||
{
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
GLuint i;
|
||||
|
||||
tnl->pipeline.new_state = ~0;
|
||||
|
||||
/* Create a writeable copy of each stage.
|
||||
*/
|
||||
for (i = 0 ; i < MAX_PIPELINE_STAGES && stages[i] ; i++) {
|
||||
struct tnl_pipeline_stage *s = &tnl->pipeline.stages[i];
|
||||
memcpy(s, stages[i], sizeof(*s));
|
||||
if (s->create)
|
||||
s->create(ctx, s);
|
||||
}
|
||||
|
||||
tnl->pipeline.nr_stages = i;
|
||||
}
|
||||
|
||||
void _tnl_destroy_pipeline( struct gl_context *ctx )
|
||||
{
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
GLuint i;
|
||||
|
||||
for (i = 0 ; i < tnl->pipeline.nr_stages ; i++) {
|
||||
struct tnl_pipeline_stage *s = &tnl->pipeline.stages[i];
|
||||
if (s->destroy)
|
||||
s->destroy(s);
|
||||
}
|
||||
|
||||
tnl->pipeline.nr_stages = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static GLuint check_input_changes( struct gl_context *ctx )
|
||||
{
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
GLuint i;
|
||||
|
||||
for (i = 0; i <= _TNL_LAST_MAT; i++) {
|
||||
if (tnl->vb.AttribPtr[i]->size != tnl->pipeline.last_attrib_size[i] ||
|
||||
tnl->vb.AttribPtr[i]->stride != tnl->pipeline.last_attrib_stride[i]) {
|
||||
tnl->pipeline.last_attrib_size[i] = tnl->vb.AttribPtr[i]->size;
|
||||
tnl->pipeline.last_attrib_stride[i] = tnl->vb.AttribPtr[i]->stride;
|
||||
tnl->pipeline.input_changes |= 1<<i;
|
||||
}
|
||||
}
|
||||
|
||||
return tnl->pipeline.input_changes;
|
||||
}
|
||||
|
||||
|
||||
static GLuint check_output_changes( struct gl_context *ctx )
|
||||
{
|
||||
#if 0
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
|
||||
for (i = 0; i < VARYING_SLOT_MAX; i++) {
|
||||
if (tnl->vb.ResultPtr[i]->size != tnl->last_result_size[i] ||
|
||||
tnl->vb.ResultPtr[i]->stride != tnl->last_result_stride[i]) {
|
||||
tnl->last_result_size[i] = tnl->vb.ResultPtr[i]->size;
|
||||
tnl->last_result_stride[i] = tnl->vb.ResultPtr[i]->stride;
|
||||
tnl->pipeline.output_changes |= 1<<i;
|
||||
}
|
||||
}
|
||||
|
||||
if (tnl->pipeline.output_changes)
|
||||
tnl->Driver.NotifyOutputChanges( ctx, tnl->pipeline.output_changes );
|
||||
|
||||
return tnl->pipeline.output_changes;
|
||||
#else
|
||||
return ~0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* START/END_FAST_MATH macros:
|
||||
*
|
||||
* START_FAST_MATH: Set x86 FPU to faster, 32-bit precision mode (and save
|
||||
* original mode to a temporary).
|
||||
* END_FAST_MATH: Restore x86 FPU to original mode.
|
||||
*/
|
||||
#if defined(__GNUC__) && defined(__i386__)
|
||||
/*
|
||||
* Set the x86 FPU control word to guarentee only 32 bits of precision
|
||||
* are stored in registers. Allowing the FPU to store more introduces
|
||||
* differences between situations where numbers are pulled out of memory
|
||||
* vs. situations where the compiler is able to optimize register usage.
|
||||
*
|
||||
* In the worst case, we force the compiler to use a memory access to
|
||||
* truncate the float, by specifying the 'volatile' keyword.
|
||||
*/
|
||||
/* Hardware default: All exceptions masked, extended double precision,
|
||||
* round to nearest (IEEE compliant):
|
||||
*/
|
||||
#define DEFAULT_X86_FPU 0x037f
|
||||
/* All exceptions masked, single precision, round to nearest:
|
||||
*/
|
||||
#define FAST_X86_FPU 0x003f
|
||||
/* The fldcw instruction will cause any pending FP exceptions to be
|
||||
* raised prior to entering the block, and we clear any pending
|
||||
* exceptions before exiting the block. Hence, asm code has free
|
||||
* reign over the FPU while in the fast math block.
|
||||
*/
|
||||
#if defined(NO_FAST_MATH)
|
||||
#define START_FAST_MATH(x) \
|
||||
do { \
|
||||
static GLuint mask = DEFAULT_X86_FPU; \
|
||||
__asm__ ( "fnstcw %0" : "=m" (*&(x)) ); \
|
||||
__asm__ ( "fldcw %0" : : "m" (mask) ); \
|
||||
} while (0)
|
||||
#else
|
||||
#define START_FAST_MATH(x) \
|
||||
do { \
|
||||
static GLuint mask = FAST_X86_FPU; \
|
||||
__asm__ ( "fnstcw %0" : "=m" (*&(x)) ); \
|
||||
__asm__ ( "fldcw %0" : : "m" (mask) ); \
|
||||
} while (0)
|
||||
#endif
|
||||
/* Restore original FPU mode, and clear any exceptions that may have
|
||||
* occurred in the FAST_MATH block.
|
||||
*/
|
||||
#define END_FAST_MATH(x) \
|
||||
do { \
|
||||
__asm__ ( "fnclex ; fldcw %0" : : "m" (*&(x)) ); \
|
||||
} while (0)
|
||||
|
||||
#elif defined(_MSC_VER) && defined(_M_IX86)
|
||||
#define DEFAULT_X86_FPU 0x037f /* See GCC comments above */
|
||||
#define FAST_X86_FPU 0x003f /* See GCC comments above */
|
||||
#if defined(NO_FAST_MATH)
|
||||
#define START_FAST_MATH(x) do {\
|
||||
static GLuint mask = DEFAULT_X86_FPU;\
|
||||
__asm fnstcw word ptr [x]\
|
||||
__asm fldcw word ptr [mask]\
|
||||
} while(0)
|
||||
#else
|
||||
#define START_FAST_MATH(x) do {\
|
||||
static GLuint mask = FAST_X86_FPU;\
|
||||
__asm fnstcw word ptr [x]\
|
||||
__asm fldcw word ptr [mask]\
|
||||
} while(0)
|
||||
#endif
|
||||
#define END_FAST_MATH(x) do {\
|
||||
__asm fnclex\
|
||||
__asm fldcw word ptr [x]\
|
||||
} while(0)
|
||||
|
||||
#else
|
||||
#define START_FAST_MATH(x) x = 0
|
||||
#define END_FAST_MATH(x) (void)(x)
|
||||
#endif
|
||||
|
||||
|
||||
void _tnl_run_pipeline( struct gl_context *ctx )
|
||||
{
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
unsigned short __tmp;
|
||||
GLuint i;
|
||||
|
||||
if (!tnl->vb.Count)
|
||||
return;
|
||||
|
||||
/* Check for changed input sizes or change in stride to/from zero
|
||||
* (ie const or non-const).
|
||||
*/
|
||||
if (check_input_changes( ctx ) || tnl->pipeline.new_state) {
|
||||
if (ctx->VertexProgram._MaintainTnlProgram)
|
||||
_tnl_UpdateFixedFunctionProgram( ctx );
|
||||
|
||||
for (i = 0; i < tnl->pipeline.nr_stages ; i++) {
|
||||
struct tnl_pipeline_stage *s = &tnl->pipeline.stages[i];
|
||||
if (s->validate)
|
||||
s->validate( ctx, s );
|
||||
}
|
||||
|
||||
tnl->pipeline.new_state = 0;
|
||||
tnl->pipeline.input_changes = 0;
|
||||
|
||||
/* Pipeline can only change its output in response to either a
|
||||
* statechange or an input size/stride change. No other changes
|
||||
* are allowed.
|
||||
*/
|
||||
if (check_output_changes( ctx ))
|
||||
_tnl_notify_pipeline_output_change( ctx );
|
||||
}
|
||||
|
||||
#ifndef _OPENMP
|
||||
/* Don't adjust FPU precision mode in case multiple threads are to be used.
|
||||
* This would require that the additional threads also changed the FPU mode
|
||||
* which is quite a mess as this had to be done in all parallelized sections;
|
||||
* otherwise the master thread and all other threads are running in different
|
||||
* modes, producing inconsistent results.
|
||||
* Note that all x64 implementations don't define/use START_FAST_MATH, so
|
||||
* this is "hack" is only used in i386 mode
|
||||
*/
|
||||
START_FAST_MATH(__tmp);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < tnl->pipeline.nr_stages ; i++) {
|
||||
struct tnl_pipeline_stage *s = &tnl->pipeline.stages[i];
|
||||
if (!s->run( ctx, s ))
|
||||
break;
|
||||
}
|
||||
|
||||
#ifndef _OPENMP
|
||||
END_FAST_MATH(__tmp);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* The default pipeline. This is useful for software rasterizers, and
|
||||
* simple hardware rasterizers. For customization, I don't recommend
|
||||
* tampering with the internals of these stages in the way that
|
||||
* drivers did in Mesa 3.4. These stages are basically black boxes,
|
||||
* and should be left intact.
|
||||
*
|
||||
* To customize the pipeline, consider:
|
||||
*
|
||||
* - removing redundant stages (making sure that the software rasterizer
|
||||
* can cope with this on fallback paths). An example is fog
|
||||
* coordinate generation, which is not required in the FX driver.
|
||||
*
|
||||
* - replacing general-purpose machine-independent stages with
|
||||
* general-purpose machine-specific stages. There is no example of
|
||||
* this to date, though it must be borne in mind that all subsequent
|
||||
* stages that reference the output of the new stage must cope with
|
||||
* any machine-specific data introduced. This may not be easy
|
||||
* unless there are no such stages (ie the new stage is the last in
|
||||
* the pipe).
|
||||
*
|
||||
* - inserting optimized (but specialized) stages ahead of the
|
||||
* general-purpose fallback implementation. For example, the old
|
||||
* fastpath mechanism, which only works when the VB->Elts input is
|
||||
* available, can be duplicated by placing the fastpath stage at the
|
||||
* head of this pipeline. Such specialized stages are currently
|
||||
* constrained to have no outputs (ie. they must either finish the *
|
||||
* pipeline by returning GL_FALSE from run(), or do nothing).
|
||||
*
|
||||
* Some work can be done to lift some of the restrictions in the final
|
||||
* case, if it becomes necessary to do so.
|
||||
*/
|
||||
const struct tnl_pipeline_stage *_tnl_default_pipeline[] = {
|
||||
&_tnl_vertex_transform_stage,
|
||||
&_tnl_normal_transform_stage,
|
||||
&_tnl_lighting_stage,
|
||||
&_tnl_texgen_stage,
|
||||
&_tnl_texture_transform_stage,
|
||||
&_tnl_point_attenuation_stage,
|
||||
&_tnl_vertex_program_stage,
|
||||
&_tnl_fog_coordinate_stage,
|
||||
&_tnl_render_stage,
|
||||
NULL
|
||||
};
|
||||
|
||||
const struct tnl_pipeline_stage *_tnl_vp_pipeline[] = {
|
||||
&_tnl_vertex_program_stage,
|
||||
&_tnl_render_stage,
|
||||
NULL
|
||||
};
|
|
@ -1,73 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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@vmware.com>
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef _T_PIPELINE_H_
|
||||
#define _T_PIPELINE_H_
|
||||
|
||||
#include "main/mtypes.h"
|
||||
#include "t_context.h"
|
||||
|
||||
extern void _tnl_run_pipeline( struct gl_context *ctx );
|
||||
|
||||
extern void _tnl_destroy_pipeline( struct gl_context *ctx );
|
||||
|
||||
extern void _tnl_install_pipeline( struct gl_context *ctx,
|
||||
const struct tnl_pipeline_stage **stages );
|
||||
|
||||
|
||||
/* These are implemented in the t_vb_*.c files:
|
||||
*/
|
||||
extern const struct tnl_pipeline_stage _tnl_vertex_transform_stage;
|
||||
extern const struct tnl_pipeline_stage _tnl_normal_transform_stage;
|
||||
extern const struct tnl_pipeline_stage _tnl_lighting_stage;
|
||||
extern const struct tnl_pipeline_stage _tnl_fog_coordinate_stage;
|
||||
extern const struct tnl_pipeline_stage _tnl_texgen_stage;
|
||||
extern const struct tnl_pipeline_stage _tnl_texture_transform_stage;
|
||||
extern const struct tnl_pipeline_stage _tnl_point_attenuation_stage;
|
||||
extern const struct tnl_pipeline_stage _tnl_vertex_program_stage;
|
||||
extern const struct tnl_pipeline_stage _tnl_render_stage;
|
||||
|
||||
/* Shorthand to plug in the default pipeline:
|
||||
*/
|
||||
extern const struct tnl_pipeline_stage *_tnl_default_pipeline[];
|
||||
extern const struct tnl_pipeline_stage *_tnl_vp_pipeline[];
|
||||
|
||||
|
||||
/* Convenience routines provided by t_vb_render.c:
|
||||
*/
|
||||
extern tnl_render_func _tnl_render_tab_elts[];
|
||||
extern tnl_render_func _tnl_render_tab_verts[];
|
||||
|
||||
extern void _tnl_RenderClippedPolygon( struct gl_context *ctx,
|
||||
const GLuint *elts, GLuint n );
|
||||
|
||||
extern void _tnl_RenderClippedLine( struct gl_context *ctx, GLuint ii, GLuint jj );
|
||||
|
||||
|
||||
#endif
|
|
@ -1,267 +0,0 @@
|
|||
|
||||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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@vmware.com>
|
||||
*/
|
||||
|
||||
/* Helper for drivers which find themselves rendering a range of
|
||||
* indices starting somewhere above zero. Typically the application
|
||||
* is issuing multiple DrawArrays() or DrawElements() to draw
|
||||
* successive primitives layed out linearly in the vertex arrays.
|
||||
* Unless the vertex arrays are all in a VBO, the OpenGL semantics
|
||||
* imply that we need to re-upload the vertex data on each draw call.
|
||||
* In that case, we want to avoid starting the upload at zero, as it
|
||||
* will mean every draw call uploads an increasing amount of not-used
|
||||
* vertex data. Worse - in the software tnl module, all those
|
||||
* vertices will be transformed and lit.
|
||||
*
|
||||
* If we just upload the new data, however, the indices will be
|
||||
* incorrect as we tend to upload each set of vertex data to a new
|
||||
* region.
|
||||
*
|
||||
* This file provides a helper to adjust the arrays, primitives and
|
||||
* indices of a draw call so that it can be re-issued with a min_index
|
||||
* of zero.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "main/bufferobj.h"
|
||||
#include "main/errors.h"
|
||||
#include "main/glheader.h"
|
||||
#include "main/macros.h"
|
||||
#include "main/mtypes.h"
|
||||
#include "vbo/vbo.h"
|
||||
|
||||
#include "t_rebase.h"
|
||||
|
||||
|
||||
#define REBASE(TYPE) \
|
||||
static void *rebase_##TYPE(const void *ptr, \
|
||||
unsigned start, \
|
||||
unsigned count, \
|
||||
TYPE min_index) \
|
||||
{ \
|
||||
const TYPE *in = (TYPE *)ptr; \
|
||||
TYPE *tmp_indices = malloc((start + count) * sizeof(TYPE)); \
|
||||
\
|
||||
if (tmp_indices == NULL) { \
|
||||
_mesa_error_no_memory(__func__); \
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
for (unsigned i = 0; i < count; i++) \
|
||||
tmp_indices[start + i] = in[start + i] - min_index; \
|
||||
\
|
||||
return (void *)tmp_indices; \
|
||||
}
|
||||
|
||||
REBASE(GLuint)
|
||||
REBASE(GLushort)
|
||||
REBASE(GLubyte)
|
||||
|
||||
|
||||
/* Adjust primitives, indices and vertex definitions so that min_index
|
||||
* becomes zero. There are lots of reasons for wanting to do this, eg:
|
||||
*
|
||||
* Software tnl:
|
||||
* - any time min_index != 0, otherwise unused vertices lower than
|
||||
* min_index will be transformed.
|
||||
*
|
||||
* Hardware tnl:
|
||||
* - if ib != NULL and min_index != 0, otherwise vertices lower than
|
||||
* min_index will be uploaded. Requires adjusting index values.
|
||||
*
|
||||
* - if ib == NULL and min_index != 0, just for convenience so this doesn't
|
||||
* have to be handled within the driver.
|
||||
*
|
||||
* Hardware tnl with VBO support:
|
||||
* - as above, but only when vertices are not (all?) in VBO's.
|
||||
* - can't save time by trying to upload half a vbo - typically it is
|
||||
* all or nothing.
|
||||
*/
|
||||
void t_rebase_prims(struct gl_context *ctx,
|
||||
const struct tnl_vertex_array *arrays,
|
||||
const struct _mesa_prim *prim,
|
||||
GLuint nr_prims,
|
||||
const struct _mesa_index_buffer *ib,
|
||||
GLuint min_index,
|
||||
GLuint max_index,
|
||||
GLuint num_instances,
|
||||
GLuint base_instance,
|
||||
tnl_draw_func draw)
|
||||
{
|
||||
struct gl_array_attributes tmp_attribs[VERT_ATTRIB_MAX];
|
||||
struct tnl_vertex_array tmp_arrays[VERT_ATTRIB_MAX];
|
||||
|
||||
struct _mesa_index_buffer tmp_ib;
|
||||
struct _mesa_prim *tmp_prims = NULL;
|
||||
void *tmp_indices = NULL;
|
||||
GLuint i;
|
||||
|
||||
assert(min_index != 0);
|
||||
|
||||
if (0)
|
||||
printf("%s %d..%d\n", __func__, min_index, max_index);
|
||||
|
||||
/* XXX this path is disabled for now.
|
||||
* There's rendering corruption in some apps when it's enabled.
|
||||
*/
|
||||
if (0 && ib && ctx->Extensions.ARB_draw_elements_base_vertex) {
|
||||
/* If we can just tell the hardware or the TNL to interpret our indices
|
||||
* with a different base, do so.
|
||||
*/
|
||||
tmp_prims = malloc(sizeof(*prim) * nr_prims);
|
||||
|
||||
if (tmp_prims == NULL) {
|
||||
_mesa_error_no_memory(__func__);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < nr_prims; i++) {
|
||||
tmp_prims[i] = prim[i];
|
||||
tmp_prims[i].basevertex -= min_index;
|
||||
}
|
||||
|
||||
prim = tmp_prims;
|
||||
} else if (ib) {
|
||||
unsigned start = prim[0].start;
|
||||
for (i = 1; i < nr_prims; i++) {
|
||||
if (prim[i].start != start) {
|
||||
if (0) {
|
||||
printf("%s recursing due to mismatched start "
|
||||
"(prim[0].start = %u vs. prim[%u].start = %u)\n",
|
||||
__func__, start, i, prim[i].start);
|
||||
}
|
||||
|
||||
t_rebase_prims(ctx, arrays, &prim[0], i, ib, min_index,
|
||||
max_index, num_instances, base_instance, draw);
|
||||
t_rebase_prims(ctx, arrays, &prim[i], nr_prims - i, ib, min_index,
|
||||
max_index, num_instances, base_instance, draw);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Unfortunately need to adjust each index individually.
|
||||
*/
|
||||
bool map_ib = false;
|
||||
const void *ptr;
|
||||
|
||||
if (ib->obj) {
|
||||
if (!ib->obj->Mappings[MAP_INTERNAL].Pointer) {
|
||||
ctx->Driver.MapBufferRange(ctx, 0, ib->obj->Size, GL_MAP_READ_BIT,
|
||||
ib->obj, MAP_INTERNAL);
|
||||
map_ib = true;
|
||||
}
|
||||
|
||||
ptr = ADD_POINTERS(ib->obj->Mappings[MAP_INTERNAL].Pointer, ib->ptr);
|
||||
} else
|
||||
ptr = ib->ptr;
|
||||
|
||||
/* Some users might prefer it if we translated elements to GLuints here.
|
||||
* Others wouldn't...
|
||||
*/
|
||||
switch (ib->index_size_shift) {
|
||||
case 2:
|
||||
tmp_indices = rebase_GLuint(ptr, start, ib->count, min_index);
|
||||
break;
|
||||
case 1:
|
||||
tmp_indices = rebase_GLushort(ptr, start, ib->count, min_index);
|
||||
break;
|
||||
case 0:
|
||||
tmp_indices = rebase_GLubyte(ptr, start, ib->count, min_index);
|
||||
break;
|
||||
}
|
||||
|
||||
if (map_ib)
|
||||
ctx->Driver.UnmapBuffer(ctx, ib->obj, MAP_INTERNAL);
|
||||
|
||||
if (tmp_indices == NULL)
|
||||
return;
|
||||
|
||||
tmp_ib.obj = NULL;
|
||||
tmp_ib.ptr = tmp_indices;
|
||||
tmp_ib.count = ib->count;
|
||||
tmp_ib.index_size_shift = ib->index_size_shift;
|
||||
|
||||
ib = &tmp_ib;
|
||||
}
|
||||
else {
|
||||
/* Otherwise the primitives need adjustment. */
|
||||
tmp_prims = malloc(sizeof(*prim) * nr_prims);
|
||||
|
||||
if (tmp_prims == NULL) {
|
||||
_mesa_error_no_memory(__func__);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < nr_prims; i++) {
|
||||
/* If this fails, it could indicate an application error: */
|
||||
assert(prim[i].start >= min_index);
|
||||
|
||||
tmp_prims[i] = prim[i];
|
||||
tmp_prims[i].start -= min_index;
|
||||
}
|
||||
|
||||
prim = tmp_prims;
|
||||
}
|
||||
|
||||
/* Just need to adjust the pointer values on each incoming array.
|
||||
* This works for VBO and non-vbo rendering and shouldn't pesimize
|
||||
* VBO-based upload schemes. However this may still not be a fast
|
||||
* path for hardware tnl for VBO based rendering as most machines
|
||||
* will be happier if you just specify a starting vertex value in
|
||||
* each primitive.
|
||||
*
|
||||
* For drivers with hardware tnl, you only want to do this if you
|
||||
* are forced to, eg non-VBO indexed rendering with start != 0.
|
||||
*/
|
||||
for (i = 0; i < VERT_ATTRIB_MAX; i++) {
|
||||
tmp_attribs[i] = *(arrays[i].VertexAttrib);
|
||||
tmp_arrays[i].BufferBinding = arrays[i].BufferBinding;
|
||||
tmp_arrays[i].VertexAttrib = &tmp_attribs[i];
|
||||
if (arrays[i].BufferBinding->BufferObj)
|
||||
tmp_attribs[i].RelativeOffset +=
|
||||
min_index * arrays[i].BufferBinding->Stride;
|
||||
else
|
||||
tmp_attribs[i].Ptr += min_index * arrays[i].BufferBinding->Stride;
|
||||
}
|
||||
|
||||
/* Re-issue the draw call. */
|
||||
draw(ctx,
|
||||
tmp_arrays,
|
||||
prim,
|
||||
nr_prims,
|
||||
ib,
|
||||
GL_TRUE,
|
||||
0,
|
||||
max_index - min_index,
|
||||
num_instances, base_instance);
|
||||
|
||||
free(tmp_indices);
|
||||
free(tmp_prims);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
/*
|
||||
* mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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 _T_REBASE_H_
|
||||
#define _T_REBASE_H_
|
||||
|
||||
#include "tnl.h"
|
||||
|
||||
void t_rebase_prims( struct gl_context *ctx,
|
||||
const struct tnl_vertex_array *arrays,
|
||||
const struct _mesa_prim *prim,
|
||||
GLuint nr_prims,
|
||||
const struct _mesa_index_buffer *ib,
|
||||
GLuint min_index,
|
||||
GLuint max_index,
|
||||
GLuint num_instances,
|
||||
GLuint base_instance,
|
||||
tnl_draw_func draw );
|
||||
|
||||
#endif
|
|
@ -1,162 +0,0 @@
|
|||
|
||||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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@vmware.com>
|
||||
*/
|
||||
|
||||
/* Deal with hardware and/or swtnl maximums:
|
||||
* - maximum number of vertices in buffer
|
||||
* - maximum number of elements (maybe zero)
|
||||
*
|
||||
* The maximums may vary with opengl state (eg if a larger hardware
|
||||
* vertex is required in this state, the maximum number of vertices
|
||||
* may be smaller than in another state).
|
||||
*
|
||||
* We want buffer splitting to be a convenience function for the code
|
||||
* actually drawing the primitives rather than a system-wide maximum,
|
||||
* otherwise it is hard to avoid pessimism.
|
||||
*
|
||||
* For instance, if a driver has no hardware limits on vertex buffer
|
||||
* dimensions, it would not ordinarily want to split vbos. But if
|
||||
* there is an unexpected fallback, eg memory manager fails to upload
|
||||
* textures, it will want to pass the drawing commands onto swtnl,
|
||||
* which does have limitations. A convenience function allows swtnl
|
||||
* to split the drawing and vbos internally without imposing its
|
||||
* limitations on drivers which want to use it as a fallback path.
|
||||
*/
|
||||
|
||||
#include "main/glheader.h"
|
||||
#include "main/mtypes.h"
|
||||
#include "vbo/vbo.h"
|
||||
|
||||
#include "t_split.h"
|
||||
|
||||
|
||||
/* True if a primitive can be split without copying of vertices, false
|
||||
* otherwise.
|
||||
*/
|
||||
GLboolean
|
||||
_tnl_split_prim_inplace(GLenum mode, GLuint *first, GLuint *incr)
|
||||
{
|
||||
switch (mode) {
|
||||
case GL_POINTS:
|
||||
*first = 1;
|
||||
*incr = 1;
|
||||
return GL_TRUE;
|
||||
case GL_LINES:
|
||||
*first = 2;
|
||||
*incr = 2;
|
||||
return GL_TRUE;
|
||||
case GL_LINE_STRIP:
|
||||
*first = 2;
|
||||
*incr = 1;
|
||||
return GL_TRUE;
|
||||
case GL_TRIANGLES:
|
||||
*first = 3;
|
||||
*incr = 3;
|
||||
return GL_TRUE;
|
||||
case GL_TRIANGLE_STRIP:
|
||||
*first = 3;
|
||||
*incr = 1;
|
||||
return GL_TRUE;
|
||||
case GL_QUADS:
|
||||
*first = 4;
|
||||
*incr = 4;
|
||||
return GL_TRUE;
|
||||
case GL_QUAD_STRIP:
|
||||
*first = 4;
|
||||
*incr = 2;
|
||||
return GL_TRUE;
|
||||
default:
|
||||
*first = 0;
|
||||
*incr = 1; /* so that count % incr works */
|
||||
return GL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
_tnl_split_prims(struct gl_context *ctx,
|
||||
const struct tnl_vertex_array arrays[],
|
||||
const struct _mesa_prim *prim,
|
||||
GLuint nr_prims,
|
||||
const struct _mesa_index_buffer *ib,
|
||||
GLuint min_index,
|
||||
GLuint max_index,
|
||||
GLuint num_instances,
|
||||
GLuint base_instance,
|
||||
tnl_draw_func draw,
|
||||
const struct split_limits *limits)
|
||||
{
|
||||
if (ib) {
|
||||
if (limits->max_indices == 0) {
|
||||
/* Could traverse the indices, re-emitting vertices in turn.
|
||||
* But it's hard to see why this case would be needed - for
|
||||
* software tnl, it is better to convert to non-indexed
|
||||
* rendering after transformation is complete. Are there any devices
|
||||
* with hardware tnl that cannot do indexed rendering?
|
||||
*
|
||||
* For now, this path is disabled.
|
||||
*/
|
||||
assert(0);
|
||||
}
|
||||
else if (max_index - min_index >= limits->max_verts) {
|
||||
/* The vertex buffers are too large for hardware (or the
|
||||
* swtnl module). Traverse the indices, re-emitting vertices
|
||||
* in turn. Use a vertex cache to preserve some of the
|
||||
* sharing from the original index list.
|
||||
*/
|
||||
_tnl_split_copy(ctx, arrays, prim, nr_prims, ib, draw, limits);
|
||||
}
|
||||
else if (ib->count > limits->max_indices) {
|
||||
/* The index buffer is too large for hardware. Try to split
|
||||
* on whole-primitive boundaries, otherwise try to split the
|
||||
* individual primitives.
|
||||
*/
|
||||
_tnl_split_inplace(ctx, arrays, prim, nr_prims, ib,
|
||||
num_instances, base_instance, draw, limits);
|
||||
}
|
||||
else {
|
||||
/* Why were we called? */
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (max_index - min_index >= limits->max_verts) {
|
||||
/* The vertex buffer is too large for hardware (or the swtnl
|
||||
* module). Try to split on whole-primitive boundaries,
|
||||
* otherwise try to split the individual primitives.
|
||||
*/
|
||||
_tnl_split_inplace(ctx, arrays, prim, nr_prims, ib,
|
||||
num_instances, base_instance, draw, limits);
|
||||
}
|
||||
else {
|
||||
/* Why were we called? */
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
/*
|
||||
* mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief VBO builder module datatypes and definitions.
|
||||
* \author Keith Whitwell
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* \mainpage The TNL splitter
|
||||
*
|
||||
* This is the private data used internally to the _tnl_split_prims()
|
||||
* helper function. Nobody outside the _tnl_split* files needs to
|
||||
* include or know about this structure.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _TNL_SPLIT_H
|
||||
#define _TNL_SPLIT_H
|
||||
|
||||
#include "tnl.h"
|
||||
|
||||
|
||||
/* True if a primitive can be split without copying of vertices, false
|
||||
* otherwise.
|
||||
*/
|
||||
GLboolean
|
||||
_tnl_split_prim_inplace(GLenum mode, GLuint *first, GLuint *incr);
|
||||
|
||||
void
|
||||
_tnl_split_inplace(struct gl_context *ctx,
|
||||
const struct tnl_vertex_array arrays[],
|
||||
const struct _mesa_prim *prim,
|
||||
GLuint nr_prims,
|
||||
const struct _mesa_index_buffer *ib,
|
||||
GLuint num_instances,
|
||||
GLuint base_instance,
|
||||
tnl_draw_func draw,
|
||||
const struct split_limits *limits);
|
||||
|
||||
/* Requires ib != NULL:
|
||||
*/
|
||||
void
|
||||
_tnl_split_copy(struct gl_context *ctx,
|
||||
const struct tnl_vertex_array arrays[],
|
||||
const struct _mesa_prim *prim,
|
||||
GLuint nr_prims,
|
||||
const struct _mesa_index_buffer *ib,
|
||||
tnl_draw_func draw,
|
||||
const struct split_limits *limits);
|
||||
|
||||
#endif
|
|
@ -1,637 +0,0 @@
|
|||
|
||||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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@vmware.com>
|
||||
*/
|
||||
|
||||
/* Split indexed primitives with per-vertex copying.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "main/glheader.h"
|
||||
#include "main/bufferobj.h"
|
||||
|
||||
#include "main/glformats.h"
|
||||
#include "main/macros.h"
|
||||
#include "main/mtypes.h"
|
||||
#include "main/varray.h"
|
||||
#include "vbo/vbo.h"
|
||||
|
||||
#include "t_split.h"
|
||||
#include "tnl.h"
|
||||
|
||||
|
||||
#define ELT_TABLE_SIZE 16
|
||||
|
||||
/**
|
||||
* Used for vertex-level splitting of indexed buffers. Note that
|
||||
* non-indexed primitives may be converted to indexed in some cases
|
||||
* (eg loops, fans) in order to use this splitting path.
|
||||
*/
|
||||
struct copy_context {
|
||||
struct gl_context *ctx;
|
||||
const struct tnl_vertex_array *array;
|
||||
const struct _mesa_prim *prim;
|
||||
GLuint nr_prims;
|
||||
const struct _mesa_index_buffer *ib;
|
||||
tnl_draw_func draw;
|
||||
|
||||
const struct split_limits *limits;
|
||||
|
||||
struct {
|
||||
GLuint attr;
|
||||
GLuint size;
|
||||
const struct tnl_vertex_array *array;
|
||||
const GLubyte *src_ptr;
|
||||
|
||||
struct gl_vertex_buffer_binding dstbinding;
|
||||
struct gl_array_attributes dstattribs;
|
||||
|
||||
} varying[VERT_ATTRIB_MAX];
|
||||
GLuint nr_varying;
|
||||
|
||||
struct tnl_vertex_array dstarray[VERT_ATTRIB_MAX];
|
||||
struct _mesa_index_buffer dstib;
|
||||
|
||||
GLuint *translated_elt_buf;
|
||||
const GLuint *srcelt;
|
||||
|
||||
/** A baby hash table to avoid re-emitting (some) duplicate
|
||||
* vertices when splitting indexed primitives.
|
||||
*/
|
||||
struct {
|
||||
GLuint in;
|
||||
GLuint out;
|
||||
} vert_cache[ELT_TABLE_SIZE];
|
||||
|
||||
GLuint vertex_size;
|
||||
GLubyte *dstbuf;
|
||||
GLubyte *dstptr; /**< dstptr == dstbuf + dstelt_max * vertsize */
|
||||
GLuint dstbuf_size; /**< in vertices */
|
||||
GLuint dstbuf_nr; /**< count of emitted vertices, also the largest value
|
||||
* in dstelt. Our MaxIndex.
|
||||
*/
|
||||
|
||||
GLuint *dstelt;
|
||||
GLuint dstelt_nr;
|
||||
GLuint dstelt_size;
|
||||
|
||||
#define MAX_PRIM 32
|
||||
struct _mesa_prim dstprim[MAX_PRIM];
|
||||
GLuint dstprim_nr;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Shallow copy one vertex array to another.
|
||||
*/
|
||||
static inline void
|
||||
copy_vertex_array(struct tnl_vertex_array *dst,
|
||||
const struct tnl_vertex_array *src)
|
||||
{
|
||||
dst->VertexAttrib = src->VertexAttrib;
|
||||
dst->BufferBinding = src->BufferBinding;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Starts returning true slightly before the buffer fills, to ensure
|
||||
* that there is sufficient room for any remaining vertices to finish
|
||||
* off the prim:
|
||||
*/
|
||||
static GLboolean
|
||||
check_flush(struct copy_context *copy)
|
||||
{
|
||||
GLenum mode = copy->dstprim[copy->dstprim_nr].mode;
|
||||
|
||||
if (GL_TRIANGLE_STRIP == mode &&
|
||||
copy->dstelt_nr & 1) { /* see bug9962 */
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
if (copy->dstbuf_nr + 4 > copy->dstbuf_size)
|
||||
return GL_TRUE;
|
||||
|
||||
if (copy->dstelt_nr + 4 > copy->dstelt_size)
|
||||
return GL_TRUE;
|
||||
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Dump the parameters/info for a vbo->draw() call.
|
||||
*/
|
||||
static void
|
||||
dump_draw_info(const struct tnl_vertex_array *arrays,
|
||||
const struct _mesa_prim *prims,
|
||||
GLuint nr_prims,
|
||||
const struct _mesa_index_buffer *ib)
|
||||
{
|
||||
GLuint i, j;
|
||||
|
||||
printf("VBO Draw:\n");
|
||||
for (i = 0; i < nr_prims; i++) {
|
||||
printf("Prim %u of %u\n", i, nr_prims);
|
||||
printf(" Prim mode 0x%x\n", prims[i].mode);
|
||||
printf(" IB: %p\n", (void*) ib);
|
||||
for (j = 0; j < VERT_ATTRIB_MAX; j++) {
|
||||
const struct tnl_vertex_array *array = &arrays[j];
|
||||
const struct gl_vertex_buffer_binding *binding
|
||||
= array->BufferBinding;
|
||||
const struct gl_array_attributes *attrib = array->VertexAttrib;
|
||||
const GLubyte *ptr = _mesa_vertex_attrib_address(attrib, binding);
|
||||
printf(" array %d at %p:\n", j, (void*) &arrays[j]);
|
||||
printf(" ptr %p, size %d, type 0x%x, stride %d\n",
|
||||
ptr, attrib->Format.Size, attrib->Format.Type, binding->Stride);
|
||||
if (0) {
|
||||
GLint k = prims[i].start + prims[i].count - 1;
|
||||
GLfloat *last = (GLfloat *) (ptr + binding->Stride * k);
|
||||
printf(" last: %f %f %f\n",
|
||||
last[0], last[1], last[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
flush(struct copy_context *copy)
|
||||
{
|
||||
struct gl_context *ctx = copy->ctx;
|
||||
GLuint i;
|
||||
|
||||
/* Set some counters:
|
||||
*/
|
||||
copy->dstib.count = copy->dstelt_nr;
|
||||
|
||||
#if 0
|
||||
dump_draw_info(copy->dstarray,
|
||||
copy->dstprim,
|
||||
copy->dstprim_nr,
|
||||
©->dstib);
|
||||
#else
|
||||
(void) dump_draw_info;
|
||||
#endif
|
||||
|
||||
copy->draw(ctx,
|
||||
copy->dstarray,
|
||||
copy->dstprim,
|
||||
copy->dstprim_nr,
|
||||
©->dstib,
|
||||
GL_TRUE,
|
||||
0,
|
||||
copy->dstbuf_nr - 1,
|
||||
1,
|
||||
0);
|
||||
|
||||
/* Reset all pointers:
|
||||
*/
|
||||
copy->dstprim_nr = 0;
|
||||
copy->dstelt_nr = 0;
|
||||
copy->dstbuf_nr = 0;
|
||||
copy->dstptr = copy->dstbuf;
|
||||
|
||||
/* Clear the vertex cache:
|
||||
*/
|
||||
for (i = 0; i < ELT_TABLE_SIZE; i++)
|
||||
copy->vert_cache[i].in = ~0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called at begin of each primitive during replay.
|
||||
*/
|
||||
static void
|
||||
begin(struct copy_context *copy, GLenum mode, GLboolean begin_flag)
|
||||
{
|
||||
struct _mesa_prim *prim = ©->dstprim[copy->dstprim_nr];
|
||||
|
||||
prim->mode = mode;
|
||||
prim->begin = begin_flag;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Use a hashtable to attempt to identify recently-emitted vertices
|
||||
* and avoid re-emitting them.
|
||||
*/
|
||||
static GLuint
|
||||
elt(struct copy_context *copy, GLuint elt_idx)
|
||||
{
|
||||
GLuint elt = copy->srcelt[elt_idx] + copy->prim->basevertex;
|
||||
GLuint slot = elt & (ELT_TABLE_SIZE-1);
|
||||
|
||||
/* Look up the incoming element in the vertex cache. Re-emit if
|
||||
* necessary.
|
||||
*/
|
||||
if (copy->vert_cache[slot].in != elt) {
|
||||
GLubyte *csr = copy->dstptr;
|
||||
GLuint i;
|
||||
|
||||
for (i = 0; i < copy->nr_varying; i++) {
|
||||
const struct tnl_vertex_array *srcarray = copy->varying[i].array;
|
||||
const struct gl_vertex_buffer_binding* srcbinding
|
||||
= srcarray->BufferBinding;
|
||||
const GLubyte *srcptr
|
||||
= copy->varying[i].src_ptr + elt * srcbinding->Stride;
|
||||
|
||||
memcpy(csr, srcptr, copy->varying[i].size);
|
||||
csr += copy->varying[i].size;
|
||||
|
||||
#ifdef NAN_CHECK
|
||||
if (srcarray->Format.Type == GL_FLOAT) {
|
||||
GLuint k;
|
||||
GLfloat *f = (GLfloat *) srcptr;
|
||||
for (k = 0; k < srcarray->Size; k++) {
|
||||
assert(!util_is_inf_or_nan(f[k]));
|
||||
assert(f[k] <= 1.0e20 && f[k] >= -1.0e20);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (0) {
|
||||
const GLuint *f = (const GLuint *)srcptr;
|
||||
GLuint j;
|
||||
printf(" varying %d: ", i);
|
||||
for (j = 0; j < copy->varying[i].size / 4; j++)
|
||||
printf("%x ", f[j]);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
copy->vert_cache[slot].in = elt;
|
||||
copy->vert_cache[slot].out = copy->dstbuf_nr++;
|
||||
copy->dstptr += copy->vertex_size;
|
||||
|
||||
assert(csr == copy->dstptr);
|
||||
assert(copy->dstptr == (copy->dstbuf +
|
||||
copy->dstbuf_nr * copy->vertex_size));
|
||||
}
|
||||
|
||||
copy->dstelt[copy->dstelt_nr++] = copy->vert_cache[slot].out;
|
||||
return check_flush(copy);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called at end of each primitive during replay.
|
||||
*/
|
||||
static void
|
||||
end(struct copy_context *copy, GLboolean end_flag)
|
||||
{
|
||||
struct _mesa_prim *prim = ©->dstprim[copy->dstprim_nr];
|
||||
|
||||
prim->end = end_flag;
|
||||
prim->count = copy->dstelt_nr - prim->start;
|
||||
|
||||
if (++copy->dstprim_nr == MAX_PRIM || check_flush(copy)) {
|
||||
flush(copy);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
replay_elts(struct copy_context *copy)
|
||||
{
|
||||
GLuint i, j, k;
|
||||
GLboolean split;
|
||||
|
||||
for (i = 0; i < copy->nr_prims; i++) {
|
||||
const struct _mesa_prim *prim = ©->prim[i];
|
||||
const GLuint start = prim->start;
|
||||
GLuint first, incr;
|
||||
|
||||
switch (prim->mode) {
|
||||
case GL_LINE_LOOP:
|
||||
/* Convert to linestrip and emit the final vertex explicitly,
|
||||
* but only in the resultant strip that requires it.
|
||||
*/
|
||||
j = 0;
|
||||
while (j != prim->count) {
|
||||
begin(copy, GL_LINE_STRIP, prim->begin && j == 0);
|
||||
|
||||
for (split = GL_FALSE; j != prim->count && !split; j++)
|
||||
split = elt(copy, start + j);
|
||||
|
||||
if (j == prim->count) {
|
||||
/* Done, emit final line. Split doesn't matter as
|
||||
* it is always raised a bit early so we can emit
|
||||
* the last verts if necessary!
|
||||
*/
|
||||
if (prim->end)
|
||||
(void)elt(copy, start + 0);
|
||||
|
||||
end(copy, prim->end);
|
||||
}
|
||||
else {
|
||||
/* Wrap
|
||||
*/
|
||||
assert(split);
|
||||
end(copy, 0);
|
||||
j--;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GL_TRIANGLE_FAN:
|
||||
case GL_POLYGON:
|
||||
j = 2;
|
||||
while (j != prim->count) {
|
||||
begin(copy, prim->mode, prim->begin && j == 0);
|
||||
|
||||
split = elt(copy, start+0);
|
||||
assert(!split);
|
||||
|
||||
split = elt(copy, start+j-1);
|
||||
assert(!split);
|
||||
|
||||
for (; j != prim->count && !split; j++)
|
||||
split = elt(copy, start+j);
|
||||
|
||||
end(copy, prim->end && j == prim->count);
|
||||
|
||||
if (j != prim->count) {
|
||||
/* Wrapped the primitive, need to repeat some vertices:
|
||||
*/
|
||||
j -= 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
(void)_tnl_split_prim_inplace(prim->mode, &first, &incr);
|
||||
|
||||
j = 0;
|
||||
while (j != prim->count) {
|
||||
|
||||
begin(copy, prim->mode, prim->begin && j == 0);
|
||||
|
||||
split = 0;
|
||||
for (k = 0; k < first; k++, j++)
|
||||
split |= elt(copy, start+j);
|
||||
|
||||
assert(!split);
|
||||
|
||||
for (; j != prim->count && !split;)
|
||||
for (k = 0; k < incr; k++, j++)
|
||||
split |= elt(copy, start+j);
|
||||
|
||||
end(copy, prim->end && j == prim->count);
|
||||
|
||||
if (j != prim->count) {
|
||||
/* Wrapped the primitive, need to repeat some vertices:
|
||||
*/
|
||||
assert(j > first - incr);
|
||||
j -= (first - incr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (copy->dstprim_nr)
|
||||
flush(copy);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
replay_init(struct copy_context *copy)
|
||||
{
|
||||
struct gl_context *ctx = copy->ctx;
|
||||
GLuint i;
|
||||
GLuint offset;
|
||||
const GLvoid *srcptr;
|
||||
|
||||
/* Make a list of varying attributes and their vbo's. Also
|
||||
* calculate vertex size.
|
||||
*/
|
||||
copy->vertex_size = 0;
|
||||
for (i = 0; i < VERT_ATTRIB_MAX; i++) {
|
||||
const struct tnl_vertex_array *array = ©->array[i];
|
||||
const struct gl_vertex_buffer_binding *binding = array->BufferBinding;
|
||||
|
||||
if (binding->Stride == 0) {
|
||||
copy_vertex_array(©->dstarray[i], array);
|
||||
}
|
||||
else {
|
||||
const struct gl_array_attributes *attrib = array->VertexAttrib;
|
||||
struct gl_buffer_object *vbo = binding->BufferObj;
|
||||
const GLubyte *ptr = _mesa_vertex_attrib_address(attrib, binding);
|
||||
GLuint j = copy->nr_varying++;
|
||||
|
||||
copy->varying[j].attr = i;
|
||||
copy->varying[j].array = ©->array[i];
|
||||
copy->varying[j].size = attrib->Format._ElementSize;
|
||||
copy->vertex_size += attrib->Format._ElementSize;
|
||||
|
||||
if (vbo) {
|
||||
if (!_mesa_bufferobj_mapped(vbo, MAP_INTERNAL)) {
|
||||
ctx->Driver.MapBufferRange(ctx, 0, vbo->Size, GL_MAP_READ_BIT, vbo,
|
||||
MAP_INTERNAL);
|
||||
}
|
||||
|
||||
copy->varying[j].src_ptr =
|
||||
ADD_POINTERS(vbo->Mappings[MAP_INTERNAL].Pointer, ptr);
|
||||
} else {
|
||||
copy->varying[j].src_ptr = ptr;
|
||||
}
|
||||
|
||||
copy->dstarray[i].VertexAttrib = ©->varying[j].dstattribs;
|
||||
copy->dstarray[i].BufferBinding = ©->varying[j].dstbinding;
|
||||
}
|
||||
}
|
||||
|
||||
/* There must always be an index buffer. Currently require the
|
||||
* caller convert non-indexed prims to indexed. Could alternately
|
||||
* do it internally.
|
||||
*/
|
||||
if (copy->ib->obj) {
|
||||
if (!_mesa_bufferobj_mapped(copy->ib->obj, MAP_INTERNAL))
|
||||
ctx->Driver.MapBufferRange(ctx, 0, copy->ib->obj->Size, GL_MAP_READ_BIT,
|
||||
copy->ib->obj, MAP_INTERNAL);
|
||||
|
||||
srcptr = (const GLubyte *)
|
||||
ADD_POINTERS(copy->ib->obj->Mappings[MAP_INTERNAL].Pointer,
|
||||
copy->ib->ptr);
|
||||
} else
|
||||
srcptr = copy->ib->ptr;
|
||||
|
||||
switch (copy->ib->index_size_shift) {
|
||||
case 0:
|
||||
copy->translated_elt_buf = malloc(sizeof(GLuint) * copy->ib->count);
|
||||
copy->srcelt = copy->translated_elt_buf;
|
||||
|
||||
for (i = 0; i < copy->ib->count; i++)
|
||||
copy->translated_elt_buf[i] = ((const GLubyte *)srcptr)[i];
|
||||
break;
|
||||
|
||||
case 1:
|
||||
copy->translated_elt_buf = malloc(sizeof(GLuint) * copy->ib->count);
|
||||
copy->srcelt = copy->translated_elt_buf;
|
||||
|
||||
for (i = 0; i < copy->ib->count; i++)
|
||||
copy->translated_elt_buf[i] = ((const GLushort *)srcptr)[i];
|
||||
break;
|
||||
|
||||
case 2:
|
||||
copy->translated_elt_buf = NULL;
|
||||
copy->srcelt = (const GLuint *)srcptr;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Figure out the maximum allowed vertex buffer size:
|
||||
*/
|
||||
if (copy->vertex_size * copy->limits->max_verts <= copy->limits->max_vb_size) {
|
||||
copy->dstbuf_size = copy->limits->max_verts;
|
||||
}
|
||||
else {
|
||||
copy->dstbuf_size = copy->limits->max_vb_size / copy->vertex_size;
|
||||
}
|
||||
|
||||
/* Allocate an output vertex buffer:
|
||||
*
|
||||
* XXX: This should be a VBO!
|
||||
*/
|
||||
copy->dstbuf = malloc(copy->dstbuf_size * copy->vertex_size);
|
||||
copy->dstptr = copy->dstbuf;
|
||||
|
||||
/* Setup new vertex arrays to point into the output buffer:
|
||||
*/
|
||||
for (offset = 0, i = 0; i < copy->nr_varying; i++) {
|
||||
const struct tnl_vertex_array *src = copy->varying[i].array;
|
||||
const struct gl_array_attributes *srcattr = src->VertexAttrib;
|
||||
struct tnl_vertex_array *dst = ©->dstarray[copy->varying[i].attr];
|
||||
struct gl_vertex_buffer_binding *dstbind = ©->varying[i].dstbinding;
|
||||
struct gl_array_attributes *dstattr = ©->varying[i].dstattribs;
|
||||
|
||||
dstattr->Format = srcattr->Format;
|
||||
dstattr->Ptr = copy->dstbuf + offset;
|
||||
dstbind->Stride = copy->vertex_size;
|
||||
dstbind->BufferObj = NULL;
|
||||
dst->BufferBinding = dstbind;
|
||||
dst->VertexAttrib = dstattr;
|
||||
|
||||
offset += copy->varying[i].size;
|
||||
}
|
||||
|
||||
/* Allocate an output element list:
|
||||
*/
|
||||
copy->dstelt_size = MIN2(65536, copy->ib->count * 2 + 3);
|
||||
copy->dstelt_size = MIN2(copy->dstelt_size, copy->limits->max_indices);
|
||||
copy->dstelt = malloc(sizeof(GLuint) * copy->dstelt_size);
|
||||
copy->dstelt_nr = 0;
|
||||
|
||||
/* Setup the new index buffer to point to the allocated element
|
||||
* list:
|
||||
*/
|
||||
copy->dstib.count = 0; /* duplicates dstelt_nr */
|
||||
copy->dstib.index_size_shift = 2;
|
||||
copy->dstib.obj = NULL;
|
||||
copy->dstib.ptr = copy->dstelt;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Free up everything allocated during split/replay.
|
||||
*/
|
||||
static void
|
||||
replay_finish(struct copy_context *copy)
|
||||
{
|
||||
struct gl_context *ctx = copy->ctx;
|
||||
GLuint i;
|
||||
|
||||
/* Free our vertex and index buffers */
|
||||
free(copy->translated_elt_buf);
|
||||
free(copy->dstbuf);
|
||||
free(copy->dstelt);
|
||||
|
||||
/* Unmap VBO's */
|
||||
for (i = 0; i < copy->nr_varying; i++) {
|
||||
struct gl_buffer_object *vbo =
|
||||
copy->varying[i].array->BufferBinding->BufferObj;
|
||||
if (vbo && _mesa_bufferobj_mapped(vbo, MAP_INTERNAL))
|
||||
ctx->Driver.UnmapBuffer(ctx, vbo, MAP_INTERNAL);
|
||||
}
|
||||
|
||||
/* Unmap index buffer */
|
||||
if (copy->ib->obj &&
|
||||
_mesa_bufferobj_mapped(copy->ib->obj, MAP_INTERNAL)) {
|
||||
ctx->Driver.UnmapBuffer(ctx, copy->ib->obj, MAP_INTERNAL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Split VBO into smaller pieces, draw the pieces.
|
||||
*/
|
||||
void
|
||||
_tnl_split_copy(struct gl_context *ctx,
|
||||
const struct tnl_vertex_array *arrays,
|
||||
const struct _mesa_prim *prim,
|
||||
GLuint nr_prims,
|
||||
const struct _mesa_index_buffer *ib,
|
||||
tnl_draw_func draw,
|
||||
const struct split_limits *limits)
|
||||
{
|
||||
struct copy_context copy;
|
||||
GLuint i, this_nr_prims;
|
||||
|
||||
for (i = 0; i < nr_prims;) {
|
||||
/* Our SW TNL pipeline doesn't handle basevertex yet, so bind_indices
|
||||
* will rebase the elements to the basevertex, and we'll only
|
||||
* emit strings of prims with the same basevertex in one draw call.
|
||||
*/
|
||||
for (this_nr_prims = 1; i + this_nr_prims < nr_prims;
|
||||
this_nr_prims++) {
|
||||
if (prim[i].basevertex != prim[i + this_nr_prims].basevertex)
|
||||
break;
|
||||
}
|
||||
|
||||
memset(©, 0, sizeof(copy));
|
||||
|
||||
/* Require indexed primitives:
|
||||
*/
|
||||
assert(ib);
|
||||
|
||||
copy.ctx = ctx;
|
||||
copy.array = arrays;
|
||||
copy.prim = &prim[i];
|
||||
copy.nr_prims = this_nr_prims;
|
||||
copy.ib = ib;
|
||||
copy.draw = draw;
|
||||
copy.limits = limits;
|
||||
|
||||
/* Clear the vertex cache:
|
||||
*/
|
||||
for (i = 0; i < ELT_TABLE_SIZE; i++)
|
||||
copy.vert_cache[i].in = ~0;
|
||||
|
||||
replay_init(©);
|
||||
replay_elts(©);
|
||||
replay_finish(©);
|
||||
}
|
||||
}
|
|
@ -1,296 +0,0 @@
|
|||
|
||||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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@vmware.com>
|
||||
*/
|
||||
|
||||
|
||||
#include "main/mtypes.h"
|
||||
#include "main/macros.h"
|
||||
#include "main/enums.h"
|
||||
#include "vbo/vbo.h"
|
||||
|
||||
#include "t_split.h"
|
||||
|
||||
|
||||
#define MAX_PRIM 32
|
||||
|
||||
/* Used for splitting without copying. No attempt is made to handle
|
||||
* too large indexed vertex buffers: In general you need to copy to do
|
||||
* that.
|
||||
*/
|
||||
struct split_context {
|
||||
struct gl_context *ctx;
|
||||
const struct tnl_vertex_array *array;
|
||||
const struct _mesa_prim *prim;
|
||||
GLuint nr_prims;
|
||||
const struct _mesa_index_buffer *ib;
|
||||
GLuint min_index;
|
||||
GLuint max_index;
|
||||
GLuint num_instances;
|
||||
GLuint base_instance;
|
||||
tnl_draw_func draw;
|
||||
|
||||
const struct split_limits *limits;
|
||||
GLuint limit;
|
||||
|
||||
struct _mesa_prim dstprim[MAX_PRIM];
|
||||
GLuint dstprim_nr;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
static void
|
||||
flush_vertex( struct split_context *split)
|
||||
{
|
||||
struct gl_context *ctx = split->ctx;
|
||||
struct _mesa_index_buffer ib;
|
||||
GLuint i;
|
||||
|
||||
if (!split->dstprim_nr)
|
||||
return;
|
||||
|
||||
if (split->ib) {
|
||||
ib = *split->ib;
|
||||
|
||||
ib.count = split->max_index - split->min_index + 1;
|
||||
ib.ptr = (const void *)((const char *)ib.ptr +
|
||||
(split->min_index << ib.index_size_shift));
|
||||
|
||||
/* Rebase the primitives to save index buffer entries. */
|
||||
for (i = 0; i < split->dstprim_nr; i++)
|
||||
split->dstprim[i].start -= split->min_index;
|
||||
}
|
||||
|
||||
assert(split->max_index >= split->min_index);
|
||||
|
||||
split->draw(ctx,
|
||||
split->array,
|
||||
split->dstprim,
|
||||
split->dstprim_nr,
|
||||
split->ib ? &ib : NULL,
|
||||
!split->ib,
|
||||
split->min_index,
|
||||
split->max_index,
|
||||
split->num_instances,
|
||||
split->base_instance);
|
||||
|
||||
split->dstprim_nr = 0;
|
||||
split->min_index = ~0;
|
||||
split->max_index = 0;
|
||||
}
|
||||
|
||||
|
||||
static struct _mesa_prim *
|
||||
next_outprim(struct split_context *split)
|
||||
{
|
||||
if (split->dstprim_nr == MAX_PRIM-1) {
|
||||
flush_vertex(split);
|
||||
}
|
||||
|
||||
{
|
||||
struct _mesa_prim *prim = &split->dstprim[split->dstprim_nr++];
|
||||
memset(prim, 0, sizeof(*prim));
|
||||
return prim;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
update_index_bounds(struct split_context *split,
|
||||
const struct _mesa_prim *prim)
|
||||
{
|
||||
split->min_index = MIN2(split->min_index, prim->start);
|
||||
split->max_index = MAX2(split->max_index, prim->start + prim->count - 1);
|
||||
}
|
||||
|
||||
|
||||
/* Return the maximum amount of vertices that can be emitted for a
|
||||
* primitive starting at 'prim->start', depending on the previous
|
||||
* index bounds.
|
||||
*/
|
||||
static GLuint
|
||||
get_max_vertices(struct split_context *split,
|
||||
const struct _mesa_prim *prim)
|
||||
{
|
||||
if ((prim->start > split->min_index &&
|
||||
prim->start - split->min_index >= split->limit) ||
|
||||
(prim->start < split->max_index &&
|
||||
split->max_index - prim->start >= split->limit))
|
||||
/* "prim" starts too far away from the old range. */
|
||||
return 0;
|
||||
|
||||
return MIN2(split->min_index, prim->start) + split->limit - prim->start;
|
||||
}
|
||||
|
||||
|
||||
/* Break large primitives into smaller ones. If not possible, convert
|
||||
* the primitive to indexed and pass to split_elts().
|
||||
*/
|
||||
static void
|
||||
split_prims(struct split_context *split)
|
||||
{
|
||||
GLuint i;
|
||||
|
||||
for (i = 0; i < split->nr_prims; i++) {
|
||||
const struct _mesa_prim *prim = &split->prim[i];
|
||||
GLuint first, incr;
|
||||
GLboolean split_inplace =
|
||||
_tnl_split_prim_inplace(prim->mode, &first, &incr);
|
||||
GLuint available = get_max_vertices(split, prim);
|
||||
GLuint count = prim->count - (prim->count - first) % incr;
|
||||
|
||||
if (prim->count < first)
|
||||
continue;
|
||||
|
||||
if ((available < count && !split_inplace) ||
|
||||
(available < first && split_inplace)) {
|
||||
flush_vertex(split);
|
||||
available = get_max_vertices(split, prim);
|
||||
}
|
||||
|
||||
if (available >= count) {
|
||||
struct _mesa_prim *outprim = next_outprim(split);
|
||||
|
||||
*outprim = *prim;
|
||||
update_index_bounds(split, outprim);
|
||||
}
|
||||
else if (split_inplace) {
|
||||
GLuint j, nr;
|
||||
|
||||
for (j = 0 ; j < count ;) {
|
||||
GLuint remaining = count - j;
|
||||
struct _mesa_prim *outprim = next_outprim(split);
|
||||
|
||||
nr = MIN2(available, remaining);
|
||||
nr -= (nr - first) % incr;
|
||||
|
||||
outprim->mode = prim->mode;
|
||||
outprim->begin = (j == 0 && prim->begin);
|
||||
outprim->end = (nr == remaining && prim->end);
|
||||
outprim->start = prim->start + j;
|
||||
outprim->count = nr;
|
||||
|
||||
update_index_bounds(split, outprim);
|
||||
|
||||
if (nr == remaining) {
|
||||
/* Finished */
|
||||
j += nr;
|
||||
}
|
||||
else {
|
||||
/* Wrapped the primitive */
|
||||
j += nr - (first - incr);
|
||||
flush_vertex(split);
|
||||
available = get_max_vertices(split, prim);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (split->ib == NULL) {
|
||||
/* XXX: could at least send the first max_verts off from the
|
||||
* inplace buffers.
|
||||
*/
|
||||
|
||||
/* else convert to indexed primitive and pass to split_elts,
|
||||
* which will do the necessary copying and turn it back into a
|
||||
* vertex primitive for rendering...
|
||||
*/
|
||||
struct _mesa_index_buffer ib;
|
||||
struct _mesa_prim tmpprim;
|
||||
GLuint *elts = malloc(count * sizeof(GLuint));
|
||||
GLuint j;
|
||||
|
||||
for (j = 0; j < count; j++)
|
||||
elts[j] = prim->start + j;
|
||||
|
||||
ib.count = count;
|
||||
ib.index_size_shift = 2;
|
||||
ib.obj = NULL;
|
||||
ib.ptr = elts;
|
||||
|
||||
tmpprim = *prim;
|
||||
tmpprim.start = 0;
|
||||
tmpprim.count = count;
|
||||
|
||||
flush_vertex(split);
|
||||
|
||||
_tnl_split_copy(split->ctx,
|
||||
split->array,
|
||||
&tmpprim, 1,
|
||||
&ib,
|
||||
split->draw,
|
||||
split->limits);
|
||||
|
||||
free(elts);
|
||||
}
|
||||
else {
|
||||
flush_vertex(split);
|
||||
|
||||
_tnl_split_copy(split->ctx,
|
||||
split->array,
|
||||
prim, 1,
|
||||
split->ib,
|
||||
split->draw,
|
||||
split->limits);
|
||||
}
|
||||
}
|
||||
|
||||
flush_vertex(split);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_tnl_split_inplace(struct gl_context *ctx,
|
||||
const struct tnl_vertex_array *arrays,
|
||||
const struct _mesa_prim *prim,
|
||||
GLuint nr_prims,
|
||||
const struct _mesa_index_buffer *ib,
|
||||
GLuint num_instances,
|
||||
GLuint base_instance,
|
||||
tnl_draw_func draw,
|
||||
const struct split_limits *limits)
|
||||
{
|
||||
struct split_context split;
|
||||
|
||||
memset(&split, 0, sizeof(split));
|
||||
|
||||
split.ctx = ctx;
|
||||
split.array = arrays;
|
||||
split.prim = prim;
|
||||
split.nr_prims = nr_prims;
|
||||
split.ib = ib;
|
||||
|
||||
/* Empty interval, makes calculations simpler. */
|
||||
split.min_index = ~0;
|
||||
split.max_index = 0;
|
||||
split.num_instances = num_instances;
|
||||
split.base_instance = base_instance;
|
||||
|
||||
split.draw = draw;
|
||||
split.limits = limits;
|
||||
split.limit = ib ? limits->max_indices : limits->max_verts;
|
||||
|
||||
split_prims(&split);
|
||||
}
|
|
@ -1,317 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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@vmware.com>
|
||||
*/
|
||||
|
||||
|
||||
#define CLIP_DOTPROD(K, A, B, C, D) X(K)*A + Y(K)*B + Z(K)*C + W(K)*D
|
||||
|
||||
#define POLY_CLIP( PLANE_BIT, A, B, C, D ) \
|
||||
do { \
|
||||
if (mask & PLANE_BIT) { \
|
||||
GLuint idxPrev = inlist[0]; \
|
||||
GLfloat dpPrev = CLIP_DOTPROD(idxPrev, A, B, C, D ); \
|
||||
GLuint outcount = 0; \
|
||||
GLuint i; \
|
||||
\
|
||||
inlist[n] = inlist[0]; /* prevent rotation of vertices */ \
|
||||
for (i = 1; i <= n; i++) { \
|
||||
GLuint idx = inlist[i]; \
|
||||
GLfloat dp = CLIP_DOTPROD(idx, A, B, C, D ); \
|
||||
\
|
||||
if (dpPrev >= 0.0f) { \
|
||||
outlist[outcount++] = idxPrev; \
|
||||
} \
|
||||
\
|
||||
if (DIFFERENT_SIGNS(dp, dpPrev)) { \
|
||||
if (dp < 0.0f) { \
|
||||
/* Going out of bounds. Avoid division by zero as we \
|
||||
* know dp != dpPrev from DIFFERENT_SIGNS, above. \
|
||||
*/ \
|
||||
GLfloat t = dp / (dp - dpPrev); \
|
||||
INTERP_4F( t, coord[newvert], coord[idx], coord[idxPrev]); \
|
||||
interp( ctx, t, newvert, idx, idxPrev, GL_TRUE ); \
|
||||
} else { \
|
||||
/* Coming back in. \
|
||||
*/ \
|
||||
GLfloat t = dpPrev / (dpPrev - dp); \
|
||||
INTERP_4F( t, coord[newvert], coord[idxPrev], coord[idx]); \
|
||||
interp( ctx, t, newvert, idxPrev, idx, GL_FALSE ); \
|
||||
} \
|
||||
outlist[outcount++] = newvert++; \
|
||||
} \
|
||||
\
|
||||
idxPrev = idx; \
|
||||
dpPrev = dp; \
|
||||
} \
|
||||
\
|
||||
if (outcount < 3) \
|
||||
return; \
|
||||
\
|
||||
{ \
|
||||
GLuint *tmp = inlist; \
|
||||
inlist = outlist; \
|
||||
outlist = tmp; \
|
||||
n = outcount; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define LINE_CLIP(PLANE_BIT, A, B, C, D ) \
|
||||
do { \
|
||||
if (mask & PLANE_BIT) { \
|
||||
const GLfloat dp0 = CLIP_DOTPROD( v0, A, B, C, D ); \
|
||||
const GLfloat dp1 = CLIP_DOTPROD( v1, A, B, C, D ); \
|
||||
const GLboolean neg_dp0 = dp0 < 0.0f; \
|
||||
const GLboolean neg_dp1 = dp1 < 0.0f; \
|
||||
\
|
||||
/* For regular clipping, we know from the clipmask that one \
|
||||
* (or both) of these must be negative (otherwise we wouldn't \
|
||||
* be here). \
|
||||
* For userclip, there is only a single bit for all active \
|
||||
* planes, so we can end up here when there is nothing to do, \
|
||||
* hence the second < 0.0f test: \
|
||||
*/ \
|
||||
if (neg_dp0 && neg_dp1) \
|
||||
return; /* both vertices outside clip plane: discard */ \
|
||||
\
|
||||
if (neg_dp1) { \
|
||||
GLfloat t = dp1 / (dp1 - dp0); \
|
||||
if (t > t1) t1 = t; \
|
||||
} else if (neg_dp0) { \
|
||||
GLfloat t = dp0 / (dp0 - dp1); \
|
||||
if (t > t0) t0 = t; \
|
||||
} \
|
||||
if (t0 + t1 >= 1.0) \
|
||||
return; /* discard */ \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
|
||||
/* Clip a line against the viewport and user clip planes.
|
||||
*/
|
||||
static inline void
|
||||
TAG(clip_line)( struct gl_context *ctx, GLuint v0, GLuint v1, GLubyte mask )
|
||||
{
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
struct vertex_buffer *VB = &tnl->vb;
|
||||
tnl_interp_func interp = tnl->Driver.Render.Interp;
|
||||
GLfloat (*coord)[4] = VB->ClipPtr->data;
|
||||
GLuint newvert = VB->Count;
|
||||
GLfloat t0 = 0;
|
||||
GLfloat t1 = 0;
|
||||
const GLuint v0_orig = v0;
|
||||
|
||||
if (mask & CLIP_FRUSTUM_BITS) {
|
||||
LINE_CLIP( CLIP_RIGHT_BIT, -1, 0, 0, 1 );
|
||||
LINE_CLIP( CLIP_LEFT_BIT, 1, 0, 0, 1 );
|
||||
LINE_CLIP( CLIP_TOP_BIT, 0, -1, 0, 1 );
|
||||
LINE_CLIP( CLIP_BOTTOM_BIT, 0, 1, 0, 1 );
|
||||
LINE_CLIP( CLIP_FAR_BIT, 0, 0, -1, 1 );
|
||||
LINE_CLIP( CLIP_NEAR_BIT, 0, 0, 1, 1 );
|
||||
}
|
||||
|
||||
if (mask & CLIP_USER_BIT) {
|
||||
GLbitfield enabled = ctx->Transform.ClipPlanesEnabled;
|
||||
while (enabled) {
|
||||
const int p = u_bit_scan(&enabled);
|
||||
const GLfloat a = ctx->Transform._ClipUserPlane[p][0];
|
||||
const GLfloat b = ctx->Transform._ClipUserPlane[p][1];
|
||||
const GLfloat c = ctx->Transform._ClipUserPlane[p][2];
|
||||
const GLfloat d = ctx->Transform._ClipUserPlane[p][3];
|
||||
LINE_CLIP( CLIP_USER_BIT, a, b, c, d );
|
||||
}
|
||||
}
|
||||
|
||||
if (VB->ClipMask[v0]) {
|
||||
INTERP_4F( t0, coord[newvert], coord[v0], coord[v1] );
|
||||
interp( ctx, t0, newvert, v0, v1, GL_FALSE );
|
||||
v0 = newvert;
|
||||
newvert++;
|
||||
}
|
||||
else {
|
||||
assert(t0 == 0.0);
|
||||
}
|
||||
|
||||
/* Note: we need to use vertex v0_orig when computing the new
|
||||
* interpolated/clipped vertex position, not the current v0 which
|
||||
* may have got set when we clipped the other end of the line!
|
||||
*/
|
||||
if (VB->ClipMask[v1]) {
|
||||
INTERP_4F( t1, coord[newvert], coord[v1], coord[v0_orig] );
|
||||
interp( ctx, t1, newvert, v1, v0_orig, GL_FALSE );
|
||||
|
||||
if (ctx->Light.ShadeModel == GL_FLAT)
|
||||
tnl->Driver.Render.CopyPV( ctx, newvert, v1 );
|
||||
|
||||
v1 = newvert;
|
||||
|
||||
newvert++;
|
||||
}
|
||||
else {
|
||||
assert(t1 == 0.0);
|
||||
}
|
||||
|
||||
tnl->Driver.Render.ClippedLine( ctx, v0, v1 );
|
||||
}
|
||||
|
||||
|
||||
/* Clip a triangle against the viewport and user clip planes.
|
||||
*/
|
||||
static inline void
|
||||
TAG(clip_tri)( struct gl_context *ctx, GLuint v0, GLuint v1, GLuint v2, GLubyte mask )
|
||||
{
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
struct vertex_buffer *VB = &tnl->vb;
|
||||
tnl_interp_func interp = tnl->Driver.Render.Interp;
|
||||
GLuint newvert = VB->Count;
|
||||
GLfloat (*coord)[4] = VB->ClipPtr->data;
|
||||
GLuint pv = v2;
|
||||
GLuint vlist[2][MAX_CLIPPED_VERTICES];
|
||||
GLuint *inlist = vlist[0], *outlist = vlist[1];
|
||||
GLuint n = 3;
|
||||
|
||||
ASSIGN_3V(inlist, v2, v0, v1 ); /* pv rotated to slot zero */
|
||||
|
||||
if (0) {
|
||||
/* print pre-clip vertex coords */
|
||||
GLuint i, j;
|
||||
printf("pre clip:\n");
|
||||
for (i = 0; i < n; i++) {
|
||||
j = inlist[i];
|
||||
printf(" %u: %u: %f, %f, %f, %f\n",
|
||||
i, j,
|
||||
coord[j][0], coord[j][1], coord[j][2], coord[j][3]);
|
||||
assert(!util_is_inf_or_nan(coord[j][0]));
|
||||
assert(!util_is_inf_or_nan(coord[j][1]));
|
||||
assert(!util_is_inf_or_nan(coord[j][2]));
|
||||
assert(!util_is_inf_or_nan(coord[j][3]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (mask & CLIP_FRUSTUM_BITS) {
|
||||
POLY_CLIP( CLIP_RIGHT_BIT, -1, 0, 0, 1 );
|
||||
POLY_CLIP( CLIP_LEFT_BIT, 1, 0, 0, 1 );
|
||||
POLY_CLIP( CLIP_TOP_BIT, 0, -1, 0, 1 );
|
||||
POLY_CLIP( CLIP_BOTTOM_BIT, 0, 1, 0, 1 );
|
||||
POLY_CLIP( CLIP_FAR_BIT, 0, 0, -1, 1 );
|
||||
POLY_CLIP( CLIP_NEAR_BIT, 0, 0, 1, 1 );
|
||||
}
|
||||
|
||||
if (mask & CLIP_USER_BIT) {
|
||||
GLbitfield enabled = ctx->Transform.ClipPlanesEnabled;
|
||||
while (enabled) {
|
||||
const int p = u_bit_scan(&enabled);
|
||||
const GLfloat a = ctx->Transform._ClipUserPlane[p][0];
|
||||
const GLfloat b = ctx->Transform._ClipUserPlane[p][1];
|
||||
const GLfloat c = ctx->Transform._ClipUserPlane[p][2];
|
||||
const GLfloat d = ctx->Transform._ClipUserPlane[p][3];
|
||||
POLY_CLIP( CLIP_USER_BIT, a, b, c, d );
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->Light.ShadeModel == GL_FLAT) {
|
||||
if (pv != inlist[0]) {
|
||||
assert( inlist[0] >= VB->Count );
|
||||
tnl->Driver.Render.CopyPV( ctx, inlist[0], pv );
|
||||
}
|
||||
}
|
||||
|
||||
if (0) {
|
||||
/* print post-clip vertex coords */
|
||||
GLuint i, j;
|
||||
printf("post clip:\n");
|
||||
for (i = 0; i < n; i++) {
|
||||
j = inlist[i];
|
||||
printf(" %u: %u: %f, %f, %f, %f\n",
|
||||
i, j,
|
||||
coord[j][0], coord[j][1], coord[j][2], coord[j][3]);
|
||||
}
|
||||
}
|
||||
|
||||
tnl->Driver.Render.ClippedPolygon( ctx, inlist, n );
|
||||
}
|
||||
|
||||
|
||||
/* Clip a quad against the viewport and user clip planes.
|
||||
*/
|
||||
static inline void
|
||||
TAG(clip_quad)( struct gl_context *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3,
|
||||
GLubyte mask )
|
||||
{
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
struct vertex_buffer *VB = &tnl->vb;
|
||||
tnl_interp_func interp = tnl->Driver.Render.Interp;
|
||||
GLuint newvert = VB->Count;
|
||||
GLfloat (*coord)[4] = VB->ClipPtr->data;
|
||||
GLuint pv = v3;
|
||||
GLuint vlist[2][MAX_CLIPPED_VERTICES];
|
||||
GLuint *inlist = vlist[0], *outlist = vlist[1];
|
||||
GLuint n = 4;
|
||||
|
||||
ASSIGN_4V(inlist, v3, v0, v1, v2 ); /* pv rotated to slot zero */
|
||||
|
||||
if (mask & CLIP_FRUSTUM_BITS) {
|
||||
POLY_CLIP( CLIP_RIGHT_BIT, -1, 0, 0, 1 );
|
||||
POLY_CLIP( CLIP_LEFT_BIT, 1, 0, 0, 1 );
|
||||
POLY_CLIP( CLIP_TOP_BIT, 0, -1, 0, 1 );
|
||||
POLY_CLIP( CLIP_BOTTOM_BIT, 0, 1, 0, 1 );
|
||||
POLY_CLIP( CLIP_FAR_BIT, 0, 0, -1, 1 );
|
||||
POLY_CLIP( CLIP_NEAR_BIT, 0, 0, 1, 1 );
|
||||
}
|
||||
|
||||
if (mask & CLIP_USER_BIT) {
|
||||
GLbitfield enabled = ctx->Transform.ClipPlanesEnabled;
|
||||
while (enabled) {
|
||||
const int p = u_bit_scan(&enabled);
|
||||
const GLfloat a = ctx->Transform._ClipUserPlane[p][0];
|
||||
const GLfloat b = ctx->Transform._ClipUserPlane[p][1];
|
||||
const GLfloat c = ctx->Transform._ClipUserPlane[p][2];
|
||||
const GLfloat d = ctx->Transform._ClipUserPlane[p][3];
|
||||
POLY_CLIP( CLIP_USER_BIT, a, b, c, d );
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->Light.ShadeModel == GL_FLAT) {
|
||||
if (pv != inlist[0]) {
|
||||
assert( inlist[0] >= VB->Count );
|
||||
tnl->Driver.Render.CopyPV( ctx, inlist[0], pv );
|
||||
}
|
||||
}
|
||||
|
||||
tnl->Driver.Render.ClippedPolygon( ctx, inlist, n );
|
||||
}
|
||||
|
||||
#undef W
|
||||
#undef Z
|
||||
#undef Y
|
||||
#undef X
|
||||
#undef SIZE
|
||||
#undef TAG
|
||||
#undef POLY_CLIP
|
||||
#undef LINE_CLIP
|
|
@ -1,277 +0,0 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* 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
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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@vmware.com>
|
||||
*/
|
||||
|
||||
|
||||
#include "c99_math.h"
|
||||
#include "main/errors.h"
|
||||
#include "main/glheader.h"
|
||||
#include "main/macros.h"
|
||||
|
||||
#include "main/mtypes.h"
|
||||
|
||||
#include "math/m_xform.h"
|
||||
|
||||
#include "t_context.h"
|
||||
#include "t_pipeline.h"
|
||||
|
||||
|
||||
struct fog_stage_data {
|
||||
GLvector4f fogcoord; /* has actual storage allocated */
|
||||
};
|
||||
|
||||
#define FOG_STAGE_DATA(stage) ((struct fog_stage_data *)stage->privatePtr)
|
||||
|
||||
#define FOG_EXP_TABLE_SIZE 256
|
||||
#define FOG_MAX (10.0F)
|
||||
#define EXP_FOG_MAX .0006595F
|
||||
#define FOG_INCR (FOG_MAX/FOG_EXP_TABLE_SIZE)
|
||||
static GLfloat exp_table[FOG_EXP_TABLE_SIZE];
|
||||
static GLfloat inited = 0;
|
||||
|
||||
#if 1
|
||||
#define NEG_EXP( result, narg ) \
|
||||
do { \
|
||||
GLfloat f = (GLfloat) (narg * (1.0F / FOG_INCR)); \
|
||||
GLint k = (GLint) f; \
|
||||
if (k > FOG_EXP_TABLE_SIZE-2) \
|
||||
result = (GLfloat) EXP_FOG_MAX; \
|
||||
else \
|
||||
result = exp_table[k] + (f-k)*(exp_table[k+1]-exp_table[k]); \
|
||||
} while (0)
|
||||
#else
|
||||
#define NEG_EXP( result, narg ) \
|
||||
do { \
|
||||
result = exp(-narg); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the exp_table[] lookup table for approximating exp().
|
||||
*/
|
||||
static void
|
||||
init_static_data( void )
|
||||
{
|
||||
GLfloat f = 0.0F;
|
||||
GLint i = 0;
|
||||
for ( ; i < FOG_EXP_TABLE_SIZE ; i++, f += FOG_INCR) {
|
||||
exp_table[i] = expf(-f);
|
||||
}
|
||||
inited = 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compute per-vertex fog blend factors from fog coordinates by
|
||||
* evaluating the GL_LINEAR, GL_EXP or GL_EXP2 fog function.
|
||||
* Fog coordinates are distances from the eye (typically between the
|
||||
* near and far clip plane distances).
|
||||
* Note that fogcoords may be negative, if eye z is source absolute
|
||||
* value must be taken earlier.
|
||||
* Fog blend factors are in the range [0,1].
|
||||
*/
|
||||
static void
|
||||
compute_fog_blend_factors(struct gl_context *ctx, GLvector4f *out, const GLvector4f *in)
|
||||
{
|
||||
GLfloat end = ctx->Fog.End;
|
||||
GLfloat *v = in->start;
|
||||
GLuint stride = in->stride;
|
||||
GLuint n = in->count;
|
||||
GLfloat (*data)[4] = out->data;
|
||||
GLfloat d;
|
||||
GLuint i;
|
||||
|
||||
out->count = in->count;
|
||||
|
||||
switch (ctx->Fog.Mode) {
|
||||
case GL_LINEAR:
|
||||
if (ctx->Fog.Start == ctx->Fog.End)
|
||||
d = 1.0F;
|
||||
else
|
||||
d = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
|
||||
for ( i = 0 ; i < n ; i++, STRIDE_F(v, stride)) {
|
||||
const GLfloat z = *v;
|
||||
GLfloat f = (end - z) * d;
|
||||
data[i][0] = CLAMP(f, 0.0F, 1.0F);
|
||||
}
|
||||
break;
|
||||
case GL_EXP:
|
||||
d = ctx->Fog.Density;
|
||||
for ( i = 0 ; i < n ; i++, STRIDE_F(v,stride)) {
|
||||
const GLfloat z = *v;
|
||||
NEG_EXP( data[i][0], d * z );
|
||||
}
|
||||
break;
|
||||
case GL_EXP2:
|
||||
d = ctx->Fog.Density*ctx->Fog.Density;
|
||||
for ( i = 0 ; i < n ; i++, STRIDE_F(v, stride)) {
|
||||
const GLfloat z = *v;
|
||||
NEG_EXP( data[i][0], d * z * z );
|
||||
}
|
||||
break;
|
||||
default:
|
||||
_mesa_problem(ctx, "Bad fog mode in make_fog_coord");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static GLboolean
|
||||
run_fog_stage(struct gl_context *ctx, struct tnl_pipeline_stage *stage)
|
||||
{
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
struct vertex_buffer *VB = &tnl->vb;
|
||||
struct fog_stage_data *store = FOG_STAGE_DATA(stage);
|
||||
GLvector4f *input;
|
||||
|
||||
|
||||
if (!ctx->Fog.Enabled)
|
||||
return GL_TRUE;
|
||||
|
||||
if (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH_EXT && !ctx->VertexProgram._Current) {
|
||||
GLuint i;
|
||||
GLfloat *coord;
|
||||
/* Fog is computed from vertex or fragment Z values */
|
||||
/* source = VB->AttribPtr[_TNL_ATTRIB_POS] or VB->EyePtr coords */
|
||||
/* dest = VB->AttribPtr[_TNL_ATTRIB_FOG] = fog stage private storage */
|
||||
VB->AttribPtr[_TNL_ATTRIB_FOG] = &store->fogcoord;
|
||||
|
||||
if (!ctx->_NeedEyeCoords) {
|
||||
/* compute fog coords from object coords */
|
||||
const GLfloat *m = ctx->ModelviewMatrixStack.Top->m;
|
||||
GLfloat plane[4];
|
||||
|
||||
/* Use this to store calculated eye z values:
|
||||
*/
|
||||
input = &store->fogcoord;
|
||||
|
||||
plane[0] = m[2];
|
||||
plane[1] = m[6];
|
||||
plane[2] = m[10];
|
||||
plane[3] = m[14];
|
||||
/* Full eye coords weren't required, just calculate the
|
||||
* eye Z values.
|
||||
*/
|
||||
_mesa_dotprod_tab[VB->AttribPtr[_TNL_ATTRIB_POS]->size]
|
||||
( (GLfloat *) input->data,
|
||||
4 * sizeof(GLfloat),
|
||||
VB->AttribPtr[_TNL_ATTRIB_POS], plane );
|
||||
|
||||
input->count = VB->AttribPtr[_TNL_ATTRIB_POS]->count;
|
||||
|
||||
/* make sure coords are really positive
|
||||
NOTE should avoid going through array twice */
|
||||
coord = input->start;
|
||||
for (i = 0; i < input->count; i++) {
|
||||
*coord = fabsf(*coord);
|
||||
STRIDE_F(coord, input->stride);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* fog coordinates = eye Z coordinates - need to copy for ABS */
|
||||
input = &store->fogcoord;
|
||||
|
||||
if (VB->EyePtr->size < 2)
|
||||
_mesa_vector4f_clean_elem( VB->EyePtr, VB->Count, 2 );
|
||||
|
||||
input->stride = 4 * sizeof(GLfloat);
|
||||
input->count = VB->EyePtr->count;
|
||||
coord = VB->EyePtr->start;
|
||||
for (i = 0 ; i < VB->EyePtr->count; i++) {
|
||||
input->data[i][0] = fabsf(coord[2]);
|
||||
STRIDE_F(coord, VB->EyePtr->stride);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* use glFogCoord() coordinates */
|
||||
input = VB->AttribPtr[_TNL_ATTRIB_FOG]; /* source data */
|
||||
|
||||
/* input->count may be one if glFogCoord was only called once
|
||||
* before glBegin. But we need to compute fog for all vertices.
|
||||
*/
|
||||
input->count = VB->AttribPtr[_TNL_ATTRIB_POS]->count;
|
||||
|
||||
VB->AttribPtr[_TNL_ATTRIB_FOG] = &store->fogcoord; /* dest data */
|
||||
}
|
||||
|
||||
if (tnl->_DoVertexFog) {
|
||||
/* compute blend factors from fog coordinates */
|
||||
compute_fog_blend_factors( ctx, VB->AttribPtr[_TNL_ATTRIB_FOG], input );
|
||||
}
|
||||
else {
|
||||
/* results = incoming fog coords (compute fog per-fragment later) */
|
||||
VB->AttribPtr[_TNL_ATTRIB_FOG] = input;
|
||||
}
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Called the first time stage->run() is invoked.
|
||||
*/
|
||||
static GLboolean
|
||||
alloc_fog_data(struct gl_context *ctx, struct tnl_pipeline_stage *stage)
|
||||
{
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
struct fog_stage_data *store;
|
||||
stage->privatePtr = malloc(sizeof(*store));
|
||||
store = FOG_STAGE_DATA(stage);
|
||||
if (!store)
|
||||
return GL_FALSE;
|
||||
|
||||
_mesa_vector4f_alloc( &store->fogcoord, 0, tnl->vb.Size, 32 );
|
||||
|
||||
if (!inited)
|
||||
init_static_data();
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
free_fog_data(struct tnl_pipeline_stage *stage)
|
||||
{
|
||||
struct fog_stage_data *store = FOG_STAGE_DATA(stage);
|
||||
if (store) {
|
||||
_mesa_vector4f_free( &store->fogcoord );
|
||||
free( store );
|
||||
stage->privatePtr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const struct tnl_pipeline_stage _tnl_fog_coordinate_stage =
|
||||
{
|
||||
"build fog coordinates", /* name */
|
||||
NULL, /* private_data */
|
||||
alloc_fog_data, /* dtr */
|
||||
free_fog_data, /* dtr */
|
||||
NULL, /* check */
|
||||
run_fog_stage /* run -- initially set to init. */
|
||||
};
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue