diff options
author | marha <marha@users.sourceforge.net> | 2011-09-08 10:54:11 +0200 |
---|---|---|
committer | marha <marha@users.sourceforge.net> | 2011-09-08 10:54:11 +0200 |
commit | 23a7aebae0a742d94ffe2304357dcc1234a99155 (patch) | |
tree | 08dbd7956bbd1c5717967a4f904f8383139bbe1e | |
parent | 53da0b7e7c183ea15692234332b3e337b3fb0cc0 (diff) | |
download | vcxsrv-23a7aebae0a742d94ffe2304357dcc1234a99155.tar.gz vcxsrv-23a7aebae0a742d94ffe2304357dcc1234a99155.tar.bz2 vcxsrv-23a7aebae0a742d94ffe2304357dcc1234a99155.zip |
mesa git update 8 sep 2011
53 files changed, 4793 insertions, 7797 deletions
diff --git a/mesalib/docs/README.3DFX b/mesalib/docs/README.3DFX deleted file mode 100644 index 7feda6f33..000000000 --- a/mesalib/docs/README.3DFX +++ /dev/null @@ -1,830 +0,0 @@ - - 3Dfx Glide device driver - - - -Requirements: -------------- - -A Voodoo-based videocard/accelerator -DOS (with DJGPP), Windows9x/2k (with MinGW), Linux -Glide3x library for your OS - -http://sourceforge.net/projects/glide/ - - - -How to compile: ---------------- - -DJGPP: - Place the Glide3 SDK in the top Mesa directory: - $(MESA)/glide3/include/ - 3dfx.h, g3ext.h, glide.h, glidesys.h, glideutl.h, sst1vid.h - $(MESA)/glide3/lib/ - libgld3x.a, libgld3i.a, glide3x.dxe - Type: - make -f Makefile.DJ X86=1 FX=1 - Look into the makefile for further information. - -MinGW: - Place the Glide3 SDK in the top Mesa directory: - $(MESA)/glide3/include/ - 3dfx.h, g3ext.h, glide.h, glidesys.h, glideutl.h, sst1vid.h - $(MESA)/glide3/lib/ - libglide3x.a, glide3x.dll - Type: - make -f Makefile.mgw X86=1 FX=1 - Look into the makefile for further information. - -Linux: - Place the Glide3 SDK in /usr/local/glide - /usr/local/glide/include/ - 3dfx.h, g3ext.h, glide.h, glidesys.h, glideutl.h, sst1vid.h - /usr/local/glide/lib/ - libglide3x.a, libglide3x.so - Type: - make linux-glide - or - make linux-x86-glide - - - -Compilation defines: --------------------- - -FX_DEBUG - enable driver debug code -FX_TRAP_GLIDE - enable Glide trace code -FX_PACKEDCOLOR - use packed color in vertex structure -FX_TC_NAPALM - map GL_COMPRESSED_RGB[A] to FXT1. Works with VSA100-based cards only. -FX_COMPRESS_S3TC_AS_FXT1_HACK - map S3TC to FXT1 -FX_RESCALE_BIG_TEXURES_HACK - fake textures larger than HW can support - (see MESA_FX_MAXLOD environment variable) - - - -Environment variables: ----------------------- - -The following environment variables affect MesaFX. Those that affect Glide -only, are beyond the scope of this section. Entries that don't have a "Value" -field, can have any value whatsoever - ex: set MESA_FX_IGNORE_CMBEXT=y - -"Note" (*) means that the environment variable affects Glide, too; also, if -the var is not found in the environment, it is searched in windoze registry. -"Note" (!) means that the environment variable is not working as expected; -may have undefined effects, might have effects only at Glide level or might -not have any effect whatsoever. Caveat emptor! Those are to be revised soon. - -It is recommended to leave the envvars alone, so that Mesa/Glide will run with -default values. Use them only when you experience crashes or strange behavior. - -FX_GLIDE_NUM_TMU - OS: all - HW: dual-TMU cards (Voodoo2, Avenger, Napalm) - Desc: force single-TMU - Note: (*) - Value: "1" -FX_GLIDE_SWAPPENDINGCOUNT - OS: all - HW: all - Desc: max # of buffers allowed to build up - Note: (*) (!) - Value: "0", "1", "2", "3", "4", "5" or "6" -FX_GLIDE_SWAPINTERVAL - OS: all - HW: all - Desc: number of vertical retraces to wait before swapping - Note: (*) (!) works only at Glide-level? -SSTH3_SLI_AA_CONFIGURATION - OS: all - HW: VSA100-based cards - Desc: SLI/AA setup - Note: (*) (!) works only at Glide-level? - Value: - 1, 2, 4 chip cards - "0" - SLI & AA disable - "1" - SLI disabled, 2 sample AA enabled - 2, 4 chip cards - "2" - 2-way SLI enabled, AA disabled - "3" - 2-way SLI enabled, 2 sample AA enabled - "4" - SLI disabled, 4 sample AA enabled - 4 chip cards - "5" - 4-way SLI enabled, AA disabled - "6" - 4-way SLI enabled, 2 sample AA enabled - "7" - 2-way SLI enabled, 4 sample AA enabled - "8" - SLI disabled, 8 sample AA enabled -SST_DUALHEAD - OS: win32 - HW: ? - Desc: ? - Note: (!) disabled? -MESA_FX_NO_SIGNALS - OS: linux - HW: all - Desc: avoid installing signals - Note: (!) untested! -MESA_FX_INFO - OS: all - HW: all - Desc: verbose to stderr - Value: any; special value "r" to redirect stderr to MESA.LOG -MESA_FX_NOSNAP - OS: all - HW: Voodoo1, Rush, Banshee - Desc: do not snap vertices inside Mesa - Note: to be used with Glide3x that snaps vertices internally -MESA_FX_POINTCAST - OS: all - HW: dual-TMU cards (some Voodoo1, Voodoo2, Avenger, Napalm) - Desc: try to use pointcast palette - Note: may give adverse effects on UMA cards (Avenger, Napalm) -MESA_FX_IGNORE_PALEXT - OS: all - HW: all - Desc: disable 6666 palette -MESA_FX_IGNORE_PIXEXT - OS: all - HW: Napalm - Desc: force 565 16bpp mode (traditional Voodoo, no 32/15bpp) -MESA_FX_IGNORE_TEXFMT - OS: all - HW: Napalm - Desc: disable 32bit textures -MESA_FX_IGNORE_CMBEXT - OS: all - HW: Napalm - Desc: disable Napalm combiners (color/alpha/texture) - Note: this option allows dual-TMU cards perform single-pass - trilinear, but some advanced (multi)texturing modes - won't work (GL_EXT_texture_env_combine) -MESA_FX_IGNORE_MIREXT - OS: all - HW: all - Desc: disable mirror extension -MESA_FX_IGNORE_TEXUMA - OS: all - HW: all - Desc: disable UMA -MESA_FX_IGNORE_TEXUS2 - OS: all - HW: all - Desc: disable Texus2 -MESA_FX_MAXLOD - OS: all - HW: non VSA-100 cards - Desc: enable large texture support using SW rescaling - Value: - "9" - 512x512 textures - "10" - 1024x1024 textures - "11" - 2048x2048 textures -MESA_FX_ALLOW_VP - OS: all - HW: all - Desc: allow vertex program extensions -MESA_GLX_FX - OS: linux - HW: Voodoo1, Rush, Voodoo2 - Desc: display mode - Note: (!) experimental - Value: - "w" - windowed mode - "f" - fullscreen mode - "d" - disable glide driver - OS: win32 - HW: Rush, Banshee, Avenger, Napalm - Desc: display mode - Note: (!) experimental - Value: - "w" - windowed mode - - - -Contact: --------- - -Daniel Borca <dborca 'at' users 'dot' sourceforge 'dot' net> -Hiroshi Morii <koolsmoky 'at' users 'dot' sourceforge 'dot' net> - - - -WARNING! The info below this line is outdated (yet some of it useful). WARNING! -******************************************************************************* - - - -Info for Mesa 4.1 ------------------ - -The 3dfx Glide driver in Mesa is disabled by default. Not too many people -use this driver anymore and at some point down the road it will be dropped. - -To use/enable the Glide driver either do this: - -'./configure --with-glide=DIR' Where DIR is the location of Glide, like - /usr/ or /usr/local - -OR - -'make linux-x86-glide' If using the old-style Makefile system. - -The rest of this file hasn't changed since Mesa 3.3. Some of it's out of -date, but some is still valid. - - - -What do you need ? ------------------- - - - A PC with a 3Dfx Voodoo1/2 Graphics or Voodoo Rush based board - (Pure3D, Monster 3D, R3D, Obsidian, Stingray 128/3D, etc.). - The Quantum3D Obsidian3D-2 X-24 requires some special env. setting - under Linux (more information in the "Useful Glide Environment - Variables"); - - - The 3Dfx Glide library 2.3 or later for your OS (the 2.4 works fine). - The Voodoo2 requires the Glide library 2.51. The Glide 3.1 is not - compatible with the Glide 2.x so it doesn't work with the current - version of the driver; - - - A compiler supported by the Glide library (Micro$oft VC++ (tested), - Watcom (tested), GCC for Linux (tested), etc.); - - - It's nice to have two monitors - one for your normal graphics - card and one for your 3Dfx card. If something goes wrong with - an application using the 3Dfx hardware you can still see your - normal screen in order to recover. - - - -Tested on: ----------- - Windows 95 - David Bucciarelli - Windows NT - Henri Fousse - MS-DOS - Linux - Daryll Strauss, Brian Paul, David Bucciarelli - FreeBSD - BeOS - Duncan Wilcox - MacOS - Fazekas Miklos - - -What is able to do ? --------------------- - - - It is able accelerate points, lines and polygon with flat - shading, gouraud shading, Z-buffer, texture mapping, blending, fog and - antialiasing (when possible). There is also the support for rendering - in a window with a slow trick for the Voodoo Graphics (available only - for Linux) and at full speed with the Voodoo Rush chipset. - Under Linux is also possible to switch on-the-fly between the fullscreen - and in-window rendering hack. - There is also the support for using more than one Voodoo Graphics in the - some application/PC (you can create one context for each board and use - multiple video outputs for driving monitors, videoprojectors or HMDs). - The driver is able to fallback to pure software rendering when afeature - isn't supported by the Voodoo hardware (however software rendering is - very slow compared to hardware supported rendering) - - - -How to compile: ---------------- - -Linux: ------- - Here are the basic steps for using the 3Dfx hardware with Mesa - on Linux: - - - You'll need the Glide library and headers. Mesa expects: - /usr/local/glide/include/*.h // all the Glide headers - /usr/local/glide/lib/libglide2x.so - - If your Glide libraries and headers are in a different directory - you'll have to modify the Mesa-config and mklib.glide files. - - - Unpack the MesaLib-3.1.tar.gz and MesaDemos-3.1.tar.gz archives; - - - If you're going to use a newer Mesa/Glide driver than v0.27 then - unpack the new driver archive over the Mesa directory. - - - In the Mesa-3.1 directory type "make linux-glide" - - - Compilation _should_ finish without errors; - - - Set your LD_LIBRARY_PATH environment variable so that the - libglide2x.so and Mesa library files can be found. For example: - setenv LD_LIBRARY_PATH "/usr/local/glide/lib:/SOMEDIR/Mesa-3.1/lib" - - - You'll have to run Glide-based programs as root or set the suid - bit on executables; - - - Try a demo: - cd gdemos - su - setenv MESA_GLX_FX f - ./gears (hit ESC to exit) - - - You can find the demos especially designed for the Voodoo driver in - in the Mesa-3.1/3Dfx/demos directory (type "make" in order to compile - everything). - -MacOS: ------- - Check the WEB page at http://valerie.inf.elte.hu/~boga/Mesa.html - -MS Windows: ------------ - - For the MSVC++: - - The glide2x.lib have to be in the default MSVC++ lib directory; - - - The Glide headers have to be in the default MSVC++ include directory; - - - You must have the vcvars32.bat script in your PATH; - - - Go to the directory Mesa-3.1 and run the mesafx.bat; - - - The script will compile everything (Mesa-3.1/lib/OpenGL32.{lib,dll}, - Mesa-3.1/lib/GLU32.{lib,dll}, Mesa-3.1/lib/GLUT32.{lib,dll} and - Voodoo demos); - - - At the end, you will be in the Mesa-3.1/3Dfx/demos directory; - - - Try some demo (fire.exe, teapot.exe, etc.) in order to check if - everything is OK (you can use Alt-Tab or Ctrl-F9 to switch between - the Voodoo screen and the windows desktop); - - - Remember to copy the Mesa OpenGL32.dll, GLU32.dll and GLUT32.dll in the - some directory were you run your Mesa based applications. - - - I think that you can easy change the Makefile.fx files in order - to work with other kind of compilers; - - - To discover how open the 3Dfx screen, read the sources under - the Mesa-3.1/3Dfx/demos directory. You can use the GLUT library or - the Diego Picciani's wgl emulator. - - NOTE: the MSVC++ 5.0 optimizer is really buggy. Also if you install the - SP3, you could have some problem (you can disable optimization in order - solve these kind of problems). - - -Doing more with Mesa & Linux Glide: ------------------------------------ - - The MESA_GLX_FX environment variable can be used to coax most - GLX-based programs into using Glide (and the __GLUT library - is GLX-based__). - - Full-screen 3Dfx rendering: - --------------------------- - - 1. Set the MESA_GLX_FX variable to "fullscreen": - - ksh: - export MESA_GLX_FX = "fullscreen" - csh: - setenv MESA_GLX_FX fullscreen - - 2. As root, run a GLX-based program (any GLUT demo on Linux). - - 3. Be careful: once the 3Dfx screen appears you won't be able - to see the GLUT windows on your X display. This can make using - the mouse tricky! One solution is to hook up your 3Dfx card to - a second monitor. If you can do this then set these env vars - first: - - setenv SST_VGA_PASS 1 - setenv SST_NOSHUTDOWN - - or for the Voodoo2: - - setenv SSTV2_VGA_PASS 1 - setenv SSTV2_NOSHUTDOWN - - Rendering into an X window with the help of the Voodoo hardware: - ---------------------------------------------------------------- - - 1. Start your X server in 16 bpp mode (XFree86: startx -- -bpp 16) - in order to have the best performance and the best visual - quality. However you can use any visual depth supported by X. - - 2. Set the following environment variables: - export MESA_GLX_FX="window" # to enable window rendering - export SST_VGA_PASS=1 # to stop video signal switching - export SST_NOSHUTDOWN=1 # to stop video signal switching - OR - setenv MESA_GLX_FX window - setenv SST_VGA_PASS 1 - setenv SST_NOSHUTDOWN 1 - - (the Voodoo2 requires to use "SSTV2_" instead "SST_"). - - 3. As root, try running a GLX-based program - - How does it work? We use the 3Dfx hardware to do rendering then - copy the image from the 3Dfx frame buffer into an X window when - the SwapBuffers() function is called. The problem with this - idea is it's slow. The image must be copied from the 3Dfx frame - buffer to main memory then copied into the X window (and when the X - visual depth doesn't match the Voodoo framebufffer bit per pixel, it - is required also a pixel format translation). - - NOTE: the in-window rendering feature only works with double-buffering. - - - On the fly switching between in window rendering and full screen rendering - -------------------------------------------------------------------------- - - The Mesa 2.6 has introduced the capability of switching - on-the-fly between the fullscreen/fullspeed rendering and the in-window - hack and vice versa. The on-the-fly switching requires a direct support - by the application but it is really easy to add. You have to start - your X server in 16 bpp mode and to add the following lines to your - application: - - #if defined(FX) && define(XMESA) - #include <GL/xmesa.h> - - static int fullscreen=1; - #endif - - ... - - /* In the GLUT keyboard event callback */ - - #if defined(FX) && !define(WIN32) - case ' ': - fullscreen=(!fullscreen); - XMesaSetFXmode(fullscreen ? XMESA_FX_FULLSCREEN : XMESA_FX_WINDOW); - break; - #endif - ... - - See the 3Dfx/demos/tunnel.c program - for an example. You have to set the -DXMESA flag in the Makefile's COPTS - to enable it. - - Rendering into an X window with the X11 software driver: - -------------------------------------------------------- - - Set the MESA_GLX_FX variable to "disable" your GLX-based program will use - the X11 software driver (the 3Dfx hardware isn't used at all). - - - -Useful Glide Environment Variables: ------------------------------------ - - - To disable the 3Dfx logo, set the FX_GLIDE_NO_SPLASH variable. - - - To disable video signal switching: - setenv SST_VGA_PASS 1 - setenv SST_NOSHUTDOWN - or for the Voodoo2: - setenv SSTV2_VGA_PASS 1 - setenv SSTV2_NOSHUTDOWN - - - To set the default screen refresh rate: - setenv SST_SCREENREFRESH=75 - - the supported values are 60, 70, 72, 75, 80, 85, 90, 100, 120. - - - To force the Mesa library to swap buffers as fast as possible, - without any vertical blanking synchronization (useful for benchmarks): - setenv FX_GLIDE_SWAPINTERVAL 0 - setenv SST_SWAP_EN_WAIT_ON_VIDSYNC 0 - - - You can slight improve the performances of your Voodoo1 board with - the following env. var.: - setenv SST_FASTMEM 1 - setenv SST_PCIRD 1 - setenv SST_GRXCLK 57 - - (don't use this setting with the Quantum3D 100SB or with any other - SLI configuration: it will hang everything !). - The following setting can be used with the Voodoo2: - setenv SSTV2_FASTMEM_RAS_READS=1 - setenv SSTV2_FASTPCIRD=1 - setenv SSTV2_GRXCLK=95 - - - The Quantum3D Obsidian3D-2 X-24 requires some special env. setting - in order to work under Linux: - - export SSTV2_FT_CLKDEL=5 - export SSTV2_TF0_CLKDEL=7 - export SSTV2_TF1_CLKDEL=7 - export SSTV2_TF2_CLKDEL=7 - export SSTV2_SLIM_VIN_CLKDEL=3 - export SSTV2_SLIM_VOUT_CLKDEL=2 - export SSTV2_SLIS_VIN_CLKDEL=3 - export SSTV2_SLIS_VOUT_CLKDEL=2 - - (Thanks to Phil Ross for this trick). - - - - -The Mesa/Voodoo Environment Variables: --------------------------------------- - - - Only for Windows/Voodoo Rush users, if you define the - env. var. MESA_WGL_FX: - export MESA_WGL_FX=fullscreen - you will get fullscreen rendering; - - - Only for Windows/Voodoo Rush users, if you define the - env. var. MESA_WGL_FX: - export MESA_WGL_FX=window - you will get window rendering (default value); - - - Only for Linux users, you can find more informations about - the env. var. MESA_GLX_FX in the "Doing more with Mesa & Linux Glide" - section; - - - If you define the env. var. MESA_FX_SWAP_PENDING: - export MESA_FX_SWAP_PENDING=4 - you will able to set the maximum number of swapbuffers - commands in the Voodoo FIFO after a swapbuffer (default value: 2); - - - If you define the env. var. MESA_FX_INFO: - export MESA_FX_INFO=1 - you will get some useful statistic. - - - If you define the env. var. MESA_FX_NO_SIGNALS: - export MESA_FX_NO_SIGNALS=1 - Mesa/FX will not install atexit() or signal() handlers. - - - -Know BUGS and Problems: ------------------------ - - - fog doesn't work in the right way when using the glDepthRange() function; - - - Maximum texture size: 256x256 (this is an hardware limit); - - - Texture border aren't yet supported; - - - A GL_BLEND in a glTexEnv() is not supported (it is an hardware limit); - - - Use the glBindTexture extension (standard in OpenGL 1.1) for texture - mapping (the old way: glTexImage inside a display list, download - the texture map each time that you call the display list !!!); - - - Stencil buffer and Accumulation buffer are emulated in software (they are not - directly supported by the Hardware); - - - Color index mode not implemented (this is an hardware limit); - - - Thre is an know bug in the Linux Glide library so the in-window-rendering hack - and any other operations that requires to read the Voodoo frame buffer - (like the accumulation buffer support) doesn't work on Voodoo SLI cards. - - - The driver switch to pure software (_slow_) rendering when: - - - Stencil enabled; - - Using the Accumulation buffer; - - Blend enabled and blend equation != GL_FUNC_ADD_EXT; - - Color logic operation enabled and color logic operation != GL_COPY; - - Using GL_SEPARATE_SPECULAR_COLOR; - - The four values of glColorMask() aren't the some; - - Texture 1D or 3D enabled; - - Texture function is GL_BLEND; - - Using the Multitexture extension with Voodoo cards with only one TMU; - - Using the Multitexture extension with Voodoo cards with more than - one TMU, and texture function isn't GL_MODULATE; - - Point size is != 1.0 or point params vector != (1.0,0.0,0.0); - - Line width != 1.0 or using stipple lines. - - Using polygon offset or stipple polygons; - - NOTE: this is list is not yet complete. - - -Hints and Special Features: ---------------------------- - - - Under Linux and with a Voodoo Graphics board, you can use - XMesaSetFXmode(XMESA_FX_FULLSCREEN or XMESA_FX_WINDOW) in order to - switch on the fly between fullscreen rendering and the in-window-rendering - hack. - - - The driver is able to use all the texture memory available: 2/4MB on - Voodoo1 boards and 8MB (!) on high-end Voodoo1 and Voodoo2 boards. - - - Trilinear filtering is fully supported on Voodoo boards with two TMUs - (high-end Voodoo1 boards and Voodoo2 boards). When only one TMU is - available the driver fallback to bilinear filter also if you ask - for trilinear filtering. - - - The Voodoo driver support multiple Voodoo Graphics boards in the - some PC. Using this feature, you can write applications that use - multiple monitors, videoprojectors or HMDs for the output. See - Mesa-3.1/3Dfx/demos/tunnel2.c for an example of how setup one - context for each board. - - - The v0.19 introduces a new powerful texture memory manager: the - texture memory is used as a cache of the set of all defined texture - maps. You can now define several MBs of texture maps also with a 2MB - of texture memory (the texture memory manager will do automatically - all the swap out/swap in - texture memory work). The new texture memory manager has also - solved a lot of other bugs/no specs compliance/problems - related to the texture memory usage. - - - Use triangles and quads strip: they are a LOT faster than sparse - triangles and quads. - - - The Voodoo driver supports the GL_EXT_paletted_texture. it works - only with GL_COLOR_INDEX8_EXT, GL_RGBA palettes and the alpha value - is ignored because this is a limitation of the current Glide - version and of the Voodoo hardware. See Mesa-3.1/3Dfx/demos/paltex.c for - a demo of this extension. - - - The Voodoo driver directly supports 3Dfx Global Palette extension. - It was written for GLQuake and I think that it isn't a good idea - to use this extension for any other purpose (it is a trick). See - Mesa-3.1/3Dfx/demos/glbpaltex.c for a demo of this extension. - - - The Voodoo driver chooses the screen resolution according to the - requested window size. If you open a 640x480 window, you will get - a 640x480 screen resolution, if you open a 800x600 window, you - will get a 800x600 screen resolution, etc. - Most GLUT demos support the '-geometry' option, so you can choose - the screen resolution: 'tunnel -geometry 800x600'. - Clearly, you Voodoo board must have enough framebuffer RAM (otherwise - the window creation will fail). - - - The glGetString(GL_RENDERER) returns more information - about the hardware configuration: "Mesa Glide <version> - <Voodoo_Graphics|Voodoo_Rush|UNKNOWN> <num> CARD/<num> FB/ - <num> TM/<num> TMU/<NOSLI|SLI>" - where: <num> CARD is the card used for the current context, - <num> FB is the number of MB for the framebuffer, - <num> TM is the number of MB for the texture memory, - <num> TMU is the number of TMU. You can try to run - Mesa/demos/glinfo in order to have an example of the output. - -Did you find a lot BUGs and problems ? Good, send me an email. - - - -FAQ: ----- - -For a complete FAQ check the Bernd Kreimeier's Linux 3Dfx HOWTO -available at http://www.gamers.org/dEngine/xf3D (it includes also -a lot of informations not strictly related to Linux, so it can be -useful also if you don't use Linux) - -1. What is 3Dfx? - -3Dfx Interactive, Inc. is the company which builds the VooDoo 3-D graphics -chipset (and others) used in popular PC cards such as the Diamond Monster 3D -and the Orchid Righteous 3D (more informations at http://www.3dfx.com). - - -2. What is Glide? - -Glide is a "thin" programming interface for the 3Dfx hardware. It was -originally written for Windows/Intel but has been ported to Linux/Intel -by Daryll Strauss. - -3Dfx, Inc. should be applauded for allowing the Linux version of Glide -to be written. - -You can directly program with the Glide library if you wish. You can -obtain Glide from the "Developer" section of the 3Dfx website: www.3dfx.com -There's a Linux/Glide newsgroup at news://news.3dfx.com/3dfx.glide.linux - - -3. What is fxmesa? - -"fxmesa" is the name of the Mesa device driver for the 3Dfx Glide library. -It was written by David Bucciarelli and others. It works on both Linux -and Windows. Basically, it allows you to write and run OpenGL-style programs -on the 3Dfx hardware. - - -4. What is GLQuake? - -Quake is a very popular game from id software, Inc. See www.idsoftware.com -GLQuake is a version of Quake written for OpenGL. There is now a Linux -version of GLQuake with works with the Mesa/3Dfx/Glide combo. - -Here's what you need to run GLQuake on Linux: - PC with 100MHz Pentium or better - a 3Dfx-based card - Mesa 3.1 libraries: libMesaGL.so libMesaGLU.so - Glide 2.4 libraries: libglide2x.so libtexus.so - GLQuake for Linux. - -Also, the windows version of GLQuake works fine with the Mesa OpenGL32.dll, -you have only to copy the Mesa-3.1/lib/OpenGL32.dll in the GLQuake directory -in order to test 'MesaQuake'. - - -5. What is GLUT? - -GLUT is Mark Kilgard's OpenGL Utility Toolkit. It provides an API for -writing portable OpenGL programs with support for multiple windows, pop- -up menus, event handling, etc. - -Check the Mark's home page for more informations (http://reality.sgi.com/mjk_asd). - -Every OpenGL programmer should check out GLUT. - -GLUT on Linux uses GLX. - - -6. What is GLX? - -GLX is the OpenGL extension to the X Window System. I defines both a -programming API (glX*() functions) and a network protocol. Mesa implements -an emulation of GLX on Linux. A real GLX implementation would requires -hooks into the X server. The 3Dfx hardware can be used with GLX-based -programs via the MESA_GLX_FX environment variable. - - -7. Is the Voodoo driver able to use the 4Mb texture memory of -the Pure3D boards ? - -Yes, the Voodoo driver v0.20 includes the support for Voodoo -Graphics boards with more than 2Mb of texture memory. - - -8. Do the Voodoo driver support the Voodoo Rush under Windows ? - -Yes, Diego Picciani has developed the support for the Voodoo -Rush but David Bucciarelli has a Pure3D and a Monster3D and Brian Paul -has a Monster3D, so the new versions of the Mesa/Voodoo sometime are -not tested with the Voodoo Rush. - - -9. Do the Voodoo driver support the Voodoo Rush under Linux ? - -No because the Linux Glide doesn't (yet) support the Voodoo Rush. - - -10. Can I sell my Mesa/Voodoo based software and include -a binary copy of the Mesa in order to make the software -working out of the box ? - -Yes. - - -11. Which is the best make target for compiling the Mesa for -Linux GLQuake ('make linux-glide', 'make linux-386-glide', etc.) ? - -'make linux-386-opt-glide' for Voodoo1 and 'make linux-386-opt-V2-glide' -for Voodoo2 boards because it doesn't include the '-fPIC' -option (4-5% faster). - - -12. Can I use a Mesa compiled with a 'make linux-386-opt-V2-glide' -for my applications/programs/demos ? - -Yes, there is only one constrain: you can't run two Mesa applications -at the some time. This isn't a big issue with the today Voodoo Graphics. - - -Thanks to: ----------- - -Henri Fousse (he has written several parts of the v0.15 and the old GLUT - emulator for Win); - -Diego Picciani (he has developed all the Voodoo Rush support and the wgl - emulator); - -Daryll Strauss (for the Linux Glide and the first Linux support); - -Brian Paul (of course); - -Dave 'Zoid' Kirsch (for the Linux GLQuake and Linux Quake2test/Q2 ports) - -Bernd Kreimeier (for the Linux 3Dfx HOWTO and for pushing companies to offer - a better Linux support) - -3Dfx and Quantum3D (for actively supporting Linux) - -The most update places where find Mesa VooDoo driver related informations are -the Mesa mailing list and my driver WEB page -(http://www-hmw.caribel.pisa.it/fxmesa/index.shtml) - - -David Bucciarelli (davibu@tin.it) - -Humanware s.r.l. -Via XXIV Maggio 62 -Pisa, Italy -Tel./Fax +39-50-554108 -email: info.hmw@plus.it -www: www-hmw.caribel.pisa.it diff --git a/mesalib/docs/README.AMIWIN b/mesalib/docs/README.AMIWIN deleted file mode 100644 index 47cf696cc..000000000 --- a/mesalib/docs/README.AMIWIN +++ /dev/null @@ -1,181 +0,0 @@ -AMIGA AMIWIN PORT of MESA: THE OPENGL SOFTWARE EMULATION -======================================================== -Port by Victor Ng-Thow-Hing (victorng@dgp.toronto.edu) -Original Author (Brian Paul (brianp@ssec.wisc.edu) - -Dec.1 , 1995: Port of release Mesa 1.2.5 - - Modifications made to minimize changes to Mesa distribution. - -Nov.25, 1995: Port of release Mesa 1.2.4 - - -HISTORY -======= -As a 3D graphics progammer, I was increasingly frustrated to see OpenGL -appearing on so many platforms EXCEPT the Amiga. Up to now, the task -of porting OpenGL directly from native Amiga drawing routines seemed like -a daunting task. However, two important events made this port possible. - -First of all, Brian Paul wrote Mesa, the OpenGL software emulator that -can be found on many platforms - except the Amiga and Atari (who cares -about the latter!). This was pretty ironic considering that Mesa was -originally prototyped on an Amiga! The second great event was when -Holger Kruse developed AmiWin, the X11R6 server for the Amiga (definitely -register for this great piece of software) and released a development kit -so one could compile X programs with SAS/C. - -Since Mesa had X routines as its primitive drawing operations, this made -a marriage of Mesa and Amiwin feasible. I copied over the sources from -an ftp site, played with the code, wrote some Smakefiles, and voila, -I had OpenGL programs displaying on my Amiga. - -Although the speed is nothing to be impressed about, this port can be -potentially useful to those who want to quickly test their code in -wireframe or perhaps learn more about programming with the OpenGL API. - -I hope Amiga developers will continue to write excellent software for -their machine, especially more X clients for Amiwin. If you have any -solutions so some of my problems in the porting notes, please send me -some email! - -See you around, -Vic. - -HOW TO CREATE THE LIBRARIES AND SAMPLE CODE -=========================================== - -Just run the shell script mklib.amiwin in the mesa directory. This will -make all the libraries and copy them into the mesa/lib directory. If you -don't want to compile everything, just go to the desired directory and -type smake in that directory. - -Change any of the variables in the smakefiles as necessary. You will REQUIRE -the Amiwin development kit to compile these libraries since you need X11.LIB -and the shareable X libraries. Some examples require the AmiTCP4.0 -net.lib static link library and related header files for unix related -header files and functions like sleep(). - -HOW TO USE THE MESA LIBRARIES -============================= - -Study the Smakefiles in the demos, samples and book directories for the -proper SAS/C options and linkable libraries to use. Basically aux calls -require Mesaaux.LIB, gl calls require MesaGL.LIB, glu calls MesaGLU.LIB, -tk calls Mesatk.LIB. There is a preliminary port of MesaGLUT.LIB toolkit -available in the lib directory with the other Mesa libraries. However, -it seems to cause crashes on some of the sample code. Someone else may want -to attempt a more stable port. - -PORTING NOTES TO AMIWIN -======================= - -My strategy of porting was to leave as much of the code untouched as -possible. I surrounded any amiga specific changes with -#ifdef AMIWIN ... #endif or #ifndef AMIWIN ... #endif preprocessor -symbols. The code was ported on an Amiga 2000, with Fusion 40 accelerator -and a Picasso II graphics card. The SAS/C 6.56 compiler was used, with -the AmiWin 2.16 X development kit. - -All compilations were done for a 68040 CPU with 68882 math coprocessor for -maximum speed. Please edit the smakefile for other compilers. -I wrote smakefiles for the directories I ported. I omitted the Windows -and Widgets directories. The former is for MS Windows and the latter -requires Motif, which is not easily available for the Amiga. - -Here are the changes I did per directory: - -* mesa -Nov. 25, 1995 v 1.2.4 - - added a mklib.amiwin shell script that will make all the libraries and - sample code for Mesa - - created this readme file: readme.AMIGA - -* mesa/include -Dec. 1, 1995 v 1.2.5 - - added the following to GL/xmesa.h - #ifdef AMIWIN - #include <pragmas/xlib_pragmas.h> - extern struct Library *XLibBase; - #endif -NET CHANGE: xmesa.h - -* mesa/src -Nov. 25, 1995 v 1.2.4 - - added the necessary pragma calls for X functions to the following: - xmesa1.c, xmesa2.c, xmesa3.c, xfonts.c, glx.c - This prevents undefined symbols errors during the linking phase for - X library calls - - created smakefile -Dec. 1, 1995 v 1.2.5 - - removed AMIWIN includes from xmesa1.c, xmesa2.c, xmesa3.c, xfonts.c, - glx.c since they are now defined in include/GL/xmesa.h -NET CHANGE: smakefile - -* mesa/src-tk -Nov. 25, 1995 v 1.2.4 - - added the necessary pragma calls for X functions to the following: - private.h - - created smakefile -Dec. 1, 1995 v 1.2.5 - - removed AMIWIN includes from private.h since it is now defined in - include/GL/xmesa.h -NET CHANGE: smakefile - -* mesa/src-glu -Nov. 25, 1995 v 1.2.4 - - created smakefile -NET CHANGE: smakefile - -* mesa/src-aux -Nov. 25, 1995 v 1.2.4 - - added the necessary pragma calls for X functions to the following: - glaux.c - - created smakefile -NET CHANGE: glaux.c, smakefile - -* mesa/demos -Nov. 25, 1995 v 1.2.4 - - added the necessary pragma calls for X functions to the following: - xdemo.c, glxdemo.c, offset.c - - created smakefile - - put #ifndef AMIWIN ... #endif around sleep() calls in xdemo.c since - they are not part of AmigaDOS. -Dec. 1, 1995 v 1.2.5 - - removed AMIWIN defines from xdemo.c, glxdemo.c, offset.c since - already defined in include/GL/xmesa.h - - modified Smakefile to include header and includes from the AmiTCP4.0 - net.lib linkable library to provide unix-compatible sys/time.h and - the sleep() function - - removed AMIWIN defines in xdemo.c since sleep() now defined -NET CHANGE: smakefile - -* mesa/samples -Nov. 25, 1995 v 1.2.4 - - added the necessary pragma calls for X functions to the following: - oglinfo.c - - created smakefile - - put #ifndef AMIWIN ... #endif around sleep() in blendxor.c - - removed olympic from smakefile targets since <sys/time.h> not defined -Dec. 1, 1995 v 1.2.5 - - removed AMIWIN defines from oglinfo.c, since already defined in - include/GL/xmesa.h - - modified Smakefile to include header and includes from the AmiTCP4.0 - net.lib linkable library to provide unix-compatible sys/time.h and - the sleep() function - - removed AMIWIN defines in blendxor.c for sleep() - - added AMIWIN defines around _MACHTEN_ in olympic.c since xrandom() - functions are not defined in any libraries - - added olympic back into the Smakefile targets -NET CHANGE: smakefile, olympic.c - -* mesa/book -Nov. 25, 1995 v 1.2.4 -- created smakefile -- removed accpersp and dof from smakefile targets since the SAS/C compile seems to - confuse the near,far variables with near/far memory models. -NET CHANGE: smakefile - -* mesa/windows -Dec. 1, 1995 v 1.2.5 -- Removed directory to save space since this is only needed for Windows based - machines. diff --git a/mesalib/docs/README.DJ b/mesalib/docs/README.DJ deleted file mode 100644 index 5f783ac53..000000000 --- a/mesalib/docs/README.DJ +++ /dev/null @@ -1,275 +0,0 @@ - Mesa 6.5 DOS/DJGPP Port v1.8 - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - - -Description: -~~~~~~~~~~~~ - -Well, guess what... this is the DOS port of Mesa 6.5, for DJGPP fans... Whoa! -The driver uses OSMesa to draw off screen, and then blits the buffer. This is -not terribly efficient, and has some drawbacks, but saves maintenance costs. - - - -Legal: -~~~~~~ - -Mesa copyright applies. - - - -Installation: -~~~~~~~~~~~~~ - -Unzip and type: - - make -f Makefile.DJ [OPTIONS...] - -Available options: - - Environment variables: - CPU optimize for the given processor. - default = pentium - GLIDE path to Glide3 SDK; used with FX. - default = $(TOP)/glide3 - FX=1 build for 3dfx Glide3. Note that this disables - compilation of most DMesa code and requires fxMesa. - As a consequence, you'll need the DJGPP Glide3 - library to build any application. - default = no - X86=1 optimize for x86 (if possible, use MMX, SSE, 3DNow). - default = no - - Targets: - all: build everything - libgl: build GL - libglu: build GLU - libglut: build GLUT - clean: remove object files - realclean: remove all generated files - - - -Tested on: - Video card: Radeon 9500 - DJGPP: djdev 2.04 + gcc v4.1.0 + make v3.80 - OS: DOS, Win98SE, WinXP (using Videoport driver) - - - -FAQ: -~~~~ - -1. Compilation - - Q) `make' barfs and exits because it cannot find some stupid file. - A) You need LFN support. - A) When compiling for Glide (FX=1), pay attention to Glide path. - - Q) Libraries built OK, but linker complains about `vsnprintf' every time I - compile some demo. - A) Upgrade to DJGPP 2.04. - A) Add `vsnprintf.c' to the CORE_SOURCES in `src/Makefile.DJ' (untested!). - A) Patch `src/mesa/main/imports.c' with the following line: - #define vsnprintf(buf, max, fmt, arg) vsprintf(buf, fmt, arg) - This hack should be safe in 90% of the cases, but if anything goes wrong, - don't come back to me crying. - - Q) `make' complains about DXE3 or something, yet it builds the libraries. - A) DXE3 refers to the DJGPP dynamic modules. You'll need either the latest - DJGPP distro, or download the separate package from my web page. Read the - DXE3 documentation on how to use them. - A) When compiling for Glide (FX=1), make sure `glide3x.dxe' can be found in - LD_LIBRARY_PATH (or top `lib' directory). - -2. Using Mesa for DJGPP - - Q) Every test I tried crashes badly. - A) If you have compiled with SSE and you're running under plain DOS, you - have to disable SSE at run-time. See environment variables below. - - Q) DMesa is so SLOOOW! The Win32 OpenGL performs so much better... - A) Is that a question? If you have a 3dfx Voodoo (any model), you're - lucky (check http://sourceforge.net/projects/glide for the DJGPP port). - If you haven't, sorry; everything is done in software. - - Q) I tried to set refresh rate w/ DMesa, but without success. - A) Refresh rate control works only for VESA 3.0 and the 3dfx driver (in - which case FX_GLIDE_REFRESH will be overwritten if it is defined and - is not 0). - - Q) I made a simple application and it does nothing. It exits right away. Not - even a blank screen. - A) Software drivers (VESA/VGA/NUL) must to be constructed as single-buffered - visuals. However, DMesaSwapBuffers must be called to get any output. - A) Another weird "feature" is that buffer width must be multiple of 8 (I'm a - lazy programmer and I found that the easiest way to keep buffer handling - at peak performance ;-). - - Q) I'm getting a "bad font!" fatal error. - A) Always use GLUT_STROKE_* and GLUT_BITMAP_* constants when dealing with - GLUT fonts. If you're using `glut.dxe', then make sure GLUT_STROKE_* and - GLUT_BITMAP_* are mapped to integer constants, not to the actual font - address (same mechanism used for Win32 _DLL). - - Q) What is NUL driver good for, if I don't get any output at all? - A) For debugging. The NUL driver is very much like OSMesa. Everything is - done just the same as VESA/VGA drivers, only it doesn't touch your video - hardware. You can query the actual buffer by issuing: - DMesaGetIntegerv(DMESA_GET_BUFFER_ADDR, &buffer); - and dump it to a file. - - Q) How do I query for a list of available video modes to choose as a visual? - A) This is an ugly hack, for which I'm sure I'll burn in hell. - First, query for a list of modes: - n = DMesaGetIntegerv(DMESA_GET_VIDEO_MODES, NULL); - If `n' is strictly positive, you allocate an array of pointers to a given - struct (which is guaranteed to be extended only - not changed in future): - struct { - int xres, yres; - int bpp; - } **l = malloc(n * sizeof(void *)); - Now pass the newly allocated buffer to fill in: - DMesaGetIntegerv(DMESA_GET_VIDEO_MODES, (GLint *)l); - And collect the info: - for (i = 0; i < n; i++) { - printf("%dx%d:%d\n", l[i]->xres, l[i]->yres, l[i]->bpp); - } - - Q) The GLUT is incomplete. - A) See below. - - - -libGLUT (the toolkit): -~~~~~~~~~~~~~~~~~~~~~~ - -Well, this "skeletal" GLUT implementation was taken from AllegGL project and -heavily changed. Thanks should go to Bernhard Tschirren, Mark Kilgard, Brian -Paul and probably others (or probably not ;-). GLUT functionality will be -extended only on an "as needed" basis. - -GLUT talks to hardware via PC_HW package which was put together from various -pieces I wrote long time ago. It consists from the keyboard, mouse and timer -drivers. - -My keyboard driver used only scancodes; as GLUT requires ASCII values for keys, -I borrowed the translation tables (and maybe more) from Allegro -- many thanks -to Shawn Hargreaves et co. Ctrl-Alt-Del (plus Ctrl-Alt-End, for Windows users) -will shut down the GLUT engine unconditionally: it will raise SIGINT, which in -turn will (hopefully) call the destructors, thus cleaning up your/my mess ;-) -NB: since the DJGPP guys ensured signal handlers won't go beyond program's -space (and since dynamic modules shall) the SIGINT can't be hooked (well, it -can, but it is useless), therefore you must live with the 'Exiting due to -signal SIGINT' message... - -The mouse driver is far from complete (lack of drawing, etc), but is enough to -make almost all the demos work. Supports the CuteMouse WheelAPI. - -The timer is pretty versatile for it supports multiple timers with different -frequencies. While not being the most accurate timer in the known universe, I -think it's OK. Take this example: you have timer A with a very high rate, and -then you have timer B with very low rate compared to A; now, A ticks OK, but -timer B will probably loose precision! - -As an addition, stdout and stderr are redirected and dumped upon exit. This -means that `printf' can be safely called during graphics. A bit of a hack, I -know, because all messages come in bulk, but I think it's better than nothing. -"Borrowed" from LIBRHUTI (Robert Hoehne). - -Window creating defaults: (0, 0, 300, 300), 16bpp. However, the video mode is -chosen in such a way that first window will fit. If you need high resolution -with small windows, set initial position far to the right (or way down); then -you can move them back to any position right before the main loop. - - - -Environment variables: -~~~~~~~~~~~~~~~~~~~~~~ - DMESA_NULDRV - (any value) force NUL driver - GLUT_FPS - print frames/second statistics to stderr - MESA_NO_SSE - (any value) safe option under pure DOS - DMESA_GLUT_REFRESH - set vertical screen refresh rate (VESA3) - DMESA_GLUT_BPP - set default bits per pixel (VGA needs 8) - DMESA_GLUT_ALPHA - set default alpha bits (8) - DMESA_GLUT_DEPTH - set default depth bits (16) - DMESA_GLUT_STENCIL - set default stencil bits (8) - DMESA_GLUT_ACCUM - set default accum bits (16) - - - -History: -~~~~~~~~ - -v1.0 (mar-2002) - initial release - -v1.1 (sep-2002) - + added 3dfx Glide3 support - + added refresh rate control - + added fonts in GLUT - * lots of minor changes - -v1.2 (nov-2002) - * synced w/ Mesa-4.1 - - removed dmesadxe.h - -v1.3 (mar-2003) - + enabled OpenGL 1.4 support - + added MMX clear/blit routines - + enabled SGI's GLU compilation - + added samples makefile - + added new GLUT functions - + added color-index modes - + added Matrox Millennium MGA2064W driver - + added 8bit FakeColor (thanks to Neil Funk) - + added VGA support (to keep Ben Decker happy) - ! fixed some compilation errors (reported by Chan Kar Heng) - * optimized driver for faster callback access... yeah, right :) - * overhauled virtual buffer and internal video drivers - * better fxMesa integration - * revamped GLUT - * switched to DXE3 - -v1.4 (dec-2003) - + enabled GLUT fonts with DXE - + truly added multi-window support in GLUT (for Adrian Woodward) - * accomodated makefiles with the new sourcetree - * fixed some ALPHA issues - * minor changes to PC_HW/timer interface - x hacked and slashed the 3dfx driver (w/ help from Hiroshi Morii) - -v1.5 (jan-2004) - + added interface to query available "visuals" (GLFW - Marcus Geelnard) - + added GLUT timer callback - - removed Matrox Millennium MGA2064W driver - x more changes to the 3dfx driver - -v1.6 (aug-2004) - + implemented NUL driver - + added DMesaGetProcAddress and glutGetProcAddress - * reorganized fxMesa wrapper to handle multiple contexts - ! fixed a horrible bug in VGA initialization routine - ! fixed partial clears - -v1.7 (???-2005) - + enabled OpenGL 2.0 support - + added support for sw texture compression - + added FreeGLUT specific functions - * no more GLX sources in DOS GLUT - * made GLUT timer callbacks less accurate but safer - -v1.8 (apr-2006) - * killed lots of code, the driver is now a front-end to OSMesa - * fixed problem with WinNT (http://www.volny.cz/martin.sulak/) - - removed 3dfx Glide3 support (temporarily?) - - - -Contact: -~~~~~~~~ - -Name: Daniel Borca -E-mail: dborca@users.sourceforge.net -WWW: http://www.geocities.com/dborca/ diff --git a/mesalib/docs/README.GGI b/mesalib/docs/README.GGI deleted file mode 100644 index ddb67725f..000000000 --- a/mesalib/docs/README.GGI +++ /dev/null @@ -1,26 +0,0 @@ -GGIMesa for LibGGI 2.x - -Requirements: -------------- -LibGGI 2.0 or greater - -Installation: -------------- -To install GGIMesa, follow the instructions in INSTALL.GNU. If you -wish to install GGIGLUT as well, first install GGIMesa and then run - -make -make install (must be root) - -in ggi/ggiglut. - -Notes: ------- - -* Set the environment variables GGIMESA_DEBUG and/or GGIGLUT_DEBUG -to 255 to see lots of debugging output. - -* GGIGLUT contains support for all of the GLUT 3.6 API except for the -high-level primitive drawing functions, but many of the functions (in -particular the menu drawing functions) are just stubs. - diff --git a/mesalib/docs/README.LYNXOS b/mesalib/docs/README.LYNXOS deleted file mode 100644 index e3ab9804b..000000000 --- a/mesalib/docs/README.LYNXOS +++ /dev/null @@ -1,64 +0,0 @@ - -Mesa 3.0 for LynxOS builds in the following way: - -make lynxos - -This will build all the libraries and demo applications. You should have -around 400 megabytes free for everything since everything is done with -static -libraries. - -Before using this make file however, you should perform the following -actions: -0) cd to the Mesa-3.0 directory -1) Copy the GL directory under the include directory to /usr/include. -2) Copy the files in the lib directory to /lib. -3) Make links so that the Mesa libraries look like ordinary OpenGL -libraries -in /lib. This is important for compatibility with other OpenGL apps. This -is done as follows: - -cd /lib -ln -s libMesaGL.a libGL.a -ln -s libMesaGLU.a libGLU.a - -Mesa 3.0 includes the GLUT (GL Utility Toolkit) by default. -The demo applications are done using this toolkit. - -Mesa makefiles for building their apps could be used as well, but the -following one is much more concise. Note that the order of the X libraries -is important to the linker so that all symbols get resolved correctly. -Changing the order may result in having to list a library twice to make -sure all linkages are made correctly. - -----cut here for Makefile ----- - -FILES = your_app.x - -SPECIAL_INCLUDES = -I/usr/include/GL - -SPECIAL_CFLAGS = -g -ansi -pedantic -funroll-loops -ffast-math -DSHM - -SPECIAL_LIBS = -lglut -lGLU -lGL -lm -L/usr/X11/lib -lXext -lXmu -lXi \ --lX11 -lbsd -g - -STANDARD_OFILES = $(FILES:.x=.o) - -%.o: %.c - gcc -c $(SPECIAL_CFLAGS) $(SPECIAL_INCLUDES) $< -o $@ - -all: $(STANDARD_OFILES) - gcc -o your_app $(STANDARD_OFILES) $(SPECIAL_LIBS) - - -----cut here for Makefile----- - -I have tested Mesa under LynxOS 3.0 and 3.01. It should build fine under -other -versions as well. Note, however, that LynxOS versions prior to 3.0 are not -binary compatible, so you will have to rebuild from source. - - -Vik Sohal -vik@lynx.com -January 13, 1999 diff --git a/mesalib/docs/README.NeXT b/mesalib/docs/README.NeXT deleted file mode 100644 index 1ad9a9e5c..000000000 --- a/mesalib/docs/README.NeXT +++ /dev/null @@ -1,6 +0,0 @@ -The NeXT support has now been incorporated into the OpenStep support. -You can build NeXT libraries simply by typing "make next", though before -linking they will need to be ranlib'd by hand. For more information see -the README.OpenStep file, together with the README files in OpenStep/Old_Demos. - --Pete French. (pete@ohm.york.ac.uk) 28/5/1998 diff --git a/mesalib/docs/README.OS2 b/mesalib/docs/README.OS2 deleted file mode 100644 index b3374ea23..000000000 --- a/mesalib/docs/README.OS2 +++ /dev/null @@ -1,96 +0,0 @@ - README for port of Mesa 3.x to XFree86 on OS/2 (X/2) - (as of 19990514) - - - Contents: - - 1) Binary release - 2) Building from sources - 3) History - 4) Todo - 5) Mesa Home Page - - -1) Binary release - - Though the Mesa sources should build in a quite reasonable time even on - a 585 class machine a binary relase is available (check topic 4) for an URL) - This package includes: - - - lib/MesaGL.dll, MesaGL.a - - lib/MesaGLU.dll, MesaGLU.a - - lib/glut.dll, glut.a - - include/GL/*.h - - Installing this in your XFree86 tree will enable you to build and - run all applications compatible with Mesa (and the current DLL - interface, of course ;-) - As usual the OMF-style libraries can be created using emxomf. - (e.g. "emxomf foo.a" creates the foo.lib omf-style library). - The static libraries are rarely used and you have to rebuild - Mesa to get them. They're a supported target, so you get - them in a straightforward way (see below). - - The testing of these libraries was limited to the supplied - demos/examples and a quite small number of third-party apps. - No warranty ... as usual ... ;-) - - -2) Instructions to build Mesa 3.x for XFree86/OS2 from sources: - - Except the official Mesa source distribution you need: - - a recent version of XFree86 (3.3.x or above) including - the programming libraries - - EMX 0.9c (0.9d might work, never checked) - - GNU make - - REXX (!) - - The creation of the DLLs as well as of the static libraries - (if you want to have them) is handled in "mklib-emx.cmd", - a small REXX script. Perhaps not the best idea, but this - way it fits best in the scheme used to build libraries - on all platforms in Mesa 3.x. - - To actually build the libraries and demos, check mklib-emx.cmd - and modify it as desired. Then type - make os2-x11 - and wait for completion ;-) - - -3) History - - Initially Darren Abbott (abbott@hiwaay.net) ported Mesa versions 2.x - to XFree86 OS/2. This port might still be available from - http://fly.HiWAAY.net/~abbott/xfree86-os2/xfree86.html - - The current port picked up things during the beta test for 3.0. - No major changes in the source were done. The build mechanism under OS/2 - has been made very similar to other platforms (if you treat mklib-emx.cmd - as a "black box"). - Advantage is that X/2 is now a valid target and all files are - integrated in the official source distribution. - Disadvantage is that this port (i.e. the DLLs' interface itself) is - definitly NOT COMPATIBLE to those of version 2.x. - It's uncertain whether this would be at all possible but since there - a _very_ few those apps it's not worth to find out anyway. - Also some libs (MesaTK, MesaAUX) are withdrawn from the Mesa distribution, - and accordingly from the OS/2 port. - -4) Todo - - By now binary compatiblity is ensured by using the function names - as entry points instead of ordinals. This might cost performance and - is subject to change in future. In addition the supplied X86 assembler - source is not used yet. - -5) Mesa Home Page - - You can get the source code and more information about Mesa from - http://www.mesa3d.org/ - - The OS/2 ports should be available from - http://r350.ee.ntu.edu.tw/~hcchu/os2/ports - --- -Alexander Mai -st002279@hrzpub.tu-darmstadt.de diff --git a/mesalib/docs/README.OpenStep b/mesalib/docs/README.OpenStep deleted file mode 100644 index a566eca67..000000000 --- a/mesalib/docs/README.OpenStep +++ /dev/null @@ -1,35 +0,0 @@ -This is a port of the GL and GLU libraries to NeXT/Apple object -orientated systems. As these systems have their own window handling -systems we simply use the offscreen rendering capability of Mesa -to generate bitmaps which may then be displayed by the application -with a View as required. Example pieces of code may be found in the -OpenStep directory. - -Sadly there are now a proliferation of different system that we need to -support compilation for: The original NextStep system, The OpenStep -system, the Rhapsody/Mac OS X system and also the windows implementations -of the latter two systems. This version of the code has been compiled and -tested under the following architectures: - - NextStep 3.3 - OpenStep 4.2 - Rhapsody DR2 - WebObjects for NT 3.5 - WebObjects for NT 4.0 - -All tests were done with Intel processors. Feedback on other systems would, -however, be appreciated ! - -On UNIX systems simply type "make openstep". Under Windows systems -with WebObjects run the "win32-openstep.sh" script from within the Bourne -shell provided with the development environment. In both cases this will -build the libraries and place them into the "lib" directory. Some examples -may be found in the OpenStep directory showing how to use the code in an -actual application (MesaView) as well as some command line demos. - -The CC variable may be specified on the command line for doing such things -as building FFAT libraries or using alternative compilers to the standard 'cc' -e.g. make CC='cc -arch m68k -arch i386' openstep" will build the libraries -with both intel and motorola architectures. - --Pete French. (pete@ohm.york.ac.uk) 7/6/1999 diff --git a/mesalib/docs/README.WINDML b/mesalib/docs/README.WINDML deleted file mode 100644 index 448db71f8..000000000 --- a/mesalib/docs/README.WINDML +++ /dev/null @@ -1,146 +0,0 @@ - - WindML Driver for Mesa 4.0 - - -Requirements ------------- - -Tornado 2 + WindML, Cumulative Patchs are recommended. - -I suppose you have a valid WindML installation. Double buffer hardware -gives better performance than double buffer software so if you can -compile your WindML driver with this option, just do it. I/O -redirection is adviced in target server. - - -Tested on ---------- - -During the development, my main target was a CoolMonster: -- Video card: CT69000 -- CPU: PENTIUM 266MHz - -and my host a Windows NT + Tornado 2. - - -Installation ------------- - -1. Mesa sources must be in root directory (C:\) - -2. Add the following line to your torVars.bat: -set MESA_BASE=C:\Mesa - -OR copy the new torVars.bat in your bin path: -c:/Mesa/src/ugl/tornado/torVars.sample -> -/mnt/nt/Tornado/host/x86-win32/bin/torVars (for example) - -3. In a command prompt: -$ torVars -$ cd c:\Mesa -$ make -f Makefile.ugl CPU=PENTIUM - -Take a long while... - -5. Include all the files from ugldemos folder to build some downloadable - application modules - -4. Download UGL/Mesa object files on target - -For example via the WindShell: -ld < c:\Tornado\target\lib\objMesaGL.o -ld < c:\Tornado\target\lib\objMesaUGL.o -ld < c:\Tornado\target\lib\objMesaGLU.o -ld < c:\Tornado\target\lib\objGLUTshapes.o -ld < c:\Tornado\target\lib\objMesaOS.o - -You can put the previous lines in a file and use: -< filename - -6. Download the application modules. - -7. In WindShell, run: --> uglalldemos - -During the show some messages will appear, it provides some useful -information on key management. - - -Coding ------- - -Sample Usage: - -In addition to the usual ugl calls to initialize UGL, (may be find an -input driver), you must do the following to use the UGL/Mesa interface: - -1. Call uglMesaCreateContext() to create a UGL/Mesa rendering context, - given the display format. - -2. Call uglMesaMakeCurrent() to bind the UGL/Mesa buffers to an - UGL/Mesa Context and to make the context the current one. - -3. Make gl* calls to render your graphics. - -4. Use uglMesaSwapBuffers() when double buffering to swap front/back buffers. - -5. Before the UGL is destroyed, call MesaDestroyContext(). - -6. Before exiting, call if required uglEventQDestroy and then - uglDeinitialize(); - -Limitations ------------ - -I found the following limitations in my driver : - - Color Indexed management is only in 8 bits - - It's possible to mix UGL/OpenGL application with a software - double buffer - -Modifications ------------- - -New files in Mesa: -- Makefile.ugl -- rules.windmlmesa -- docs/README.UGL -- include/GL/uglmesa.h -- si-glu/Makefile.ugl -- src/Makefile.ugl -- src/ugl/torGLUTShapesInit.c -- src/ugl/torMesaUGLInit.c -- src/ugl/ugl_api.c -- src/ugl/ugl_dd.c -- src/ugl/ugl_glutshapes.c -- src/ugl/ugl_line.c -- src/ugl/ugl_span.c -- src/ugl/ugl_tri.c -- src/ugl/uglmesaP.h -- ugldemos/* - -Modified files in Tornado 2.0: -- c:\Tornado\host\x86-win32\bin\torVars.bat -rem Command line build environments -set WIND_HOST_TYPE=x86-win32 -set WIND_BASE=C:\Tornado -set MESA_BASE=C:\Mesa -set PATH=%WIND_BASE%\host\%WIND_HOST_TYPE%\bin;%PATH% -- c:\Tornado\target\config\comps\VxWorks\01uglmesa.cdf -- c:\Tornado\target\h\GL\* - -Todo ----- -- GCC 2.96, ASM compilation - -Thanks to: ----------- - -Precision Insight team for their great job around Mesa, XFree, and DRI. -Wind River Systems to take me as an intern. - - -Stephane Raimbault -<stephane.raimbault@windriver.com> -<stephane.raimbault@deesse.univ-lemans.fr> - -July 24, 2001 diff --git a/mesalib/docs/games.html b/mesalib/docs/games.html index dcf5cf2d0..82e3d09a4 100644 --- a/mesalib/docs/games.html +++ b/mesalib/docs/games.html @@ -29,7 +29,6 @@ simulator </li><li><a href="http://freetrek.linuxgames.com/" target="_parent">Free Trek</a> - Star Trek battle simulator - </li><li><a href="http://mesa3d.sourceforge.net/notfound.html">Gepetto</a> - Dance Choreography </li><li><a href="http://glchess.sourceforge.net/" target="_parent">GLChess</a> - chess game </li><li><a href="http://heretic.linuxgames.com/" target="_parent">GLHeretic</a> - Heretic for Linux @@ -61,4 +60,4 @@ </li></ul> -</body></html>
\ No newline at end of file +</body></html> diff --git a/mesalib/docs/libraries.html b/mesalib/docs/libraries.html index eaeb0451a..1c425cf1b 100644 --- a/mesalib/docs/libraries.html +++ b/mesalib/docs/libraries.html @@ -47,11 +47,10 @@ Open SG PLUS</a> - a scene-graph library <li><a href="http://sgl.sourceforge.net/" target="_parent">SGL</a> - a 3D Scene Graph Library <li><a href="http://www.lal.in2p3.fr/SI/SoFree/" target="_parent">SoFree</a> - a free implementation of Open Inventor <li><a href="http://togl.sourceforge.net/" target="_parent">Togl</a> - Tcl/Tk widget for OpenGL -<li><a href="http://mesa3d.sourceforge.net/notfound.html">VLE</a> - Virtual Reality Toolkit <li><a href="http://www.int.com/" target="_parent">View3D Widget</a> - 3-D GUI widget <li><a href="http://www.vtk.org/" target="_parent">VTK</a> - Visualization Toolkit <li><a href="http://home.earthlink.net/%7Erzeh/YAJOGLB/doc/YAJOGLB.html" target="_parent">YAJOGL</a> - Yet Another Java GL Binding. </ul> -</body></html>
\ No newline at end of file +</body></html> diff --git a/mesalib/docs/lists.html b/mesalib/docs/lists.html index 148789153..033b0b70a 100644 --- a/mesalib/docs/lists.html +++ b/mesalib/docs/lists.html @@ -37,6 +37,13 @@ versions are sent to this list. Very low traffic. </ul> <p> +<b>NOTE</b>: You <b>must</b> subscribe to these lists in order to post to them. +If you try to post to a list and you're not a subscriber (or if you try to post +from a different email address than you subscribed with) your posting will be +held for an indefinite period or may be discarded entirely. +</p> + +<p> Follow the links above for list archives. </p> @@ -55,10 +62,6 @@ kernels, see the DRI wiki</a>. </p> -<p> -<b>Notice</b>: You must subscribe to these lists in order to post to them. -</p> - <br> diff --git a/mesalib/docs/modelers.html b/mesalib/docs/modelers.html index aae968695..2e90a5268 100644 --- a/mesalib/docs/modelers.html +++ b/mesalib/docs/modelers.html @@ -11,7 +11,6 @@ <ul> <li><a href="http://www.aqsis.org/" target="_parent">Aqsis</a> - a RenderMan compatible renderer</li> <li><a href="http://www.ac3d.org/" target="_parent">AC3D</a> - 3-D modeler - </li><li><a href="http://mesa3d.sourceforge.net/notfound.html">ARCAD</a> - CAD program </li><li><a href="http://www.mediascape.com/" target="_parent">Artstream</a> - provides functionality like Corel Draw and Illustrator </li><li><a href="http://www.blender.org/" target="_parent">Blender</a> - 3-D animation @@ -27,7 +26,6 @@ exploration </li><li><a href="http://innovation3d.sourceforge.net/" target="_parent">Innovation3D</a> - 3D modeling program - </li><li><a href="http://mesa3d.sourceforge.net/notfound.html" target="_parent">KWRL</a> - VRML browser </li><li><a href="http://www.openvrml.org/" target="_parent">LibVRML97/Lookat</a> - VRML viewer </li><li><a href="http://aig.cs.man.ac.uk/systems/Maverik/" target="_parent">Maverik</a> @@ -40,7 +38,6 @@ 3D</a> - 3D modeler/animator </li><li><a href="http://mindseye.sourceforge.net/" target="_parent">Mindseye</a> - Rendering/Modeling Package - </li><li><a href="http://mesa3d.sourceforge.net/notfound.html">Moonlight Atelier</a> - modeling and rendering package </li><li><a href="http://www.neuralvr.com/" target="_parent">Pansophica</a> - Virtual Reality web organizer </li><li><a href="http://www.sim.no/reducer.html" target="_parent">Rational Reducer</a> - polygon reduction tool @@ -52,14 +49,12 @@ - inside-out sphere visualization </li><li><a href="http://www.cs.kuleuven.ac.be/cwis/research/graphics/3DOM/" target="_parent">3Dom</a> - 3-D modeler - </li><li><a href="http://mesa3d.sourceforge.net/notfound.html">3D Studio file viewer</a> - by David Farrell </li><li><a href="http://www.microform.se/" target="_parent">VARKON</a> - product engineering, design, modeling </li><li><a href="http://www.sim.no/vrmlview.html" target="_parent">VRMLview</a> - VRML model viewer </li><li><a href="http://www.iicm.edu/vrwave/" target="_parent">VRWave</a> - a VRML 2.0 browser - </li><li><a href="http://mesa3d.sourceforge.net/notfound.html">VRweb</a> - VRML browser </li><li><a href="http://www.csv.ica.uni-stuttgart.de/vrml/dune/" target="_parent">white_dune</a> - graphical VRML97 Editor and animation tool </li></ul> diff --git a/mesalib/docs/relnotes-7.12.html b/mesalib/docs/relnotes-7.12.html new file mode 100644 index 000000000..ac20788ef --- /dev/null +++ b/mesalib/docs/relnotes-7.12.html @@ -0,0 +1,64 @@ +<HTML> + +<head> +<TITLE>Mesa Release Notes</TITLE> +<link rel="stylesheet" type="text/css" href="mesa.css"> +<meta http-equiv="content-type" content="text/html; charset=utf-8" /> +</head> + +<BODY> + +<body bgcolor="#eeeeee"> + +<H1>Mesa 7.12 Release Notes / (release date TBD)</H1> + +<p> +Mesa 7.12 is a new development release. +People who are concerned with stability and reliability should stick +with a previous release or wait for Mesa 7.12.1. +</p> +<p> +Mesa 7.12 implements the OpenGL 2.1 API, but the version reported by +glGetString(GL_VERSION) depends on the particular driver being used. +Some drivers don't support all the features required in OpenGL 2.1. +</p> +<p> +See the <a href="install.html">Compiling/Installing page</a> for prerequisites +for DRI hardware acceleration. +</p> + + +<h2>MD5 checksums</h2> +<pre> +tbd +</pre> + + +<h2>New features</h2> +<ul> +</ul> + + +<h2>Bug fixes</h2> +<ul> +</ul> + + +<h2>Changes</h2> +<ul> +<li>Removed all DRI drivers that did not support DRI2. Specifically, + i810, mach64, mga, r128, savage, sis, tdfx, and unichrome were + removed.</li> +<li>Removed support for BeOS.</li> +<li>Removed the obsolete (and unmaintained) Windows "gldirect" and + "ICD" drivers.</li> +<li>Removed the linux-fbdev software driver.</li> +<li>Removed all remnants of paletted texture support. As required by + desktop OpenGL, <tt>GL_COLOR_INDEX</tt> data can still be uploaded + to a color (e.g., RGBA) texture. However, the data cannot be stored + internally as color-index.</li> +</ul> + + +</body> +</html> diff --git a/mesalib/docs/relnotes.html b/mesalib/docs/relnotes.html index e1f0c3299..7e02172ed 100644 --- a/mesalib/docs/relnotes.html +++ b/mesalib/docs/relnotes.html @@ -13,6 +13,7 @@ The release notes summarize what's new or changed in each Mesa release. </p> <UL> +<LI><A HREF="relnotes-7.12.html">7.12 release notes</A> <LI><A HREF="relnotes-7.11.html">7.11 release notes</A> <LI><A HREF="relnotes-7.10.3.html">7.10.3 release notes</A> <LI><A HREF="relnotes-7.10.2.html">7.10.2 release notes</A> diff --git a/mesalib/docs/science.html b/mesalib/docs/science.html index f55cf3124..0b3384303 100644 --- a/mesalib/docs/science.html +++ b/mesalib/docs/science.html @@ -10,7 +10,6 @@ <ul> <li><a href="http://www.softintegration.com/products/toolkit/opengl/" target="_parent">Ch</a> - OpenGL bindings for the Ch C/C++ interpreter - </li><li><a href="http://mesa3d.sourceforge.net/notfound.html">CLEO3D</a> - event displayer for the CLEOIII detector </li><li><a href="http://www.bioz.unibas.ch/%7Exray/dino/" target="_parent">DINO</a> - Visualizing Structural Biology </li><li><a href="http://www-xdiv.lanl.gov/XCM/gmv/GMVHome.html" target="_parent">General @@ -34,7 +33,7 @@ - a real-time, interactive relativistic simulator </li><li><a href="http://linkwinds.jpl.nasa.gov/" target="_parent">LinkWinds</a> - scientific vis - </li><li><a href="http://mesa3d.sourceforge.net/notfound.html" target="_parent">MathGL3d</a> - Mathematica viewer + </li><li><a href="http://phong.informatik.uni-leipzig.de/~kuska/mathgl3dv3/index.htm" target="_parent">MathGL3d</a> - Mathematica viewer </li><li><a href="http://www.mathworks.com/products/matlab" target="_parent">Mathworks</a> - mathematics and visualization </li><li><a href="http://www-rocq.inria.fr/gamma/medit/medit.html" target="_parent">Medit</a> - 3D surface mesh viewer @@ -50,7 +49,6 @@ </li> <li><a href="http://www.paraview.org/" target="_parent">ParaView</a> - Scientific visualization package </li> - <li><a href="http://mesa3d.sourceforge.net/notfound.html">PHLEX</a> - Finite element vis </li><li><a href="http://root.cern.ch/" target="_parent">ROOT</a> - Object Oriented Data Analysis Framework </li><li><a href="http://www.slffea.com/" target="_parent">SLFFEA</a> - GNU finite element @@ -59,7 +57,6 @@ modeling </li><li><a href="http://www1.las.es/%7Eamil/ssystem" target="_parent">Ssystem</a> - solar system simulation - </li><li><a href="http://mesa3d.sourceforge.net/notfound.html">SPARROW</a> - robot simulation </li><li><a href="http://www.ssec.wisc.edu/%7Ebillh/vis5d.html" target="_parent">Vis5D</a> - atmospheric visualization </li><li><a href="http://www.ks.uiuc.edu/Research/vmd/" target="_parent">VMD</a> - molecular @@ -69,4 +66,4 @@ </li></ul> -</body></html>
\ No newline at end of file +</body></html> diff --git a/mesalib/docs/systems.html b/mesalib/docs/systems.html index 03db779a1..035a48962 100644 --- a/mesalib/docs/systems.html +++ b/mesalib/docs/systems.html @@ -38,32 +38,5 @@ and Unix-like operating systems <LI>DEC VMS <A HREF="README.VMS">(README.VMS)</A> </UL> - -<h2>Deprecated Systems</h2> - -<p> -These drivers have not been maintained and are being deprecated. -They can be saved if someone steps up to help. -</p> - -<UL> -<LI>3dfx/Glide <A HREF="README.3DFX">(README.3DFX)</A> -<LI>GGI <A HREF="README.GGI">(README.GGI)</A> -<LI>Amiga Amiwin <A HREF="README.AMIWIN">(README.AMIWIN)</A> -<LI>Direct3D driver <A HREF="README.D3D">(README.D3D)</A> -<LI>DJGPP <A HREF="README.DJ">(README.DJ)</A> -<LI>LynxOS <A HREF="README.LYNXOS">(README.LYNXOS)</A> -<LI>Mingw32 <A HREF="README.MINGW32">(README.MINGW32)</A> -<LI>NeXT <A HREF="README.NeXT">(README.NeXT)</A> -<LI>OpenStep <A HREF="README.OpenStep">(README.OpenStep)</A> -<LI>OS/2 <A HREF="README.OS2">(README.OS2)</A> -<LI>WindML <A HREF="README.WINDML">(README.WINDML)</A> -</UL> - -And for historical reference: -<UL> -<LI><a href="http://utah-glx.sourceforge.net/" target="_parent">Utah GLX drivers</a> -</UL> - </body> </html> diff --git a/mesalib/docs/utility.html b/mesalib/docs/utility.html index c7cad0114..dfb4a909f 100644 --- a/mesalib/docs/utility.html +++ b/mesalib/docs/utility.html @@ -25,9 +25,6 @@ <li><a href="http://threedsia.sourceforge.net/" target="_parent">3Dsia</a> - 3D user interface -<li><a href="http://mesa3d.sourceforge.net/notfound.html">VRML Site -Map</a> - 3D GUI - <li><a href="http://www.vros.com/" target="_parent">VR/OS</a> - VR user interface diff --git a/mesalib/include/GL/glfbdev.h b/mesalib/include/GL/glfbdev.h deleted file mode 100644 index 452a643a4..000000000 --- a/mesalib/include/GL/glfbdev.h +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Mesa 3-D graphics library - * Version: 6.5 - * - * 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 - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - - -#ifndef GLFBDEV_H -#define GLFBDEV_H - - -/* for size_t */ -#include <stdlib.h> - -/* avoid including linux/fb.h */ -struct fb_fix_screeninfo; -struct fb_var_screeninfo; - - -/* public types */ -typedef struct GLFBDevVisualRec *GLFBDevVisualPtr; -typedef struct GLFBDevBufferRec *GLFBDevBufferPtr; -typedef struct GLFBDevContextRec *GLFBDevContextPtr; - - -/* API version */ -#define GLFBDEV_VERSION_1_0 1 - - -/* For glFBDevCreateVisual */ -#define GLFBDEV_DOUBLE_BUFFER 100 -#define GLFBDEV_COLOR_INDEX 101 -#define GLFBDEV_DEPTH_SIZE 102 -#define GLFBDEV_STENCIL_SIZE 103 -#define GLFBDEV_ACCUM_SIZE 104 -#define GLFBDEV_LEVEL 105 -#define GLFBDEV_MULTISAMPLE 106 -#define GLFBDEV_NONE 0 - -/* For glFBDevGetString */ -#define GLFBDEV_VERSION 200 -#define GLFBDEV_VENDOR 201 - - -/* Misc functions */ - -extern const char * -glFBDevGetString( int str ); - - -typedef void (*GLFBDevProc)(); - - -extern GLFBDevProc -glFBDevGetProcAddress( const char *procName ); - - - -/** - * Create a GLFBDevVisual. - * \param fixInfo - needed to get the visual types, etc. - * \param varInfo - needed to get the bits_per_pixel, etc. - * \param attribs - for requesting depth, stencil, accum buffers, etc. - */ -extern GLFBDevVisualPtr -glFBDevCreateVisual( const struct fb_fix_screeninfo *fixInfo, - const struct fb_var_screeninfo *varInfo, - const int *attribs ); - -extern void -glFBDevDestroyVisual( GLFBDevVisualPtr visual ); - -extern int -glFBDevGetVisualAttrib( const GLFBDevVisualPtr visual, int attrib); - - - -/** - * Create a GLFBDevBuffer. - * \param fixInfo, varInfo - needed in order to get the screen size - * (resolution), etc. - * \param visual - as returned by glFBDevCreateVisual() - * \param frontBuffer - address of front color buffer - * \param backBuffer - address of back color buffer (may be NULL) - * \param size - size of the color buffer(s) in bytes. - */ -extern GLFBDevBufferPtr -glFBDevCreateBuffer( const struct fb_fix_screeninfo *fixInfo, - const struct fb_var_screeninfo *varInfo, - const GLFBDevVisualPtr visual, - void *frontBuffer, void *backBuffer, size_t size ); - -extern void -glFBDevDestroyBuffer( GLFBDevBufferPtr buffer ); - -extern int -glFBDevGetBufferAttrib( const GLFBDevBufferPtr buffer, int attrib); - -extern GLFBDevBufferPtr -glFBDevGetCurrentDrawBuffer( void ); - -extern GLFBDevBufferPtr -glFBDevGetCurrentReadBuffer( void ); - -extern void -glFBDevSwapBuffers( GLFBDevBufferPtr buffer ); - - - -/** - * Create a GLFBDevContext. - * \param visual - as created by glFBDevCreateVisual. - * \param share - specifies another context with which to share textures, - * display lists, etc. (may be NULL). - */ -extern GLFBDevContextPtr -glFBDevCreateContext( const GLFBDevVisualPtr visual, GLFBDevContextPtr share ); - -extern void -glFBDevDestroyContext( GLFBDevContextPtr context ); - -extern int -glFBDevGetContextAttrib( const GLFBDevContextPtr context, int attrib); - -extern GLFBDevContextPtr -glFBDevGetCurrentContext( void ); - -extern int -glFBDevMakeCurrent( GLFBDevContextPtr context, - GLFBDevBufferPtr drawBuffer, - GLFBDevBufferPtr readBuffer ); - - -#endif /* GLFBDEV_H */ diff --git a/mesalib/scons/crossmingw.py b/mesalib/scons/crossmingw.py index 949fc4fb1..893002f64 100644 --- a/mesalib/scons/crossmingw.py +++ b/mesalib/scons/crossmingw.py @@ -225,14 +225,6 @@ def generate(env): # default in recent gcc versions env.AppendUnique(CCFLAGS = ['-gstabs']) - env.AppendUnique(CPPDEFINES = [('__MSVCRT_VERSION__', '0x0700')]) - #env.AppendUnique(LIBS = ['iberty']) - env.AppendUnique(SHLINKFLAGS = ['-Wl,--enable-stdcall-fixup']) - #env.AppendUnique(SHLINKFLAGS = ['-Wl,--kill-at']) - - # Avoid depending on gcc runtime DLLs - env.AppendUnique(LINKFLAGS = ['-static-libgcc']) - env.AddMethod(compile_without_gstabs, 'compile_without_gstabs') def exists(env): diff --git a/mesalib/scons/gallium.py b/mesalib/scons/gallium.py index 7135251d7..dc77904f0 100644 --- a/mesalib/scons/gallium.py +++ b/mesalib/scons/gallium.py @@ -279,6 +279,8 @@ def generate(env): ('_WIN32_WINNT', '0x0601'), ('WINVER', '0x0601'), ] + if gcc: + cppdefines += [('__MSVCRT_VERSION__', '0x0700')] if msvc and env['toolchain'] != 'winddk': cppdefines += [ 'VC_EXTRALEAN', @@ -532,6 +534,14 @@ def generate(env): pass else: env['_LIBFLAGS'] = '-Wl,--start-group ' + env['_LIBFLAGS'] + ' -Wl,--end-group' + if env['platform'] == 'windows': + # Avoid depending on gcc runtime DLLs + linkflags += ['-static-libgcc'] + if env['machine'] == 'x86_64': + linkflags += ['-static-libstdc++'] + # Handle the @xx symbol munging of DLL exports + shlinkflags += ['-Wl,--enable-stdcall-fixup'] + #shlinkflags += ['-Wl,--kill-at'] if msvc: if env['build'] == 'release': # enable Link-time Code Generation diff --git a/mesalib/src/glsl/ir_reader.cpp b/mesalib/src/glsl/ir_reader.cpp index 22009eebc..2d0bccb78 100644 --- a/mesalib/src/glsl/ir_reader.cpp +++ b/mesalib/src/glsl/ir_reader.cpp @@ -777,7 +777,7 @@ ir_reader::read_constant(s_expression *expr) ir_constant_data data = { { 0 } }; // Read in list of values (at most 16). - int k = 0; + unsigned k = 0; foreach_iter(exec_list_iterator, it, values->subexpressions) { if (k >= 16) { ir_read_error(values, "expected at most 16 numbers"); @@ -820,6 +820,11 @@ ir_reader::read_constant(s_expression *expr) } ++k; } + if (k != type->components()) { + ir_read_error(values, "expected %u constant values, found %u", + type->components(), k); + return NULL; + } return new(mem_ctx) ir_constant(type, &data); } diff --git a/mesalib/src/mesa/drivers/common/driverfuncs.c b/mesalib/src/mesa/drivers/common/driverfuncs.c index 78caa0542..6484d284d 100644 --- a/mesalib/src/mesa/drivers/common/driverfuncs.c +++ b/mesalib/src/mesa/drivers/common/driverfuncs.c @@ -118,11 +118,6 @@ _mesa_init_driver_functions(struct dd_function_table *driver) driver->UnmapTexture = NULL; driver->TextureMemCpy = memcpy; driver->IsTextureResident = NULL; - driver->UpdateTexturePalette = NULL; - - /* imaging */ - driver->CopyColorTable = _mesa_meta_CopyColorTable; - driver->CopyColorSubTable = _mesa_meta_CopyColorSubTable; /* Vertex/fragment programs */ driver->BindProgram = NULL; diff --git a/mesalib/src/mesa/drivers/common/meta.c b/mesalib/src/mesa/drivers/common/meta.c index 291d91212..ad04d369f 100644 --- a/mesalib/src/mesa/drivers/common/meta.c +++ b/mesalib/src/mesa/drivers/common/meta.c @@ -2939,58 +2939,3 @@ _mesa_meta_CopyTexSubImage3D(struct gl_context *ctx, GLenum target, GLint level, copy_tex_sub_image(ctx, 3, target, level, xoffset, yoffset, zoffset, x, y, width, height); } - - -void -_mesa_meta_CopyColorTable(struct gl_context *ctx, - GLenum target, GLenum internalformat, - GLint x, GLint y, GLsizei width) -{ - GLfloat *buf; - - buf = (GLfloat *) malloc(width * 4 * sizeof(GLfloat)); - if (!buf) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyColorTable"); - return; - } - - /* - * Read image from framebuffer (disable pixel transfer ops) - */ - _mesa_meta_begin(ctx, MESA_META_PIXEL_STORE | MESA_META_PIXEL_TRANSFER); - ctx->Driver.ReadPixels(ctx, x, y, width, 1, - GL_RGBA, GL_FLOAT, &ctx->Pack, buf); - - _mesa_ColorTable(target, internalformat, width, GL_RGBA, GL_FLOAT, buf); - - _mesa_meta_end(ctx); - - free(buf); -} - - -void -_mesa_meta_CopyColorSubTable(struct gl_context *ctx,GLenum target, GLsizei start, - GLint x, GLint y, GLsizei width) -{ - GLfloat *buf; - - buf = (GLfloat *) malloc(width * 4 * sizeof(GLfloat)); - if (!buf) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyColorSubTable"); - return; - } - - /* - * Read image from framebuffer (disable pixel transfer ops) - */ - _mesa_meta_begin(ctx, MESA_META_PIXEL_STORE | MESA_META_PIXEL_TRANSFER); - ctx->Driver.ReadPixels(ctx, x, y, width, 1, - GL_RGBA, GL_FLOAT, &ctx->Pack, buf); - - _mesa_ColorSubTable(target, start, width, GL_RGBA, GL_FLOAT, buf); - - _mesa_meta_end(ctx); - - free(buf); -} diff --git a/mesalib/src/mesa/drivers/common/meta.h b/mesalib/src/mesa/drivers/common/meta.h index ac20e370e..9a92613c4 100644 --- a/mesalib/src/mesa/drivers/common/meta.h +++ b/mesalib/src/mesa/drivers/common/meta.h @@ -121,24 +121,4 @@ _mesa_meta_CopyTexSubImage3D(struct gl_context *ctx, GLenum target, GLint level, GLint x, GLint y, GLsizei width, GLsizei height); -extern void -_mesa_meta_CopyColorTable(struct gl_context *ctx, - GLenum target, GLenum internalformat, - GLint x, GLint y, GLsizei width); - -extern void -_mesa_meta_CopyColorSubTable(struct gl_context *ctx,GLenum target, GLsizei start, - GLint x, GLint y, GLsizei width); - -extern void -_mesa_meta_CopyConvolutionFilter1D(struct gl_context *ctx, GLenum target, - GLenum internalFormat, - GLint x, GLint y, GLsizei width); - -extern void -_mesa_meta_CopyConvolutionFilter2D(struct gl_context *ctx, GLenum target, - GLenum internalFormat, GLint x, GLint y, - GLsizei width, GLsizei height); - - #endif /* META_H */ diff --git a/mesalib/src/mesa/main/colortab.c b/mesalib/src/mesa/main/colortab.c index ddb0f1f65..f20dee677 100644 --- a/mesalib/src/mesa/main/colortab.c +++ b/mesalib/src/mesa/main/colortab.c @@ -41,361 +41,14 @@ #if FEATURE_colortable - -/** - * Given an internalFormat token passed to glColorTable, - * return the corresponding base format. - * Return -1 if invalid token. - */ -static GLint -base_colortab_format( GLenum format ) -{ - switch (format) { - case GL_ALPHA: - case GL_ALPHA4: - case GL_ALPHA8: - case GL_ALPHA12: - case GL_ALPHA16: - return GL_ALPHA; - case GL_LUMINANCE: - case GL_LUMINANCE4: - case GL_LUMINANCE8: - case GL_LUMINANCE12: - case GL_LUMINANCE16: - return GL_LUMINANCE; - case GL_LUMINANCE_ALPHA: - case GL_LUMINANCE4_ALPHA4: - case GL_LUMINANCE6_ALPHA2: - case GL_LUMINANCE8_ALPHA8: - case GL_LUMINANCE12_ALPHA4: - case GL_LUMINANCE12_ALPHA12: - case GL_LUMINANCE16_ALPHA16: - return GL_LUMINANCE_ALPHA; - case GL_INTENSITY: - case GL_INTENSITY4: - case GL_INTENSITY8: - case GL_INTENSITY12: - case GL_INTENSITY16: - return GL_INTENSITY; - 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: - return GL_RGB; - case GL_RGBA: - case GL_RGBA2: - case GL_RGBA4: - case GL_RGB5_A1: - case GL_RGBA8: - case GL_RGB10_A2: - case GL_RGBA12: - case GL_RGBA16: - return GL_RGBA; - default: - return -1; /* error */ - } -} - - - -/** - * Examine table's format and set the component sizes accordingly. - */ -static void -set_component_sizes( struct gl_color_table *table ) -{ - /* assuming the ubyte table */ - const GLubyte sz = 8; - - switch (table->_BaseFormat) { - case GL_ALPHA: - table->RedSize = 0; - table->GreenSize = 0; - table->BlueSize = 0; - table->AlphaSize = sz; - table->IntensitySize = 0; - table->LuminanceSize = 0; - break; - case GL_LUMINANCE: - table->RedSize = 0; - table->GreenSize = 0; - table->BlueSize = 0; - table->AlphaSize = 0; - table->IntensitySize = 0; - table->LuminanceSize = sz; - break; - case GL_LUMINANCE_ALPHA: - table->RedSize = 0; - table->GreenSize = 0; - table->BlueSize = 0; - table->AlphaSize = sz; - table->IntensitySize = 0; - table->LuminanceSize = sz; - break; - case GL_INTENSITY: - table->RedSize = 0; - table->GreenSize = 0; - table->BlueSize = 0; - table->AlphaSize = 0; - table->IntensitySize = sz; - table->LuminanceSize = 0; - break; - case GL_RGB: - table->RedSize = sz; - table->GreenSize = sz; - table->BlueSize = sz; - table->AlphaSize = 0; - table->IntensitySize = 0; - table->LuminanceSize = 0; - break; - case GL_RGBA: - table->RedSize = sz; - table->GreenSize = sz; - table->BlueSize = sz; - table->AlphaSize = sz; - table->IntensitySize = 0; - table->LuminanceSize = 0; - break; - default: - _mesa_problem(NULL, "unexpected format in set_component_sizes"); - } -} - - - -/** - * Update/replace all or part of a color table. Helper function - * used by _mesa_ColorTable() and _mesa_ColorSubTable(). - * The table->Table buffer should already be allocated. - * \param start first entry to update - * \param count number of entries to update - * \param format format of user-provided table data - * \param type datatype of user-provided table data - * \param data user-provided table data - * \param [rgba]Scale - RGBA scale factors - * \param [rgba]Bias - RGBA bias factors - */ -static void -store_colortable_entries(struct gl_context *ctx, struct gl_color_table *table, - GLsizei start, GLsizei count, - GLenum format, GLenum type, const GLvoid *data, - GLfloat rScale, GLfloat rBias, - GLfloat gScale, GLfloat gBias, - GLfloat bScale, GLfloat bBias, - GLfloat aScale, GLfloat aBias) -{ - data = _mesa_map_validate_pbo_source(ctx, - 1, &ctx->Unpack, count, 1, 1, - format, type, INT_MAX, data, - "glColor[Sub]Table"); - if (!data) - return; - - { - /* convert user-provided data to GLfloat values */ - GLfloat tempTab[MAX_COLOR_TABLE_SIZE * 4]; - GLfloat *tableF; - GLint i; - - _mesa_unpack_color_span_float(ctx, - count, /* number of pixels */ - table->_BaseFormat, /* dest format */ - tempTab, /* dest address */ - format, type, /* src format/type */ - data, /* src data */ - &ctx->Unpack, - IMAGE_CLAMP_BIT); /* transfer ops */ - - /* the destination */ - tableF = table->TableF; - - /* Apply scale & bias & clamp now */ - switch (table->_BaseFormat) { - case GL_INTENSITY: - for (i = 0; i < count; i++) { - GLuint j = start + i; - tableF[j] = CLAMP(tempTab[i] * rScale + rBias, 0.0F, 1.0F); - } - break; - case GL_LUMINANCE: - for (i = 0; i < count; i++) { - GLuint j = start + i; - tableF[j] = CLAMP(tempTab[i] * rScale + rBias, 0.0F, 1.0F); - } - break; - case GL_ALPHA: - for (i = 0; i < count; i++) { - GLuint j = start + i; - tableF[j] = CLAMP(tempTab[i] * aScale + aBias, 0.0F, 1.0F); - } - break; - case GL_LUMINANCE_ALPHA: - for (i = 0; i < count; i++) { - GLuint j = start + i; - tableF[j*2+0] = CLAMP(tempTab[i*2+0] * rScale + rBias, 0.0F, 1.0F); - tableF[j*2+1] = CLAMP(tempTab[i*2+1] * aScale + aBias, 0.0F, 1.0F); - } - break; - case GL_RGB: - for (i = 0; i < count; i++) { - GLuint j = start + i; - tableF[j*3+0] = CLAMP(tempTab[i*3+0] * rScale + rBias, 0.0F, 1.0F); - tableF[j*3+1] = CLAMP(tempTab[i*3+1] * gScale + gBias, 0.0F, 1.0F); - tableF[j*3+2] = CLAMP(tempTab[i*3+2] * bScale + bBias, 0.0F, 1.0F); - } - break; - case GL_RGBA: - for (i = 0; i < count; i++) { - GLuint j = start + i; - tableF[j*4+0] = CLAMP(tempTab[i*4+0] * rScale + rBias, 0.0F, 1.0F); - tableF[j*4+1] = CLAMP(tempTab[i*4+1] * gScale + gBias, 0.0F, 1.0F); - tableF[j*4+2] = CLAMP(tempTab[i*4+2] * bScale + bBias, 0.0F, 1.0F); - tableF[j*4+3] = CLAMP(tempTab[i*4+3] * aScale + aBias, 0.0F, 1.0F); - } - break; - default: - _mesa_problem(ctx, "Bad format in store_colortable_entries"); - return; - } - } - - /* update the ubyte table */ - { - const GLint comps = _mesa_components_in_format(table->_BaseFormat); - const GLfloat *tableF = table->TableF + start * comps; - GLubyte *tableUB = table->TableUB + start * comps; - GLint i; - for (i = 0; i < count * comps; i++) { - CLAMPED_FLOAT_TO_UBYTE(tableUB[i], tableF[i]); - } - } - - _mesa_unmap_pbo_source(ctx, &ctx->Unpack); -} - - - void GLAPIENTRY _mesa_ColorTable( GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid *data ) { - static const GLfloat one[4] = { 1.0, 1.0, 1.0, 1.0 }; - static const GLfloat zero[4] = { 0.0, 0.0, 0.0, 0.0 }; GET_CURRENT_CONTEXT(ctx); - struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx); - struct gl_texture_object *texObj = NULL; - struct gl_color_table *table = NULL; - GLboolean proxy = GL_FALSE; - GLint baseFormat; - const GLfloat *scale = one, *bias = zero; - GLint comps; - - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* too complex */ - - switch (target) { - case GL_SHARED_TEXTURE_PALETTE_EXT: - table = &ctx->Texture.Palette; - break; - default: - /* try texture targets */ - { - struct gl_texture_object *texobj - = _mesa_select_tex_object(ctx, texUnit, target); - if (texobj) { - table = &texobj->Palette; - proxy = _mesa_is_proxy_texture(target); - } - else { - _mesa_error(ctx, GL_INVALID_ENUM, "glColorTable(target)"); - return; - } - } - } - - assert(table); - - if (!_mesa_is_legal_format_and_type(ctx, format, type) || - format == GL_INTENSITY) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glColorTable(format or type)"); - return; - } - - baseFormat = base_colortab_format(internalFormat); - if (baseFormat < 0) { - _mesa_error(ctx, GL_INVALID_ENUM, "glColorTable(internalFormat)"); - return; - } - - if (width < 0 || (width != 0 && !_mesa_is_pow_two(width))) { - /* error */ - if (proxy) { - table->Size = 0; - table->InternalFormat = (GLenum) 0; - table->_BaseFormat = (GLenum) 0; - } - else { - _mesa_error(ctx, GL_INVALID_VALUE, "glColorTable(width=%d)", width); - } - return; - } - - if (width > (GLsizei) ctx->Const.MaxColorTableSize) { - if (proxy) { - table->Size = 0; - table->InternalFormat = (GLenum) 0; - table->_BaseFormat = (GLenum) 0; - } - else { - _mesa_error(ctx, GL_TABLE_TOO_LARGE, "glColorTable(width)"); - } - return; - } - - table->Size = width; - table->InternalFormat = internalFormat; - table->_BaseFormat = (GLenum) baseFormat; - - comps = _mesa_components_in_format(table->_BaseFormat); - assert(comps > 0); /* error should have been caught sooner */ - - if (!proxy) { - _mesa_free_colortable_data(table); - - if (width > 0) { - table->TableF = (GLfloat *) malloc(comps * width * sizeof(GLfloat)); - table->TableUB = (GLubyte *) malloc(comps * width * sizeof(GLubyte)); - - if (!table->TableF || !table->TableUB) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glColorTable"); - return; - } - - store_colortable_entries(ctx, table, - 0, width, /* start, count */ - format, type, data, - scale[0], bias[0], - scale[1], bias[1], - scale[2], bias[2], - scale[3], bias[3]); - } - } /* proxy */ - - /* do this after the table's Type and Format are set */ - set_component_sizes(table); - - if (texObj || target == GL_SHARED_TEXTURE_PALETTE_EXT) { - /* texture object palette, texObj==NULL means the shared palette */ - if (ctx->Driver.UpdateTexturePalette) { - (*ctx->Driver.UpdateTexturePalette)( ctx, texObj ); - } - } - - ctx->NewState |= _NEW_PIXEL; + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + _mesa_error(ctx, GL_INVALID_ENUM, "glColorTable(target)"); } @@ -405,73 +58,9 @@ _mesa_ColorSubTable( GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data ) { - static const GLfloat one[4] = { 1.0, 1.0, 1.0, 1.0 }; - static const GLfloat zero[4] = { 0.0, 0.0, 0.0, 0.0 }; GET_CURRENT_CONTEXT(ctx); - struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx); - struct gl_texture_object *texObj = NULL; - struct gl_color_table *table = NULL; - const GLfloat *scale = one, *bias = zero; - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); - - switch (target) { - case GL_SHARED_TEXTURE_PALETTE_EXT: - table = &ctx->Texture.Palette; - break; - default: - /* try texture targets */ - texObj = _mesa_select_tex_object(ctx, texUnit, target); - if (texObj && !_mesa_is_proxy_texture(target)) { - table = &texObj->Palette; - } - else { - _mesa_error(ctx, GL_INVALID_ENUM, "glColorSubTable(target)"); - return; - } - } - - assert(table); - - if (!_mesa_is_legal_format_and_type(ctx, format, type) || - format == GL_INTENSITY) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glColorSubTable(format or type)"); - return; - } - - if (count < 1) { - _mesa_error(ctx, GL_INVALID_VALUE, "glColorSubTable(count)"); - return; - } - - /* error should have been caught sooner */ - assert(_mesa_components_in_format(table->_BaseFormat) > 0); - - if (start + count > (GLint) table->Size) { - _mesa_error(ctx, GL_INVALID_VALUE, "glColorSubTable(count)"); - return; - } - - if (!table->TableF || !table->TableUB) { - /* a GL_OUT_OF_MEMORY error would have been recorded previously */ - return; - } - - store_colortable_entries(ctx, table, start, count, - format, type, data, - scale[0], bias[0], - scale[1], bias[1], - scale[2], bias[2], - scale[3], bias[3]); - - if (texObj || target == GL_SHARED_TEXTURE_PALETTE_EXT) { - /* per-texture object palette */ - if (ctx->Driver.UpdateTexturePalette) { - (*ctx->Driver.UpdateTexturePalette)( ctx, texObj ); - } - } - - ctx->NewState |= _NEW_PIXEL; + _mesa_error(ctx, GL_INVALID_ENUM, "glColorSubTable(target)"); } @@ -482,12 +71,7 @@ _mesa_CopyColorTable(GLenum target, GLenum internalformat, { GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); - - if (!ctx->ReadBuffer->_ColorReadBuffer) { - return; /* no readbuffer - OK */ - } - - ctx->Driver.CopyColorTable( ctx, target, internalformat, x, y, width ); + _mesa_error(ctx, GL_INVALID_ENUM, "glCopyColorTable(target)"); } @@ -498,12 +82,7 @@ _mesa_CopyColorSubTable(GLenum target, GLsizei start, { GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); - - if (!ctx->ReadBuffer->_ColorReadBuffer) { - return; /* no readbuffer - OK */ - } - - ctx->Driver.CopyColorSubTable( ctx, target, start, x, y, width ); + _mesa_error(ctx, GL_INVALID_ENUM, "glCopyColorSubTable(target)"); } @@ -513,120 +92,8 @@ _mesa_GetnColorTableARB( GLenum target, GLenum format, GLenum type, GLsizei bufSize, GLvoid *data ) { GET_CURRENT_CONTEXT(ctx); - struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx); - struct gl_color_table *table = NULL; - GLfloat rgba[MAX_COLOR_TABLE_SIZE][4]; - GLbitfield transferOps = 0; ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); - - if (ctx->NewState) { - _mesa_update_state(ctx); - } - - switch (target) { - case GL_SHARED_TEXTURE_PALETTE_EXT: - table = &ctx->Texture.Palette; - break; - default: - /* try texture targets */ - { - struct gl_texture_object *texobj - = _mesa_select_tex_object(ctx, texUnit, target); - if (texobj && !_mesa_is_proxy_texture(target)) { - table = &texobj->Palette; - } - else { - _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTable(target)"); - return; - } - } - } - - ASSERT(table); - - if (table->Size <= 0) { - return; - } - - switch (table->_BaseFormat) { - case GL_ALPHA: - { - GLuint i; - for (i = 0; i < table->Size; i++) { - rgba[i][RCOMP] = 0; - rgba[i][GCOMP] = 0; - rgba[i][BCOMP] = 0; - rgba[i][ACOMP] = table->TableF[i]; - } - } - break; - case GL_LUMINANCE: - { - GLuint i; - for (i = 0; i < table->Size; i++) { - rgba[i][RCOMP] = - rgba[i][GCOMP] = - rgba[i][BCOMP] = table->TableF[i]; - rgba[i][ACOMP] = 1.0F; - } - } - break; - case GL_LUMINANCE_ALPHA: - { - GLuint i; - for (i = 0; i < table->Size; i++) { - rgba[i][RCOMP] = - rgba[i][GCOMP] = - rgba[i][BCOMP] = table->TableF[i*2+0]; - rgba[i][ACOMP] = table->TableF[i*2+1]; - } - } - break; - case GL_INTENSITY: - { - GLuint i; - for (i = 0; i < table->Size; i++) { - rgba[i][RCOMP] = - rgba[i][GCOMP] = - rgba[i][BCOMP] = - rgba[i][ACOMP] = table->TableF[i]; - } - } - break; - case GL_RGB: - { - GLuint i; - for (i = 0; i < table->Size; i++) { - rgba[i][RCOMP] = table->TableF[i*3+0]; - rgba[i][GCOMP] = table->TableF[i*3+1]; - rgba[i][BCOMP] = table->TableF[i*3+2]; - rgba[i][ACOMP] = 1.0F; - } - } - break; - case GL_RGBA: - memcpy(rgba, table->TableF, 4 * table->Size * sizeof(GLfloat)); - break; - default: - _mesa_problem(ctx, "bad table format in glGetColorTable"); - return; - } - - data = _mesa_map_validate_pbo_dest(ctx, - 1, &ctx->Pack, table->Size, 1, 1, - format, type, bufSize, data, - "glGetColorTable"); - if (!data) - return; - - /* TODO: is this correct? */ - if(ctx->Color._ClampReadColor) - transferOps |= IMAGE_CLAMP_BIT; - - _mesa_pack_rgba_span_float(ctx, table->Size, rgba, - format, type, data, &ctx->Pack, transferOps); - - _mesa_unmap_pbo_dest(ctx, &ctx->Pack); + _mesa_error(ctx, GL_INVALID_ENUM, "glGetnColorTableARB(target)"); } @@ -634,7 +101,9 @@ static void GLAPIENTRY _mesa_GetColorTable( GLenum target, GLenum format, GLenum type, GLvoid *data ) { - _mesa_GetnColorTableARB(target, format, type, INT_MAX, data); + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTable(target)"); } @@ -664,61 +133,8 @@ static void GLAPIENTRY _mesa_GetColorTableParameterfv( GLenum target, GLenum pname, GLfloat *params ) { GET_CURRENT_CONTEXT(ctx); - struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx); - struct gl_color_table *table = NULL; ASSERT_OUTSIDE_BEGIN_END(ctx); - - switch (target) { - case GL_SHARED_TEXTURE_PALETTE_EXT: - table = &ctx->Texture.Palette; - break; - default: - /* try texture targets */ - { - struct gl_texture_object *texobj - = _mesa_select_tex_object(ctx, texUnit, target); - if (texobj) { - table = &texobj->Palette; - } - else { - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetColorTableParameterfv(target)"); - return; - } - } - } - - assert(table); - - switch (pname) { - case GL_COLOR_TABLE_FORMAT: - *params = (GLfloat) table->InternalFormat; - break; - case GL_COLOR_TABLE_WIDTH: - *params = (GLfloat) table->Size; - break; - case GL_COLOR_TABLE_RED_SIZE: - *params = (GLfloat) table->RedSize; - break; - case GL_COLOR_TABLE_GREEN_SIZE: - *params = (GLfloat) table->GreenSize; - break; - case GL_COLOR_TABLE_BLUE_SIZE: - *params = (GLfloat) table->BlueSize; - break; - case GL_COLOR_TABLE_ALPHA_SIZE: - *params = (GLfloat) table->AlphaSize; - break; - case GL_COLOR_TABLE_LUMINANCE_SIZE: - *params = (GLfloat) table->LuminanceSize; - break; - case GL_COLOR_TABLE_INTENSITY_SIZE: - *params = (GLfloat) table->IntensitySize; - break; - default: - _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTableParameterfv(pname)" ); - return; - } + _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTableParameterfv(target)"); } @@ -727,61 +143,8 @@ static void GLAPIENTRY _mesa_GetColorTableParameteriv( GLenum target, GLenum pname, GLint *params ) { GET_CURRENT_CONTEXT(ctx); - struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx); - struct gl_color_table *table = NULL; ASSERT_OUTSIDE_BEGIN_END(ctx); - - switch (target) { - case GL_SHARED_TEXTURE_PALETTE_EXT: - table = &ctx->Texture.Palette; - break; - default: - /* Try texture targets */ - { - struct gl_texture_object *texobj - = _mesa_select_tex_object(ctx, texUnit, target); - if (texobj) { - table = &texobj->Palette; - } - else { - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetColorTableParameteriv(target)"); - return; - } - } - } - - assert(table); - - switch (pname) { - case GL_COLOR_TABLE_FORMAT: - *params = table->InternalFormat; - break; - case GL_COLOR_TABLE_WIDTH: - *params = table->Size; - break; - case GL_COLOR_TABLE_RED_SIZE: - *params = table->RedSize; - break; - case GL_COLOR_TABLE_GREEN_SIZE: - *params = table->GreenSize; - break; - case GL_COLOR_TABLE_BLUE_SIZE: - *params = table->BlueSize; - break; - case GL_COLOR_TABLE_ALPHA_SIZE: - *params = table->AlphaSize; - break; - case GL_COLOR_TABLE_LUMINANCE_SIZE: - *params = table->LuminanceSize; - break; - case GL_COLOR_TABLE_INTENSITY_SIZE: - *params = table->IntensitySize; - break; - default: - _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTableParameteriv(pname)" ); - return; - } + _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTableParameteriv(target)"); } @@ -804,33 +167,3 @@ _mesa_init_colortable_dispatch(struct _glapi_table *disp) #endif /* FEATURE_colortable */ - - -/**********************************************************************/ -/***** Initialization *****/ -/**********************************************************************/ - - -void -_mesa_init_colortable( struct gl_color_table *p ) -{ - p->TableF = NULL; - p->TableUB = NULL; - p->Size = 0; - p->InternalFormat = GL_RGBA; -} - - - -void -_mesa_free_colortable_data( struct gl_color_table *p ) -{ - if (p->TableF) { - free(p->TableF); - p->TableF = NULL; - } - if (p->TableUB) { - free(p->TableUB); - p->TableUB = NULL; - } -} diff --git a/mesalib/src/mesa/main/colortab.h b/mesalib/src/mesa/main/colortab.h index 81b4e008b..b0d2b5db8 100644 --- a/mesalib/src/mesa/main/colortab.h +++ b/mesalib/src/mesa/main/colortab.h @@ -1,84 +1,76 @@ -/*
- * Mesa 3-D graphics library
- * Version: 6.5.2
- *
- * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#ifndef COLORTAB_H
-#define COLORTAB_H
-
-
-#include "compiler.h"
-#include "glheader.h"
-#include "mfeatures.h"
-
-struct _glapi_table;
-struct gl_color_table;
-
-#if FEATURE_colortable
-
-extern void GLAPIENTRY
-_mesa_ColorTable( GLenum target, GLenum internalformat,
- GLsizei width, GLenum format, GLenum type,
- const GLvoid *table );
-
-extern void GLAPIENTRY
-_mesa_ColorSubTable( GLenum target, GLsizei start,
- GLsizei count, GLenum format, GLenum type,
- const GLvoid *table );
-
-extern void
-_mesa_init_colortable_dispatch(struct _glapi_table *disp);
-
-#else /* FEATURE_colortable */
-
-static INLINE void GLAPIENTRY
-_mesa_ColorTable( GLenum target, GLenum internalformat,
- GLsizei width, GLenum format, GLenum type,
- const GLvoid *table )
-{
- ASSERT_NO_FEATURE();
-}
-
-static INLINE void GLAPIENTRY
-_mesa_ColorSubTable( GLenum target, GLsizei start,
- GLsizei count, GLenum format, GLenum type,
- const GLvoid *table )
-{
- ASSERT_NO_FEATURE();
-}
-
-static INLINE void
-_mesa_init_colortable_dispatch(struct _glapi_table *disp)
-{
-}
-
-#endif /* FEATURE_colortable */
-
-
-extern void
-_mesa_init_colortable( struct gl_color_table *table );
-
-extern void
-_mesa_free_colortable_data( struct gl_color_table *table );
-
-#endif /* COLORTAB_H */
+/* + * Mesa 3-D graphics library + * Version: 6.5.2 + * + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef COLORTAB_H +#define COLORTAB_H + + +#include "compiler.h" +#include "glheader.h" +#include "mfeatures.h" + +struct _glapi_table; + +#if FEATURE_colortable + +extern void GLAPIENTRY +_mesa_ColorTable( GLenum target, GLenum internalformat, + GLsizei width, GLenum format, GLenum type, + const GLvoid *table ); + +extern void GLAPIENTRY +_mesa_ColorSubTable( GLenum target, GLsizei start, + GLsizei count, GLenum format, GLenum type, + const GLvoid *table ); + +extern void +_mesa_init_colortable_dispatch(struct _glapi_table *disp); + +#else /* FEATURE_colortable */ + +static INLINE void GLAPIENTRY +_mesa_ColorTable( GLenum target, GLenum internalformat, + GLsizei width, GLenum format, GLenum type, + const GLvoid *table ) +{ + ASSERT_NO_FEATURE(); +} + +static INLINE void GLAPIENTRY +_mesa_ColorSubTable( GLenum target, GLsizei start, + GLsizei count, GLenum format, GLenum type, + const GLvoid *table ) +{ + ASSERT_NO_FEATURE(); +} + +static INLINE void +_mesa_init_colortable_dispatch(struct _glapi_table *disp) +{ +} + +#endif /* FEATURE_colortable */ + +#endif /* COLORTAB_H */ diff --git a/mesalib/src/mesa/main/dd.h b/mesalib/src/mesa/main/dd.h index b9305addc..b77e4f092 100644 --- a/mesalib/src/mesa/main/dd.h +++ b/mesalib/src/mesa/main/dd.h @@ -523,29 +523,6 @@ struct dd_function_table { */ GLboolean (*IsTextureResident)( struct gl_context *ctx, struct gl_texture_object *t ); - - /** - * Called when the texture's color lookup table is changed. - * - * If \p tObj is NULL then the shared texture palette - * gl_texture_object::Palette is to be updated. - */ - void (*UpdateTexturePalette)( struct gl_context *ctx, - struct gl_texture_object *tObj ); - /*@}*/ - - - /** - * \name Imaging functionality - */ - /*@{*/ - void (*CopyColorTable)( struct gl_context *ctx, - GLenum target, GLenum internalformat, - GLint x, GLint y, GLsizei width ); - - void (*CopyColorSubTable)( struct gl_context *ctx, - GLenum target, GLsizei start, - GLint x, GLint y, GLsizei width ); /*@}*/ diff --git a/mesalib/src/mesa/main/enable.c b/mesalib/src/mesa/main/enable.c index 3ba4df634..4bf1809e7 100644 --- a/mesalib/src/mesa/main/enable.c +++ b/mesalib/src/mesa/main/enable.c @@ -576,12 +576,6 @@ _mesa_set_enable(struct gl_context *ctx, GLenum cap, GLboolean state) FLUSH_VERTICES(ctx, _NEW_SCISSOR); ctx->Scissor.Enabled = state; break; - case GL_SHARED_TEXTURE_PALETTE_EXT: - if (ctx->Texture.SharedPalette == state) - return; - FLUSH_VERTICES(ctx, _NEW_TEXTURE); - ctx->Texture.SharedPalette = state; - break; case GL_STENCIL_TEST: if (ctx->Stencil.Enabled == state) return; @@ -1175,8 +1169,6 @@ _mesa_IsEnabled( GLenum cap ) return ctx->Transform.RescaleNormals; case GL_SCISSOR_TEST: return ctx->Scissor.Enabled; - case GL_SHARED_TEXTURE_PALETTE_EXT: - return ctx->Texture.SharedPalette; case GL_STENCIL_TEST: return ctx->Stencil.Enabled; case GL_TEXTURE_1D: diff --git a/mesalib/src/mesa/main/extensions.c b/mesalib/src/mesa/main/extensions.c index 14b0cf9ac..1903a503c 100644 --- a/mesalib/src/mesa/main/extensions.c +++ b/mesalib/src/mesa/main/extensions.c @@ -172,7 +172,6 @@ static const struct extension extension_table[] = { { "GL_EXT_packed_depth_stencil", o(EXT_packed_depth_stencil), GL, 2005 }, { "GL_EXT_packed_float", o(EXT_packed_float), GL, 2004 }, { "GL_EXT_packed_pixels", o(EXT_packed_pixels), GL, 1997 }, - { "GL_EXT_paletted_texture", o(EXT_paletted_texture), GL, 1995 }, { "GL_EXT_pixel_buffer_object", o(EXT_pixel_buffer_object), GL, 2004 }, { "GL_EXT_point_parameters", o(EXT_point_parameters), GL, 1997 }, { "GL_EXT_polygon_offset", o(EXT_polygon_offset), GL, 1995 }, @@ -182,7 +181,6 @@ static const struct extension extension_table[] = { { "GL_EXT_separate_shader_objects", o(EXT_separate_shader_objects), GL, 2008 }, { "GL_EXT_separate_specular_color", o(EXT_separate_specular_color), GL, 1997 }, { "GL_EXT_shadow_funcs", o(EXT_shadow_funcs), GL, 2002 }, - { "GL_EXT_shared_texture_palette", o(EXT_shared_texture_palette), GL, 2000 }, { "GL_EXT_stencil_two_side", o(EXT_stencil_two_side), GL, 2001 }, { "GL_EXT_stencil_wrap", o(EXT_stencil_wrap), GL, 2002 }, { "GL_EXT_subtexture", o(EXT_subtexture), GL, 1995 }, @@ -488,7 +486,6 @@ _mesa_enable_sw_extensions(struct gl_context *ctx) #endif /*ctx->Extensions.EXT_multi_draw_arrays = GL_TRUE;*/ ctx->Extensions.EXT_packed_depth_stencil = GL_TRUE; - ctx->Extensions.EXT_paletted_texture = GL_TRUE; #if FEATURE_EXT_pixel_buffer_object ctx->Extensions.EXT_pixel_buffer_object = GL_TRUE; #endif @@ -496,7 +493,6 @@ _mesa_enable_sw_extensions(struct gl_context *ctx) ctx->Extensions.EXT_provoking_vertex = GL_TRUE; ctx->Extensions.EXT_shadow_funcs = GL_TRUE; ctx->Extensions.EXT_secondary_color = GL_TRUE; - ctx->Extensions.EXT_shared_texture_palette = GL_TRUE; ctx->Extensions.EXT_stencil_wrap = GL_TRUE; ctx->Extensions.EXT_stencil_two_side = GL_TRUE; ctx->Extensions.EXT_texture_array = GL_TRUE; diff --git a/mesalib/src/mesa/main/formats.c b/mesalib/src/mesa/main/formats.c index c0fcf9cd4..c6634c458 100644 --- a/mesalib/src/mesa/main/formats.c +++ b/mesalib/src/mesa/main/formats.c @@ -1175,7 +1175,6 @@ _mesa_get_format_bits(gl_format format, GLenum pname) case GL_TEXTURE_LUMINANCE_SIZE: return info->LuminanceBits; case GL_INDEX_BITS: - case GL_TEXTURE_INDEX_SIZE_EXT: return info->IndexBits; case GL_DEPTH_BITS: case GL_TEXTURE_DEPTH_SIZE_ARB: diff --git a/mesalib/src/mesa/main/framebuffer.c b/mesalib/src/mesa/main/framebuffer.c index 23fa1b2c1..42da17678 100644 --- a/mesalib/src/mesa/main/framebuffer.c +++ b/mesalib/src/mesa/main/framebuffer.c @@ -888,7 +888,6 @@ _mesa_source_buffer_exists(struct gl_context *ctx, GLenum format) case GL_RGBA: case GL_BGRA: case GL_ABGR_EXT: - case GL_COLOR_INDEX: case GL_RED_INTEGER_EXT: case GL_GREEN_INTEGER_EXT: case GL_BLUE_INTEGER_EXT: @@ -976,7 +975,6 @@ _mesa_dest_buffer_exists(struct gl_context *ctx, GLenum format) case GL_RGBA: case GL_BGRA: case GL_ABGR_EXT: - case GL_COLOR_INDEX: case GL_RED_INTEGER_EXT: case GL_GREEN_INTEGER_EXT: case GL_BLUE_INTEGER_EXT: diff --git a/mesalib/src/mesa/main/get.c b/mesalib/src/mesa/main/get.c index d32c68a53..069254b18 100644 --- a/mesalib/src/mesa/main/get.c +++ b/mesalib/src/mesa/main/get.c @@ -857,7 +857,6 @@ static const struct value_desc values[] = { { GL_RENDER_MODE, CONTEXT_ENUM(RenderMode), NO_EXTRA }, { GL_RGBA_MODE, CONST(1), NO_EXTRA }, { GL_SELECTION_BUFFER_SIZE, CONTEXT_INT(Select.BufferSize), NO_EXTRA }, - { GL_SHARED_TEXTURE_PALETTE_EXT, CONTEXT_BOOL(Texture.SharedPalette), NO_EXTRA }, { GL_STEREO, BUFFER_INT(Visual.stereoMode), NO_EXTRA }, diff --git a/mesalib/src/mesa/main/image.c b/mesalib/src/mesa/main/image.c index 37127dcb7..3e75e7c6b 100644 --- a/mesalib/src/mesa/main/image.c +++ b/mesalib/src/mesa/main/image.c @@ -249,12 +249,6 @@ _mesa_components_in_format( GLenum format ) { switch (format) { case GL_COLOR_INDEX: - case GL_COLOR_INDEX1_EXT: - case GL_COLOR_INDEX2_EXT: - case GL_COLOR_INDEX4_EXT: - case GL_COLOR_INDEX8_EXT: - case GL_COLOR_INDEX12_EXT: - case GL_COLOR_INDEX16_EXT: case GL_STENCIL_INDEX: case GL_DEPTH_COMPONENT: case GL_RED: @@ -863,27 +857,6 @@ _mesa_is_color_format(GLenum format) /** - * Test if the given image format is a color index format. - */ -GLboolean -_mesa_is_index_format(GLenum format) -{ - switch (format) { - case GL_COLOR_INDEX: - case GL_COLOR_INDEX1_EXT: - case GL_COLOR_INDEX2_EXT: - case GL_COLOR_INDEX4_EXT: - case GL_COLOR_INDEX8_EXT: - case GL_COLOR_INDEX12_EXT: - case GL_COLOR_INDEX16_EXT: - return GL_TRUE; - default: - return GL_FALSE; - } -} - - -/** * Test if the given image format is a depth component format. */ GLboolean diff --git a/mesalib/src/mesa/main/image.h b/mesalib/src/mesa/main/image.h index 6fa93924c..46adaec41 100644 --- a/mesalib/src/mesa/main/image.h +++ b/mesalib/src/mesa/main/image.h @@ -1,176 +1,173 @@ -/*
- * Mesa 3-D graphics library
- * Version: 7.1
- *
- * 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
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#ifndef IMAGE_H
-#define IMAGE_H
-
-
-#include "glheader.h"
-
-struct gl_context;
-struct gl_pixelstore_attrib;
-
-extern void
-_mesa_swap2( GLushort *p, GLuint n );
-
-extern void
-_mesa_swap4( GLuint *p, GLuint n );
-
-extern GLboolean
-_mesa_type_is_packed(GLenum type);
-
-extern GLint
-_mesa_sizeof_type( GLenum type );
-
-extern GLint
-_mesa_sizeof_packed_type( GLenum type );
-
-extern GLint
-_mesa_components_in_format( GLenum format );
-
-extern GLint
-_mesa_bytes_per_pixel( GLenum format, GLenum type );
-
-extern GLboolean
-_mesa_is_legal_format_and_type(const struct gl_context *ctx,
- GLenum format, GLenum type);
-
-extern GLboolean
-_mesa_is_color_format(GLenum format);
-
-extern GLboolean
-_mesa_is_index_format(GLenum format);
-
-extern GLboolean
-_mesa_is_depth_format(GLenum format);
-
-extern GLboolean
-_mesa_is_stencil_format(GLenum format);
-
-extern GLboolean
-_mesa_is_ycbcr_format(GLenum format);
-
-extern GLboolean
-_mesa_is_depthstencil_format(GLenum format);
-
-extern GLboolean
-_mesa_is_depth_or_stencil_format(GLenum format);
-
-extern GLboolean
-_mesa_is_dudv_format(GLenum format);
-
-extern GLboolean
-_mesa_is_integer_format(GLenum format);
-
-extern GLboolean
-_mesa_is_compressed_format(struct gl_context *ctx, GLenum format);
-
-extern GLvoid *
-_mesa_image_address( GLuint dimensions,
- const struct gl_pixelstore_attrib *packing,
- const GLvoid *image,
- GLsizei width, GLsizei height,
- GLenum format, GLenum type,
- GLint img, GLint row, GLint column );
-
-extern GLvoid *
-_mesa_image_address1d( const struct gl_pixelstore_attrib *packing,
- const GLvoid *image,
- GLsizei width,
- GLenum format, GLenum type,
- GLint column );
-
-extern GLvoid *
-_mesa_image_address2d( const struct gl_pixelstore_attrib *packing,
- const GLvoid *image,
- GLsizei width, GLsizei height,
- GLenum format, GLenum type,
- GLint row, GLint column );
-
-extern GLvoid *
-_mesa_image_address3d( const struct gl_pixelstore_attrib *packing,
- const GLvoid *image,
- GLsizei width, GLsizei height,
- GLenum format, GLenum type,
- GLint img, GLint row, GLint column );
-
-
-extern GLint
-_mesa_image_row_stride( const struct gl_pixelstore_attrib *packing,
- GLint width, GLenum format, GLenum type );
-
-
-extern GLint
-_mesa_image_image_stride( const struct gl_pixelstore_attrib *packing,
- GLint width, GLint height,
- GLenum format, GLenum type );
-
-
-extern void
-_mesa_expand_bitmap(GLsizei width, GLsizei height,
- const struct gl_pixelstore_attrib *unpack,
- const GLubyte *bitmap,
- GLubyte *destBuffer, GLint destStride,
- GLubyte onValue);
-
-
-extern void
-_mesa_convert_colors(GLenum srcType, const GLvoid *src,
- GLenum dstType, GLvoid *dst,
- GLuint count, const GLubyte mask[]);
-
-
-extern GLboolean
-_mesa_clip_drawpixels(const struct gl_context *ctx,
- GLint *destX, GLint *destY,
- GLsizei *width, GLsizei *height,
- struct gl_pixelstore_attrib *unpack);
-
-
-extern GLboolean
-_mesa_clip_readpixels(const struct gl_context *ctx,
- GLint *srcX, GLint *srcY,
- GLsizei *width, GLsizei *height,
- struct gl_pixelstore_attrib *pack);
-
-extern GLboolean
-_mesa_clip_copytexsubimage(const struct gl_context *ctx,
- GLint *destX, GLint *destY,
- GLint *srcX, GLint *srcY,
- GLsizei *width, GLsizei *height);
-
-extern GLboolean
-_mesa_clip_to_region(GLint xmin, GLint ymin,
- GLint xmax, GLint ymax,
- GLint *x, GLint *y,
- GLsizei *width, GLsizei *height );
-
-extern GLboolean
-_mesa_clip_blit(struct gl_context *ctx,
- GLint *srcX0, GLint *srcY0, GLint *srcX1, GLint *srcY1,
- GLint *dstX0, GLint *dstY0, GLint *dstX1, GLint *dstY1);
-
-
-#endif
+/* + * Mesa 3-D graphics library + * Version: 7.1 + * + * 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 + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef IMAGE_H +#define IMAGE_H + + +#include "glheader.h" + +struct gl_context; +struct gl_pixelstore_attrib; + +extern void +_mesa_swap2( GLushort *p, GLuint n ); + +extern void +_mesa_swap4( GLuint *p, GLuint n ); + +extern GLboolean +_mesa_type_is_packed(GLenum type); + +extern GLint +_mesa_sizeof_type( GLenum type ); + +extern GLint +_mesa_sizeof_packed_type( GLenum type ); + +extern GLint +_mesa_components_in_format( GLenum format ); + +extern GLint +_mesa_bytes_per_pixel( GLenum format, GLenum type ); + +extern GLboolean +_mesa_is_legal_format_and_type(const struct gl_context *ctx, + GLenum format, GLenum type); + +extern GLboolean +_mesa_is_color_format(GLenum format); + +extern GLboolean +_mesa_is_depth_format(GLenum format); + +extern GLboolean +_mesa_is_stencil_format(GLenum format); + +extern GLboolean +_mesa_is_ycbcr_format(GLenum format); + +extern GLboolean +_mesa_is_depthstencil_format(GLenum format); + +extern GLboolean +_mesa_is_depth_or_stencil_format(GLenum format); + +extern GLboolean +_mesa_is_dudv_format(GLenum format); + +extern GLboolean +_mesa_is_integer_format(GLenum format); + +extern GLboolean +_mesa_is_compressed_format(struct gl_context *ctx, GLenum format); + +extern GLvoid * +_mesa_image_address( GLuint dimensions, + const struct gl_pixelstore_attrib *packing, + const GLvoid *image, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + GLint img, GLint row, GLint column ); + +extern GLvoid * +_mesa_image_address1d( const struct gl_pixelstore_attrib *packing, + const GLvoid *image, + GLsizei width, + GLenum format, GLenum type, + GLint column ); + +extern GLvoid * +_mesa_image_address2d( const struct gl_pixelstore_attrib *packing, + const GLvoid *image, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + GLint row, GLint column ); + +extern GLvoid * +_mesa_image_address3d( const struct gl_pixelstore_attrib *packing, + const GLvoid *image, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + GLint img, GLint row, GLint column ); + + +extern GLint +_mesa_image_row_stride( const struct gl_pixelstore_attrib *packing, + GLint width, GLenum format, GLenum type ); + + +extern GLint +_mesa_image_image_stride( const struct gl_pixelstore_attrib *packing, + GLint width, GLint height, + GLenum format, GLenum type ); + + +extern void +_mesa_expand_bitmap(GLsizei width, GLsizei height, + const struct gl_pixelstore_attrib *unpack, + const GLubyte *bitmap, + GLubyte *destBuffer, GLint destStride, + GLubyte onValue); + + +extern void +_mesa_convert_colors(GLenum srcType, const GLvoid *src, + GLenum dstType, GLvoid *dst, + GLuint count, const GLubyte mask[]); + + +extern GLboolean +_mesa_clip_drawpixels(const struct gl_context *ctx, + GLint *destX, GLint *destY, + GLsizei *width, GLsizei *height, + struct gl_pixelstore_attrib *unpack); + + +extern GLboolean +_mesa_clip_readpixels(const struct gl_context *ctx, + GLint *srcX, GLint *srcY, + GLsizei *width, GLsizei *height, + struct gl_pixelstore_attrib *pack); + +extern GLboolean +_mesa_clip_copytexsubimage(const struct gl_context *ctx, + GLint *destX, GLint *destY, + GLint *srcX, GLint *srcY, + GLsizei *width, GLsizei *height); + +extern GLboolean +_mesa_clip_to_region(GLint xmin, GLint ymin, + GLint xmax, GLint ymax, + GLint *x, GLint *y, + GLsizei *width, GLsizei *height ); + +extern GLboolean +_mesa_clip_blit(struct gl_context *ctx, + GLint *srcX0, GLint *srcY0, GLint *srcX1, GLint *srcY1, + GLint *dstX0, GLint *dstY0, GLint *dstX1, GLint *dstY1); + + +#endif diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h index ad5979796..ae500b4c2 100644 --- a/mesalib/src/mesa/main/mtypes.h +++ b/mesalib/src/mesa/main/mtypes.h @@ -215,7 +215,9 @@ typedef enum /** - * Indexes for vertex program result attributes + * Indexes for vertex program result attributes. Note that + * _mesa_vert_result_to_frag_attrib() and _mesa_frag_attrib_to_vert_result() make + * assumptions about the layout of this enum. */ typedef enum { @@ -313,7 +315,9 @@ typedef enum /** - * Indexes for fragment program input attributes. + * Indexes for fragment program input attributes. Note that + * _mesa_vert_result_to_frag_attrib() and frag_attrib_to_vert_result() make + * assumptions about the layout of this enum. */ typedef enum { @@ -335,6 +339,48 @@ typedef enum FRAG_ATTRIB_MAX = (FRAG_ATTRIB_VAR0 + MAX_VARYING) } gl_frag_attrib; + +/** + * Convert from a gl_vert_result value to the corresponding gl_frag_attrib. + * + * VERT_RESULT_HPOS is converted to FRAG_ATTRIB_WPOS. + * + * gl_vert_result values which have no corresponding gl_frag_attrib + * (VERT_RESULT_PSIZ, VERT_RESULT_BFC0, VERT_RESULT_BFC1, and + * VERT_RESULT_EDGE) are converted to a value of -1. + */ +static INLINE int +_mesa_vert_result_to_frag_attrib(gl_vert_result vert_result) +{ + if (vert_result >= VERT_RESULT_VAR0) + return vert_result - VERT_RESULT_VAR0 + FRAG_ATTRIB_VAR0; + else if (vert_result <= VERT_RESULT_TEX7) + return vert_result; + else + return -1; +} + + +/** + * Convert from a gl_frag_attrib value to the corresponding gl_vert_result. + * + * FRAG_ATTRIB_WPOS is converted to VERT_RESULT_HPOS. + * + * gl_frag_attrib values which have no corresponding gl_vert_result + * (FRAG_ATTRIB_FACE and FRAG_ATTRIB_PNTC) are converted to a value of -1. + */ +static INLINE int +_mesa_frag_attrib_to_vert_result(gl_frag_attrib frag_attrib) +{ + if (frag_attrib <= FRAG_ATTRIB_TEX7) + return frag_attrib; + else if (frag_attrib >= FRAG_ATTRIB_VAR0) + return frag_attrib - FRAG_ATTRIB_VAR0 + VERT_RESULT_VAR0; + else + return -1; +} + + /** * Bitflags for fragment program input attributes. */ @@ -524,25 +570,6 @@ struct gl_config /** - * Data structure for color tables - */ -struct gl_color_table -{ - GLenum InternalFormat; /**< The user-specified format */ - GLenum _BaseFormat; /**< GL_ALPHA, GL_RGBA, GL_RGB, etc */ - GLuint Size; /**< number of entries in table */ - GLfloat *TableF; /**< Color table, floating point values */ - GLubyte *TableUB; /**< Color table, ubyte values */ - GLubyte RedSize; - GLubyte GreenSize; - GLubyte BlueSize; - GLubyte AlphaSize; - GLubyte LuminanceSize; - GLubyte IntensitySize; -}; - - -/** * \name Bit flags used for updating material values. */ /*@{*/ @@ -1255,9 +1282,9 @@ struct gl_texture_image GLint InternalFormat; /**< Internal format as given by the user */ GLenum _BaseFormat; /**< Either GL_RGB, GL_RGBA, GL_ALPHA, * GL_LUMINANCE, GL_LUMINANCE_ALPHA, - * GL_INTENSITY, GL_COLOR_INDEX, - * GL_DEPTH_COMPONENT or GL_DEPTH_STENCIL_EXT - * only. Used for choosing TexEnv arithmetic. + * GL_INTENSITY, GL_DEPTH_COMPONENT or + * GL_DEPTH_STENCIL_EXT only. Used for + * choosing TexEnv arithmetic. */ gl_format TexFormat; /**< The actual texture memory format */ @@ -1354,8 +1381,7 @@ struct gl_sampler_object /** * Texture object state. Contains the array of mipmap images, border color, - * wrap modes, filter modes, shadow/texcompare state, and the per-texture - * color palette. + * wrap modes, filter modes, and shadow/texcompare state. */ struct gl_texture_object { @@ -1386,9 +1412,6 @@ struct gl_texture_object struct gl_buffer_object *BufferObject; GLenum BufferObjectFormat; - /** GL_EXT_paletted_texture */ - struct gl_color_table Palette; - /** * \name For device driver. * Note: instead of attaching driver data to this pointer, it's preferable @@ -1504,10 +1527,6 @@ struct gl_texture_attrib /** GL_ARB_seamless_cubemap */ GLboolean CubeMapSeamless; - /** GL_EXT_shared_texture_palette */ - GLboolean SharedPalette; - struct gl_color_table Palette; - /** Texture units/samplers used by vertex or fragment texturing */ GLbitfield _EnabledUnits; @@ -2852,7 +2871,6 @@ struct gl_extensions GLboolean EXT_gpu_program_parameters; GLboolean EXT_gpu_shader4; GLboolean EXT_multi_draw_arrays; - GLboolean EXT_paletted_texture; GLboolean EXT_packed_depth_stencil; GLboolean EXT_packed_float; GLboolean EXT_packed_pixels; @@ -2865,7 +2883,6 @@ struct gl_extensions GLboolean EXT_secondary_color; GLboolean EXT_separate_shader_objects; GLboolean EXT_separate_specular_color; - GLboolean EXT_shared_texture_palette; GLboolean EXT_stencil_wrap; GLboolean EXT_stencil_two_side; GLboolean EXT_subtexture; diff --git a/mesalib/src/mesa/main/pack.c b/mesalib/src/mesa/main/pack.c index 7de1d05b9..fd3f89d82 100644 --- a/mesalib/src/mesa/main/pack.c +++ b/mesalib/src/mesa/main/pack.c @@ -3459,8 +3459,7 @@ _mesa_unpack_color_span_chan( struct gl_context *ctx, dstFormat == GL_RED || dstFormat == GL_RG || dstFormat == GL_RGB || - dstFormat == GL_RGBA || - dstFormat == GL_COLOR_INDEX); + dstFormat == GL_RGBA); ASSERT(srcFormat == GL_RED || srcFormat == GL_GREEN || @@ -3646,24 +3645,11 @@ _mesa_unpack_color_span_chan( struct gl_context *ctx, extract_uint_indexes(n, indexes, srcFormat, srcType, source, srcPacking); - if (dstFormat == GL_COLOR_INDEX) { - GLuint i; - _mesa_apply_ci_transfer_ops(ctx, transferOps, n, indexes); - /* convert to GLchan and return */ - for (i = 0; i < n; i++) { - dest[i] = (GLchan) (indexes[i] & 0xff); - } - free(indexes); - free(rgba); - return; - } - else { - /* Convert indexes to RGBA */ - if (transferOps & IMAGE_SHIFT_OFFSET_BIT) { - _mesa_shift_and_offset_ci(ctx, n, indexes); - } - _mesa_map_ci_to_rgba(ctx, n, indexes, rgba); - } + /* Convert indexes to RGBA */ + if (transferOps & IMAGE_SHIFT_OFFSET_BIT) { + _mesa_shift_and_offset_ci(ctx, n, indexes); + } + _mesa_map_ci_to_rgba(ctx, n, indexes, rgba); /* Don't do RGBA scale/bias or RGBA->RGBA mapping if starting * with color indexes. @@ -3773,8 +3759,7 @@ _mesa_unpack_color_span_float( struct gl_context *ctx, dstFormat == GL_RED || dstFormat == GL_RG || dstFormat == GL_RGB || - dstFormat == GL_RGBA || - dstFormat == GL_COLOR_INDEX); + dstFormat == GL_RGBA); ASSERT(srcFormat == GL_RED || srcFormat == GL_GREEN || @@ -3855,24 +3840,11 @@ _mesa_unpack_color_span_float( struct gl_context *ctx, extract_uint_indexes(n, indexes, srcFormat, srcType, source, srcPacking); - if (dstFormat == GL_COLOR_INDEX) { - GLuint i; - _mesa_apply_ci_transfer_ops(ctx, transferOps, n, indexes); - /* convert to GLchan and return */ - for (i = 0; i < n; i++) { - dest[i] = (GLchan) (indexes[i] & 0xff); - } - free(indexes); - free(rgba); - return; - } - else { - /* Convert indexes to RGBA */ - if (transferOps & IMAGE_SHIFT_OFFSET_BIT) { - _mesa_shift_and_offset_ci(ctx, n, indexes); - } - _mesa_map_ci_to_rgba(ctx, n, indexes, rgba); - } + /* Convert indexes to RGBA */ + if (transferOps & IMAGE_SHIFT_OFFSET_BIT) { + _mesa_shift_and_offset_ci(ctx, n, indexes); + } + _mesa_map_ci_to_rgba(ctx, n, indexes, rgba); /* Don't do RGBA scale/bias or RGBA->RGBA mapping if starting * with color indexes. diff --git a/mesalib/src/mesa/main/pixeltransfer.c b/mesalib/src/mesa/main/pixeltransfer.c index 092ee3a14..5e881436a 100644 --- a/mesalib/src/mesa/main/pixeltransfer.c +++ b/mesalib/src/mesa/main/pixeltransfer.c @@ -1,567 +1,306 @@ -/*
- * Mesa 3-D graphics library
- *
- * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
- * Copyright (C) 2009-2010 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 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 pixeltransfer.c
- * Pixel transfer operations (scale, bias, table lookups, etc)
- */
-
-
-#include "glheader.h"
-#include "colormac.h"
-#include "pixeltransfer.h"
-#include "imports.h"
-#include "mtypes.h"
-
-
-/*
- * Apply scale and bias factors to an array of RGBA pixels.
- */
-void
-_mesa_scale_and_bias_rgba(GLuint n, GLfloat rgba[][4],
- GLfloat rScale, GLfloat gScale,
- GLfloat bScale, GLfloat aScale,
- GLfloat rBias, GLfloat gBias,
- GLfloat bBias, GLfloat aBias)
-{
- if (rScale != 1.0 || rBias != 0.0) {
- GLuint i;
- for (i = 0; i < n; i++) {
- rgba[i][RCOMP] = rgba[i][RCOMP] * rScale + rBias;
- }
- }
- if (gScale != 1.0 || gBias != 0.0) {
- GLuint i;
- for (i = 0; i < n; i++) {
- rgba[i][GCOMP] = rgba[i][GCOMP] * gScale + gBias;
- }
- }
- if (bScale != 1.0 || bBias != 0.0) {
- GLuint i;
- for (i = 0; i < n; i++) {
- rgba[i][BCOMP] = rgba[i][BCOMP] * bScale + bBias;
- }
- }
- if (aScale != 1.0 || aBias != 0.0) {
- GLuint i;
- for (i = 0; i < n; i++) {
- rgba[i][ACOMP] = rgba[i][ACOMP] * aScale + aBias;
- }
- }
-}
-
-
-/*
- * Apply pixel mapping to an array of floating point RGBA pixels.
- */
-void
-_mesa_map_rgba( const struct gl_context *ctx, GLuint n, GLfloat rgba[][4] )
-{
- const GLfloat rscale = (GLfloat) (ctx->PixelMaps.RtoR.Size - 1);
- const GLfloat gscale = (GLfloat) (ctx->PixelMaps.GtoG.Size - 1);
- const GLfloat bscale = (GLfloat) (ctx->PixelMaps.BtoB.Size - 1);
- const GLfloat ascale = (GLfloat) (ctx->PixelMaps.AtoA.Size - 1);
- const GLfloat *rMap = ctx->PixelMaps.RtoR.Map;
- const GLfloat *gMap = ctx->PixelMaps.GtoG.Map;
- const GLfloat *bMap = ctx->PixelMaps.BtoB.Map;
- const GLfloat *aMap = ctx->PixelMaps.AtoA.Map;
- GLuint i;
- for (i=0;i<n;i++) {
- GLfloat r = CLAMP(rgba[i][RCOMP], 0.0F, 1.0F);
- GLfloat g = CLAMP(rgba[i][GCOMP], 0.0F, 1.0F);
- GLfloat b = CLAMP(rgba[i][BCOMP], 0.0F, 1.0F);
- GLfloat a = CLAMP(rgba[i][ACOMP], 0.0F, 1.0F);
- rgba[i][RCOMP] = rMap[IROUND(r * rscale)];
- rgba[i][GCOMP] = gMap[IROUND(g * gscale)];
- rgba[i][BCOMP] = bMap[IROUND(b * bscale)];
- rgba[i][ACOMP] = aMap[IROUND(a * ascale)];
- }
-}
-
-/**
- * Apply a color table lookup to an array of floating point RGBA colors.
- */
-void
-_mesa_lookup_rgba_float(const struct gl_color_table *table,
- GLuint n, GLfloat rgba[][4])
-{
- const GLint max = table->Size - 1;
- const GLfloat scale = (GLfloat) max;
- const GLfloat *lut = table->TableF;
- GLuint i;
-
- if (!table->TableF || table->Size == 0)
- return;
-
- switch (table->_BaseFormat) {
- case GL_INTENSITY:
- /* replace RGBA with I */
- for (i = 0; i < n; i++) {
- GLint j = IROUND(rgba[i][RCOMP] * scale);
- GLfloat c = lut[CLAMP(j, 0, max)];
- rgba[i][RCOMP] =
- rgba[i][GCOMP] =
- rgba[i][BCOMP] =
- rgba[i][ACOMP] = c;
- }
- break;
- case GL_LUMINANCE:
- /* replace RGB with L */
- for (i = 0; i < n; i++) {
- GLint j = IROUND(rgba[i][RCOMP] * scale);
- GLfloat c = lut[CLAMP(j, 0, max)];
- rgba[i][RCOMP] =
- rgba[i][GCOMP] =
- rgba[i][BCOMP] = c;
- }
- break;
- case GL_ALPHA:
- /* replace A with A */
- for (i = 0; i < n; i++) {
- GLint j = IROUND(rgba[i][ACOMP] * scale);
- rgba[i][ACOMP] = lut[CLAMP(j, 0, max)];
- }
- break;
- case GL_LUMINANCE_ALPHA:
- /* replace RGBA with LLLA */
- for (i = 0; i < n; i++) {
- GLint jL = IROUND(rgba[i][RCOMP] * scale);
- GLint jA = IROUND(rgba[i][ACOMP] * scale);
- GLfloat luminance, alpha;
- jL = CLAMP(jL, 0, max);
- jA = CLAMP(jA, 0, max);
- luminance = lut[jL * 2 + 0];
- alpha = lut[jA * 2 + 1];
- rgba[i][RCOMP] =
- rgba[i][GCOMP] =
- rgba[i][BCOMP] = luminance;
- rgba[i][ACOMP] = alpha;;
- }
- break;
- case GL_RED:
- /* replace RGB with RGB */
- for (i = 0; i < n; i++) {
- GLint jR = IROUND(rgba[i][RCOMP] * scale);
- jR = CLAMP(jR, 0, max);
- rgba[i][RCOMP] = lut[jR * 3 + 0];
- }
- break;
- case GL_RG:
- /* replace RG with RG */
- for (i = 0; i < n; i++) {
- GLint jR = IROUND(rgba[i][RCOMP] * scale);
- GLint jG = IROUND(rgba[i][GCOMP] * scale);
- jR = CLAMP(jR, 0, max);
- jG = CLAMP(jG, 0, max);
- rgba[i][RCOMP] = lut[jR * 3 + 0];
- rgba[i][GCOMP] = lut[jG * 3 + 1];
- }
- break;
- case GL_RGB:
- /* replace RGB with RGB */
- for (i = 0; i < n; i++) {
- GLint jR = IROUND(rgba[i][RCOMP] * scale);
- GLint jG = IROUND(rgba[i][GCOMP] * scale);
- GLint jB = IROUND(rgba[i][BCOMP] * scale);
- jR = CLAMP(jR, 0, max);
- jG = CLAMP(jG, 0, max);
- jB = CLAMP(jB, 0, max);
- rgba[i][RCOMP] = lut[jR * 3 + 0];
- rgba[i][GCOMP] = lut[jG * 3 + 1];
- rgba[i][BCOMP] = lut[jB * 3 + 2];
- }
- break;
- case GL_RGBA:
- /* replace RGBA with RGBA */
- for (i = 0; i < n; i++) {
- GLint jR = IROUND(rgba[i][RCOMP] * scale);
- GLint jG = IROUND(rgba[i][GCOMP] * scale);
- GLint jB = IROUND(rgba[i][BCOMP] * scale);
- GLint jA = IROUND(rgba[i][ACOMP] * scale);
- jR = CLAMP(jR, 0, max);
- jG = CLAMP(jG, 0, max);
- jB = CLAMP(jB, 0, max);
- jA = CLAMP(jA, 0, max);
- rgba[i][RCOMP] = lut[jR * 4 + 0];
- rgba[i][GCOMP] = lut[jG * 4 + 1];
- rgba[i][BCOMP] = lut[jB * 4 + 2];
- rgba[i][ACOMP] = lut[jA * 4 + 3];
- }
- break;
- default:
- _mesa_problem(NULL, "Bad format in _mesa_lookup_rgba_float");
- return;
- }
-}
-
-
-
-/**
- * Apply a color table lookup to an array of ubyte/RGBA colors.
- */
-void
-_mesa_lookup_rgba_ubyte(const struct gl_color_table *table,
- GLuint n, GLubyte rgba[][4])
-{
- const GLubyte *lut = table->TableUB;
- const GLfloat scale = (GLfloat) (table->Size - 1) / (GLfloat)255.0;
- GLuint i;
-
- if (!table->TableUB || table->Size == 0)
- return;
-
- switch (table->_BaseFormat) {
- case GL_INTENSITY:
- /* replace RGBA with I */
- if (table->Size == 256) {
- for (i = 0; i < n; i++) {
- const GLubyte c = lut[rgba[i][RCOMP]];
- rgba[i][RCOMP] =
- rgba[i][GCOMP] =
- rgba[i][BCOMP] =
- rgba[i][ACOMP] = c;
- }
- }
- else {
- for (i = 0; i < n; i++) {
- GLint j = IROUND((GLfloat) rgba[i][RCOMP] * scale);
- rgba[i][RCOMP] =
- rgba[i][GCOMP] =
- rgba[i][BCOMP] =
- rgba[i][ACOMP] = lut[j];
- }
- }
- break;
- case GL_LUMINANCE:
- /* replace RGB with L */
- if (table->Size == 256) {
- for (i = 0; i < n; i++) {
- const GLubyte c = lut[rgba[i][RCOMP]];
- rgba[i][RCOMP] =
- rgba[i][GCOMP] =
- rgba[i][BCOMP] = c;
- }
- }
- else {
- for (i = 0; i < n; i++) {
- GLint j = IROUND((GLfloat) rgba[i][RCOMP] * scale);
- rgba[i][RCOMP] =
- rgba[i][GCOMP] =
- rgba[i][BCOMP] = lut[j];
- }
- }
- break;
- case GL_ALPHA:
- /* replace A with A */
- if (table->Size == 256) {
- for (i = 0; i < n; i++) {
- rgba[i][ACOMP] = lut[rgba[i][ACOMP]];
- }
- }
- else {
- for (i = 0; i < n; i++) {
- GLint j = IROUND((GLfloat) rgba[i][ACOMP] * scale);
- rgba[i][ACOMP] = lut[j];
- }
- }
- break;
- case GL_LUMINANCE_ALPHA:
- /* replace RGBA with LLLA */
- if (table->Size == 256) {
- for (i = 0; i < n; i++) {
- GLubyte l = lut[rgba[i][RCOMP] * 2 + 0];
- GLubyte a = lut[rgba[i][ACOMP] * 2 + 1];;
- rgba[i][RCOMP] =
- rgba[i][GCOMP] =
- rgba[i][BCOMP] = l;
- rgba[i][ACOMP] = a;
- }
- }
- else {
- for (i = 0; i < n; i++) {
- GLint jL = IROUND((GLfloat) rgba[i][RCOMP] * scale);
- GLint jA = IROUND((GLfloat) rgba[i][ACOMP] * scale);
- GLubyte luminance = lut[jL * 2 + 0];
- GLubyte alpha = lut[jA * 2 + 1];
- rgba[i][RCOMP] =
- rgba[i][GCOMP] =
- rgba[i][BCOMP] = luminance;
- rgba[i][ACOMP] = alpha;
- }
- }
- break;
- case GL_RGB:
- if (table->Size == 256) {
- for (i = 0; i < n; i++) {
- rgba[i][RCOMP] = lut[rgba[i][RCOMP] * 3 + 0];
- rgba[i][GCOMP] = lut[rgba[i][GCOMP] * 3 + 1];
- rgba[i][BCOMP] = lut[rgba[i][BCOMP] * 3 + 2];
- }
- }
- else {
- for (i = 0; i < n; i++) {
- GLint jR = IROUND((GLfloat) rgba[i][RCOMP] * scale);
- GLint jG = IROUND((GLfloat) rgba[i][GCOMP] * scale);
- GLint jB = IROUND((GLfloat) rgba[i][BCOMP] * scale);
- rgba[i][RCOMP] = lut[jR * 3 + 0];
- rgba[i][GCOMP] = lut[jG * 3 + 1];
- rgba[i][BCOMP] = lut[jB * 3 + 2];
- }
- }
- break;
- case GL_RGBA:
- if (table->Size == 256) {
- for (i = 0; i < n; i++) {
- rgba[i][RCOMP] = lut[rgba[i][RCOMP] * 4 + 0];
- rgba[i][GCOMP] = lut[rgba[i][GCOMP] * 4 + 1];
- rgba[i][BCOMP] = lut[rgba[i][BCOMP] * 4 + 2];
- rgba[i][ACOMP] = lut[rgba[i][ACOMP] * 4 + 3];
- }
- }
- else {
- for (i = 0; i < n; i++) {
- GLint jR = IROUND((GLfloat) rgba[i][RCOMP] * scale);
- GLint jG = IROUND((GLfloat) rgba[i][GCOMP] * scale);
- GLint jB = IROUND((GLfloat) rgba[i][BCOMP] * scale);
- GLint jA = IROUND((GLfloat) rgba[i][ACOMP] * scale);
- CLAMPED_FLOAT_TO_CHAN(rgba[i][RCOMP], lut[jR * 4 + 0]);
- CLAMPED_FLOAT_TO_CHAN(rgba[i][GCOMP], lut[jG * 4 + 1]);
- CLAMPED_FLOAT_TO_CHAN(rgba[i][BCOMP], lut[jB * 4 + 2]);
- CLAMPED_FLOAT_TO_CHAN(rgba[i][ACOMP], lut[jA * 4 + 3]);
- }
- }
- break;
- default:
- _mesa_problem(NULL, "Bad format in _mesa_lookup_rgba_chan");
- return;
- }
-}
-
-
-
-/*
- * Map color indexes to float rgba values.
- */
-void
-_mesa_map_ci_to_rgba( const struct gl_context *ctx, GLuint n,
- const GLuint index[], GLfloat rgba[][4] )
-{
- GLuint rmask = ctx->PixelMaps.ItoR.Size - 1;
- GLuint gmask = ctx->PixelMaps.ItoG.Size - 1;
- GLuint bmask = ctx->PixelMaps.ItoB.Size - 1;
- GLuint amask = ctx->PixelMaps.ItoA.Size - 1;
- const GLfloat *rMap = ctx->PixelMaps.ItoR.Map;
- const GLfloat *gMap = ctx->PixelMaps.ItoG.Map;
- const GLfloat *bMap = ctx->PixelMaps.ItoB.Map;
- const GLfloat *aMap = ctx->PixelMaps.ItoA.Map;
- GLuint i;
- for (i=0;i<n;i++) {
- rgba[i][RCOMP] = rMap[index[i] & rmask];
- rgba[i][GCOMP] = gMap[index[i] & gmask];
- rgba[i][BCOMP] = bMap[index[i] & bmask];
- rgba[i][ACOMP] = aMap[index[i] & amask];
- }
-}
-
-
-/**
- * Map ubyte color indexes to ubyte/RGBA values.
- */
-void
-_mesa_map_ci8_to_rgba8(const struct gl_context *ctx,
- GLuint n, const GLubyte index[],
- GLubyte rgba[][4])
-{
- GLuint rmask = ctx->PixelMaps.ItoR.Size - 1;
- GLuint gmask = ctx->PixelMaps.ItoG.Size - 1;
- GLuint bmask = ctx->PixelMaps.ItoB.Size - 1;
- GLuint amask = ctx->PixelMaps.ItoA.Size - 1;
- const GLubyte *rMap = ctx->PixelMaps.ItoR.Map8;
- const GLubyte *gMap = ctx->PixelMaps.ItoG.Map8;
- const GLubyte *bMap = ctx->PixelMaps.ItoB.Map8;
- const GLubyte *aMap = ctx->PixelMaps.ItoA.Map8;
- GLuint i;
- for (i=0;i<n;i++) {
- rgba[i][RCOMP] = rMap[index[i] & rmask];
- rgba[i][GCOMP] = gMap[index[i] & gmask];
- rgba[i][BCOMP] = bMap[index[i] & bmask];
- rgba[i][ACOMP] = aMap[index[i] & amask];
- }
-}
-
-
-void
-_mesa_scale_and_bias_depth(const struct gl_context *ctx, GLuint n,
- GLfloat depthValues[])
-{
- const GLfloat scale = ctx->Pixel.DepthScale;
- const GLfloat bias = ctx->Pixel.DepthBias;
- GLuint i;
- for (i = 0; i < n; i++) {
- GLfloat d = depthValues[i] * scale + bias;
- depthValues[i] = CLAMP(d, 0.0F, 1.0F);
- }
-}
-
-
-void
-_mesa_scale_and_bias_depth_uint(const struct gl_context *ctx, GLuint n,
- GLuint depthValues[])
-{
- const GLdouble max = (double) 0xffffffff;
- const GLdouble scale = ctx->Pixel.DepthScale;
- const GLdouble bias = ctx->Pixel.DepthBias * max;
- GLuint i;
- for (i = 0; i < n; i++) {
- GLdouble d = (GLdouble) depthValues[i] * scale + bias;
- d = CLAMP(d, 0.0, max);
- depthValues[i] = (GLuint) d;
- }
-}
-
-/**
- * Apply various pixel transfer operations to an array of RGBA pixels
- * as indicated by the transferOps bitmask
- */
-void
-_mesa_apply_rgba_transfer_ops(struct gl_context *ctx, GLbitfield transferOps,
- GLuint n, GLfloat rgba[][4])
-{
- /* scale & bias */
- if (transferOps & IMAGE_SCALE_BIAS_BIT) {
- _mesa_scale_and_bias_rgba(n, rgba,
- ctx->Pixel.RedScale, ctx->Pixel.GreenScale,
- ctx->Pixel.BlueScale, ctx->Pixel.AlphaScale,
- ctx->Pixel.RedBias, ctx->Pixel.GreenBias,
- ctx->Pixel.BlueBias, ctx->Pixel.AlphaBias);
- }
- /* color map lookup */
- if (transferOps & IMAGE_MAP_COLOR_BIT) {
- _mesa_map_rgba( ctx, n, rgba );
- }
-
- /* clamping to [0,1] */
- if (transferOps & IMAGE_CLAMP_BIT) {
- GLuint i;
- for (i = 0; i < n; i++) {
- rgba[i][RCOMP] = CLAMP(rgba[i][RCOMP], 0.0F, 1.0F);
- rgba[i][GCOMP] = CLAMP(rgba[i][GCOMP], 0.0F, 1.0F);
- rgba[i][BCOMP] = CLAMP(rgba[i][BCOMP], 0.0F, 1.0F);
- rgba[i][ACOMP] = CLAMP(rgba[i][ACOMP], 0.0F, 1.0F);
- }
- }
-}
-
-
-/*
- * Apply color index shift and offset to an array of pixels.
- */
-void
-_mesa_shift_and_offset_ci(const struct gl_context *ctx,
- GLuint n, GLuint indexes[])
-{
- GLint shift = ctx->Pixel.IndexShift;
- GLint offset = ctx->Pixel.IndexOffset;
- GLuint i;
- if (shift > 0) {
- for (i=0;i<n;i++) {
- indexes[i] = (indexes[i] << shift) + offset;
- }
- }
- else if (shift < 0) {
- shift = -shift;
- for (i=0;i<n;i++) {
- indexes[i] = (indexes[i] >> shift) + offset;
- }
- }
- else {
- for (i=0;i<n;i++) {
- indexes[i] = indexes[i] + offset;
- }
- }
-}
-
-
-
-/**
- * Apply color index shift, offset and table lookup to an array
- * of color indexes;
- */
-void
-_mesa_apply_ci_transfer_ops(const struct gl_context *ctx,
- GLbitfield transferOps,
- GLuint n, GLuint indexes[])
-{
- if (transferOps & IMAGE_SHIFT_OFFSET_BIT) {
- _mesa_shift_and_offset_ci(ctx, n, indexes);
- }
- if (transferOps & IMAGE_MAP_COLOR_BIT) {
- const GLuint mask = ctx->PixelMaps.ItoI.Size - 1;
- GLuint i;
- for (i = 0; i < n; i++) {
- const GLuint j = indexes[i] & mask;
- indexes[i] = IROUND(ctx->PixelMaps.ItoI.Map[j]);
- }
- }
-}
-
-
-/**
- * Apply stencil index shift, offset and table lookup to an array
- * of stencil values.
- */
-void
-_mesa_apply_stencil_transfer_ops(const struct gl_context *ctx, GLuint n,
- GLstencil stencil[])
-{
- if (ctx->Pixel.IndexShift != 0 || ctx->Pixel.IndexOffset != 0) {
- const GLint offset = ctx->Pixel.IndexOffset;
- GLint shift = ctx->Pixel.IndexShift;
- GLuint i;
- if (shift > 0) {
- for (i = 0; i < n; i++) {
- stencil[i] = (stencil[i] << shift) + offset;
- }
- }
- else if (shift < 0) {
- shift = -shift;
- for (i = 0; i < n; i++) {
- stencil[i] = (stencil[i] >> shift) + offset;
- }
- }
- else {
- for (i = 0; i < n; i++) {
- stencil[i] = stencil[i] + offset;
- }
- }
- }
- if (ctx->Pixel.MapStencilFlag) {
- GLuint mask = ctx->PixelMaps.StoS.Size - 1;
- GLuint i;
- for (i = 0; i < n; i++) {
- stencil[i] = (GLstencil)ctx->PixelMaps.StoS.Map[ stencil[i] & mask ];
- }
- }
-}
+/* + * Mesa 3-D graphics library + * + * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. + * Copyright (C) 2009-2010 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 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 pixeltransfer.c + * Pixel transfer operations (scale, bias, table lookups, etc) + */ + + +#include "glheader.h" +#include "colormac.h" +#include "pixeltransfer.h" +#include "imports.h" +#include "mtypes.h" + + +/* + * Apply scale and bias factors to an array of RGBA pixels. + */ +void +_mesa_scale_and_bias_rgba(GLuint n, GLfloat rgba[][4], + GLfloat rScale, GLfloat gScale, + GLfloat bScale, GLfloat aScale, + GLfloat rBias, GLfloat gBias, + GLfloat bBias, GLfloat aBias) +{ + if (rScale != 1.0 || rBias != 0.0) { + GLuint i; + for (i = 0; i < n; i++) { + rgba[i][RCOMP] = rgba[i][RCOMP] * rScale + rBias; + } + } + if (gScale != 1.0 || gBias != 0.0) { + GLuint i; + for (i = 0; i < n; i++) { + rgba[i][GCOMP] = rgba[i][GCOMP] * gScale + gBias; + } + } + if (bScale != 1.0 || bBias != 0.0) { + GLuint i; + for (i = 0; i < n; i++) { + rgba[i][BCOMP] = rgba[i][BCOMP] * bScale + bBias; + } + } + if (aScale != 1.0 || aBias != 0.0) { + GLuint i; + for (i = 0; i < n; i++) { + rgba[i][ACOMP] = rgba[i][ACOMP] * aScale + aBias; + } + } +} + + +/* + * Apply pixel mapping to an array of floating point RGBA pixels. + */ +void +_mesa_map_rgba( const struct gl_context *ctx, GLuint n, GLfloat rgba[][4] ) +{ + const GLfloat rscale = (GLfloat) (ctx->PixelMaps.RtoR.Size - 1); + const GLfloat gscale = (GLfloat) (ctx->PixelMaps.GtoG.Size - 1); + const GLfloat bscale = (GLfloat) (ctx->PixelMaps.BtoB.Size - 1); + const GLfloat ascale = (GLfloat) (ctx->PixelMaps.AtoA.Size - 1); + const GLfloat *rMap = ctx->PixelMaps.RtoR.Map; + const GLfloat *gMap = ctx->PixelMaps.GtoG.Map; + const GLfloat *bMap = ctx->PixelMaps.BtoB.Map; + const GLfloat *aMap = ctx->PixelMaps.AtoA.Map; + GLuint i; + for (i=0;i<n;i++) { + GLfloat r = CLAMP(rgba[i][RCOMP], 0.0F, 1.0F); + GLfloat g = CLAMP(rgba[i][GCOMP], 0.0F, 1.0F); + GLfloat b = CLAMP(rgba[i][BCOMP], 0.0F, 1.0F); + GLfloat a = CLAMP(rgba[i][ACOMP], 0.0F, 1.0F); + rgba[i][RCOMP] = rMap[IROUND(r * rscale)]; + rgba[i][GCOMP] = gMap[IROUND(g * gscale)]; + rgba[i][BCOMP] = bMap[IROUND(b * bscale)]; + rgba[i][ACOMP] = aMap[IROUND(a * ascale)]; + } +} + +/* + * Map color indexes to float rgba values. + */ +void +_mesa_map_ci_to_rgba( const struct gl_context *ctx, GLuint n, + const GLuint index[], GLfloat rgba[][4] ) +{ + GLuint rmask = ctx->PixelMaps.ItoR.Size - 1; + GLuint gmask = ctx->PixelMaps.ItoG.Size - 1; + GLuint bmask = ctx->PixelMaps.ItoB.Size - 1; + GLuint amask = ctx->PixelMaps.ItoA.Size - 1; + const GLfloat *rMap = ctx->PixelMaps.ItoR.Map; + const GLfloat *gMap = ctx->PixelMaps.ItoG.Map; + const GLfloat *bMap = ctx->PixelMaps.ItoB.Map; + const GLfloat *aMap = ctx->PixelMaps.ItoA.Map; + GLuint i; + for (i=0;i<n;i++) { + rgba[i][RCOMP] = rMap[index[i] & rmask]; + rgba[i][GCOMP] = gMap[index[i] & gmask]; + rgba[i][BCOMP] = bMap[index[i] & bmask]; + rgba[i][ACOMP] = aMap[index[i] & amask]; + } +} + + +/** + * Map ubyte color indexes to ubyte/RGBA values. + */ +void +_mesa_map_ci8_to_rgba8(const struct gl_context *ctx, + GLuint n, const GLubyte index[], + GLubyte rgba[][4]) +{ + GLuint rmask = ctx->PixelMaps.ItoR.Size - 1; + GLuint gmask = ctx->PixelMaps.ItoG.Size - 1; + GLuint bmask = ctx->PixelMaps.ItoB.Size - 1; + GLuint amask = ctx->PixelMaps.ItoA.Size - 1; + const GLubyte *rMap = ctx->PixelMaps.ItoR.Map8; + const GLubyte *gMap = ctx->PixelMaps.ItoG.Map8; + const GLubyte *bMap = ctx->PixelMaps.ItoB.Map8; + const GLubyte *aMap = ctx->PixelMaps.ItoA.Map8; + GLuint i; + for (i=0;i<n;i++) { + rgba[i][RCOMP] = rMap[index[i] & rmask]; + rgba[i][GCOMP] = gMap[index[i] & gmask]; + rgba[i][BCOMP] = bMap[index[i] & bmask]; + rgba[i][ACOMP] = aMap[index[i] & amask]; + } +} + + +void +_mesa_scale_and_bias_depth(const struct gl_context *ctx, GLuint n, + GLfloat depthValues[]) +{ + const GLfloat scale = ctx->Pixel.DepthScale; + const GLfloat bias = ctx->Pixel.DepthBias; + GLuint i; + for (i = 0; i < n; i++) { + GLfloat d = depthValues[i] * scale + bias; + depthValues[i] = CLAMP(d, 0.0F, 1.0F); + } +} + + +void +_mesa_scale_and_bias_depth_uint(const struct gl_context *ctx, GLuint n, + GLuint depthValues[]) +{ + const GLdouble max = (double) 0xffffffff; + const GLdouble scale = ctx->Pixel.DepthScale; + const GLdouble bias = ctx->Pixel.DepthBias * max; + GLuint i; + for (i = 0; i < n; i++) { + GLdouble d = (GLdouble) depthValues[i] * scale + bias; + d = CLAMP(d, 0.0, max); + depthValues[i] = (GLuint) d; + } +} + +/** + * Apply various pixel transfer operations to an array of RGBA pixels + * as indicated by the transferOps bitmask + */ +void +_mesa_apply_rgba_transfer_ops(struct gl_context *ctx, GLbitfield transferOps, + GLuint n, GLfloat rgba[][4]) +{ + /* scale & bias */ + if (transferOps & IMAGE_SCALE_BIAS_BIT) { + _mesa_scale_and_bias_rgba(n, rgba, + ctx->Pixel.RedScale, ctx->Pixel.GreenScale, + ctx->Pixel.BlueScale, ctx->Pixel.AlphaScale, + ctx->Pixel.RedBias, ctx->Pixel.GreenBias, + ctx->Pixel.BlueBias, ctx->Pixel.AlphaBias); + } + /* color map lookup */ + if (transferOps & IMAGE_MAP_COLOR_BIT) { + _mesa_map_rgba( ctx, n, rgba ); + } + + /* clamping to [0,1] */ + if (transferOps & IMAGE_CLAMP_BIT) { + GLuint i; + for (i = 0; i < n; i++) { + rgba[i][RCOMP] = CLAMP(rgba[i][RCOMP], 0.0F, 1.0F); + rgba[i][GCOMP] = CLAMP(rgba[i][GCOMP], 0.0F, 1.0F); + rgba[i][BCOMP] = CLAMP(rgba[i][BCOMP], 0.0F, 1.0F); + rgba[i][ACOMP] = CLAMP(rgba[i][ACOMP], 0.0F, 1.0F); + } + } +} + + +/* + * Apply color index shift and offset to an array of pixels. + */ +void +_mesa_shift_and_offset_ci(const struct gl_context *ctx, + GLuint n, GLuint indexes[]) +{ + GLint shift = ctx->Pixel.IndexShift; + GLint offset = ctx->Pixel.IndexOffset; + GLuint i; + if (shift > 0) { + for (i=0;i<n;i++) { + indexes[i] = (indexes[i] << shift) + offset; + } + } + else if (shift < 0) { + shift = -shift; + for (i=0;i<n;i++) { + indexes[i] = (indexes[i] >> shift) + offset; + } + } + else { + for (i=0;i<n;i++) { + indexes[i] = indexes[i] + offset; + } + } +} + + + +/** + * Apply color index shift, offset and table lookup to an array + * of color indexes; + */ +void +_mesa_apply_ci_transfer_ops(const struct gl_context *ctx, + GLbitfield transferOps, + GLuint n, GLuint indexes[]) +{ + if (transferOps & IMAGE_SHIFT_OFFSET_BIT) { + _mesa_shift_and_offset_ci(ctx, n, indexes); + } + if (transferOps & IMAGE_MAP_COLOR_BIT) { + const GLuint mask = ctx->PixelMaps.ItoI.Size - 1; + GLuint i; + for (i = 0; i < n; i++) { + const GLuint j = indexes[i] & mask; + indexes[i] = IROUND(ctx->PixelMaps.ItoI.Map[j]); + } + } +} + + +/** + * Apply stencil index shift, offset and table lookup to an array + * of stencil values. + */ +void +_mesa_apply_stencil_transfer_ops(const struct gl_context *ctx, GLuint n, + GLstencil stencil[]) +{ + if (ctx->Pixel.IndexShift != 0 || ctx->Pixel.IndexOffset != 0) { + const GLint offset = ctx->Pixel.IndexOffset; + GLint shift = ctx->Pixel.IndexShift; + GLuint i; + if (shift > 0) { + for (i = 0; i < n; i++) { + stencil[i] = (stencil[i] << shift) + offset; + } + } + else if (shift < 0) { + shift = -shift; + for (i = 0; i < n; i++) { + stencil[i] = (stencil[i] >> shift) + offset; + } + } + else { + for (i = 0; i < n; i++) { + stencil[i] = stencil[i] + offset; + } + } + } + if (ctx->Pixel.MapStencilFlag) { + GLuint mask = ctx->PixelMaps.StoS.Size - 1; + GLuint i; + for (i = 0; i < n; i++) { + stencil[i] = (GLstencil)ctx->PixelMaps.StoS.Map[ stencil[i] & mask ]; + } + } +} diff --git a/mesalib/src/mesa/main/pixeltransfer.h b/mesalib/src/mesa/main/pixeltransfer.h index c00da3f2a..8af2e9ee2 100644 --- a/mesalib/src/mesa/main/pixeltransfer.h +++ b/mesalib/src/mesa/main/pixeltransfer.h @@ -1,90 +1,81 @@ -/*
- * Mesa 3-D graphics library
- *
- * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
- * Copyright (C) 2009-2010 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 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 PIXELTRANSFER_H
-#define PIXELTRANSFER_H
-
-
-#include "mtypes.h"
-
-
-extern void
-_mesa_scale_and_bias_rgba(GLuint n, GLfloat rgba[][4],
- GLfloat rScale, GLfloat gScale,
- GLfloat bScale, GLfloat aScale,
- GLfloat rBias, GLfloat gBias,
- GLfloat bBias, GLfloat aBias);
-
-extern void
-_mesa_map_rgba(const struct gl_context *ctx, GLuint n, GLfloat rgba[][4]);
-
-extern void
-_mesa_lookup_rgba_float(const struct gl_color_table *table,
- GLuint n, GLfloat rgba[][4]);
-
-extern void
-_mesa_lookup_rgba_ubyte(const struct gl_color_table *table,
- GLuint n, GLubyte rgba[][4]);
-
-
-extern void
-_mesa_map_ci_to_rgba(const struct gl_context *ctx,
- GLuint n, const GLuint index[], GLfloat rgba[][4]);
-
-
-extern void
-_mesa_map_ci8_to_rgba8(const struct gl_context *ctx,
- GLuint n, const GLubyte index[],
- GLubyte rgba[][4]);
-
-
-extern void
-_mesa_scale_and_bias_depth(const struct gl_context *ctx, GLuint n,
- GLfloat depthValues[]);
-
-extern void
-_mesa_scale_and_bias_depth_uint(const struct gl_context *ctx, GLuint n,
- GLuint depthValues[]);
-
-extern void
-_mesa_apply_rgba_transfer_ops(struct gl_context *ctx, GLbitfield transferOps,
- GLuint n, GLfloat rgba[][4]);
-
-extern void
-_mesa_shift_and_offset_ci(const struct gl_context *ctx,
- GLuint n, GLuint indexes[]);
-
-extern void
-_mesa_apply_ci_transfer_ops(const struct gl_context *ctx,
- GLbitfield transferOps,
- GLuint n, GLuint indexes[]);
-
-
-extern void
-_mesa_apply_stencil_transfer_ops(const struct gl_context *ctx, GLuint n,
- GLstencil stencil[]);
-
-
-#endif
+/* + * Mesa 3-D graphics library + * + * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. + * Copyright (C) 2009-2010 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 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 PIXELTRANSFER_H +#define PIXELTRANSFER_H + + +#include "mtypes.h" + + +extern void +_mesa_scale_and_bias_rgba(GLuint n, GLfloat rgba[][4], + GLfloat rScale, GLfloat gScale, + GLfloat bScale, GLfloat aScale, + GLfloat rBias, GLfloat gBias, + GLfloat bBias, GLfloat aBias); + +extern void +_mesa_map_rgba(const struct gl_context *ctx, GLuint n, GLfloat rgba[][4]); + +extern void +_mesa_map_ci_to_rgba(const struct gl_context *ctx, + GLuint n, const GLuint index[], GLfloat rgba[][4]); + + +extern void +_mesa_map_ci8_to_rgba8(const struct gl_context *ctx, + GLuint n, const GLubyte index[], + GLubyte rgba[][4]); + + +extern void +_mesa_scale_and_bias_depth(const struct gl_context *ctx, GLuint n, + GLfloat depthValues[]); + +extern void +_mesa_scale_and_bias_depth_uint(const struct gl_context *ctx, GLuint n, + GLuint depthValues[]); + +extern void +_mesa_apply_rgba_transfer_ops(struct gl_context *ctx, GLbitfield transferOps, + GLuint n, GLfloat rgba[][4]); + +extern void +_mesa_shift_and_offset_ci(const struct gl_context *ctx, + GLuint n, GLuint indexes[]); + +extern void +_mesa_apply_ci_transfer_ops(const struct gl_context *ctx, + GLbitfield transferOps, + GLuint n, GLuint indexes[]); + + +extern void +_mesa_apply_stencil_transfer_ops(const struct gl_context *ctx, GLuint n, + GLstencil stencil[]); + + +#endif diff --git a/mesalib/src/mesa/main/texformat.c b/mesalib/src/mesa/main/texformat.c index 075c40c86..4f02720ce 100644 --- a/mesalib/src/mesa/main/texformat.c +++ b/mesalib/src/mesa/main/texformat.c @@ -197,13 +197,6 @@ _mesa_choose_tex_format( struct gl_context *ctx, GLint internalFormat, RETURN_IF_SUPPORTED(MESA_FORMAT_I8); break; - case GL_COLOR_INDEX: - case GL_COLOR_INDEX1_EXT: - case GL_COLOR_INDEX2_EXT: - case GL_COLOR_INDEX4_EXT: - case GL_COLOR_INDEX12_EXT: - case GL_COLOR_INDEX16_EXT: - case GL_COLOR_INDEX8_EXT: default: ; /* fallthrough */ } diff --git a/mesalib/src/mesa/main/texgetimage.c b/mesalib/src/mesa/main/texgetimage.c index b2ebb0de4..99ace91a9 100644 --- a/mesalib/src/mesa/main/texgetimage.c +++ b/mesalib/src/mesa/main/texgetimage.c @@ -65,55 +65,6 @@ type_with_negative_values(GLenum type) /** - * glGetTexImage for color index pixels. - */ -static void -get_tex_color_index(struct gl_context *ctx, GLuint dimensions, - GLenum format, GLenum type, GLvoid *pixels, - const struct gl_texture_image *texImage) -{ - const GLint width = texImage->Width; - const GLint height = texImage->Height; - const GLint depth = texImage->Depth; - const GLint rowstride = texImage->RowStride; - const GLuint indexBits = - _mesa_get_format_bits(texImage->TexFormat, GL_TEXTURE_INDEX_SIZE_EXT); - const GLbitfield transferOps = 0x0; - GLint img, row, col; - - for (img = 0; img < depth; img++) { - for (row = 0; row < height; row++) { - GLuint indexRow[MAX_WIDTH] = { 0 }; - void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels, - width, height, format, type, - img, row, 0); - assert(dest); - - if (indexBits == 8) { - const GLubyte *src = (const GLubyte *) texImage->Data; - src += rowstride * (img * height + row); - for (col = 0; col < width; col++) { - indexRow[col] = src[col]; - } - } - else if (indexBits == 16) { - const GLushort *src = (const GLushort *) texImage->Data; - src += rowstride * (img * height + row); - for (col = 0; col < width; col++) { - indexRow[col] = src[col]; - } - } - else { - _mesa_problem(ctx, "Color index problem in _mesa_GetTexImage"); - } - _mesa_pack_index_span(ctx, width, type, dest, - indexRow, &ctx->Pack, transferOps); - } - } -} - - -/** * glGetTexImage for depth/Z pixels. */ static void @@ -457,9 +408,6 @@ _mesa_get_teximage(struct gl_context *ctx, GLenum target, GLint level, if (get_tex_memcpy(ctx, format, type, pixels, texObj, texImage)) { /* all done */ } - else if (format == GL_COLOR_INDEX) { - get_tex_color_index(ctx, dimensions, format, type, pixels, texImage); - } else if (format == GL_DEPTH_COMPONENT) { get_tex_depth(ctx, dimensions, format, type, pixels, texImage); } @@ -567,16 +515,12 @@ getteximage_error_check(struct gl_context *ctx, GLenum target, GLint level, } if (_mesa_components_in_format(format) <= 0 || - format == GL_STENCIL_INDEX) { + format == GL_STENCIL_INDEX || + format == GL_COLOR_INDEX) { _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" ); return GL_TRUE; } - if (!ctx->Extensions.EXT_paletted_texture && _mesa_is_index_format(format)) { - _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); - return GL_TRUE; - } - if (!ctx->Extensions.ARB_depth_texture && _mesa_is_depth_format(format)) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); return GL_TRUE; @@ -615,17 +559,10 @@ getteximage_error_check(struct gl_context *ctx, GLenum target, GLint level, baseFormat = _mesa_get_format_base_format(texImage->TexFormat); /* Make sure the requested image format is compatible with the - * texture's format. Note that a color index texture can be converted - * to RGBA so that combo is allowed. + * texture's format. */ if (_mesa_is_color_format(format) - && !_mesa_is_color_format(baseFormat) - && !_mesa_is_index_format(baseFormat)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); - return GL_TRUE; - } - else if (_mesa_is_index_format(format) - && !_mesa_is_index_format(baseFormat)) { + && !_mesa_is_color_format(baseFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); return GL_TRUE; } diff --git a/mesalib/src/mesa/main/teximage.c b/mesalib/src/mesa/main/teximage.c index 886e52114..cb4a5b4e4 100644 --- a/mesalib/src/mesa/main/teximage.c +++ b/mesalib/src/mesa/main/teximage.c @@ -159,21 +159,6 @@ _mesa_base_tex_format( struct gl_context *ctx, GLint internalFormat ) } } - if (ctx->Extensions.EXT_paletted_texture) { - switch (internalFormat) { - case GL_COLOR_INDEX: - case GL_COLOR_INDEX1_EXT: - case GL_COLOR_INDEX2_EXT: - case GL_COLOR_INDEX4_EXT: - case GL_COLOR_INDEX8_EXT: - case GL_COLOR_INDEX12_EXT: - case GL_COLOR_INDEX16_EXT: - return GL_COLOR_INDEX; - default: - ; /* fallthrough */ - } - } - if (ctx->Extensions.ARB_depth_texture) { switch (internalFormat) { case GL_DEPTH_COMPONENT: @@ -1554,7 +1539,13 @@ texture_error_check( struct gl_context *ctx, const GLenum proxyTarget = get_proxy_target(target); const GLboolean isProxy = target == proxyTarget; GLboolean sizeOK = GL_TRUE; - GLboolean colorFormat, indexFormat; + GLboolean colorFormat; + + /* Even though there are no color-index textures, we still have to support + * uploading color-index data and remapping it to RGB via the + * GL_PIXEL_MAP_I_TO_[RGBA] tables. + */ + const GLboolean indexFormat = (format == GL_COLOR_INDEX); /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */ if (level < 0 || level >= MAX_TEXTURE_LEVELS) { @@ -1635,9 +1626,7 @@ texture_error_check( struct gl_context *ctx, /* make sure internal format and format basically agree */ colorFormat = _mesa_is_color_format(format); - indexFormat = _mesa_is_index_format(format); if ((_mesa_is_color_format(internalFormat) && !colorFormat && !indexFormat) || - (_mesa_is_index_format(internalFormat) && !indexFormat) || (_mesa_is_depth_format(internalFormat) != _mesa_is_depth_format(format)) || (_mesa_is_ycbcr_format(internalFormat) != _mesa_is_ycbcr_format(format)) || (_mesa_is_depthstencil_format(internalFormat) != _mesa_is_depthstencil_format(format)) || diff --git a/mesalib/src/mesa/main/texobj.c b/mesalib/src/mesa/main/texobj.c index 078a43ab1..1168f1842 100644 --- a/mesalib/src/mesa/main/texobj.c +++ b/mesalib/src/mesa/main/texobj.c @@ -198,8 +198,6 @@ _mesa_delete_texture_object(struct gl_context *ctx, */ texObj->Target = 0x99; - _mesa_free_colortable_data(&texObj->Palette); - /* free the texture images */ for (face = 0; face < 6; face++) { for (i = 0; i < MAX_TEXTURE_LEVELS; i++) { @@ -258,7 +256,6 @@ _mesa_copy_texture_object( struct gl_texture_object *dest, dest->_MaxLevel = src->_MaxLevel; dest->_MaxLambda = src->_MaxLambda; dest->GenerateMipmap = src->GenerateMipmap; - dest->Palette = src->Palette; dest->_Complete = src->_Complete; COPY_4V(dest->Swizzle, src->Swizzle); dest->_Swizzle = src->_Swizzle; diff --git a/mesalib/src/mesa/main/texparam.c b/mesalib/src/mesa/main/texparam.c index bbbb306b2..19a01a14d 100644 --- a/mesalib/src/mesa/main/texparam.c +++ b/mesalib/src/mesa/main/texparam.c @@ -987,12 +987,6 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level, } } break; - case GL_TEXTURE_INDEX_SIZE_EXT: - if (img->_BaseFormat == GL_COLOR_INDEX) - *params = _mesa_get_format_bits(texFormat, pname); - else - *params = 0; - break; case GL_TEXTURE_DEPTH_SIZE_ARB: if (!ctx->Extensions.ARB_depth_texture) goto invalid_pname; diff --git a/mesalib/src/mesa/main/texstate.c b/mesalib/src/mesa/main/texstate.c index 1810b88b2..e02f16240 100644 --- a/mesalib/src/mesa/main/texstate.c +++ b/mesalib/src/mesa/main/texstate.c @@ -75,7 +75,6 @@ _mesa_copy_texture_state( const struct gl_context *src, struct gl_context *dst ) dst->Texture._GenFlags = src->Texture._GenFlags; dst->Texture._TexGenEnabled = src->Texture._TexGenEnabled; dst->Texture._TexMatEnabled = src->Texture._TexMatEnabled; - dst->Texture.SharedPalette = src->Texture.SharedPalette; /* per-unit state */ for (u = 0; u < src->Const.MaxCombinedTextureImageUnits; u++) { @@ -402,11 +401,8 @@ update_tex_combine(struct gl_context *ctx, struct gl_texture_unit *texUnit) else { const struct gl_texture_object *texObj = texUnit->_Current; GLenum format = texObj->Image[0][texObj->BaseLevel]->_BaseFormat; - if (format == GL_COLOR_INDEX) { - format = GL_RGBA; /* a bit of a hack */ - } - else if (format == GL_DEPTH_COMPONENT || - format == GL_DEPTH_STENCIL_EXT) { + + if (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL_EXT) { format = texObj->Sampler.DepthMode; } calculate_derived_texenv(&texUnit->_EnvMode, texUnit->EnvMode, format); @@ -778,8 +774,6 @@ _mesa_init_texture(struct gl_context *ctx) /* Texture group */ ctx->Texture.CurrentUnit = 0; /* multitexture */ ctx->Texture._EnabledUnits = 0x0; - ctx->Texture.SharedPalette = GL_FALSE; - _mesa_init_colortable(&ctx->Texture.Palette); for (u = 0; u < Elements(ctx->Texture.Unit); u++) init_texture_unit(ctx, u); diff --git a/mesalib/src/mesa/main/texstore.c b/mesalib/src/mesa/main/texstore.c index e9915a7f0..2cdc8ed67 100644 --- a/mesalib/src/mesa/main/texstore.c +++ b/mesalib/src/mesa/main/texstore.c @@ -340,7 +340,6 @@ _mesa_make_temp_float_image(struct gl_context *ctx, GLuint dims, logicalBaseFormat == GL_LUMINANCE || logicalBaseFormat == GL_ALPHA || logicalBaseFormat == GL_INTENSITY || - logicalBaseFormat == GL_COLOR_INDEX || logicalBaseFormat == GL_DEPTH_COMPONENT); ASSERT(textureBaseFormat == GL_RGBA || @@ -351,7 +350,6 @@ _mesa_make_temp_float_image(struct gl_context *ctx, GLuint dims, textureBaseFormat == GL_LUMINANCE || textureBaseFormat == GL_ALPHA || textureBaseFormat == GL_INTENSITY || - textureBaseFormat == GL_COLOR_INDEX || textureBaseFormat == GL_DEPTH_COMPONENT); tempImage = (GLfloat *) malloc(srcWidth * srcHeight * srcDepth diff --git a/mesalib/src/mesa/main/varray.c b/mesalib/src/mesa/main/varray.c index 9c9d0d66e..13b3405e5 100644 --- a/mesalib/src/mesa/main/varray.c +++ b/mesalib/src/mesa/main/varray.c @@ -160,10 +160,17 @@ update_array(struct gl_context *ctx, if (ctx->Extensions.EXT_vertex_array_bgra && sizeMax == BGRA_OR_4 && size == GL_BGRA) { - if (type != GL_UNSIGNED_BYTE && - (ctx->Extensions.ARB_vertex_type_2_10_10_10_rev && - (type != GL_UNSIGNED_INT_2_10_10_10_REV && - type != GL_INT_2_10_10_10_REV))) { + GLboolean bgra_error = GL_FALSE; + + if (ctx->Extensions.ARB_vertex_type_2_10_10_10_rev) { + if (type != GL_UNSIGNED_INT_2_10_10_10_REV && + type != GL_INT_2_10_10_10_REV && + type != GL_UNSIGNED_BYTE) + bgra_error = GL_TRUE; + } else if (type != GL_UNSIGNED_BYTE) + bgra_error = GL_TRUE; + + if (bgra_error) { _mesa_error(ctx, GL_INVALID_VALUE, "%s(GL_BGRA/GLubyte)", func); return; } diff --git a/mesalib/src/mesa/state_tracker/st_cb_eglimage.c b/mesalib/src/mesa/state_tracker/st_cb_eglimage.c index d7518c0b4..531296fb3 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_eglimage.c +++ b/mesalib/src/mesa/state_tracker/st_cb_eglimage.c @@ -1,170 +1,169 @@ -/*
- * Mesa 3-D graphics library
- * Version: 7.9
- *
- * Copyright (C) 2010 LunarG 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.
- *
- * Authors:
- * Chia-I Wu <olv@lunarg.com>
- */
-
-#include "main/mfeatures.h"
-#include "main/texobj.h"
-#include "main/texfetch.h"
-#include "main/teximage.h"
-#include "util/u_inlines.h"
-#include "util/u_format.h"
-#include "st_cb_eglimage.h"
-#include "st_cb_fbo.h"
-#include "st_context.h"
-#include "st_texture.h"
-#include "st_format.h"
-#include "st_manager.h"
-
-#if FEATURE_OES_EGL_image
-
-/**
- * Return the base format just like _mesa_base_fbo_format does.
- */
-static GLenum
-st_pipe_format_to_base_format(enum pipe_format format)
-{
- GLenum base_format;
-
- if (util_format_is_depth_or_stencil(format)) {
- if (util_format_is_depth_and_stencil(format)) {
- base_format = GL_DEPTH_STENCIL;
- }
- else {
- if (format == PIPE_FORMAT_S8_USCALED)
- base_format = GL_STENCIL_INDEX;
- else
- base_format = GL_DEPTH_COMPONENT;
- }
- }
- else {
- /* is this enough? */
- if (util_format_has_alpha(format))
- base_format = GL_RGBA;
- else
- base_format = GL_RGB;
- }
-
- return base_format;
-}
-
-static void
-st_egl_image_target_renderbuffer_storage(struct gl_context *ctx,
- struct gl_renderbuffer *rb,
- GLeglImageOES image_handle)
-{
- struct st_context *st = st_context(ctx);
- struct st_renderbuffer *strb = st_renderbuffer(rb);
- struct pipe_surface *ps;
- unsigned usage;
-
- usage = PIPE_BIND_RENDER_TARGET;
- ps = st_manager_get_egl_image_surface(st, (void *) image_handle, usage);
- if (ps) {
- strb->Base.Width = ps->width;
- strb->Base.Height = ps->height;
- strb->Base.Format = st_pipe_format_to_mesa_format(ps->format);
- strb->Base.DataType = st_format_datatype(ps->format);
- strb->Base._BaseFormat = st_pipe_format_to_base_format(ps->format);
- strb->Base.InternalFormat = strb->Base._BaseFormat;
-
- pipe_surface_reference(&strb->surface, ps);
- pipe_resource_reference(&strb->texture, ps->texture);
-
- pipe_surface_reference(&ps, NULL);
- }
-}
-
-static void
-st_bind_surface(struct gl_context *ctx, GLenum target,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage,
- struct pipe_surface *ps)
-{
- struct st_texture_object *stObj;
- struct st_texture_image *stImage;
- GLenum internalFormat;
- gl_format texFormat;
-
- /* map pipe format to base format */
- if (util_format_get_component_bits(ps->format, UTIL_FORMAT_COLORSPACE_RGB, 3) > 0)
- internalFormat = GL_RGBA;
- else
- internalFormat = GL_RGB;
-
- stObj = st_texture_object(texObj);
- stImage = st_texture_image(texImage);
-
- /* switch to surface based */
- if (!stObj->surface_based) {
- _mesa_clear_texture_object(ctx, texObj);
- stObj->surface_based = GL_TRUE;
- }
-
- texFormat = st_pipe_format_to_mesa_format(ps->format);
-
- _mesa_init_teximage_fields(ctx, target, texImage,
- ps->width, ps->height, 1, 0, internalFormat,
- texFormat);
-
- /* FIXME create a non-default sampler view from the pipe_surface? */
- pipe_resource_reference(&stObj->pt, ps->texture);
- pipe_sampler_view_reference(&stObj->sampler_view, NULL);
- pipe_resource_reference(&stImage->pt, stObj->pt);
-
- stObj->width0 = ps->width;
- stObj->height0 = ps->height;
- stObj->depth0 = 1;
-
- _mesa_dirty_texobj(ctx, texObj, GL_TRUE);
-}
-
-static void
-st_egl_image_target_texture_2d(struct gl_context *ctx, GLenum target,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage,
- GLeglImageOES image_handle)
-{
- struct st_context *st = st_context(ctx);
- struct pipe_surface *ps;
- unsigned usage;
-
- usage = PIPE_BIND_SAMPLER_VIEW;
- ps = st_manager_get_egl_image_surface(st, (void *) image_handle, usage);
- if (ps) {
- st_bind_surface(ctx, target, texObj, texImage, ps);
- pipe_surface_reference(&ps, NULL);
- }
-}
-
-void
-st_init_eglimage_functions(struct dd_function_table *functions)
-{
- functions->EGLImageTargetTexture2D = st_egl_image_target_texture_2d;
- functions->EGLImageTargetRenderbufferStorage = st_egl_image_target_renderbuffer_storage;
-}
-
-#endif /* FEATURE_OES_EGL_image */
+/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG 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. + * + * Authors: + * Chia-I Wu <olv@lunarg.com> + */ + +#include "main/mfeatures.h" +#include "main/texobj.h" +#include "main/teximage.h" +#include "util/u_inlines.h" +#include "util/u_format.h" +#include "st_cb_eglimage.h" +#include "st_cb_fbo.h" +#include "st_context.h" +#include "st_texture.h" +#include "st_format.h" +#include "st_manager.h" + +#if FEATURE_OES_EGL_image + +/** + * Return the base format just like _mesa_base_fbo_format does. + */ +static GLenum +st_pipe_format_to_base_format(enum pipe_format format) +{ + GLenum base_format; + + if (util_format_is_depth_or_stencil(format)) { + if (util_format_is_depth_and_stencil(format)) { + base_format = GL_DEPTH_STENCIL; + } + else { + if (format == PIPE_FORMAT_S8_USCALED) + base_format = GL_STENCIL_INDEX; + else + base_format = GL_DEPTH_COMPONENT; + } + } + else { + /* is this enough? */ + if (util_format_has_alpha(format)) + base_format = GL_RGBA; + else + base_format = GL_RGB; + } + + return base_format; +} + +static void +st_egl_image_target_renderbuffer_storage(struct gl_context *ctx, + struct gl_renderbuffer *rb, + GLeglImageOES image_handle) +{ + struct st_context *st = st_context(ctx); + struct st_renderbuffer *strb = st_renderbuffer(rb); + struct pipe_surface *ps; + unsigned usage; + + usage = PIPE_BIND_RENDER_TARGET; + ps = st_manager_get_egl_image_surface(st, (void *) image_handle, usage); + if (ps) { + strb->Base.Width = ps->width; + strb->Base.Height = ps->height; + strb->Base.Format = st_pipe_format_to_mesa_format(ps->format); + strb->Base.DataType = st_format_datatype(ps->format); + strb->Base._BaseFormat = st_pipe_format_to_base_format(ps->format); + strb->Base.InternalFormat = strb->Base._BaseFormat; + + pipe_surface_reference(&strb->surface, ps); + pipe_resource_reference(&strb->texture, ps->texture); + + pipe_surface_reference(&ps, NULL); + } +} + +static void +st_bind_surface(struct gl_context *ctx, GLenum target, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage, + struct pipe_surface *ps) +{ + struct st_texture_object *stObj; + struct st_texture_image *stImage; + GLenum internalFormat; + gl_format texFormat; + + /* map pipe format to base format */ + if (util_format_get_component_bits(ps->format, UTIL_FORMAT_COLORSPACE_RGB, 3) > 0) + internalFormat = GL_RGBA; + else + internalFormat = GL_RGB; + + stObj = st_texture_object(texObj); + stImage = st_texture_image(texImage); + + /* switch to surface based */ + if (!stObj->surface_based) { + _mesa_clear_texture_object(ctx, texObj); + stObj->surface_based = GL_TRUE; + } + + texFormat = st_pipe_format_to_mesa_format(ps->format); + + _mesa_init_teximage_fields(ctx, target, texImage, + ps->width, ps->height, 1, 0, internalFormat, + texFormat); + + /* FIXME create a non-default sampler view from the pipe_surface? */ + pipe_resource_reference(&stObj->pt, ps->texture); + pipe_sampler_view_reference(&stObj->sampler_view, NULL); + pipe_resource_reference(&stImage->pt, stObj->pt); + + stObj->width0 = ps->width; + stObj->height0 = ps->height; + stObj->depth0 = 1; + + _mesa_dirty_texobj(ctx, texObj, GL_TRUE); +} + +static void +st_egl_image_target_texture_2d(struct gl_context *ctx, GLenum target, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage, + GLeglImageOES image_handle) +{ + struct st_context *st = st_context(ctx); + struct pipe_surface *ps; + unsigned usage; + + usage = PIPE_BIND_SAMPLER_VIEW; + ps = st_manager_get_egl_image_surface(st, (void *) image_handle, usage); + if (ps) { + st_bind_surface(ctx, target, texObj, texImage, ps); + pipe_surface_reference(&ps, NULL); + } +} + +void +st_init_eglimage_functions(struct dd_function_table *functions) +{ + functions->EGLImageTargetTexture2D = st_egl_image_target_texture_2d; + functions->EGLImageTargetRenderbufferStorage = st_egl_image_target_renderbuffer_storage; +} + +#endif /* FEATURE_OES_EGL_image */ diff --git a/mesalib/src/mesa/state_tracker/st_cb_fbo.c b/mesalib/src/mesa/state_tracker/st_cb_fbo.c index 5b9e20374..d43f67ac9 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_fbo.c +++ b/mesalib/src/mesa/state_tracker/st_cb_fbo.c @@ -112,7 +112,6 @@ st_renderbuffer_alloc_storage(struct gl_context * ctx, */ pipe_surface_reference( &strb->surface, NULL ); pipe_resource_reference( &strb->texture, NULL ); - pipe_sampler_view_reference(&strb->sampler_view, NULL); /* Setup new texture template. */ @@ -165,7 +164,6 @@ st_renderbuffer_delete(struct gl_renderbuffer *rb) ASSERT(strb); pipe_surface_reference(&strb->surface, NULL); pipe_resource_reference(&strb->texture, NULL); - pipe_sampler_view_reference(&strb->sampler_view, NULL); free(strb->data); free(strb); } @@ -388,9 +386,6 @@ st_render_texture(struct gl_context *ctx, pipe_surface_reference(&strb->surface, NULL); - pipe_sampler_view_reference(&strb->sampler_view, - st_get_texture_sampler_view(stObj, pipe)); - assert(strb->rtt_level <= strb->texture->last_level); /* new surface for rendering into the texture */ @@ -650,14 +645,4 @@ void st_init_fbo_functions(struct dd_function_table *functions) functions->ReadBuffer = st_ReadBuffer; } -/* XXX unused ? */ -struct pipe_sampler_view * -st_get_renderbuffer_sampler_view(struct st_renderbuffer *rb, - struct pipe_context *pipe) -{ - if (!rb->sampler_view) { - rb->sampler_view = st_create_texture_sampler_view(pipe, rb->texture); - } - return rb->sampler_view; -} diff --git a/mesalib/src/mesa/state_tracker/st_cb_fbo.h b/mesalib/src/mesa/state_tracker/st_cb_fbo.h index 228be8fed..1afa3fe6e 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_fbo.h +++ b/mesalib/src/mesa/state_tracker/st_cb_fbo.h @@ -1,96 +1,84 @@ -/**************************************************************************
- *
- * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
-
-#ifndef ST_CB_FBO_H
-#define ST_CB_FBO_H
-
-#include "main/compiler.h"
-#include "main/glheader.h"
-#include "main/mtypes.h"
-
-#include "pipe/p_compiler.h"
-#include "pipe/p_format.h"
-
-struct dd_function_table;
-struct pipe_context;
-
-/**
- * Derived renderbuffer class. Just need to add a pointer to the
- * pipe surface.
- */
-struct st_renderbuffer
-{
- struct gl_renderbuffer Base;
- struct pipe_resource *texture;
- struct pipe_surface *surface; /* temporary view into texture */
- struct pipe_sampler_view *sampler_view;
- enum pipe_format format; /** preferred format, or PIPE_FORMAT_NONE */
- GLboolean defined; /**< defined contents? */
-
- /**
- * Used only when hardware accumulation buffers are not supported.
- */
- boolean software;
- size_t stride;
- void *data;
-
- struct st_texture_object *rtt; /**< GL render to texture's texture */
- int rtt_level, rtt_face, rtt_slice;
-
- /** Render to texture state */
- struct pipe_resource *texture_save;
- struct pipe_surface *surface_save;
- struct pipe_sampler_view *sampler_view_save;
-};
-
-
-static INLINE struct st_renderbuffer *
-st_renderbuffer(struct gl_renderbuffer *rb)
-{
- return (struct st_renderbuffer *) rb;
-}
-
-
-extern struct gl_renderbuffer *
-st_new_renderbuffer_fb(enum pipe_format format, int samples, boolean sw);
-
-extern void
-st_init_fbo_functions(struct dd_function_table *functions);
-
-/* XXX unused ? */
-extern struct pipe_sampler_view *
-st_get_renderbuffer_sampler_view(struct st_renderbuffer *rb,
- struct pipe_context *pipe);
-
-
-extern GLboolean
-st_is_depth_stencil_combined(const struct gl_renderbuffer_attachment *depth,
- const struct gl_renderbuffer_attachment *stencil);
-
-
-#endif /* ST_CB_FBO_H */
+/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + +#ifndef ST_CB_FBO_H +#define ST_CB_FBO_H + +#include "main/compiler.h" +#include "main/glheader.h" +#include "main/mtypes.h" + +#include "pipe/p_compiler.h" +#include "pipe/p_format.h" + +struct dd_function_table; +struct pipe_context; + +/** + * Derived renderbuffer class. Just need to add a pointer to the + * pipe surface. + */ +struct st_renderbuffer +{ + struct gl_renderbuffer Base; + struct pipe_resource *texture; + struct pipe_surface *surface; /* temporary view into texture */ + enum pipe_format format; /** preferred format, or PIPE_FORMAT_NONE */ + GLboolean defined; /**< defined contents? */ + + /** + * Used only when hardware accumulation buffers are not supported. + */ + boolean software; + size_t stride; + void *data; + + struct st_texture_object *rtt; /**< GL render to texture's texture */ + int rtt_level, rtt_face, rtt_slice; +}; + + +static INLINE struct st_renderbuffer * +st_renderbuffer(struct gl_renderbuffer *rb) +{ + return (struct st_renderbuffer *) rb; +} + + +extern struct gl_renderbuffer * +st_new_renderbuffer_fb(enum pipe_format format, int samples, boolean sw); + +extern void +st_init_fbo_functions(struct dd_function_table *functions); + +extern GLboolean +st_is_depth_stencil_combined(const struct gl_renderbuffer_attachment *depth, + const struct gl_renderbuffer_attachment *stencil); + + +#endif /* ST_CB_FBO_H */ diff --git a/mesalib/src/mesa/swrast/s_drawpix.c b/mesalib/src/mesa/swrast/s_drawpix.c index 11c63457f..63bfa79b5 100644 --- a/mesalib/src/mesa/swrast/s_drawpix.c +++ b/mesalib/src/mesa/swrast/s_drawpix.c @@ -335,7 +335,7 @@ draw_stencil_pixels( struct gl_context *ctx, GLint x, GLint y, ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT; const GLvoid *source = _mesa_image_address2d(unpack, pixels, width, height, - GL_COLOR_INDEX, type, + GL_STENCIL_INDEX, type, row, skipPixels); _mesa_unpack_stencil_span(ctx, spanWidth, destType, values, type, source, unpack, diff --git a/mesalib/src/mesa/swrast/s_texfilter.c b/mesalib/src/mesa/swrast/s_texfilter.c index 237e5d28a..ad31e3778 100644 --- a/mesalib/src/mesa/swrast/s_texfilter.c +++ b/mesalib/src/mesa/swrast/s_texfilter.c @@ -1,3710 +1,3706 @@ -/*
- * Mesa 3-D graphics library
- * Version: 7.3
- *
- * 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
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#include "main/glheader.h"
-#include "main/context.h"
-#include "main/colormac.h"
-#include "main/imports.h"
-
-#include "s_context.h"
-#include "s_texfilter.h"
-
-
-/*
- * Note, the FRAC macro has to work perfectly. Otherwise you'll sometimes
- * see 1-pixel bands of improperly weighted linear-filtered textures.
- * The tests/texwrap.c demo is a good test.
- * Also note, FRAC(x) doesn't truly return the fractional part of x for x < 0.
- * Instead, if x < 0 then FRAC(x) = 1 - true_frac(x).
- */
-#define FRAC(f) ((f) - IFLOOR(f))
-
-
-
-/**
- * Linear interpolation macro
- */
-#define LERP(T, A, B) ( (A) + (T) * ((B) - (A)) )
-
-
-/**
- * Do 2D/biliner interpolation of float values.
- * v00, v10, v01 and v11 are typically four texture samples in a square/box.
- * a and b are the horizontal and vertical interpolants.
- * It's important that this function is inlined when compiled with
- * optimization! If we find that's not true on some systems, convert
- * to a macro.
- */
-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);
-}
-
-
-/**
- * Do 3D/trilinear interpolation of float values.
- * \sa lerp_2d
- */
-static INLINE GLfloat
-lerp_3d(GLfloat a, GLfloat b, GLfloat c,
- GLfloat v000, GLfloat v100, GLfloat v010, GLfloat v110,
- GLfloat v001, GLfloat v101, GLfloat v011, GLfloat v111)
-{
- const GLfloat temp00 = LERP(a, v000, v100);
- const GLfloat temp10 = LERP(a, v010, v110);
- const GLfloat temp01 = LERP(a, v001, v101);
- const GLfloat temp11 = LERP(a, v011, v111);
- const GLfloat temp0 = LERP(b, temp00, temp10);
- const GLfloat temp1 = LERP(b, temp01, temp11);
- return LERP(c, temp0, temp1);
-}
-
-
-/**
- * Do linear interpolation of colors.
- */
-static INLINE void
-lerp_rgba(GLfloat result[4], GLfloat t, const GLfloat a[4], const GLfloat b[4])
-{
- result[0] = LERP(t, a[0], b[0]);
- result[1] = LERP(t, a[1], b[1]);
- result[2] = LERP(t, a[2], b[2]);
- result[3] = LERP(t, a[3], b[3]);
-}
-
-
-/**
- * Do bilinear interpolation of colors.
- */
-static INLINE void
-lerp_rgba_2d(GLfloat result[4], GLfloat a, GLfloat b,
- const GLfloat t00[4], const GLfloat t10[4],
- const GLfloat t01[4], const GLfloat t11[4])
-{
- result[0] = lerp_2d(a, b, t00[0], t10[0], t01[0], t11[0]);
- result[1] = lerp_2d(a, b, t00[1], t10[1], t01[1], t11[1]);
- result[2] = lerp_2d(a, b, t00[2], t10[2], t01[2], t11[2]);
- result[3] = lerp_2d(a, b, t00[3], t10[3], t01[3], t11[3]);
-}
-
-
-/**
- * Do trilinear interpolation of colors.
- */
-static INLINE void
-lerp_rgba_3d(GLfloat result[4], GLfloat a, GLfloat b, GLfloat c,
- const GLfloat t000[4], const GLfloat t100[4],
- const GLfloat t010[4], const GLfloat t110[4],
- const GLfloat t001[4], const GLfloat t101[4],
- const GLfloat t011[4], const GLfloat t111[4])
-{
- GLuint k;
- /* compiler should unroll these short loops */
- for (k = 0; k < 4; k++) {
- result[k] = lerp_3d(a, b, c, t000[k], t100[k], t010[k], t110[k],
- t001[k], t101[k], t011[k], t111[k]);
- }
-}
-
-
-/**
- * Used for GL_REPEAT wrap mode. Using A % B doesn't produce the
- * right results for A<0. Casting to A to be unsigned only works if B
- * is a power of two. Adding a bias to A (which is a multiple of B)
- * avoids the problems with A < 0 (for reasonable A) without using a
- * conditional.
- */
-#define REMAINDER(A, B) (((A) + (B) * 1024) % (B))
-
-
-/**
- * Used to compute texel locations for linear sampling.
- * Input:
- * wrapMode = GL_REPEAT, GL_CLAMP, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER
- * s = texcoord in [0,1]
- * size = width (or height or depth) of texture
- * Output:
- * i0, i1 = returns two nearest texel indexes
- * weight = returns blend factor between texels
- */
-static INLINE void
-linear_texel_locations(GLenum wrapMode,
- const struct gl_texture_image *img,
- GLint size, GLfloat s,
- GLint *i0, GLint *i1, GLfloat *weight)
-{
- GLfloat u;
- switch (wrapMode) {
- case GL_REPEAT:
- u = s * size - 0.5F;
- if (img->_IsPowerOfTwo) {
- *i0 = IFLOOR(u) & (size - 1);
- *i1 = (*i0 + 1) & (size - 1);
- }
- else {
- *i0 = REMAINDER(IFLOOR(u), size);
- *i1 = REMAINDER(*i0 + 1, size);
- }
- break;
- case GL_CLAMP_TO_EDGE:
- if (s <= 0.0F)
- u = 0.0F;
- else if (s >= 1.0F)
- u = (GLfloat) size;
- else
- u = s * size;
- u -= 0.5F;
- *i0 = IFLOOR(u);
- *i1 = *i0 + 1;
- if (*i0 < 0)
- *i0 = 0;
- if (*i1 >= (GLint) size)
- *i1 = size - 1;
- break;
- case GL_CLAMP_TO_BORDER:
- {
- const GLfloat min = -1.0F / (2.0F * size);
- const GLfloat max = 1.0F - min;
- if (s <= min)
- u = min * size;
- else if (s >= max)
- u = max * size;
- else
- u = s * size;
- u -= 0.5F;
- *i0 = IFLOOR(u);
- *i1 = *i0 + 1;
- }
- break;
- case GL_MIRRORED_REPEAT:
- {
- const GLint flr = IFLOOR(s);
- if (flr & 1)
- u = 1.0F - (s - (GLfloat) flr);
- else
- u = s - (GLfloat) flr;
- u = (u * size) - 0.5F;
- *i0 = IFLOOR(u);
- *i1 = *i0 + 1;
- if (*i0 < 0)
- *i0 = 0;
- if (*i1 >= (GLint) size)
- *i1 = size - 1;
- }
- break;
- case GL_MIRROR_CLAMP_EXT:
- u = FABSF(s);
- if (u >= 1.0F)
- u = (GLfloat) size;
- else
- u *= size;
- u -= 0.5F;
- *i0 = IFLOOR(u);
- *i1 = *i0 + 1;
- break;
- case GL_MIRROR_CLAMP_TO_EDGE_EXT:
- u = FABSF(s);
- if (u >= 1.0F)
- u = (GLfloat) size;
- else
- u *= size;
- u -= 0.5F;
- *i0 = IFLOOR(u);
- *i1 = *i0 + 1;
- if (*i0 < 0)
- *i0 = 0;
- if (*i1 >= (GLint) size)
- *i1 = size - 1;
- break;
- case GL_MIRROR_CLAMP_TO_BORDER_EXT:
- {
- const GLfloat min = -1.0F / (2.0F * size);
- const GLfloat max = 1.0F - min;
- u = FABSF(s);
- if (u <= min)
- u = min * size;
- else if (u >= max)
- u = max * size;
- else
- u *= size;
- u -= 0.5F;
- *i0 = IFLOOR(u);
- *i1 = *i0 + 1;
- }
- break;
- case GL_CLAMP:
- if (s <= 0.0F)
- u = 0.0F;
- else if (s >= 1.0F)
- u = (GLfloat) size;
- else
- u = s * size;
- u -= 0.5F;
- *i0 = IFLOOR(u);
- *i1 = *i0 + 1;
- break;
- default:
- _mesa_problem(NULL, "Bad wrap mode");
- u = 0.0F;
- }
- *weight = FRAC(u);
-}
-
-
-/**
- * Used to compute texel location for nearest sampling.
- */
-static INLINE GLint
-nearest_texel_location(GLenum wrapMode,
- const struct gl_texture_image *img,
- GLint size, GLfloat s)
-{
- GLint i;
-
- switch (wrapMode) {
- case GL_REPEAT:
- /* s limited to [0,1) */
- /* i limited to [0,size-1] */
- i = IFLOOR(s * size);
- if (img->_IsPowerOfTwo)
- i &= (size - 1);
- else
- i = REMAINDER(i, size);
- return i;
- case GL_CLAMP_TO_EDGE:
- {
- /* s limited to [min,max] */
- /* i limited to [0, size-1] */
- const GLfloat min = 1.0F / (2.0F * size);
- const GLfloat max = 1.0F - min;
- if (s < min)
- i = 0;
- else if (s > max)
- i = size - 1;
- else
- i = IFLOOR(s * size);
- }
- return i;
- case GL_CLAMP_TO_BORDER:
- {
- /* s limited to [min,max] */
- /* i limited to [-1, size] */
- const GLfloat min = -1.0F / (2.0F * size);
- const GLfloat max = 1.0F - min;
- if (s <= min)
- i = -1;
- else if (s >= max)
- i = size;
- else
- i = IFLOOR(s * size);
- }
- return i;
- case GL_MIRRORED_REPEAT:
- {
- const GLfloat min = 1.0F / (2.0F * size);
- const GLfloat max = 1.0F - min;
- const GLint flr = IFLOOR(s);
- GLfloat u;
- if (flr & 1)
- u = 1.0F - (s - (GLfloat) flr);
- else
- u = s - (GLfloat) flr;
- if (u < min)
- i = 0;
- else if (u > max)
- i = size - 1;
- else
- i = IFLOOR(u * size);
- }
- return i;
- case GL_MIRROR_CLAMP_EXT:
- {
- /* s limited to [0,1] */
- /* i limited to [0,size-1] */
- const GLfloat u = FABSF(s);
- if (u <= 0.0F)
- i = 0;
- else if (u >= 1.0F)
- i = size - 1;
- else
- i = IFLOOR(u * size);
- }
- return i;
- case GL_MIRROR_CLAMP_TO_EDGE_EXT:
- {
- /* s limited to [min,max] */
- /* i limited to [0, size-1] */
- const GLfloat min = 1.0F / (2.0F * size);
- const GLfloat max = 1.0F - min;
- const GLfloat u = FABSF(s);
- if (u < min)
- i = 0;
- else if (u > max)
- i = size - 1;
- else
- i = IFLOOR(u * size);
- }
- return i;
- case GL_MIRROR_CLAMP_TO_BORDER_EXT:
- {
- /* s limited to [min,max] */
- /* i limited to [0, size-1] */
- const GLfloat min = -1.0F / (2.0F * size);
- const GLfloat max = 1.0F - min;
- const GLfloat u = FABSF(s);
- if (u < min)
- i = -1;
- else if (u > max)
- i = size;
- else
- i = IFLOOR(u * size);
- }
- return i;
- case GL_CLAMP:
- /* s limited to [0,1] */
- /* i limited to [0,size-1] */
- if (s <= 0.0F)
- i = 0;
- else if (s >= 1.0F)
- i = size - 1;
- else
- i = IFLOOR(s * size);
- return i;
- default:
- _mesa_problem(NULL, "Bad wrap mode");
- return 0;
- }
-}
-
-
-/* Power of two image sizes only */
-static INLINE void
-linear_repeat_texel_location(GLuint size, GLfloat s,
- GLint *i0, GLint *i1, GLfloat *weight)
-{
- GLfloat u = s * size - 0.5F;
- *i0 = IFLOOR(u) & (size - 1);
- *i1 = (*i0 + 1) & (size - 1);
- *weight = FRAC(u);
-}
-
-
-/**
- * Do clamp/wrap for a texture rectangle coord, GL_NEAREST filter mode.
- */
-static INLINE GLint
-clamp_rect_coord_nearest(GLenum wrapMode, GLfloat coord, GLint max)
-{
- switch (wrapMode) {
- case GL_CLAMP:
- return IFLOOR( CLAMP(coord, 0.0F, max - 1) );
- case GL_CLAMP_TO_EDGE:
- return IFLOOR( CLAMP(coord, 0.5F, max - 0.5F) );
- case GL_CLAMP_TO_BORDER:
- return IFLOOR( CLAMP(coord, -0.5F, max + 0.5F) );
- default:
- _mesa_problem(NULL, "bad wrapMode in clamp_rect_coord_nearest");
- return 0;
- }
-}
-
-
-/**
- * As above, but GL_LINEAR filtering.
- */
-static INLINE void
-clamp_rect_coord_linear(GLenum wrapMode, GLfloat coord, GLint max,
- GLint *i0out, GLint *i1out, GLfloat *weight)
-{
- GLfloat fcol;
- GLint i0, i1;
- switch (wrapMode) {
- case GL_CLAMP:
- /* Not exactly what the spec says, but it matches NVIDIA output */
- fcol = CLAMP(coord - 0.5F, 0.0F, max - 1);
- i0 = IFLOOR(fcol);
- i1 = i0 + 1;
- break;
- case GL_CLAMP_TO_EDGE:
- fcol = CLAMP(coord, 0.5F, max - 0.5F);
- fcol -= 0.5F;
- i0 = IFLOOR(fcol);
- i1 = i0 + 1;
- if (i1 > max - 1)
- i1 = max - 1;
- break;
- case GL_CLAMP_TO_BORDER:
- fcol = CLAMP(coord, -0.5F, max + 0.5F);
- fcol -= 0.5F;
- i0 = IFLOOR(fcol);
- i1 = i0 + 1;
- break;
- default:
- _mesa_problem(NULL, "bad wrapMode in clamp_rect_coord_linear");
- i0 = i1 = 0;
- fcol = 0.0F;
- }
- *i0out = i0;
- *i1out = i1;
- *weight = FRAC(fcol);
-}
-
-
-/**
- * Compute slice/image to use for 1D or 2D array texture.
- */
-static INLINE GLint
-tex_array_slice(GLfloat coord, GLsizei size)
-{
- GLint slice = IFLOOR(coord + 0.5f);
- slice = CLAMP(slice, 0, size - 1);
- return slice;
-}
-
-
-/**
- * Compute nearest integer texcoords for given texobj and coordinate.
- * NOTE: only used for depth texture sampling.
- */
-static INLINE void
-nearest_texcoord(const struct gl_texture_object *texObj,
- GLuint level,
- const GLfloat texcoord[4],
- GLint *i, GLint *j, GLint *k)
-{
- const struct gl_texture_image *img = texObj->Image[0][level];
- const GLint width = img->Width;
- const GLint height = img->Height;
- const GLint depth = img->Depth;
-
- switch (texObj->Target) {
- case GL_TEXTURE_RECTANGLE_ARB:
- *i = clamp_rect_coord_nearest(texObj->Sampler.WrapS, texcoord[0], width);
- *j = clamp_rect_coord_nearest(texObj->Sampler.WrapT, texcoord[1], height);
- *k = 0;
- break;
- case GL_TEXTURE_1D:
- *i = nearest_texel_location(texObj->Sampler.WrapS, img, width, texcoord[0]);
- *j = 0;
- *k = 0;
- break;
- case GL_TEXTURE_2D:
- *i = nearest_texel_location(texObj->Sampler.WrapS, img, width, texcoord[0]);
- *j = nearest_texel_location(texObj->Sampler.WrapT, img, height, texcoord[1]);
- *k = 0;
- break;
- case GL_TEXTURE_1D_ARRAY_EXT:
- *i = nearest_texel_location(texObj->Sampler.WrapS, img, width, texcoord[0]);
- *j = tex_array_slice(texcoord[1], height);
- *k = 0;
- break;
- case GL_TEXTURE_2D_ARRAY_EXT:
- *i = nearest_texel_location(texObj->Sampler.WrapS, img, width, texcoord[0]);
- *j = nearest_texel_location(texObj->Sampler.WrapT, img, height, texcoord[1]);
- *k = tex_array_slice(texcoord[2], depth);
- break;
- default:
- *i = *j = *k = 0;
- }
-}
-
-
-/**
- * Compute linear integer texcoords for given texobj and coordinate.
- * NOTE: only used for depth texture sampling.
- */
-static INLINE void
-linear_texcoord(const struct gl_texture_object *texObj,
- GLuint level,
- const GLfloat texcoord[4],
- GLint *i0, GLint *i1, GLint *j0, GLint *j1, GLint *slice,
- GLfloat *wi, GLfloat *wj)
-{
- const struct gl_texture_image *img = texObj->Image[0][level];
- const GLint width = img->Width;
- const GLint height = img->Height;
- const GLint depth = img->Depth;
-
- switch (texObj->Target) {
- case GL_TEXTURE_RECTANGLE_ARB:
- clamp_rect_coord_linear(texObj->Sampler.WrapS, texcoord[0],
- width, i0, i1, wi);
- clamp_rect_coord_linear(texObj->Sampler.WrapT, texcoord[1],
- height, j0, j1, wj);
- *slice = 0;
- break;
-
- case GL_TEXTURE_1D:
- case GL_TEXTURE_2D:
- linear_texel_locations(texObj->Sampler.WrapS, img, width,
- texcoord[0], i0, i1, wi);
- linear_texel_locations(texObj->Sampler.WrapT, img, height,
- texcoord[1], j0, j1, wj);
- *slice = 0;
- break;
-
- case GL_TEXTURE_1D_ARRAY_EXT:
- linear_texel_locations(texObj->Sampler.WrapS, img, width,
- texcoord[0], i0, i1, wi);
- *j0 = tex_array_slice(texcoord[1], height);
- *j1 = *j0;
- *slice = 0;
- break;
-
- case GL_TEXTURE_2D_ARRAY_EXT:
- linear_texel_locations(texObj->Sampler.WrapS, img, width,
- texcoord[0], i0, i1, wi);
- linear_texel_locations(texObj->Sampler.WrapT, img, height,
- texcoord[1], j0, j1, wj);
- *slice = tex_array_slice(texcoord[2], depth);
- break;
-
- default:
- *slice = 0;
- }
-}
-
-
-
-/**
- * For linear interpolation between mipmap levels N and N+1, this function
- * computes N.
- */
-static INLINE GLint
-linear_mipmap_level(const struct gl_texture_object *tObj, GLfloat lambda)
-{
- if (lambda < 0.0F)
- return tObj->BaseLevel;
- else if (lambda > tObj->_MaxLambda)
- return (GLint) (tObj->BaseLevel + tObj->_MaxLambda);
- else
- return (GLint) (tObj->BaseLevel + lambda);
-}
-
-
-/**
- * Compute the nearest mipmap level to take texels from.
- */
-static INLINE GLint
-nearest_mipmap_level(const struct gl_texture_object *tObj, GLfloat lambda)
-{
- GLfloat l;
- GLint level;
- if (lambda <= 0.5F)
- l = 0.0F;
- else if (lambda > tObj->_MaxLambda + 0.4999F)
- l = tObj->_MaxLambda + 0.4999F;
- else
- l = lambda;
- level = (GLint) (tObj->BaseLevel + l + 0.5F);
- if (level > tObj->_MaxLevel)
- level = tObj->_MaxLevel;
- return level;
-}
-
-
-
-/*
- * Bitflags for texture border color sampling.
- */
-#define I0BIT 1
-#define I1BIT 2
-#define J0BIT 4
-#define J1BIT 8
-#define K0BIT 16
-#define K1BIT 32
-
-
-
-/**
- * The lambda[] array values are always monotonic. Either the whole span
- * will be minified, magnified, or split between the two. This function
- * determines the subranges in [0, n-1] that are to be minified or magnified.
- */
-static INLINE void
-compute_min_mag_ranges(const struct gl_texture_object *tObj,
- GLuint n, const GLfloat lambda[],
- GLuint *minStart, GLuint *minEnd,
- GLuint *magStart, GLuint *magEnd)
-{
- GLfloat minMagThresh;
-
- /* we shouldn't be here if minfilter == magfilter */
- ASSERT(tObj->Sampler.MinFilter != tObj->Sampler.MagFilter);
-
- /* This bit comes from the OpenGL spec: */
- if (tObj->Sampler.MagFilter == GL_LINEAR
- && (tObj->Sampler.MinFilter == GL_NEAREST_MIPMAP_NEAREST ||
- tObj->Sampler.MinFilter == GL_NEAREST_MIPMAP_LINEAR)) {
- minMagThresh = 0.5F;
- }
- else {
- minMagThresh = 0.0F;
- }
-
-#if 0
- /* DEBUG CODE: Verify that lambda[] is monotonic.
- * We can't really use this because the inaccuracy in the LOG2 function
- * causes this test to fail, yet the resulting texturing is correct.
- */
- if (n > 1) {
- GLuint i;
- printf("lambda delta = %g\n", lambda[0] - lambda[n-1]);
- if (lambda[0] >= lambda[n-1]) { /* decreasing */
- for (i = 0; i < n - 1; i++) {
- ASSERT((GLint) (lambda[i] * 10) >= (GLint) (lambda[i+1] * 10));
- }
- }
- else { /* increasing */
- for (i = 0; i < n - 1; i++) {
- ASSERT((GLint) (lambda[i] * 10) <= (GLint) (lambda[i+1] * 10));
- }
- }
- }
-#endif /* DEBUG */
-
- if (lambda[0] <= minMagThresh && (n <= 1 || lambda[n-1] <= minMagThresh)) {
- /* magnification for whole span */
- *magStart = 0;
- *magEnd = n;
- *minStart = *minEnd = 0;
- }
- else if (lambda[0] > minMagThresh && (n <=1 || lambda[n-1] > minMagThresh)) {
- /* minification for whole span */
- *minStart = 0;
- *minEnd = n;
- *magStart = *magEnd = 0;
- }
- else {
- /* a mix of minification and magnification */
- GLuint i;
- if (lambda[0] > minMagThresh) {
- /* start with minification */
- for (i = 1; i < n; i++) {
- if (lambda[i] <= minMagThresh)
- break;
- }
- *minStart = 0;
- *minEnd = i;
- *magStart = i;
- *magEnd = n;
- }
- else {
- /* start with magnification */
- for (i = 1; i < n; i++) {
- if (lambda[i] > minMagThresh)
- break;
- }
- *magStart = 0;
- *magEnd = i;
- *minStart = i;
- *minEnd = n;
- }
- }
-
-#if 0
- /* Verify the min/mag Start/End values
- * We don't use this either (see above)
- */
- {
- GLint i;
- for (i = 0; i < n; i++) {
- if (lambda[i] > minMagThresh) {
- /* minification */
- ASSERT(i >= *minStart);
- ASSERT(i < *minEnd);
- }
- else {
- /* magnification */
- ASSERT(i >= *magStart);
- ASSERT(i < *magEnd);
- }
- }
- }
-#endif
-}
-
-
-/**
- * When we sample the border color, it must be interpreted according to
- * the base texture format. Ex: if the texture base format it GL_ALPHA,
- * we return (0,0,0,BorderAlpha).
- */
-static INLINE void
-get_border_color(const struct gl_texture_object *tObj,
- const struct gl_texture_image *img,
- GLfloat rgba[4])
-{
- switch (img->_BaseFormat) {
- case GL_RGB:
- rgba[0] = tObj->Sampler.BorderColor.f[0];
- rgba[1] = tObj->Sampler.BorderColor.f[1];
- rgba[2] = tObj->Sampler.BorderColor.f[2];
- rgba[3] = 1.0F;
- break;
- case GL_ALPHA:
- rgba[0] = rgba[1] = rgba[2] = 0.0;
- rgba[3] = tObj->Sampler.BorderColor.f[3];
- break;
- case GL_LUMINANCE:
- rgba[0] = rgba[1] = rgba[2] = tObj->Sampler.BorderColor.f[0];
- rgba[3] = 1.0;
- break;
- case GL_LUMINANCE_ALPHA:
- rgba[0] = rgba[1] = rgba[2] = tObj->Sampler.BorderColor.f[0];
- rgba[3] = tObj->Sampler.BorderColor.f[3];
- break;
- case GL_INTENSITY:
- rgba[0] = rgba[1] = rgba[2] = rgba[3] = tObj->Sampler.BorderColor.f[0];
- break;
- default:
- COPY_4V(rgba, tObj->Sampler.BorderColor.f);
- }
-}
-
-
-/**********************************************************************/
-/* 1-D Texture Sampling Functions */
-/**********************************************************************/
-
-/**
- * Return the texture sample for coordinate (s) using GL_NEAREST filter.
- */
-static INLINE void
-sample_1d_nearest(struct gl_context *ctx,
- const struct gl_texture_object *tObj,
- const struct gl_texture_image *img,
- const GLfloat texcoord[4], GLfloat rgba[4])
-{
- const GLint width = img->Width2; /* without border, power of two */
- GLint i;
- i = nearest_texel_location(tObj->Sampler.WrapS, img, width, texcoord[0]);
- /* skip over the border, if any */
- i += img->Border;
- if (i < 0 || i >= (GLint) img->Width) {
- /* Need this test for GL_CLAMP_TO_BORDER mode */
- get_border_color(tObj, img, rgba);
- }
- else {
- img->FetchTexelf(img, i, 0, 0, rgba);
- }
-}
-
-
-/**
- * Return the texture sample for coordinate (s) using GL_LINEAR filter.
- */
-static INLINE void
-sample_1d_linear(struct gl_context *ctx,
- const struct gl_texture_object *tObj,
- const struct gl_texture_image *img,
- const GLfloat texcoord[4], GLfloat rgba[4])
-{
- const GLint width = img->Width2;
- GLint i0, i1;
- GLbitfield useBorderColor = 0x0;
- GLfloat a;
- GLfloat t0[4], t1[4]; /* texels */
-
- linear_texel_locations(tObj->Sampler.WrapS, img, width, texcoord[0], &i0, &i1, &a);
-
- if (img->Border) {
- i0 += img->Border;
- i1 += img->Border;
- }
- else {
- if (i0 < 0 || i0 >= width) useBorderColor |= I0BIT;
- if (i1 < 0 || i1 >= width) useBorderColor |= I1BIT;
- }
-
- /* fetch texel colors */
- if (useBorderColor & I0BIT) {
- get_border_color(tObj, img, t0);
- }
- else {
- img->FetchTexelf(img, i0, 0, 0, t0);
- }
- if (useBorderColor & I1BIT) {
- get_border_color(tObj, img, t1);
- }
- else {
- img->FetchTexelf(img, i1, 0, 0, t1);
- }
-
- lerp_rgba(rgba, a, t0, t1);
-}
-
-
-static void
-sample_1d_nearest_mipmap_nearest(struct gl_context *ctx,
- const struct gl_texture_object *tObj,
- GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLfloat rgba[][4])
-{
- GLuint i;
- ASSERT(lambda != NULL);
- for (i = 0; i < n; i++) {
- GLint level = nearest_mipmap_level(tObj, lambda[i]);
- sample_1d_nearest(ctx, tObj, tObj->Image[0][level], texcoord[i], rgba[i]);
- }
-}
-
-
-static void
-sample_1d_linear_mipmap_nearest(struct gl_context *ctx,
- const struct gl_texture_object *tObj,
- GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLfloat rgba[][4])
-{
- GLuint i;
- ASSERT(lambda != NULL);
- for (i = 0; i < n; i++) {
- GLint level = nearest_mipmap_level(tObj, lambda[i]);
- sample_1d_linear(ctx, tObj, tObj->Image[0][level], texcoord[i], rgba[i]);
- }
-}
-
-
-static void
-sample_1d_nearest_mipmap_linear(struct gl_context *ctx,
- const struct gl_texture_object *tObj,
- GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLfloat rgba[][4])
-{
- GLuint i;
- ASSERT(lambda != NULL);
- for (i = 0; i < n; i++) {
- GLint level = linear_mipmap_level(tObj, lambda[i]);
- if (level >= tObj->_MaxLevel) {
- sample_1d_nearest(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
- texcoord[i], rgba[i]);
- }
- else {
- GLfloat t0[4], t1[4];
- const GLfloat f = FRAC(lambda[i]);
- sample_1d_nearest(ctx, tObj, tObj->Image[0][level ], texcoord[i], t0);
- sample_1d_nearest(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
- lerp_rgba(rgba[i], f, t0, t1);
- }
- }
-}
-
-
-static void
-sample_1d_linear_mipmap_linear(struct gl_context *ctx,
- const struct gl_texture_object *tObj,
- GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLfloat rgba[][4])
-{
- GLuint i;
- ASSERT(lambda != NULL);
- for (i = 0; i < n; i++) {
- GLint level = linear_mipmap_level(tObj, lambda[i]);
- if (level >= tObj->_MaxLevel) {
- sample_1d_linear(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
- texcoord[i], rgba[i]);
- }
- else {
- GLfloat t0[4], t1[4];
- const GLfloat f = FRAC(lambda[i]);
- sample_1d_linear(ctx, tObj, tObj->Image[0][level ], texcoord[i], t0);
- sample_1d_linear(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
- lerp_rgba(rgba[i], f, t0, t1);
- }
- }
-}
-
-
-/** Sample 1D texture, nearest filtering for both min/magnification */
-static void
-sample_nearest_1d( struct gl_context *ctx,
- const struct gl_texture_object *tObj, GLuint n,
- const GLfloat texcoords[][4], const GLfloat lambda[],
- GLfloat rgba[][4] )
-{
- GLuint i;
- struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
- (void) lambda;
- for (i = 0; i < n; i++) {
- sample_1d_nearest(ctx, tObj, image, texcoords[i], rgba[i]);
- }
-}
-
-
-/** Sample 1D texture, linear filtering for both min/magnification */
-static void
-sample_linear_1d( struct gl_context *ctx,
- const struct gl_texture_object *tObj, GLuint n,
- const GLfloat texcoords[][4], const GLfloat lambda[],
- GLfloat rgba[][4] )
-{
- GLuint i;
- struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
- (void) lambda;
- for (i = 0; i < n; i++) {
- sample_1d_linear(ctx, tObj, image, texcoords[i], rgba[i]);
- }
-}
-
-
-/** Sample 1D texture, using lambda to choose between min/magnification */
-static void
-sample_lambda_1d( struct gl_context *ctx,
- const struct gl_texture_object *tObj, GLuint n,
- const GLfloat texcoords[][4],
- const GLfloat lambda[], GLfloat rgba[][4] )
-{
- GLuint minStart, minEnd; /* texels with minification */
- GLuint magStart, magEnd; /* texels with magnification */
- GLuint i;
-
- ASSERT(lambda != NULL);
- compute_min_mag_ranges(tObj, n, lambda,
- &minStart, &minEnd, &magStart, &magEnd);
-
- if (minStart < minEnd) {
- /* do the minified texels */
- const GLuint m = minEnd - minStart;
- switch (tObj->Sampler.MinFilter) {
- case GL_NEAREST:
- for (i = minStart; i < minEnd; i++)
- sample_1d_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
- texcoords[i], rgba[i]);
- break;
- case GL_LINEAR:
- for (i = minStart; i < minEnd; i++)
- sample_1d_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
- texcoords[i], rgba[i]);
- break;
- case GL_NEAREST_MIPMAP_NEAREST:
- sample_1d_nearest_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
- lambda + minStart, rgba + minStart);
- break;
- case GL_LINEAR_MIPMAP_NEAREST:
- sample_1d_linear_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
- lambda + minStart, rgba + minStart);
- break;
- case GL_NEAREST_MIPMAP_LINEAR:
- sample_1d_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart,
- lambda + minStart, rgba + minStart);
- break;
- case GL_LINEAR_MIPMAP_LINEAR:
- sample_1d_linear_mipmap_linear(ctx, tObj, m, texcoords + minStart,
- lambda + minStart, rgba + minStart);
- break;
- default:
- _mesa_problem(ctx, "Bad min filter in sample_1d_texture");
- return;
- }
- }
-
- if (magStart < magEnd) {
- /* do the magnified texels */
- switch (tObj->Sampler.MagFilter) {
- case GL_NEAREST:
- for (i = magStart; i < magEnd; i++)
- sample_1d_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
- texcoords[i], rgba[i]);
- break;
- case GL_LINEAR:
- for (i = magStart; i < magEnd; i++)
- sample_1d_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
- texcoords[i], rgba[i]);
- break;
- default:
- _mesa_problem(ctx, "Bad mag filter in sample_1d_texture");
- return;
- }
- }
-}
-
-
-/**********************************************************************/
-/* 2-D Texture Sampling Functions */
-/**********************************************************************/
-
-
-/**
- * Return the texture sample for coordinate (s,t) using GL_NEAREST filter.
- */
-static INLINE void
-sample_2d_nearest(struct gl_context *ctx,
- const struct gl_texture_object *tObj,
- const struct gl_texture_image *img,
- const GLfloat texcoord[4],
- GLfloat rgba[])
-{
- const GLint width = img->Width2; /* without border, power of two */
- const GLint height = img->Height2; /* without border, power of two */
- GLint i, j;
- (void) ctx;
-
- i = nearest_texel_location(tObj->Sampler.WrapS, img, width, texcoord[0]);
- j = nearest_texel_location(tObj->Sampler.WrapT, img, height, texcoord[1]);
-
- /* skip over the border, if any */
- i += img->Border;
- j += img->Border;
-
- if (i < 0 || i >= (GLint) img->Width || j < 0 || j >= (GLint) img->Height) {
- /* Need this test for GL_CLAMP_TO_BORDER mode */
- get_border_color(tObj, img, rgba);
- }
- else {
- img->FetchTexelf(img, i, j, 0, rgba);
- }
-}
-
-
-/**
- * Return the texture sample for coordinate (s,t) using GL_LINEAR filter.
- * New sampling code contributed by Lynn Quam <quam@ai.sri.com>.
- */
-static INLINE void
-sample_2d_linear(struct gl_context *ctx,
- const struct gl_texture_object *tObj,
- const struct gl_texture_image *img,
- const GLfloat texcoord[4],
- GLfloat rgba[])
-{
- const GLint width = img->Width2;
- const GLint height = img->Height2;
- GLint i0, j0, i1, j1;
- GLbitfield useBorderColor = 0x0;
- GLfloat a, b;
- GLfloat t00[4], t10[4], t01[4], t11[4]; /* sampled texel colors */
-
- linear_texel_locations(tObj->Sampler.WrapS, img, width, texcoord[0], &i0, &i1, &a);
- linear_texel_locations(tObj->Sampler.WrapT, img, height, texcoord[1], &j0, &j1, &b);
-
- if (img->Border) {
- i0 += img->Border;
- i1 += img->Border;
- j0 += img->Border;
- j1 += img->Border;
- }
- else {
- if (i0 < 0 || i0 >= width) useBorderColor |= I0BIT;
- if (i1 < 0 || i1 >= width) useBorderColor |= I1BIT;
- if (j0 < 0 || j0 >= height) useBorderColor |= J0BIT;
- if (j1 < 0 || j1 >= height) useBorderColor |= J1BIT;
- }
-
- /* fetch four texel colors */
- if (useBorderColor & (I0BIT | J0BIT)) {
- get_border_color(tObj, img, t00);
- }
- else {
- img->FetchTexelf(img, i0, j0, 0, t00);
- }
- if (useBorderColor & (I1BIT | J0BIT)) {
- get_border_color(tObj, img, t10);
- }
- else {
- img->FetchTexelf(img, i1, j0, 0, t10);
- }
- if (useBorderColor & (I0BIT | J1BIT)) {
- get_border_color(tObj, img, t01);
- }
- else {
- img->FetchTexelf(img, i0, j1, 0, t01);
- }
- if (useBorderColor & (I1BIT | J1BIT)) {
- get_border_color(tObj, img, t11);
- }
- else {
- img->FetchTexelf(img, i1, j1, 0, t11);
- }
-
- lerp_rgba_2d(rgba, a, b, t00, t10, t01, t11);
-}
-
-
-/**
- * As above, but we know WRAP_S == REPEAT and WRAP_T == REPEAT.
- * We don't have to worry about the texture border.
- */
-static INLINE void
-sample_2d_linear_repeat(struct gl_context *ctx,
- const struct gl_texture_object *tObj,
- const struct gl_texture_image *img,
- const GLfloat texcoord[4],
- GLfloat rgba[])
-{
- const GLint width = img->Width2;
- const GLint height = img->Height2;
- GLint i0, j0, i1, j1;
- GLfloat wi, wj;
- GLfloat t00[4], t10[4], t01[4], t11[4]; /* sampled texel colors */
-
- (void) ctx;
-
- ASSERT(tObj->Sampler.WrapS == GL_REPEAT);
- ASSERT(tObj->Sampler.WrapT == GL_REPEAT);
- ASSERT(img->Border == 0);
- ASSERT(img->_BaseFormat != GL_COLOR_INDEX);
- ASSERT(img->_IsPowerOfTwo);
-
- linear_repeat_texel_location(width, texcoord[0], &i0, &i1, &wi);
- linear_repeat_texel_location(height, texcoord[1], &j0, &j1, &wj);
-
- img->FetchTexelf(img, i0, j0, 0, t00);
- img->FetchTexelf(img, i1, j0, 0, t10);
- img->FetchTexelf(img, i0, j1, 0, t01);
- img->FetchTexelf(img, i1, j1, 0, t11);
-
- lerp_rgba_2d(rgba, wi, wj, t00, t10, t01, t11);
-}
-
-
-static void
-sample_2d_nearest_mipmap_nearest(struct gl_context *ctx,
- const struct gl_texture_object *tObj,
- GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLfloat rgba[][4])
-{
- GLuint i;
- for (i = 0; i < n; i++) {
- GLint level = nearest_mipmap_level(tObj, lambda[i]);
- sample_2d_nearest(ctx, tObj, tObj->Image[0][level], texcoord[i], rgba[i]);
- }
-}
-
-
-static void
-sample_2d_linear_mipmap_nearest(struct gl_context *ctx,
- const struct gl_texture_object *tObj,
- GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLfloat rgba[][4])
-{
- GLuint i;
- ASSERT(lambda != NULL);
- for (i = 0; i < n; i++) {
- GLint level = nearest_mipmap_level(tObj, lambda[i]);
- sample_2d_linear(ctx, tObj, tObj->Image[0][level], texcoord[i], rgba[i]);
- }
-}
-
-
-static void
-sample_2d_nearest_mipmap_linear(struct gl_context *ctx,
- const struct gl_texture_object *tObj,
- GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLfloat rgba[][4])
-{
- GLuint i;
- ASSERT(lambda != NULL);
- for (i = 0; i < n; i++) {
- GLint level = linear_mipmap_level(tObj, lambda[i]);
- if (level >= tObj->_MaxLevel) {
- sample_2d_nearest(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
- texcoord[i], rgba[i]);
- }
- else {
- GLfloat t0[4], t1[4]; /* texels */
- const GLfloat f = FRAC(lambda[i]);
- sample_2d_nearest(ctx, tObj, tObj->Image[0][level ], texcoord[i], t0);
- sample_2d_nearest(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
- lerp_rgba(rgba[i], f, t0, t1);
- }
- }
-}
-
-
-static void
-sample_2d_linear_mipmap_linear( struct gl_context *ctx,
- const struct gl_texture_object *tObj,
- GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLfloat rgba[][4] )
-{
- GLuint i;
- ASSERT(lambda != NULL);
- for (i = 0; i < n; i++) {
- GLint level = linear_mipmap_level(tObj, lambda[i]);
- if (level >= tObj->_MaxLevel) {
- sample_2d_linear(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
- texcoord[i], rgba[i]);
- }
- else {
- GLfloat t0[4], t1[4]; /* texels */
- const GLfloat f = FRAC(lambda[i]);
- sample_2d_linear(ctx, tObj, tObj->Image[0][level ], texcoord[i], t0);
- sample_2d_linear(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
- lerp_rgba(rgba[i], f, t0, t1);
- }
- }
-}
-
-
-static void
-sample_2d_linear_mipmap_linear_repeat(struct gl_context *ctx,
- const struct gl_texture_object *tObj,
- GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLfloat rgba[][4])
-{
- GLuint i;
- ASSERT(lambda != NULL);
- ASSERT(tObj->Sampler.WrapS == GL_REPEAT);
- ASSERT(tObj->Sampler.WrapT == GL_REPEAT);
- for (i = 0; i < n; i++) {
- GLint level = linear_mipmap_level(tObj, lambda[i]);
- if (level >= tObj->_MaxLevel) {
- sample_2d_linear_repeat(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
- texcoord[i], rgba[i]);
- }
- else {
- GLfloat t0[4], t1[4]; /* texels */
- const GLfloat f = FRAC(lambda[i]);
- sample_2d_linear_repeat(ctx, tObj, tObj->Image[0][level ],
- texcoord[i], t0);
- sample_2d_linear_repeat(ctx, tObj, tObj->Image[0][level+1],
- texcoord[i], t1);
- lerp_rgba(rgba[i], f, t0, t1);
- }
- }
-}
-
-
-/** Sample 2D texture, nearest filtering for both min/magnification */
-static void
-sample_nearest_2d(struct gl_context *ctx,
- const struct gl_texture_object *tObj, GLuint n,
- const GLfloat texcoords[][4],
- const GLfloat lambda[], GLfloat rgba[][4])
-{
- GLuint i;
- struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
- (void) lambda;
- for (i = 0; i < n; i++) {
- sample_2d_nearest(ctx, tObj, image, texcoords[i], rgba[i]);
- }
-}
-
-
-/** Sample 2D texture, linear filtering for both min/magnification */
-static void
-sample_linear_2d(struct gl_context *ctx,
- const struct gl_texture_object *tObj, GLuint n,
- const GLfloat texcoords[][4],
- const GLfloat lambda[], GLfloat rgba[][4])
-{
- GLuint i;
- struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
- (void) lambda;
- if (tObj->Sampler.WrapS == GL_REPEAT &&
- tObj->Sampler.WrapT == GL_REPEAT &&
- image->_IsPowerOfTwo &&
- image->Border == 0) {
- for (i = 0; i < n; i++) {
- sample_2d_linear_repeat(ctx, tObj, image, texcoords[i], rgba[i]);
- }
- }
- else {
- for (i = 0; i < n; i++) {
- sample_2d_linear(ctx, tObj, image, texcoords[i], rgba[i]);
- }
- }
-}
-
-
-/**
- * Optimized 2-D texture sampling:
- * S and T wrap mode == GL_REPEAT
- * GL_NEAREST min/mag filter
- * No border,
- * RowStride == Width,
- * Format = GL_RGB
- */
-static void
-opt_sample_rgb_2d(struct gl_context *ctx,
- const struct gl_texture_object *tObj,
- GLuint n, const GLfloat texcoords[][4],
- const GLfloat lambda[], GLfloat rgba[][4])
-{
- const struct gl_texture_image *img = tObj->Image[0][tObj->BaseLevel];
- const GLfloat width = (GLfloat) img->Width;
- const GLfloat height = (GLfloat) img->Height;
- const GLint colMask = img->Width - 1;
- const GLint rowMask = img->Height - 1;
- const GLint shift = img->WidthLog2;
- GLuint k;
- (void) ctx;
- (void) lambda;
- ASSERT(tObj->Sampler.WrapS==GL_REPEAT);
- ASSERT(tObj->Sampler.WrapT==GL_REPEAT);
- ASSERT(img->Border==0);
- ASSERT(img->TexFormat == MESA_FORMAT_RGB888);
- ASSERT(img->_IsPowerOfTwo);
-
- for (k=0; k<n; k++) {
- GLint i = IFLOOR(texcoords[k][0] * width) & colMask;
- GLint j = IFLOOR(texcoords[k][1] * height) & rowMask;
- GLint pos = (j << shift) | i;
- GLubyte *texel = ((GLubyte *) img->Data) + 3*pos;
- rgba[k][RCOMP] = UBYTE_TO_FLOAT(texel[2]);
- rgba[k][GCOMP] = UBYTE_TO_FLOAT(texel[1]);
- rgba[k][BCOMP] = UBYTE_TO_FLOAT(texel[0]);
- rgba[k][ACOMP] = 1.0F;
- }
-}
-
-
-/**
- * Optimized 2-D texture sampling:
- * S and T wrap mode == GL_REPEAT
- * GL_NEAREST min/mag filter
- * No border
- * RowStride == Width,
- * Format = GL_RGBA
- */
-static void
-opt_sample_rgba_2d(struct gl_context *ctx,
- const struct gl_texture_object *tObj,
- GLuint n, const GLfloat texcoords[][4],
- const GLfloat lambda[], GLfloat rgba[][4])
-{
- const struct gl_texture_image *img = tObj->Image[0][tObj->BaseLevel];
- const GLfloat width = (GLfloat) img->Width;
- const GLfloat height = (GLfloat) img->Height;
- const GLint colMask = img->Width - 1;
- const GLint rowMask = img->Height - 1;
- const GLint shift = img->WidthLog2;
- GLuint i;
- (void) ctx;
- (void) lambda;
- ASSERT(tObj->Sampler.WrapS==GL_REPEAT);
- ASSERT(tObj->Sampler.WrapT==GL_REPEAT);
- ASSERT(img->Border==0);
- ASSERT(img->TexFormat == MESA_FORMAT_RGBA8888);
- ASSERT(img->_IsPowerOfTwo);
-
- for (i = 0; i < n; i++) {
- const GLint col = IFLOOR(texcoords[i][0] * width) & colMask;
- const GLint row = IFLOOR(texcoords[i][1] * height) & rowMask;
- const GLint pos = (row << shift) | col;
- const GLuint texel = *((GLuint *) img->Data + pos);
- rgba[i][RCOMP] = UBYTE_TO_FLOAT( (texel >> 24) );
- rgba[i][GCOMP] = UBYTE_TO_FLOAT( (texel >> 16) & 0xff );
- rgba[i][BCOMP] = UBYTE_TO_FLOAT( (texel >> 8) & 0xff );
- rgba[i][ACOMP] = UBYTE_TO_FLOAT( (texel ) & 0xff );
- }
-}
-
-
-/** Sample 2D texture, using lambda to choose between min/magnification */
-static void
-sample_lambda_2d(struct gl_context *ctx,
- const struct gl_texture_object *tObj,
- GLuint n, const GLfloat texcoords[][4],
- const GLfloat lambda[], GLfloat rgba[][4])
-{
- const struct gl_texture_image *tImg = tObj->Image[0][tObj->BaseLevel];
- GLuint minStart, minEnd; /* texels with minification */
- GLuint magStart, magEnd; /* texels with magnification */
-
- const GLboolean repeatNoBorderPOT = (tObj->Sampler.WrapS == GL_REPEAT)
- && (tObj->Sampler.WrapT == GL_REPEAT)
- && (tImg->Border == 0 && (tImg->Width == tImg->RowStride))
- && (tImg->_BaseFormat != GL_COLOR_INDEX)
- && tImg->_IsPowerOfTwo;
-
- ASSERT(lambda != NULL);
- compute_min_mag_ranges(tObj, n, lambda,
- &minStart, &minEnd, &magStart, &magEnd);
-
- if (minStart < minEnd) {
- /* do the minified texels */
- const GLuint m = minEnd - minStart;
- switch (tObj->Sampler.MinFilter) {
- case GL_NEAREST:
- if (repeatNoBorderPOT) {
- switch (tImg->TexFormat) {
- case MESA_FORMAT_RGB888:
- opt_sample_rgb_2d(ctx, tObj, m, texcoords + minStart,
- NULL, rgba + minStart);
- break;
- case MESA_FORMAT_RGBA8888:
- opt_sample_rgba_2d(ctx, tObj, m, texcoords + minStart,
- NULL, rgba + minStart);
- break;
- default:
- sample_nearest_2d(ctx, tObj, m, texcoords + minStart,
- NULL, rgba + minStart );
- }
- }
- else {
- sample_nearest_2d(ctx, tObj, m, texcoords + minStart,
- NULL, rgba + minStart);
- }
- break;
- case GL_LINEAR:
- sample_linear_2d(ctx, tObj, m, texcoords + minStart,
- NULL, rgba + minStart);
- break;
- case GL_NEAREST_MIPMAP_NEAREST:
- sample_2d_nearest_mipmap_nearest(ctx, tObj, m,
- texcoords + minStart,
- lambda + minStart, rgba + minStart);
- break;
- case GL_LINEAR_MIPMAP_NEAREST:
- sample_2d_linear_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
- lambda + minStart, rgba + minStart);
- break;
- case GL_NEAREST_MIPMAP_LINEAR:
- sample_2d_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart,
- lambda + minStart, rgba + minStart);
- break;
- case GL_LINEAR_MIPMAP_LINEAR:
- if (repeatNoBorderPOT)
- sample_2d_linear_mipmap_linear_repeat(ctx, tObj, m,
- texcoords + minStart, lambda + minStart, rgba + minStart);
- else
- sample_2d_linear_mipmap_linear(ctx, tObj, m, texcoords + minStart,
- lambda + minStart, rgba + minStart);
- break;
- default:
- _mesa_problem(ctx, "Bad min filter in sample_2d_texture");
- return;
- }
- }
-
- if (magStart < magEnd) {
- /* do the magnified texels */
- const GLuint m = magEnd - magStart;
-
- switch (tObj->Sampler.MagFilter) {
- case GL_NEAREST:
- if (repeatNoBorderPOT) {
- switch (tImg->TexFormat) {
- case MESA_FORMAT_RGB888:
- opt_sample_rgb_2d(ctx, tObj, m, texcoords + magStart,
- NULL, rgba + magStart);
- break;
- case MESA_FORMAT_RGBA8888:
- opt_sample_rgba_2d(ctx, tObj, m, texcoords + magStart,
- NULL, rgba + magStart);
- break;
- default:
- sample_nearest_2d(ctx, tObj, m, texcoords + magStart,
- NULL, rgba + magStart );
- }
- }
- else {
- sample_nearest_2d(ctx, tObj, m, texcoords + magStart,
- NULL, rgba + magStart);
- }
- break;
- case GL_LINEAR:
- sample_linear_2d(ctx, tObj, m, texcoords + magStart,
- NULL, rgba + magStart);
- break;
- default:
- _mesa_problem(ctx, "Bad mag filter in sample_lambda_2d");
- }
- }
-}
-
-
-/* For anisotropic filtering */
-#define WEIGHT_LUT_SIZE 1024
-
-static GLfloat *weightLut = NULL;
-
-/**
- * Creates the look-up table used to speed-up EWA sampling
- */
-static void
-create_filter_table(void)
-{
- GLuint i;
- if (!weightLut) {
- weightLut = (GLfloat *) malloc(WEIGHT_LUT_SIZE * sizeof(GLfloat));
-
- for (i = 0; i < WEIGHT_LUT_SIZE; ++i) {
- GLfloat alpha = 2;
- GLfloat r2 = (GLfloat) i / (GLfloat) (WEIGHT_LUT_SIZE - 1);
- GLfloat weight = (GLfloat) exp(-alpha * r2);
- weightLut[i] = weight;
- }
- }
-}
-
-
-/**
- * Elliptical weighted average (EWA) filter for producing high quality
- * anisotropic filtered results.
- * Based on the Higher Quality Elliptical Weighted Avarage Filter
- * published by Paul S. Heckbert in his Master's Thesis
- * "Fundamentals of Texture Mapping and Image Warping" (1989)
- */
-static void
-sample_2d_ewa(struct gl_context *ctx,
- const struct gl_texture_object *tObj,
- const GLfloat texcoord[4],
- const GLfloat dudx, const GLfloat dvdx,
- const GLfloat dudy, const GLfloat dvdy, const GLint lod,
- GLfloat rgba[])
-{
- GLint level = lod > 0 ? lod : 0;
- GLfloat scaling = 1.0 / (1 << level);
- const struct gl_texture_image *img = tObj->Image[0][level];
- const struct gl_texture_image *mostDetailedImage =
- tObj->Image[0][tObj->BaseLevel];
- GLfloat tex_u=-0.5 + texcoord[0] * mostDetailedImage->WidthScale * scaling;
- GLfloat tex_v=-0.5 + texcoord[1] * mostDetailedImage->HeightScale * scaling;
-
- GLfloat ux = dudx * scaling;
- GLfloat vx = dvdx * scaling;
- GLfloat uy = dudy * scaling;
- GLfloat vy = dvdy * scaling;
-
- /* compute ellipse coefficients to bound the region:
- * A*x*x + B*x*y + C*y*y = F.
- */
- GLfloat A = vx*vx+vy*vy+1;
- GLfloat B = -2*(ux*vx+uy*vy);
- GLfloat C = ux*ux+uy*uy+1;
- GLfloat F = A*C-B*B/4.0;
-
- /* check if it is an ellipse */
- /* ASSERT(F > 0.0); */
-
- /* Compute the ellipse's (u,v) bounding box in texture space */
- GLfloat d = -B*B+4.0*C*A;
- GLfloat box_u = 2.0 / d * sqrt(d*C*F); /* box_u -> half of bbox with */
- GLfloat box_v = 2.0 / d * sqrt(A*d*F); /* box_v -> half of bbox height */
-
- GLint u0 = floor(tex_u - box_u);
- GLint u1 = ceil (tex_u + box_u);
- GLint v0 = floor(tex_v - box_v);
- GLint v1 = ceil (tex_v + box_v);
-
- GLfloat num[4] = {0.0F, 0.0F, 0.0F, 0.0F};
- GLfloat newCoord[2];
- GLfloat den = 0.0F;
- GLfloat ddq;
- GLfloat U = u0 - tex_u;
- GLint v;
-
- /* Scale ellipse formula to directly index the Filter Lookup Table.
- * i.e. scale so that F = WEIGHT_LUT_SIZE-1
- */
- double formScale = (double) (WEIGHT_LUT_SIZE - 1) / F;
- A *= formScale;
- B *= formScale;
- C *= formScale;
- /* F *= formScale; */ /* no need to scale F as we don't use it below here */
-
- /* Heckbert MS thesis, p. 59; scan over the bounding box of the ellipse
- * and incrementally update the value of Ax^2+Bxy*Cy^2; when this
- * value, q, is less than F, we're inside the ellipse
- */
- ddq = 2 * A;
- for (v = v0; v <= v1; ++v) {
- GLfloat V = v - tex_v;
- GLfloat dq = A * (2 * U + 1) + B * V;
- GLfloat q = (C * V + B * U) * V + A * U * U;
-
- GLint u;
- for (u = u0; u <= u1; ++u) {
- /* Note that the ellipse has been pre-scaled so F = WEIGHT_LUT_SIZE - 1 */
- if (q < WEIGHT_LUT_SIZE) {
- /* as a LUT is used, q must never be negative;
- * should not happen, though
- */
- const GLint qClamped = q >= 0.0F ? q : 0;
- GLfloat weight = weightLut[qClamped];
-
- newCoord[0] = u / ((GLfloat) img->Width2);
- newCoord[1] = v / ((GLfloat) img->Height2);
-
- sample_2d_nearest(ctx, tObj, img, newCoord, rgba);
- num[0] += weight * rgba[0];
- num[1] += weight * rgba[1];
- num[2] += weight * rgba[2];
- num[3] += weight * rgba[3];
-
- den += weight;
- }
- q += dq;
- dq += ddq;
- }
- }
-
- if (den <= 0.0F) {
- /* Reaching this place would mean
- * that no pixels intersected the ellipse.
- * This should never happen because
- * the filter we use always
- * intersects at least one pixel.
- */
-
- /*rgba[0]=0;
- rgba[1]=0;
- rgba[2]=0;
- rgba[3]=0;*/
- /* not enough pixels in resampling, resort to direct interpolation */
- sample_2d_linear(ctx, tObj, img, texcoord, rgba);
- return;
- }
-
- rgba[0] = num[0] / den;
- rgba[1] = num[1] / den;
- rgba[2] = num[2] / den;
- rgba[3] = num[3] / den;
-}
-
-
-/**
- * Anisotropic filtering using footprint assembly as outlined in the
- * EXT_texture_filter_anisotropic spec:
- * http://www.opengl.org/registry/specs/EXT/texture_filter_anisotropic.txt
- * Faster than EWA but has less quality (more aliasing effects)
- */
-static void
-sample_2d_footprint(struct gl_context *ctx,
- const struct gl_texture_object *tObj,
- const GLfloat texcoord[4],
- const GLfloat dudx, const GLfloat dvdx,
- const GLfloat dudy, const GLfloat dvdy, const GLint lod,
- GLfloat rgba[])
-{
- GLint level = lod > 0 ? lod : 0;
- GLfloat scaling = 1.0F / (1 << level);
- const struct gl_texture_image *img = tObj->Image[0][level];
-
- GLfloat ux = dudx * scaling;
- GLfloat vx = dvdx * scaling;
- GLfloat uy = dudy * scaling;
- GLfloat vy = dvdy * scaling;
-
- GLfloat Px2 = ux * ux + vx * vx; /* squared length of dx */
- GLfloat Py2 = uy * uy + vy * vy; /* squared length of dy */
-
- GLint numSamples;
- GLfloat ds;
- GLfloat dt;
-
- GLfloat num[4] = {0.0F, 0.0F, 0.0F, 0.0F};
- GLfloat newCoord[2];
- GLint s;
-
- /* Calculate the per anisotropic sample offsets in s,t space. */
- if (Px2 > Py2) {
- numSamples = ceil(SQRTF(Px2));
- ds = ux / ((GLfloat) img->Width2);
- dt = vx / ((GLfloat) img->Height2);
- }
- else {
- numSamples = ceil(SQRTF(Py2));
- ds = uy / ((GLfloat) img->Width2);
- dt = vy / ((GLfloat) img->Height2);
- }
-
- for (s = 0; s<numSamples; s++) {
- newCoord[0] = texcoord[0] + ds * ((GLfloat)(s+1) / (numSamples+1) -0.5);
- newCoord[1] = texcoord[1] + dt * ((GLfloat)(s+1) / (numSamples+1) -0.5);
-
- sample_2d_linear(ctx, tObj, img, newCoord, rgba);
- num[0] += rgba[0];
- num[1] += rgba[1];
- num[2] += rgba[2];
- num[3] += rgba[3];
- }
-
- rgba[0] = num[0] / numSamples;
- rgba[1] = num[1] / numSamples;
- rgba[2] = num[2] / numSamples;
- rgba[3] = num[3] / numSamples;
-}
-
-
-/**
- * Returns the index of the specified texture object in the
- * gl_context texture unit array.
- */
-static INLINE GLuint
-texture_unit_index(const struct gl_context *ctx,
- const struct gl_texture_object *tObj)
-{
- const GLuint maxUnit
- = (ctx->Texture._EnabledCoordUnits > 1) ? ctx->Const.MaxTextureUnits : 1;
- GLuint u;
-
- /* XXX CoordUnits vs. ImageUnits */
- for (u = 0; u < maxUnit; u++) {
- if (ctx->Texture.Unit[u]._Current == tObj)
- break; /* found */
- }
- if (u >= maxUnit)
- u = 0; /* not found, use 1st one; should never happen */
-
- return u;
-}
-
-
-/**
- * Sample 2D texture using an anisotropic filter.
- * NOTE: the const GLfloat lambda_iso[] parameter does *NOT* contain
- * the lambda float array but a "hidden" SWspan struct which is required
- * by this function but is not available in the texture_sample_func signature.
- * See _swrast_texture_span( struct gl_context *ctx, SWspan *span ) on how
- * this function is called.
- */
-static void
-sample_lambda_2d_aniso(struct gl_context *ctx,
- const struct gl_texture_object *tObj,
- GLuint n, const GLfloat texcoords[][4],
- const GLfloat lambda_iso[], GLfloat rgba[][4])
-{
- const struct gl_texture_image *tImg = tObj->Image[0][tObj->BaseLevel];
- const GLfloat maxEccentricity =
- tObj->Sampler.MaxAnisotropy * tObj->Sampler.MaxAnisotropy;
-
- /* re-calculate the lambda values so that they are usable with anisotropic
- * filtering
- */
- SWspan *span = (SWspan *)lambda_iso; /* access the "hidden" SWspan struct */
-
- /* based on interpolate_texcoords(struct gl_context *ctx, SWspan *span)
- * in swrast/s_span.c
- */
-
- /* find the texture unit index by looking up the current texture object
- * from the context list of available texture objects.
- */
- const GLuint u = texture_unit_index(ctx, tObj);
- const GLuint attr = FRAG_ATTRIB_TEX0 + u;
- GLfloat texW, texH;
-
- const GLfloat dsdx = span->attrStepX[attr][0];
- const GLfloat dsdy = span->attrStepY[attr][0];
- const GLfloat dtdx = span->attrStepX[attr][1];
- const GLfloat dtdy = span->attrStepY[attr][1];
- const GLfloat dqdx = span->attrStepX[attr][3];
- const GLfloat dqdy = span->attrStepY[attr][3];
- GLfloat s = span->attrStart[attr][0] + span->leftClip * dsdx;
- GLfloat t = span->attrStart[attr][1] + span->leftClip * dtdx;
- GLfloat q = span->attrStart[attr][3] + span->leftClip * dqdx;
-
- /* from swrast/s_texcombine.c _swrast_texture_span */
- const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[u];
- const GLboolean adjustLOD =
- (texUnit->LodBias + tObj->Sampler.LodBias != 0.0F)
- || (tObj->Sampler.MinLod != -1000.0 || tObj->Sampler.MaxLod != 1000.0);
-
- GLuint i;
-
- /* on first access create the lookup table containing the filter weights. */
- if (!weightLut) {
- create_filter_table();
- }
-
- texW = tImg->WidthScale;
- texH = tImg->HeightScale;
-
- for (i = 0; i < n; i++) {
- const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
-
- GLfloat dudx = texW * ((s + dsdx) / (q + dqdx) - s * invQ);
- GLfloat dvdx = texH * ((t + dtdx) / (q + dqdx) - t * invQ);
- GLfloat dudy = texW * ((s + dsdy) / (q + dqdy) - s * invQ);
- GLfloat dvdy = texH * ((t + dtdy) / (q + dqdy) - t * invQ);
-
- /* note: instead of working with Px and Py, we will use the
- * squared length instead, to avoid sqrt.
- */
- GLfloat Px2 = dudx * dudx + dvdx * dvdx;
- GLfloat Py2 = dudy * dudy + dvdy * dvdy;
-
- GLfloat Pmax2;
- GLfloat Pmin2;
- GLfloat e;
- GLfloat lod;
-
- s += dsdx;
- t += dtdx;
- q += dqdx;
-
- if (Px2 < Py2) {
- Pmax2 = Py2;
- Pmin2 = Px2;
- }
- else {
- Pmax2 = Px2;
- Pmin2 = Py2;
- }
-
- /* if the eccentricity of the ellipse is too big, scale up the shorter
- * of the two vectors to limit the maximum amount of work per pixel
- */
- e = Pmax2 / Pmin2;
- if (e > maxEccentricity) {
- /* GLfloat s=e / maxEccentricity;
- minor[0] *= s;
- minor[1] *= s;
- Pmin2 *= s; */
- Pmin2 = Pmax2 / maxEccentricity;
- }
-
- /* note: we need to have Pmin=sqrt(Pmin2) here, but we can avoid
- * this since 0.5*log(x) = log(sqrt(x))
- */
- lod = 0.5 * LOG2(Pmin2);
-
- if (adjustLOD) {
- /* from swrast/s_texcombine.c _swrast_texture_span */
- if (texUnit->LodBias + tObj->Sampler.LodBias != 0.0F) {
- /* apply LOD bias, but don't clamp yet */
- const GLfloat bias =
- CLAMP(texUnit->LodBias + tObj->Sampler.LodBias,
- -ctx->Const.MaxTextureLodBias,
- ctx->Const.MaxTextureLodBias);
- lod += bias;
-
- if (tObj->Sampler.MinLod != -1000.0 ||
- tObj->Sampler.MaxLod != 1000.0) {
- /* apply LOD clamping to lambda */
- lod = CLAMP(lod, tObj->Sampler.MinLod, tObj->Sampler.MaxLod);
- }
- }
- }
-
- /* If the ellipse covers the whole image, we can
- * simply return the average of the whole image.
- */
- if (lod >= tObj->_MaxLevel) {
- sample_2d_linear(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
- texcoords[i], rgba[i]);
- }
- else {
- /* don't bother interpolating between multiple LODs; it doesn't
- * seem to be worth the extra running time.
- */
- sample_2d_ewa(ctx, tObj, texcoords[i],
- dudx, dvdx, dudy, dvdy, floor(lod), rgba[i]);
-
- /* unused: */
- (void) sample_2d_footprint;
- /*
- sample_2d_footprint(ctx, tObj, texcoords[i],
- dudx, dvdx, dudy, dvdy, floor(lod), rgba[i]);
- */
- }
- }
-}
-
-
-
-/**********************************************************************/
-/* 3-D Texture Sampling Functions */
-/**********************************************************************/
-
-/**
- * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
- */
-static INLINE void
-sample_3d_nearest(struct gl_context *ctx,
- const struct gl_texture_object *tObj,
- const struct gl_texture_image *img,
- const GLfloat texcoord[4],
- GLfloat rgba[4])
-{
- const GLint width = img->Width2; /* without border, power of two */
- const GLint height = img->Height2; /* without border, power of two */
- const GLint depth = img->Depth2; /* without border, power of two */
- GLint i, j, k;
- (void) ctx;
-
- i = nearest_texel_location(tObj->Sampler.WrapS, img, width, texcoord[0]);
- j = nearest_texel_location(tObj->Sampler.WrapT, img, height, texcoord[1]);
- k = nearest_texel_location(tObj->Sampler.WrapR, img, depth, texcoord[2]);
-
- if (i < 0 || i >= (GLint) img->Width ||
- j < 0 || j >= (GLint) img->Height ||
- k < 0 || k >= (GLint) img->Depth) {
- /* Need this test for GL_CLAMP_TO_BORDER mode */
- get_border_color(tObj, img, rgba);
- }
- else {
- img->FetchTexelf(img, i, j, k, rgba);
- }
-}
-
-
-/**
- * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
- */
-static void
-sample_3d_linear(struct gl_context *ctx,
- const struct gl_texture_object *tObj,
- const struct gl_texture_image *img,
- const GLfloat texcoord[4],
- GLfloat rgba[4])
-{
- const GLint width = img->Width2;
- const GLint height = img->Height2;
- const GLint depth = img->Depth2;
- GLint i0, j0, k0, i1, j1, k1;
- GLbitfield useBorderColor = 0x0;
- GLfloat a, b, c;
- GLfloat t000[4], t010[4], t001[4], t011[4];
- GLfloat t100[4], t110[4], t101[4], t111[4];
-
- linear_texel_locations(tObj->Sampler.WrapS, img, width, texcoord[0], &i0, &i1, &a);
- linear_texel_locations(tObj->Sampler.WrapT, img, height, texcoord[1], &j0, &j1, &b);
- linear_texel_locations(tObj->Sampler.WrapR, img, depth, texcoord[2], &k0, &k1, &c);
-
- if (img->Border) {
- i0 += img->Border;
- i1 += img->Border;
- j0 += img->Border;
- j1 += img->Border;
- k0 += img->Border;
- k1 += img->Border;
- }
- else {
- /* check if sampling texture border color */
- if (i0 < 0 || i0 >= width) useBorderColor |= I0BIT;
- if (i1 < 0 || i1 >= width) useBorderColor |= I1BIT;
- if (j0 < 0 || j0 >= height) useBorderColor |= J0BIT;
- if (j1 < 0 || j1 >= height) useBorderColor |= J1BIT;
- if (k0 < 0 || k0 >= depth) useBorderColor |= K0BIT;
- if (k1 < 0 || k1 >= depth) useBorderColor |= K1BIT;
- }
-
- /* Fetch texels */
- if (useBorderColor & (I0BIT | J0BIT | K0BIT)) {
- get_border_color(tObj, img, t000);
- }
- else {
- img->FetchTexelf(img, i0, j0, k0, t000);
- }
- if (useBorderColor & (I1BIT | J0BIT | K0BIT)) {
- get_border_color(tObj, img, t100);
- }
- else {
- img->FetchTexelf(img, i1, j0, k0, t100);
- }
- if (useBorderColor & (I0BIT | J1BIT | K0BIT)) {
- get_border_color(tObj, img, t010);
- }
- else {
- img->FetchTexelf(img, i0, j1, k0, t010);
- }
- if (useBorderColor & (I1BIT | J1BIT | K0BIT)) {
- get_border_color(tObj, img, t110);
- }
- else {
- img->FetchTexelf(img, i1, j1, k0, t110);
- }
-
- if (useBorderColor & (I0BIT | J0BIT | K1BIT)) {
- get_border_color(tObj, img, t001);
- }
- else {
- img->FetchTexelf(img, i0, j0, k1, t001);
- }
- if (useBorderColor & (I1BIT | J0BIT | K1BIT)) {
- get_border_color(tObj, img, t101);
- }
- else {
- img->FetchTexelf(img, i1, j0, k1, t101);
- }
- if (useBorderColor & (I0BIT | J1BIT | K1BIT)) {
- get_border_color(tObj, img, t011);
- }
- else {
- img->FetchTexelf(img, i0, j1, k1, t011);
- }
- if (useBorderColor & (I1BIT | J1BIT | K1BIT)) {
- get_border_color(tObj, img, t111);
- }
- else {
- img->FetchTexelf(img, i1, j1, k1, t111);
- }
-
- /* trilinear interpolation of samples */
- lerp_rgba_3d(rgba, a, b, c, t000, t100, t010, t110, t001, t101, t011, t111);
-}
-
-
-static void
-sample_3d_nearest_mipmap_nearest(struct gl_context *ctx,
- const struct gl_texture_object *tObj,
- GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLfloat rgba[][4] )
-{
- GLuint i;
- for (i = 0; i < n; i++) {
- GLint level = nearest_mipmap_level(tObj, lambda[i]);
- sample_3d_nearest(ctx, tObj, tObj->Image[0][level], texcoord[i], rgba[i]);
- }
-}
-
-
-static void
-sample_3d_linear_mipmap_nearest(struct gl_context *ctx,
- const struct gl_texture_object *tObj,
- GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLfloat rgba[][4])
-{
- GLuint i;
- ASSERT(lambda != NULL);
- for (i = 0; i < n; i++) {
- GLint level = nearest_mipmap_level(tObj, lambda[i]);
- sample_3d_linear(ctx, tObj, tObj->Image[0][level], texcoord[i], rgba[i]);
- }
-}
-
-
-static void
-sample_3d_nearest_mipmap_linear(struct gl_context *ctx,
- const struct gl_texture_object *tObj,
- GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLfloat rgba[][4])
-{
- GLuint i;
- ASSERT(lambda != NULL);
- for (i = 0; i < n; i++) {
- GLint level = linear_mipmap_level(tObj, lambda[i]);
- if (level >= tObj->_MaxLevel) {
- sample_3d_nearest(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
- texcoord[i], rgba[i]);
- }
- else {
- GLfloat t0[4], t1[4]; /* texels */
- const GLfloat f = FRAC(lambda[i]);
- sample_3d_nearest(ctx, tObj, tObj->Image[0][level ], texcoord[i], t0);
- sample_3d_nearest(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
- lerp_rgba(rgba[i], f, t0, t1);
- }
- }
-}
-
-
-static void
-sample_3d_linear_mipmap_linear(struct gl_context *ctx,
- const struct gl_texture_object *tObj,
- GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLfloat rgba[][4])
-{
- GLuint i;
- ASSERT(lambda != NULL);
- for (i = 0; i < n; i++) {
- GLint level = linear_mipmap_level(tObj, lambda[i]);
- if (level >= tObj->_MaxLevel) {
- sample_3d_linear(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
- texcoord[i], rgba[i]);
- }
- else {
- GLfloat t0[4], t1[4]; /* texels */
- const GLfloat f = FRAC(lambda[i]);
- sample_3d_linear(ctx, tObj, tObj->Image[0][level ], texcoord[i], t0);
- sample_3d_linear(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
- lerp_rgba(rgba[i], f, t0, t1);
- }
- }
-}
-
-
-/** Sample 3D texture, nearest filtering for both min/magnification */
-static void
-sample_nearest_3d(struct gl_context *ctx,
- const struct gl_texture_object *tObj, GLuint n,
- const GLfloat texcoords[][4], const GLfloat lambda[],
- GLfloat rgba[][4])
-{
- GLuint i;
- struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
- (void) lambda;
- for (i = 0; i < n; i++) {
- sample_3d_nearest(ctx, tObj, image, texcoords[i], rgba[i]);
- }
-}
-
-
-/** Sample 3D texture, linear filtering for both min/magnification */
-static void
-sample_linear_3d(struct gl_context *ctx,
- const struct gl_texture_object *tObj, GLuint n,
- const GLfloat texcoords[][4],
- const GLfloat lambda[], GLfloat rgba[][4])
-{
- GLuint i;
- struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
- (void) lambda;
- for (i = 0; i < n; i++) {
- sample_3d_linear(ctx, tObj, image, texcoords[i], rgba[i]);
- }
-}
-
-
-/** Sample 3D texture, using lambda to choose between min/magnification */
-static void
-sample_lambda_3d(struct gl_context *ctx,
- const struct gl_texture_object *tObj, GLuint n,
- const GLfloat texcoords[][4], const GLfloat lambda[],
- GLfloat rgba[][4])
-{
- GLuint minStart, minEnd; /* texels with minification */
- GLuint magStart, magEnd; /* texels with magnification */
- GLuint i;
-
- ASSERT(lambda != NULL);
- compute_min_mag_ranges(tObj, n, lambda,
- &minStart, &minEnd, &magStart, &magEnd);
-
- if (minStart < minEnd) {
- /* do the minified texels */
- GLuint m = minEnd - minStart;
- switch (tObj->Sampler.MinFilter) {
- case GL_NEAREST:
- for (i = minStart; i < minEnd; i++)
- sample_3d_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
- texcoords[i], rgba[i]);
- break;
- case GL_LINEAR:
- for (i = minStart; i < minEnd; i++)
- sample_3d_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
- texcoords[i], rgba[i]);
- break;
- case GL_NEAREST_MIPMAP_NEAREST:
- sample_3d_nearest_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
- lambda + minStart, rgba + minStart);
- break;
- case GL_LINEAR_MIPMAP_NEAREST:
- sample_3d_linear_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
- lambda + minStart, rgba + minStart);
- break;
- case GL_NEAREST_MIPMAP_LINEAR:
- sample_3d_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart,
- lambda + minStart, rgba + minStart);
- break;
- case GL_LINEAR_MIPMAP_LINEAR:
- sample_3d_linear_mipmap_linear(ctx, tObj, m, texcoords + minStart,
- lambda + minStart, rgba + minStart);
- break;
- default:
- _mesa_problem(ctx, "Bad min filter in sample_3d_texture");
- return;
- }
- }
-
- if (magStart < magEnd) {
- /* do the magnified texels */
- switch (tObj->Sampler.MagFilter) {
- case GL_NEAREST:
- for (i = magStart; i < magEnd; i++)
- sample_3d_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
- texcoords[i], rgba[i]);
- break;
- case GL_LINEAR:
- for (i = magStart; i < magEnd; i++)
- sample_3d_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
- texcoords[i], rgba[i]);
- break;
- default:
- _mesa_problem(ctx, "Bad mag filter in sample_3d_texture");
- return;
- }
- }
-}
-
-
-/**********************************************************************/
-/* Texture Cube Map Sampling Functions */
-/**********************************************************************/
-
-/**
- * Choose one of six sides of a texture cube map given the texture
- * coord (rx,ry,rz). Return pointer to corresponding array of texture
- * images.
- */
-static const struct gl_texture_image **
-choose_cube_face(const struct gl_texture_object *texObj,
- const GLfloat texcoord[4], GLfloat newCoord[4])
-{
- /*
- major axis
- direction target sc tc ma
- ---------- ------------------------------- --- --- ---
- +rx TEXTURE_CUBE_MAP_POSITIVE_X_EXT -rz -ry rx
- -rx TEXTURE_CUBE_MAP_NEGATIVE_X_EXT +rz -ry rx
- +ry TEXTURE_CUBE_MAP_POSITIVE_Y_EXT +rx +rz ry
- -ry TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT +rx -rz ry
- +rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz
- -rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz
- */
- const GLfloat rx = texcoord[0];
- const GLfloat ry = texcoord[1];
- const GLfloat rz = texcoord[2];
- const GLfloat arx = FABSF(rx), ary = FABSF(ry), arz = FABSF(rz);
- GLuint face;
- GLfloat sc, tc, ma;
-
- if (arx >= ary && arx >= arz) {
- if (rx >= 0.0F) {
- face = FACE_POS_X;
- sc = -rz;
- tc = -ry;
- ma = arx;
- }
- else {
- face = FACE_NEG_X;
- sc = rz;
- tc = -ry;
- ma = arx;
- }
- }
- else if (ary >= arx && ary >= arz) {
- if (ry >= 0.0F) {
- face = FACE_POS_Y;
- sc = rx;
- tc = rz;
- ma = ary;
- }
- else {
- face = FACE_NEG_Y;
- sc = rx;
- tc = -rz;
- ma = ary;
- }
- }
- else {
- if (rz > 0.0F) {
- face = FACE_POS_Z;
- sc = rx;
- tc = -ry;
- ma = arz;
- }
- else {
- face = FACE_NEG_Z;
- sc = -rx;
- tc = -ry;
- ma = arz;
- }
- }
-
- {
- const float ima = 1.0F / ma;
- newCoord[0] = ( sc * ima + 1.0F ) * 0.5F;
- newCoord[1] = ( tc * ima + 1.0F ) * 0.5F;
- }
-
- return (const struct gl_texture_image **) texObj->Image[face];
-}
-
-
-static void
-sample_nearest_cube(struct gl_context *ctx,
- const struct gl_texture_object *tObj, GLuint n,
- const GLfloat texcoords[][4], const GLfloat lambda[],
- GLfloat rgba[][4])
-{
- GLuint i;
- (void) lambda;
- for (i = 0; i < n; i++) {
- const struct gl_texture_image **images;
- GLfloat newCoord[4];
- images = choose_cube_face(tObj, texcoords[i], newCoord);
- sample_2d_nearest(ctx, tObj, images[tObj->BaseLevel],
- newCoord, rgba[i]);
- }
-}
-
-
-static void
-sample_linear_cube(struct gl_context *ctx,
- const struct gl_texture_object *tObj, GLuint n,
- const GLfloat texcoords[][4],
- const GLfloat lambda[], GLfloat rgba[][4])
-{
- GLuint i;
- (void) lambda;
- for (i = 0; i < n; i++) {
- const struct gl_texture_image **images;
- GLfloat newCoord[4];
- images = choose_cube_face(tObj, texcoords[i], newCoord);
- sample_2d_linear(ctx, tObj, images[tObj->BaseLevel],
- newCoord, rgba[i]);
- }
-}
-
-
-static void
-sample_cube_nearest_mipmap_nearest(struct gl_context *ctx,
- const struct gl_texture_object *tObj,
- GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLfloat rgba[][4])
-{
- GLuint i;
- ASSERT(lambda != NULL);
- for (i = 0; i < n; i++) {
- const struct gl_texture_image **images;
- GLfloat newCoord[4];
- GLint level;
- images = choose_cube_face(tObj, texcoord[i], newCoord);
-
- /* XXX we actually need to recompute lambda here based on the newCoords.
- * But we would need the texcoords of adjacent fragments to compute that
- * properly, and we don't have those here.
- * For now, do an approximation: subtracting 1 from the chosen mipmap
- * level seems to work in some test cases.
- * The same adjustment is done in the next few functions.
- */
- level = nearest_mipmap_level(tObj, lambda[i]);
- level = MAX2(level - 1, 0);
-
- sample_2d_nearest(ctx, tObj, images[level], newCoord, rgba[i]);
- }
-}
-
-
-static void
-sample_cube_linear_mipmap_nearest(struct gl_context *ctx,
- const struct gl_texture_object *tObj,
- GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLfloat rgba[][4])
-{
- GLuint i;
- ASSERT(lambda != NULL);
- for (i = 0; i < n; i++) {
- const struct gl_texture_image **images;
- GLfloat newCoord[4];
- GLint level = nearest_mipmap_level(tObj, lambda[i]);
- level = MAX2(level - 1, 0); /* see comment above */
- images = choose_cube_face(tObj, texcoord[i], newCoord);
- sample_2d_linear(ctx, tObj, images[level], newCoord, rgba[i]);
- }
-}
-
-
-static void
-sample_cube_nearest_mipmap_linear(struct gl_context *ctx,
- const struct gl_texture_object *tObj,
- GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLfloat rgba[][4])
-{
- GLuint i;
- ASSERT(lambda != NULL);
- for (i = 0; i < n; i++) {
- const struct gl_texture_image **images;
- GLfloat newCoord[4];
- GLint level = linear_mipmap_level(tObj, lambda[i]);
- level = MAX2(level - 1, 0); /* see comment above */
- images = choose_cube_face(tObj, texcoord[i], newCoord);
- if (level >= tObj->_MaxLevel) {
- sample_2d_nearest(ctx, tObj, images[tObj->_MaxLevel],
- newCoord, rgba[i]);
- }
- else {
- GLfloat t0[4], t1[4]; /* texels */
- const GLfloat f = FRAC(lambda[i]);
- sample_2d_nearest(ctx, tObj, images[level ], newCoord, t0);
- sample_2d_nearest(ctx, tObj, images[level+1], newCoord, t1);
- lerp_rgba(rgba[i], f, t0, t1);
- }
- }
-}
-
-
-static void
-sample_cube_linear_mipmap_linear(struct gl_context *ctx,
- const struct gl_texture_object *tObj,
- GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLfloat rgba[][4])
-{
- GLuint i;
- ASSERT(lambda != NULL);
- for (i = 0; i < n; i++) {
- const struct gl_texture_image **images;
- GLfloat newCoord[4];
- GLint level = linear_mipmap_level(tObj, lambda[i]);
- level = MAX2(level - 1, 0); /* see comment above */
- images = choose_cube_face(tObj, texcoord[i], newCoord);
- if (level >= tObj->_MaxLevel) {
- sample_2d_linear(ctx, tObj, images[tObj->_MaxLevel],
- newCoord, rgba[i]);
- }
- else {
- GLfloat t0[4], t1[4];
- const GLfloat f = FRAC(lambda[i]);
- sample_2d_linear(ctx, tObj, images[level ], newCoord, t0);
- sample_2d_linear(ctx, tObj, images[level+1], newCoord, t1);
- lerp_rgba(rgba[i], f, t0, t1);
- }
- }
-}
-
-
-/** Sample cube texture, using lambda to choose between min/magnification */
-static void
-sample_lambda_cube(struct gl_context *ctx,
- const struct gl_texture_object *tObj, GLuint n,
- const GLfloat texcoords[][4], const GLfloat lambda[],
- GLfloat rgba[][4])
-{
- GLuint minStart, minEnd; /* texels with minification */
- GLuint magStart, magEnd; /* texels with magnification */
-
- ASSERT(lambda != NULL);
- compute_min_mag_ranges(tObj, n, lambda,
- &minStart, &minEnd, &magStart, &magEnd);
-
- if (minStart < minEnd) {
- /* do the minified texels */
- const GLuint m = minEnd - minStart;
- switch (tObj->Sampler.MinFilter) {
- case GL_NEAREST:
- sample_nearest_cube(ctx, tObj, m, texcoords + minStart,
- lambda + minStart, rgba + minStart);
- break;
- case GL_LINEAR:
- sample_linear_cube(ctx, tObj, m, texcoords + minStart,
- lambda + minStart, rgba + minStart);
- break;
- case GL_NEAREST_MIPMAP_NEAREST:
- sample_cube_nearest_mipmap_nearest(ctx, tObj, m,
- texcoords + minStart,
- lambda + minStart, rgba + minStart);
- break;
- case GL_LINEAR_MIPMAP_NEAREST:
- sample_cube_linear_mipmap_nearest(ctx, tObj, m,
- texcoords + minStart,
- lambda + minStart, rgba + minStart);
- break;
- case GL_NEAREST_MIPMAP_LINEAR:
- sample_cube_nearest_mipmap_linear(ctx, tObj, m,
- texcoords + minStart,
- lambda + minStart, rgba + minStart);
- break;
- case GL_LINEAR_MIPMAP_LINEAR:
- sample_cube_linear_mipmap_linear(ctx, tObj, m,
- texcoords + minStart,
- lambda + minStart, rgba + minStart);
- break;
- default:
- _mesa_problem(ctx, "Bad min filter in sample_lambda_cube");
- }
- }
-
- if (magStart < magEnd) {
- /* do the magnified texels */
- const GLuint m = magEnd - magStart;
- switch (tObj->Sampler.MagFilter) {
- case GL_NEAREST:
- sample_nearest_cube(ctx, tObj, m, texcoords + magStart,
- lambda + magStart, rgba + magStart);
- break;
- case GL_LINEAR:
- sample_linear_cube(ctx, tObj, m, texcoords + magStart,
- lambda + magStart, rgba + magStart);
- break;
- default:
- _mesa_problem(ctx, "Bad mag filter in sample_lambda_cube");
- }
- }
-}
-
-
-/**********************************************************************/
-/* Texture Rectangle Sampling Functions */
-/**********************************************************************/
-
-
-static void
-sample_nearest_rect(struct gl_context *ctx,
- const struct gl_texture_object *tObj, GLuint n,
- const GLfloat texcoords[][4], const GLfloat lambda[],
- GLfloat rgba[][4])
-{
- const struct gl_texture_image *img = tObj->Image[0][0];
- const GLint width = img->Width;
- const GLint height = img->Height;
- GLuint i;
-
- (void) ctx;
- (void) lambda;
-
- ASSERT(tObj->Sampler.WrapS == GL_CLAMP ||
- tObj->Sampler.WrapS == GL_CLAMP_TO_EDGE ||
- tObj->Sampler.WrapS == GL_CLAMP_TO_BORDER);
- ASSERT(tObj->Sampler.WrapT == GL_CLAMP ||
- tObj->Sampler.WrapT == GL_CLAMP_TO_EDGE ||
- tObj->Sampler.WrapT == GL_CLAMP_TO_BORDER);
- ASSERT(img->_BaseFormat != GL_COLOR_INDEX);
-
- for (i = 0; i < n; i++) {
- GLint row, col;
- col = clamp_rect_coord_nearest(tObj->Sampler.WrapS, texcoords[i][0], width);
- row = clamp_rect_coord_nearest(tObj->Sampler.WrapT, texcoords[i][1], height);
- if (col < 0 || col >= width || row < 0 || row >= height)
- get_border_color(tObj, img, rgba[i]);
- else
- img->FetchTexelf(img, col, row, 0, rgba[i]);
- }
-}
-
-
-static void
-sample_linear_rect(struct gl_context *ctx,
- const struct gl_texture_object *tObj, GLuint n,
- const GLfloat texcoords[][4],
- const GLfloat lambda[], GLfloat rgba[][4])
-{
- const struct gl_texture_image *img = tObj->Image[0][0];
- const GLint width = img->Width;
- const GLint height = img->Height;
- GLuint i;
-
- (void) ctx;
- (void) lambda;
-
- ASSERT(tObj->Sampler.WrapS == GL_CLAMP ||
- tObj->Sampler.WrapS == GL_CLAMP_TO_EDGE ||
- tObj->Sampler.WrapS == GL_CLAMP_TO_BORDER);
- ASSERT(tObj->Sampler.WrapT == GL_CLAMP ||
- tObj->Sampler.WrapT == GL_CLAMP_TO_EDGE ||
- tObj->Sampler.WrapT == GL_CLAMP_TO_BORDER);
- ASSERT(img->_BaseFormat != GL_COLOR_INDEX);
-
- for (i = 0; i < n; i++) {
- GLint i0, j0, i1, j1;
- GLfloat t00[4], t01[4], t10[4], t11[4];
- GLfloat a, b;
- GLbitfield useBorderColor = 0x0;
-
- clamp_rect_coord_linear(tObj->Sampler.WrapS, texcoords[i][0], width,
- &i0, &i1, &a);
- clamp_rect_coord_linear(tObj->Sampler.WrapT, texcoords[i][1], height,
- &j0, &j1, &b);
-
- /* compute integer rows/columns */
- if (i0 < 0 || i0 >= width) useBorderColor |= I0BIT;
- if (i1 < 0 || i1 >= width) useBorderColor |= I1BIT;
- if (j0 < 0 || j0 >= height) useBorderColor |= J0BIT;
- if (j1 < 0 || j1 >= height) useBorderColor |= J1BIT;
-
- /* get four texel samples */
- if (useBorderColor & (I0BIT | J0BIT))
- get_border_color(tObj, img, t00);
- else
- img->FetchTexelf(img, i0, j0, 0, t00);
-
- if (useBorderColor & (I1BIT | J0BIT))
- get_border_color(tObj, img, t10);
- else
- img->FetchTexelf(img, i1, j0, 0, t10);
-
- if (useBorderColor & (I0BIT | J1BIT))
- get_border_color(tObj, img, t01);
- else
- img->FetchTexelf(img, i0, j1, 0, t01);
-
- if (useBorderColor & (I1BIT | J1BIT))
- get_border_color(tObj, img, t11);
- else
- img->FetchTexelf(img, i1, j1, 0, t11);
-
- lerp_rgba_2d(rgba[i], a, b, t00, t10, t01, t11);
- }
-}
-
-
-/** Sample Rect texture, using lambda to choose between min/magnification */
-static void
-sample_lambda_rect(struct gl_context *ctx,
- const struct gl_texture_object *tObj, GLuint n,
- const GLfloat texcoords[][4], const GLfloat lambda[],
- GLfloat rgba[][4])
-{
- GLuint minStart, minEnd, magStart, magEnd;
-
- /* We only need lambda to decide between minification and magnification.
- * There is no mipmapping with rectangular textures.
- */
- compute_min_mag_ranges(tObj, n, lambda,
- &minStart, &minEnd, &magStart, &magEnd);
-
- if (minStart < minEnd) {
- if (tObj->Sampler.MinFilter == GL_NEAREST) {
- sample_nearest_rect(ctx, tObj, minEnd - minStart,
- texcoords + minStart, NULL, rgba + minStart);
- }
- else {
- sample_linear_rect(ctx, tObj, minEnd - minStart,
- texcoords + minStart, NULL, rgba + minStart);
- }
- }
- if (magStart < magEnd) {
- if (tObj->Sampler.MagFilter == GL_NEAREST) {
- sample_nearest_rect(ctx, tObj, magEnd - magStart,
- texcoords + magStart, NULL, rgba + magStart);
- }
- else {
- sample_linear_rect(ctx, tObj, magEnd - magStart,
- texcoords + magStart, NULL, rgba + magStart);
- }
- }
-}
-
-
-/**********************************************************************/
-/* 2D Texture Array Sampling Functions */
-/**********************************************************************/
-
-/**
- * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
- */
-static void
-sample_2d_array_nearest(struct gl_context *ctx,
- const struct gl_texture_object *tObj,
- const struct gl_texture_image *img,
- const GLfloat texcoord[4],
- GLfloat rgba[4])
-{
- const GLint width = img->Width2; /* without border, power of two */
- const GLint height = img->Height2; /* without border, power of two */
- const GLint depth = img->Depth;
- GLint i, j;
- GLint array;
- (void) ctx;
-
- i = nearest_texel_location(tObj->Sampler.WrapS, img, width, texcoord[0]);
- j = nearest_texel_location(tObj->Sampler.WrapT, img, height, texcoord[1]);
- array = tex_array_slice(texcoord[2], depth);
-
- if (i < 0 || i >= (GLint) img->Width ||
- j < 0 || j >= (GLint) img->Height ||
- array < 0 || array >= (GLint) img->Depth) {
- /* Need this test for GL_CLAMP_TO_BORDER mode */
- get_border_color(tObj, img, rgba);
- }
- else {
- img->FetchTexelf(img, i, j, array, rgba);
- }
-}
-
-
-/**
- * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
- */
-static void
-sample_2d_array_linear(struct gl_context *ctx,
- const struct gl_texture_object *tObj,
- const struct gl_texture_image *img,
- const GLfloat texcoord[4],
- GLfloat rgba[4])
-{
- const GLint width = img->Width2;
- const GLint height = img->Height2;
- const GLint depth = img->Depth;
- GLint i0, j0, i1, j1;
- GLint array;
- GLbitfield useBorderColor = 0x0;
- GLfloat a, b;
- GLfloat t00[4], t01[4], t10[4], t11[4];
-
- linear_texel_locations(tObj->Sampler.WrapS, img, width, texcoord[0], &i0, &i1, &a);
- linear_texel_locations(tObj->Sampler.WrapT, img, height, texcoord[1], &j0, &j1, &b);
- array = tex_array_slice(texcoord[2], depth);
-
- if (array < 0 || array >= depth) {
- COPY_4V(rgba, tObj->Sampler.BorderColor.f);
- }
- else {
- if (img->Border) {
- i0 += img->Border;
- i1 += img->Border;
- j0 += img->Border;
- j1 += img->Border;
- }
- else {
- /* check if sampling texture border color */
- if (i0 < 0 || i0 >= width) useBorderColor |= I0BIT;
- if (i1 < 0 || i1 >= width) useBorderColor |= I1BIT;
- if (j0 < 0 || j0 >= height) useBorderColor |= J0BIT;
- if (j1 < 0 || j1 >= height) useBorderColor |= J1BIT;
- }
-
- /* Fetch texels */
- if (useBorderColor & (I0BIT | J0BIT)) {
- get_border_color(tObj, img, t00);
- }
- else {
- img->FetchTexelf(img, i0, j0, array, t00);
- }
- if (useBorderColor & (I1BIT | J0BIT)) {
- get_border_color(tObj, img, t10);
- }
- else {
- img->FetchTexelf(img, i1, j0, array, t10);
- }
- if (useBorderColor & (I0BIT | J1BIT)) {
- get_border_color(tObj, img, t01);
- }
- else {
- img->FetchTexelf(img, i0, j1, array, t01);
- }
- if (useBorderColor & (I1BIT | J1BIT)) {
- get_border_color(tObj, img, t11);
- }
- else {
- img->FetchTexelf(img, i1, j1, array, t11);
- }
-
- /* trilinear interpolation of samples */
- lerp_rgba_2d(rgba, a, b, t00, t10, t01, t11);
- }
-}
-
-
-static void
-sample_2d_array_nearest_mipmap_nearest(struct gl_context *ctx,
- const struct gl_texture_object *tObj,
- GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLfloat rgba[][4])
-{
- GLuint i;
- for (i = 0; i < n; i++) {
- GLint level = nearest_mipmap_level(tObj, lambda[i]);
- sample_2d_array_nearest(ctx, tObj, tObj->Image[0][level], texcoord[i],
- rgba[i]);
- }
-}
-
-
-static void
-sample_2d_array_linear_mipmap_nearest(struct gl_context *ctx,
- const struct gl_texture_object *tObj,
- GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLfloat rgba[][4])
-{
- GLuint i;
- ASSERT(lambda != NULL);
- for (i = 0; i < n; i++) {
- GLint level = nearest_mipmap_level(tObj, lambda[i]);
- sample_2d_array_linear(ctx, tObj, tObj->Image[0][level],
- texcoord[i], rgba[i]);
- }
-}
-
-
-static void
-sample_2d_array_nearest_mipmap_linear(struct gl_context *ctx,
- const struct gl_texture_object *tObj,
- GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLfloat rgba[][4])
-{
- GLuint i;
- ASSERT(lambda != NULL);
- for (i = 0; i < n; i++) {
- GLint level = linear_mipmap_level(tObj, lambda[i]);
- if (level >= tObj->_MaxLevel) {
- sample_2d_array_nearest(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
- texcoord[i], rgba[i]);
- }
- else {
- GLfloat t0[4], t1[4]; /* texels */
- const GLfloat f = FRAC(lambda[i]);
- sample_2d_array_nearest(ctx, tObj, tObj->Image[0][level ],
- texcoord[i], t0);
- sample_2d_array_nearest(ctx, tObj, tObj->Image[0][level+1],
- texcoord[i], t1);
- lerp_rgba(rgba[i], f, t0, t1);
- }
- }
-}
-
-
-static void
-sample_2d_array_linear_mipmap_linear(struct gl_context *ctx,
- const struct gl_texture_object *tObj,
- GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLfloat rgba[][4])
-{
- GLuint i;
- ASSERT(lambda != NULL);
- for (i = 0; i < n; i++) {
- GLint level = linear_mipmap_level(tObj, lambda[i]);
- if (level >= tObj->_MaxLevel) {
- sample_2d_array_linear(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
- texcoord[i], rgba[i]);
- }
- else {
- GLfloat t0[4], t1[4]; /* texels */
- const GLfloat f = FRAC(lambda[i]);
- sample_2d_array_linear(ctx, tObj, tObj->Image[0][level ],
- texcoord[i], t0);
- sample_2d_array_linear(ctx, tObj, tObj->Image[0][level+1],
- texcoord[i], t1);
- lerp_rgba(rgba[i], f, t0, t1);
- }
- }
-}
-
-
-/** Sample 2D Array texture, nearest filtering for both min/magnification */
-static void
-sample_nearest_2d_array(struct gl_context *ctx,
- const struct gl_texture_object *tObj, GLuint n,
- const GLfloat texcoords[][4], const GLfloat lambda[],
- GLfloat rgba[][4])
-{
- GLuint i;
- struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
- (void) lambda;
- for (i = 0; i < n; i++) {
- sample_2d_array_nearest(ctx, tObj, image, texcoords[i], rgba[i]);
- }
-}
-
-
-
-/** Sample 2D Array texture, linear filtering for both min/magnification */
-static void
-sample_linear_2d_array(struct gl_context *ctx,
- const struct gl_texture_object *tObj, GLuint n,
- const GLfloat texcoords[][4],
- const GLfloat lambda[], GLfloat rgba[][4])
-{
- GLuint i;
- struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
- (void) lambda;
- for (i = 0; i < n; i++) {
- sample_2d_array_linear(ctx, tObj, image, texcoords[i], rgba[i]);
- }
-}
-
-
-/** Sample 2D Array texture, using lambda to choose between min/magnification */
-static void
-sample_lambda_2d_array(struct gl_context *ctx,
- const struct gl_texture_object *tObj, GLuint n,
- const GLfloat texcoords[][4], const GLfloat lambda[],
- GLfloat rgba[][4])
-{
- GLuint minStart, minEnd; /* texels with minification */
- GLuint magStart, magEnd; /* texels with magnification */
- GLuint i;
-
- ASSERT(lambda != NULL);
- compute_min_mag_ranges(tObj, n, lambda,
- &minStart, &minEnd, &magStart, &magEnd);
-
- if (minStart < minEnd) {
- /* do the minified texels */
- GLuint m = minEnd - minStart;
- switch (tObj->Sampler.MinFilter) {
- case GL_NEAREST:
- for (i = minStart; i < minEnd; i++)
- sample_2d_array_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
- texcoords[i], rgba[i]);
- break;
- case GL_LINEAR:
- for (i = minStart; i < minEnd; i++)
- sample_2d_array_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
- texcoords[i], rgba[i]);
- break;
- case GL_NEAREST_MIPMAP_NEAREST:
- sample_2d_array_nearest_mipmap_nearest(ctx, tObj, m,
- texcoords + minStart,
- lambda + minStart,
- rgba + minStart);
- break;
- case GL_LINEAR_MIPMAP_NEAREST:
- sample_2d_array_linear_mipmap_nearest(ctx, tObj, m,
- texcoords + minStart,
- lambda + minStart,
- rgba + minStart);
- break;
- case GL_NEAREST_MIPMAP_LINEAR:
- sample_2d_array_nearest_mipmap_linear(ctx, tObj, m,
- texcoords + minStart,
- lambda + minStart,
- rgba + minStart);
- break;
- case GL_LINEAR_MIPMAP_LINEAR:
- sample_2d_array_linear_mipmap_linear(ctx, tObj, m,
- texcoords + minStart,
- lambda + minStart,
- rgba + minStart);
- break;
- default:
- _mesa_problem(ctx, "Bad min filter in sample_2d_array_texture");
- return;
- }
- }
-
- if (magStart < magEnd) {
- /* do the magnified texels */
- switch (tObj->Sampler.MagFilter) {
- case GL_NEAREST:
- for (i = magStart; i < magEnd; i++)
- sample_2d_array_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
- texcoords[i], rgba[i]);
- break;
- case GL_LINEAR:
- for (i = magStart; i < magEnd; i++)
- sample_2d_array_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
- texcoords[i], rgba[i]);
- break;
- default:
- _mesa_problem(ctx, "Bad mag filter in sample_2d_array_texture");
- return;
- }
- }
-}
-
-
-
-
-/**********************************************************************/
-/* 1D Texture Array Sampling Functions */
-/**********************************************************************/
-
-/**
- * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
- */
-static void
-sample_1d_array_nearest(struct gl_context *ctx,
- const struct gl_texture_object *tObj,
- const struct gl_texture_image *img,
- const GLfloat texcoord[4],
- GLfloat rgba[4])
-{
- const GLint width = img->Width2; /* without border, power of two */
- const GLint height = img->Height;
- GLint i;
- GLint array;
- (void) ctx;
-
- i = nearest_texel_location(tObj->Sampler.WrapS, img, width, texcoord[0]);
- array = tex_array_slice(texcoord[1], height);
-
- if (i < 0 || i >= (GLint) img->Width ||
- array < 0 || array >= (GLint) img->Height) {
- /* Need this test for GL_CLAMP_TO_BORDER mode */
- get_border_color(tObj, img, rgba);
- }
- else {
- img->FetchTexelf(img, i, array, 0, rgba);
- }
-}
-
-
-/**
- * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
- */
-static void
-sample_1d_array_linear(struct gl_context *ctx,
- const struct gl_texture_object *tObj,
- const struct gl_texture_image *img,
- const GLfloat texcoord[4],
- GLfloat rgba[4])
-{
- const GLint width = img->Width2;
- const GLint height = img->Height;
- GLint i0, i1;
- GLint array;
- GLbitfield useBorderColor = 0x0;
- GLfloat a;
- GLfloat t0[4], t1[4];
-
- linear_texel_locations(tObj->Sampler.WrapS, img, width, texcoord[0], &i0, &i1, &a);
- array = tex_array_slice(texcoord[1], height);
-
- if (img->Border) {
- i0 += img->Border;
- i1 += img->Border;
- }
- else {
- /* check if sampling texture border color */
- if (i0 < 0 || i0 >= width) useBorderColor |= I0BIT;
- if (i1 < 0 || i1 >= width) useBorderColor |= I1BIT;
- }
-
- if (array < 0 || array >= height) useBorderColor |= K0BIT;
-
- /* Fetch texels */
- if (useBorderColor & (I0BIT | K0BIT)) {
- get_border_color(tObj, img, t0);
- }
- else {
- img->FetchTexelf(img, i0, array, 0, t0);
- }
- if (useBorderColor & (I1BIT | K0BIT)) {
- get_border_color(tObj, img, t1);
- }
- else {
- img->FetchTexelf(img, i1, array, 0, t1);
- }
-
- /* bilinear interpolation of samples */
- lerp_rgba(rgba, a, t0, t1);
-}
-
-
-static void
-sample_1d_array_nearest_mipmap_nearest(struct gl_context *ctx,
- const struct gl_texture_object *tObj,
- GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLfloat rgba[][4])
-{
- GLuint i;
- for (i = 0; i < n; i++) {
- GLint level = nearest_mipmap_level(tObj, lambda[i]);
- sample_1d_array_nearest(ctx, tObj, tObj->Image[0][level], texcoord[i],
- rgba[i]);
- }
-}
-
-
-static void
-sample_1d_array_linear_mipmap_nearest(struct gl_context *ctx,
- const struct gl_texture_object *tObj,
- GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLfloat rgba[][4])
-{
- GLuint i;
- ASSERT(lambda != NULL);
- for (i = 0; i < n; i++) {
- GLint level = nearest_mipmap_level(tObj, lambda[i]);
- sample_1d_array_linear(ctx, tObj, tObj->Image[0][level],
- texcoord[i], rgba[i]);
- }
-}
-
-
-static void
-sample_1d_array_nearest_mipmap_linear(struct gl_context *ctx,
- const struct gl_texture_object *tObj,
- GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLfloat rgba[][4])
-{
- GLuint i;
- ASSERT(lambda != NULL);
- for (i = 0; i < n; i++) {
- GLint level = linear_mipmap_level(tObj, lambda[i]);
- if (level >= tObj->_MaxLevel) {
- sample_1d_array_nearest(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
- texcoord[i], rgba[i]);
- }
- else {
- GLfloat t0[4], t1[4]; /* texels */
- const GLfloat f = FRAC(lambda[i]);
- sample_1d_array_nearest(ctx, tObj, tObj->Image[0][level ], texcoord[i], t0);
- sample_1d_array_nearest(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
- lerp_rgba(rgba[i], f, t0, t1);
- }
- }
-}
-
-
-static void
-sample_1d_array_linear_mipmap_linear(struct gl_context *ctx,
- const struct gl_texture_object *tObj,
- GLuint n, const GLfloat texcoord[][4],
- const GLfloat lambda[], GLfloat rgba[][4])
-{
- GLuint i;
- ASSERT(lambda != NULL);
- for (i = 0; i < n; i++) {
- GLint level = linear_mipmap_level(tObj, lambda[i]);
- if (level >= tObj->_MaxLevel) {
- sample_1d_array_linear(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
- texcoord[i], rgba[i]);
- }
- else {
- GLfloat t0[4], t1[4]; /* texels */
- const GLfloat f = FRAC(lambda[i]);
- sample_1d_array_linear(ctx, tObj, tObj->Image[0][level ], texcoord[i], t0);
- sample_1d_array_linear(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
- lerp_rgba(rgba[i], f, t0, t1);
- }
- }
-}
-
-
-/** Sample 1D Array texture, nearest filtering for both min/magnification */
-static void
-sample_nearest_1d_array(struct gl_context *ctx,
- const struct gl_texture_object *tObj, GLuint n,
- const GLfloat texcoords[][4], const GLfloat lambda[],
- GLfloat rgba[][4])
-{
- GLuint i;
- struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
- (void) lambda;
- for (i = 0; i < n; i++) {
- sample_1d_array_nearest(ctx, tObj, image, texcoords[i], rgba[i]);
- }
-}
-
-
-/** Sample 1D Array texture, linear filtering for both min/magnification */
-static void
-sample_linear_1d_array(struct gl_context *ctx,
- const struct gl_texture_object *tObj, GLuint n,
- const GLfloat texcoords[][4],
- const GLfloat lambda[], GLfloat rgba[][4])
-{
- GLuint i;
- struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
- (void) lambda;
- for (i = 0; i < n; i++) {
- sample_1d_array_linear(ctx, tObj, image, texcoords[i], rgba[i]);
- }
-}
-
-
-/** Sample 1D Array texture, using lambda to choose between min/magnification */
-static void
-sample_lambda_1d_array(struct gl_context *ctx,
- const struct gl_texture_object *tObj, GLuint n,
- const GLfloat texcoords[][4], const GLfloat lambda[],
- GLfloat rgba[][4])
-{
- GLuint minStart, minEnd; /* texels with minification */
- GLuint magStart, magEnd; /* texels with magnification */
- GLuint i;
-
- ASSERT(lambda != NULL);
- compute_min_mag_ranges(tObj, n, lambda,
- &minStart, &minEnd, &magStart, &magEnd);
-
- if (minStart < minEnd) {
- /* do the minified texels */
- GLuint m = minEnd - minStart;
- switch (tObj->Sampler.MinFilter) {
- case GL_NEAREST:
- for (i = minStart; i < minEnd; i++)
- sample_1d_array_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
- texcoords[i], rgba[i]);
- break;
- case GL_LINEAR:
- for (i = minStart; i < minEnd; i++)
- sample_1d_array_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
- texcoords[i], rgba[i]);
- break;
- case GL_NEAREST_MIPMAP_NEAREST:
- sample_1d_array_nearest_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
- lambda + minStart, rgba + minStart);
- break;
- case GL_LINEAR_MIPMAP_NEAREST:
- sample_1d_array_linear_mipmap_nearest(ctx, tObj, m,
- texcoords + minStart,
- lambda + minStart,
- rgba + minStart);
- break;
- case GL_NEAREST_MIPMAP_LINEAR:
- sample_1d_array_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart,
- lambda + minStart, rgba + minStart);
- break;
- case GL_LINEAR_MIPMAP_LINEAR:
- sample_1d_array_linear_mipmap_linear(ctx, tObj, m,
- texcoords + minStart,
- lambda + minStart,
- rgba + minStart);
- break;
- default:
- _mesa_problem(ctx, "Bad min filter in sample_1d_array_texture");
- return;
- }
- }
-
- if (magStart < magEnd) {
- /* do the magnified texels */
- switch (tObj->Sampler.MagFilter) {
- case GL_NEAREST:
- for (i = magStart; i < magEnd; i++)
- sample_1d_array_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
- texcoords[i], rgba[i]);
- break;
- case GL_LINEAR:
- for (i = magStart; i < magEnd; i++)
- sample_1d_array_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
- texcoords[i], rgba[i]);
- break;
- default:
- _mesa_problem(ctx, "Bad mag filter in sample_1d_array_texture");
- return;
- }
- }
-}
-
-
-/**
- * Compare texcoord against depth sample. Return 1.0 or the ambient value.
- */
-static INLINE GLfloat
-shadow_compare(GLenum function, GLfloat coord, GLfloat depthSample,
- GLfloat ambient)
-{
- switch (function) {
- case GL_LEQUAL:
- return (coord <= depthSample) ? 1.0F : ambient;
- case GL_GEQUAL:
- return (coord >= depthSample) ? 1.0F : ambient;
- case GL_LESS:
- return (coord < depthSample) ? 1.0F : ambient;
- case GL_GREATER:
- return (coord > depthSample) ? 1.0F : ambient;
- case GL_EQUAL:
- return (coord == depthSample) ? 1.0F : ambient;
- case GL_NOTEQUAL:
- return (coord != depthSample) ? 1.0F : ambient;
- case GL_ALWAYS:
- return 1.0F;
- case GL_NEVER:
- return ambient;
- case GL_NONE:
- return depthSample;
- default:
- _mesa_problem(NULL, "Bad compare func in shadow_compare");
- return ambient;
- }
-}
-
-
-/**
- * Compare texcoord against four depth samples.
- */
-static INLINE GLfloat
-shadow_compare4(GLenum function, GLfloat coord,
- GLfloat depth00, GLfloat depth01,
- GLfloat depth10, GLfloat depth11,
- GLfloat ambient, GLfloat wi, GLfloat wj)
-{
- const GLfloat d = (1.0F - (GLfloat) ambient) * 0.25F;
- GLfloat luminance = 1.0F;
-
- switch (function) {
- case GL_LEQUAL:
- if (coord > depth00) luminance -= d;
- if (coord > depth01) luminance -= d;
- if (coord > depth10) luminance -= d;
- if (coord > depth11) luminance -= d;
- return luminance;
- case GL_GEQUAL:
- if (coord < depth00) luminance -= d;
- if (coord < depth01) luminance -= d;
- if (coord < depth10) luminance -= d;
- if (coord < depth11) luminance -= d;
- return luminance;
- case GL_LESS:
- if (coord >= depth00) luminance -= d;
- if (coord >= depth01) luminance -= d;
- if (coord >= depth10) luminance -= d;
- if (coord >= depth11) luminance -= d;
- return luminance;
- case GL_GREATER:
- if (coord <= depth00) luminance -= d;
- if (coord <= depth01) luminance -= d;
- if (coord <= depth10) luminance -= d;
- if (coord <= depth11) luminance -= d;
- return luminance;
- case GL_EQUAL:
- if (coord != depth00) luminance -= d;
- if (coord != depth01) luminance -= d;
- if (coord != depth10) luminance -= d;
- if (coord != depth11) luminance -= d;
- return luminance;
- case GL_NOTEQUAL:
- if (coord == depth00) luminance -= d;
- if (coord == depth01) luminance -= d;
- if (coord == depth10) luminance -= d;
- if (coord == depth11) luminance -= d;
- return luminance;
- case GL_ALWAYS:
- return 1.0F;
- case GL_NEVER:
- return ambient;
- case GL_NONE:
- /* ordinary bilinear filtering */
- return lerp_2d(wi, wj, depth00, depth10, depth01, depth11);
- default:
- _mesa_problem(NULL, "Bad compare func in sample_compare4");
- return ambient;
- }
-}
-
-
-/**
- * Choose the mipmap level to use when sampling from a depth texture.
- */
-static int
-choose_depth_texture_level(const struct gl_texture_object *tObj, GLfloat lambda)
-{
- GLint level;
-
- if (tObj->Sampler.MinFilter == GL_NEAREST || tObj->Sampler.MinFilter == GL_LINEAR) {
- /* no mipmapping - use base level */
- level = tObj->BaseLevel;
- }
- else {
- /* choose mipmap level */
- lambda = CLAMP(lambda, tObj->Sampler.MinLod, tObj->Sampler.MaxLod);
- level = (GLint) lambda;
- level = CLAMP(level, tObj->BaseLevel, tObj->_MaxLevel);
- }
-
- return level;
-}
-
-
-/**
- * Sample a shadow/depth texture. This function is incomplete. It doesn't
- * check for minification vs. magnification, etc.
- */
-static void
-sample_depth_texture( struct gl_context *ctx,
- const struct gl_texture_object *tObj, GLuint n,
- const GLfloat texcoords[][4], const GLfloat lambda[],
- GLfloat texel[][4] )
-{
- const GLint level = choose_depth_texture_level(tObj, lambda[0]);
- const struct gl_texture_image *img = tObj->Image[0][level];
- const GLint width = img->Width;
- const GLint height = img->Height;
- const GLint depth = img->Depth;
- const GLuint compare_coord = (tObj->Target == GL_TEXTURE_2D_ARRAY_EXT)
- ? 3 : 2;
- GLfloat ambient;
- GLenum function;
- GLfloat result;
-
- ASSERT(img->_BaseFormat == GL_DEPTH_COMPONENT ||
- img->_BaseFormat == GL_DEPTH_STENCIL_EXT);
-
- ASSERT(tObj->Target == GL_TEXTURE_1D ||
- tObj->Target == GL_TEXTURE_2D ||
- tObj->Target == GL_TEXTURE_RECTANGLE_NV ||
- tObj->Target == GL_TEXTURE_1D_ARRAY_EXT ||
- tObj->Target == GL_TEXTURE_2D_ARRAY_EXT);
-
- ambient = tObj->Sampler.CompareFailValue;
-
- /* XXXX if tObj->Sampler.MinFilter != tObj->Sampler.MagFilter, we're ignoring lambda */
-
- function = (tObj->Sampler.CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB) ?
- tObj->Sampler.CompareFunc : GL_NONE;
-
- if (tObj->Sampler.MagFilter == GL_NEAREST) {
- GLuint i;
- for (i = 0; i < n; i++) {
- GLfloat depthSample, depthRef;
- GLint col, row, slice;
-
- nearest_texcoord(tObj, level, texcoords[i], &col, &row, &slice);
-
- if (col >= 0 && row >= 0 && col < width && row < height &&
- slice >= 0 && slice < depth) {
- img->FetchTexelf(img, col, row, slice, &depthSample);
- }
- else {
- depthSample = tObj->Sampler.BorderColor.f[0];
- }
-
- depthRef = CLAMP(texcoords[i][compare_coord], 0.0F, 1.0F);
-
- result = shadow_compare(function, depthRef, depthSample, ambient);
-
- switch (tObj->Sampler.DepthMode) {
- case GL_LUMINANCE:
- ASSIGN_4V(texel[i], result, result, result, 1.0F);
- break;
- case GL_INTENSITY:
- ASSIGN_4V(texel[i], result, result, result, result);
- break;
- case GL_ALPHA:
- ASSIGN_4V(texel[i], 0.0F, 0.0F, 0.0F, result);
- break;
- case GL_RED:
- ASSIGN_4V(texel[i], result, 0.0F, 0.0F, 1.0F);
- break;
- default:
- _mesa_problem(ctx, "Bad depth texture mode");
- }
- }
- }
- else {
- GLuint i;
- ASSERT(tObj->Sampler.MagFilter == GL_LINEAR);
- for (i = 0; i < n; i++) {
- GLfloat depth00, depth01, depth10, depth11, depthRef;
- GLint i0, i1, j0, j1;
- GLint slice;
- GLfloat wi, wj;
- GLuint useBorderTexel;
-
- linear_texcoord(tObj, level, texcoords[i], &i0, &i1, &j0, &j1, &slice,
- &wi, &wj);
-
- useBorderTexel = 0;
- if (img->Border) {
- i0 += img->Border;
- i1 += img->Border;
- if (tObj->Target != GL_TEXTURE_1D_ARRAY_EXT) {
- j0 += img->Border;
- j1 += img->Border;
- }
- }
- else {
- if (i0 < 0 || i0 >= (GLint) width) useBorderTexel |= I0BIT;
- if (i1 < 0 || i1 >= (GLint) width) useBorderTexel |= I1BIT;
- if (j0 < 0 || j0 >= (GLint) height) useBorderTexel |= J0BIT;
- if (j1 < 0 || j1 >= (GLint) height) useBorderTexel |= J1BIT;
- }
-
- if (slice < 0 || slice >= (GLint) depth) {
- depth00 = tObj->Sampler.BorderColor.f[0];
- depth01 = tObj->Sampler.BorderColor.f[0];
- depth10 = tObj->Sampler.BorderColor.f[0];
- depth11 = tObj->Sampler.BorderColor.f[0];
- }
- else {
- /* get four depth samples from the texture */
- if (useBorderTexel & (I0BIT | J0BIT)) {
- depth00 = tObj->Sampler.BorderColor.f[0];
- }
- else {
- img->FetchTexelf(img, i0, j0, slice, &depth00);
- }
- if (useBorderTexel & (I1BIT | J0BIT)) {
- depth10 = tObj->Sampler.BorderColor.f[0];
- }
- else {
- img->FetchTexelf(img, i1, j0, slice, &depth10);
- }
-
- if (tObj->Target != GL_TEXTURE_1D_ARRAY_EXT) {
- if (useBorderTexel & (I0BIT | J1BIT)) {
- depth01 = tObj->Sampler.BorderColor.f[0];
- }
- else {
- img->FetchTexelf(img, i0, j1, slice, &depth01);
- }
- if (useBorderTexel & (I1BIT | J1BIT)) {
- depth11 = tObj->Sampler.BorderColor.f[0];
- }
- else {
- img->FetchTexelf(img, i1, j1, slice, &depth11);
- }
- }
- else {
- depth01 = depth00;
- depth11 = depth10;
- }
- }
-
- depthRef = CLAMP(texcoords[i][compare_coord], 0.0F, 1.0F);
-
- result = shadow_compare4(function, depthRef,
- depth00, depth01, depth10, depth11,
- ambient, wi, wj);
-
- switch (tObj->Sampler.DepthMode) {
- case GL_LUMINANCE:
- ASSIGN_4V(texel[i], result, result, result, 1.0F);
- break;
- case GL_INTENSITY:
- ASSIGN_4V(texel[i], result, result, result, result);
- break;
- case GL_ALPHA:
- ASSIGN_4V(texel[i], 0.0F, 0.0F, 0.0F, result);
- break;
- default:
- _mesa_problem(ctx, "Bad depth texture mode");
- }
-
- } /* for */
- } /* if filter */
-}
-
-
-/**
- * We use this function when a texture object is in an "incomplete" state.
- * When a fragment program attempts to sample an incomplete texture we
- * return black (see issue 23 in GL_ARB_fragment_program spec).
- * Note: fragment programs don't observe the texture enable/disable flags.
- */
-static void
-null_sample_func( struct gl_context *ctx,
- const struct gl_texture_object *tObj, GLuint n,
- const GLfloat texcoords[][4], const GLfloat lambda[],
- GLfloat rgba[][4])
-{
- GLuint i;
- (void) ctx;
- (void) tObj;
- (void) texcoords;
- (void) lambda;
- for (i = 0; i < n; i++) {
- rgba[i][RCOMP] = 0;
- rgba[i][GCOMP] = 0;
- rgba[i][BCOMP] = 0;
- rgba[i][ACOMP] = 1.0;
- }
-}
-
-
-/**
- * Choose the texture sampling function for the given texture object.
- */
-texture_sample_func
-_swrast_choose_texture_sample_func( struct gl_context *ctx,
- const struct gl_texture_object *t )
-{
- if (!t || !t->_Complete) {
- return &null_sample_func;
- }
- else {
- const GLboolean needLambda =
- (GLboolean) (t->Sampler.MinFilter != t->Sampler.MagFilter);
- const GLenum format = t->Image[0][t->BaseLevel]->_BaseFormat;
-
- switch (t->Target) {
- case GL_TEXTURE_1D:
- if (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL_EXT) {
- return &sample_depth_texture;
- }
- else if (needLambda) {
- return &sample_lambda_1d;
- }
- else if (t->Sampler.MinFilter == GL_LINEAR) {
- return &sample_linear_1d;
- }
- else {
- ASSERT(t->Sampler.MinFilter == GL_NEAREST);
- return &sample_nearest_1d;
- }
- case GL_TEXTURE_2D:
- if (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL_EXT) {
- return &sample_depth_texture;
- }
- else if (needLambda) {
- /* Anisotropic filtering extension. Activated only if mipmaps are used */
- if (t->Sampler.MaxAnisotropy > 1.0 &&
- t->Sampler.MinFilter == GL_LINEAR_MIPMAP_LINEAR) {
- return &sample_lambda_2d_aniso;
- }
- return &sample_lambda_2d;
- }
- else if (t->Sampler.MinFilter == GL_LINEAR) {
- return &sample_linear_2d;
- }
- else {
- /* check for a few optimized cases */
- const struct gl_texture_image *img = t->Image[0][t->BaseLevel];
- ASSERT(t->Sampler.MinFilter == GL_NEAREST);
- if (t->Sampler.WrapS == GL_REPEAT &&
- t->Sampler.WrapT == GL_REPEAT &&
- img->_IsPowerOfTwo &&
- img->Border == 0 &&
- img->TexFormat == MESA_FORMAT_RGB888) {
- return &opt_sample_rgb_2d;
- }
- else if (t->Sampler.WrapS == GL_REPEAT &&
- t->Sampler.WrapT == GL_REPEAT &&
- img->_IsPowerOfTwo &&
- img->Border == 0 &&
- img->TexFormat == MESA_FORMAT_RGBA8888) {
- return &opt_sample_rgba_2d;
- }
- else {
- return &sample_nearest_2d;
- }
- }
- case GL_TEXTURE_3D:
- if (needLambda) {
- return &sample_lambda_3d;
- }
- else if (t->Sampler.MinFilter == GL_LINEAR) {
- return &sample_linear_3d;
- }
- else {
- ASSERT(t->Sampler.MinFilter == GL_NEAREST);
- return &sample_nearest_3d;
- }
- case GL_TEXTURE_CUBE_MAP:
- if (needLambda) {
- return &sample_lambda_cube;
- }
- else if (t->Sampler.MinFilter == GL_LINEAR) {
- return &sample_linear_cube;
- }
- else {
- ASSERT(t->Sampler.MinFilter == GL_NEAREST);
- return &sample_nearest_cube;
- }
- case GL_TEXTURE_RECTANGLE_NV:
- if (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL_EXT) {
- return &sample_depth_texture;
- }
- else if (needLambda) {
- return &sample_lambda_rect;
- }
- else if (t->Sampler.MinFilter == GL_LINEAR) {
- return &sample_linear_rect;
- }
- else {
- ASSERT(t->Sampler.MinFilter == GL_NEAREST);
- return &sample_nearest_rect;
- }
- case GL_TEXTURE_1D_ARRAY_EXT:
- if (needLambda) {
- return &sample_lambda_1d_array;
- }
- else if (t->Sampler.MinFilter == GL_LINEAR) {
- return &sample_linear_1d_array;
- }
- else {
- ASSERT(t->Sampler.MinFilter == GL_NEAREST);
- return &sample_nearest_1d_array;
- }
- case GL_TEXTURE_2D_ARRAY_EXT:
- if (needLambda) {
- return &sample_lambda_2d_array;
- }
- else if (t->Sampler.MinFilter == GL_LINEAR) {
- return &sample_linear_2d_array;
- }
- else {
- ASSERT(t->Sampler.MinFilter == GL_NEAREST);
- return &sample_nearest_2d_array;
- }
- default:
- _mesa_problem(ctx,
- "invalid target in _swrast_choose_texture_sample_func");
- return &null_sample_func;
- }
- }
-}
+/* + * Mesa 3-D graphics library + * Version: 7.3 + * + * 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 + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#include "main/glheader.h" +#include "main/context.h" +#include "main/colormac.h" +#include "main/imports.h" + +#include "s_context.h" +#include "s_texfilter.h" + + +/* + * Note, the FRAC macro has to work perfectly. Otherwise you'll sometimes + * see 1-pixel bands of improperly weighted linear-filtered textures. + * The tests/texwrap.c demo is a good test. + * Also note, FRAC(x) doesn't truly return the fractional part of x for x < 0. + * Instead, if x < 0 then FRAC(x) = 1 - true_frac(x). + */ +#define FRAC(f) ((f) - IFLOOR(f)) + + + +/** + * Linear interpolation macro + */ +#define LERP(T, A, B) ( (A) + (T) * ((B) - (A)) ) + + +/** + * Do 2D/biliner interpolation of float values. + * v00, v10, v01 and v11 are typically four texture samples in a square/box. + * a and b are the horizontal and vertical interpolants. + * It's important that this function is inlined when compiled with + * optimization! If we find that's not true on some systems, convert + * to a macro. + */ +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); +} + + +/** + * Do 3D/trilinear interpolation of float values. + * \sa lerp_2d + */ +static INLINE GLfloat +lerp_3d(GLfloat a, GLfloat b, GLfloat c, + GLfloat v000, GLfloat v100, GLfloat v010, GLfloat v110, + GLfloat v001, GLfloat v101, GLfloat v011, GLfloat v111) +{ + const GLfloat temp00 = LERP(a, v000, v100); + const GLfloat temp10 = LERP(a, v010, v110); + const GLfloat temp01 = LERP(a, v001, v101); + const GLfloat temp11 = LERP(a, v011, v111); + const GLfloat temp0 = LERP(b, temp00, temp10); + const GLfloat temp1 = LERP(b, temp01, temp11); + return LERP(c, temp0, temp1); +} + + +/** + * Do linear interpolation of colors. + */ +static INLINE void +lerp_rgba(GLfloat result[4], GLfloat t, const GLfloat a[4], const GLfloat b[4]) +{ + result[0] = LERP(t, a[0], b[0]); + result[1] = LERP(t, a[1], b[1]); + result[2] = LERP(t, a[2], b[2]); + result[3] = LERP(t, a[3], b[3]); +} + + +/** + * Do bilinear interpolation of colors. + */ +static INLINE void +lerp_rgba_2d(GLfloat result[4], GLfloat a, GLfloat b, + const GLfloat t00[4], const GLfloat t10[4], + const GLfloat t01[4], const GLfloat t11[4]) +{ + result[0] = lerp_2d(a, b, t00[0], t10[0], t01[0], t11[0]); + result[1] = lerp_2d(a, b, t00[1], t10[1], t01[1], t11[1]); + result[2] = lerp_2d(a, b, t00[2], t10[2], t01[2], t11[2]); + result[3] = lerp_2d(a, b, t00[3], t10[3], t01[3], t11[3]); +} + + +/** + * Do trilinear interpolation of colors. + */ +static INLINE void +lerp_rgba_3d(GLfloat result[4], GLfloat a, GLfloat b, GLfloat c, + const GLfloat t000[4], const GLfloat t100[4], + const GLfloat t010[4], const GLfloat t110[4], + const GLfloat t001[4], const GLfloat t101[4], + const GLfloat t011[4], const GLfloat t111[4]) +{ + GLuint k; + /* compiler should unroll these short loops */ + for (k = 0; k < 4; k++) { + result[k] = lerp_3d(a, b, c, t000[k], t100[k], t010[k], t110[k], + t001[k], t101[k], t011[k], t111[k]); + } +} + + +/** + * Used for GL_REPEAT wrap mode. Using A % B doesn't produce the + * right results for A<0. Casting to A to be unsigned only works if B + * is a power of two. Adding a bias to A (which is a multiple of B) + * avoids the problems with A < 0 (for reasonable A) without using a + * conditional. + */ +#define REMAINDER(A, B) (((A) + (B) * 1024) % (B)) + + +/** + * Used to compute texel locations for linear sampling. + * Input: + * wrapMode = GL_REPEAT, GL_CLAMP, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER + * s = texcoord in [0,1] + * size = width (or height or depth) of texture + * Output: + * i0, i1 = returns two nearest texel indexes + * weight = returns blend factor between texels + */ +static INLINE void +linear_texel_locations(GLenum wrapMode, + const struct gl_texture_image *img, + GLint size, GLfloat s, + GLint *i0, GLint *i1, GLfloat *weight) +{ + GLfloat u; + switch (wrapMode) { + case GL_REPEAT: + u = s * size - 0.5F; + if (img->_IsPowerOfTwo) { + *i0 = IFLOOR(u) & (size - 1); + *i1 = (*i0 + 1) & (size - 1); + } + else { + *i0 = REMAINDER(IFLOOR(u), size); + *i1 = REMAINDER(*i0 + 1, size); + } + break; + case GL_CLAMP_TO_EDGE: + if (s <= 0.0F) + u = 0.0F; + else if (s >= 1.0F) + u = (GLfloat) size; + else + u = s * size; + u -= 0.5F; + *i0 = IFLOOR(u); + *i1 = *i0 + 1; + if (*i0 < 0) + *i0 = 0; + if (*i1 >= (GLint) size) + *i1 = size - 1; + break; + case GL_CLAMP_TO_BORDER: + { + const GLfloat min = -1.0F / (2.0F * size); + const GLfloat max = 1.0F - min; + if (s <= min) + u = min * size; + else if (s >= max) + u = max * size; + else + u = s * size; + u -= 0.5F; + *i0 = IFLOOR(u); + *i1 = *i0 + 1; + } + break; + case GL_MIRRORED_REPEAT: + { + const GLint flr = IFLOOR(s); + if (flr & 1) + u = 1.0F - (s - (GLfloat) flr); + else + u = s - (GLfloat) flr; + u = (u * size) - 0.5F; + *i0 = IFLOOR(u); + *i1 = *i0 + 1; + if (*i0 < 0) + *i0 = 0; + if (*i1 >= (GLint) size) + *i1 = size - 1; + } + break; + case GL_MIRROR_CLAMP_EXT: + u = FABSF(s); + if (u >= 1.0F) + u = (GLfloat) size; + else + u *= size; + u -= 0.5F; + *i0 = IFLOOR(u); + *i1 = *i0 + 1; + break; + case GL_MIRROR_CLAMP_TO_EDGE_EXT: + u = FABSF(s); + if (u >= 1.0F) + u = (GLfloat) size; + else + u *= size; + u -= 0.5F; + *i0 = IFLOOR(u); + *i1 = *i0 + 1; + if (*i0 < 0) + *i0 = 0; + if (*i1 >= (GLint) size) + *i1 = size - 1; + break; + case GL_MIRROR_CLAMP_TO_BORDER_EXT: + { + const GLfloat min = -1.0F / (2.0F * size); + const GLfloat max = 1.0F - min; + u = FABSF(s); + if (u <= min) + u = min * size; + else if (u >= max) + u = max * size; + else + u *= size; + u -= 0.5F; + *i0 = IFLOOR(u); + *i1 = *i0 + 1; + } + break; + case GL_CLAMP: + if (s <= 0.0F) + u = 0.0F; + else if (s >= 1.0F) + u = (GLfloat) size; + else + u = s * size; + u -= 0.5F; + *i0 = IFLOOR(u); + *i1 = *i0 + 1; + break; + default: + _mesa_problem(NULL, "Bad wrap mode"); + u = 0.0F; + } + *weight = FRAC(u); +} + + +/** + * Used to compute texel location for nearest sampling. + */ +static INLINE GLint +nearest_texel_location(GLenum wrapMode, + const struct gl_texture_image *img, + GLint size, GLfloat s) +{ + GLint i; + + switch (wrapMode) { + case GL_REPEAT: + /* s limited to [0,1) */ + /* i limited to [0,size-1] */ + i = IFLOOR(s * size); + if (img->_IsPowerOfTwo) + i &= (size - 1); + else + i = REMAINDER(i, size); + return i; + case GL_CLAMP_TO_EDGE: + { + /* s limited to [min,max] */ + /* i limited to [0, size-1] */ + const GLfloat min = 1.0F / (2.0F * size); + const GLfloat max = 1.0F - min; + if (s < min) + i = 0; + else if (s > max) + i = size - 1; + else + i = IFLOOR(s * size); + } + return i; + case GL_CLAMP_TO_BORDER: + { + /* s limited to [min,max] */ + /* i limited to [-1, size] */ + const GLfloat min = -1.0F / (2.0F * size); + const GLfloat max = 1.0F - min; + if (s <= min) + i = -1; + else if (s >= max) + i = size; + else + i = IFLOOR(s * size); + } + return i; + case GL_MIRRORED_REPEAT: + { + const GLfloat min = 1.0F / (2.0F * size); + const GLfloat max = 1.0F - min; + const GLint flr = IFLOOR(s); + GLfloat u; + if (flr & 1) + u = 1.0F - (s - (GLfloat) flr); + else + u = s - (GLfloat) flr; + if (u < min) + i = 0; + else if (u > max) + i = size - 1; + else + i = IFLOOR(u * size); + } + return i; + case GL_MIRROR_CLAMP_EXT: + { + /* s limited to [0,1] */ + /* i limited to [0,size-1] */ + const GLfloat u = FABSF(s); + if (u <= 0.0F) + i = 0; + else if (u >= 1.0F) + i = size - 1; + else + i = IFLOOR(u * size); + } + return i; + case GL_MIRROR_CLAMP_TO_EDGE_EXT: + { + /* s limited to [min,max] */ + /* i limited to [0, size-1] */ + const GLfloat min = 1.0F / (2.0F * size); + const GLfloat max = 1.0F - min; + const GLfloat u = FABSF(s); + if (u < min) + i = 0; + else if (u > max) + i = size - 1; + else + i = IFLOOR(u * size); + } + return i; + case GL_MIRROR_CLAMP_TO_BORDER_EXT: + { + /* s limited to [min,max] */ + /* i limited to [0, size-1] */ + const GLfloat min = -1.0F / (2.0F * size); + const GLfloat max = 1.0F - min; + const GLfloat u = FABSF(s); + if (u < min) + i = -1; + else if (u > max) + i = size; + else + i = IFLOOR(u * size); + } + return i; + case GL_CLAMP: + /* s limited to [0,1] */ + /* i limited to [0,size-1] */ + if (s <= 0.0F) + i = 0; + else if (s >= 1.0F) + i = size - 1; + else + i = IFLOOR(s * size); + return i; + default: + _mesa_problem(NULL, "Bad wrap mode"); + return 0; + } +} + + +/* Power of two image sizes only */ +static INLINE void +linear_repeat_texel_location(GLuint size, GLfloat s, + GLint *i0, GLint *i1, GLfloat *weight) +{ + GLfloat u = s * size - 0.5F; + *i0 = IFLOOR(u) & (size - 1); + *i1 = (*i0 + 1) & (size - 1); + *weight = FRAC(u); +} + + +/** + * Do clamp/wrap for a texture rectangle coord, GL_NEAREST filter mode. + */ +static INLINE GLint +clamp_rect_coord_nearest(GLenum wrapMode, GLfloat coord, GLint max) +{ + switch (wrapMode) { + case GL_CLAMP: + return IFLOOR( CLAMP(coord, 0.0F, max - 1) ); + case GL_CLAMP_TO_EDGE: + return IFLOOR( CLAMP(coord, 0.5F, max - 0.5F) ); + case GL_CLAMP_TO_BORDER: + return IFLOOR( CLAMP(coord, -0.5F, max + 0.5F) ); + default: + _mesa_problem(NULL, "bad wrapMode in clamp_rect_coord_nearest"); + return 0; + } +} + + +/** + * As above, but GL_LINEAR filtering. + */ +static INLINE void +clamp_rect_coord_linear(GLenum wrapMode, GLfloat coord, GLint max, + GLint *i0out, GLint *i1out, GLfloat *weight) +{ + GLfloat fcol; + GLint i0, i1; + switch (wrapMode) { + case GL_CLAMP: + /* Not exactly what the spec says, but it matches NVIDIA output */ + fcol = CLAMP(coord - 0.5F, 0.0F, max - 1); + i0 = IFLOOR(fcol); + i1 = i0 + 1; + break; + case GL_CLAMP_TO_EDGE: + fcol = CLAMP(coord, 0.5F, max - 0.5F); + fcol -= 0.5F; + i0 = IFLOOR(fcol); + i1 = i0 + 1; + if (i1 > max - 1) + i1 = max - 1; + break; + case GL_CLAMP_TO_BORDER: + fcol = CLAMP(coord, -0.5F, max + 0.5F); + fcol -= 0.5F; + i0 = IFLOOR(fcol); + i1 = i0 + 1; + break; + default: + _mesa_problem(NULL, "bad wrapMode in clamp_rect_coord_linear"); + i0 = i1 = 0; + fcol = 0.0F; + } + *i0out = i0; + *i1out = i1; + *weight = FRAC(fcol); +} + + +/** + * Compute slice/image to use for 1D or 2D array texture. + */ +static INLINE GLint +tex_array_slice(GLfloat coord, GLsizei size) +{ + GLint slice = IFLOOR(coord + 0.5f); + slice = CLAMP(slice, 0, size - 1); + return slice; +} + + +/** + * Compute nearest integer texcoords for given texobj and coordinate. + * NOTE: only used for depth texture sampling. + */ +static INLINE void +nearest_texcoord(const struct gl_texture_object *texObj, + GLuint level, + const GLfloat texcoord[4], + GLint *i, GLint *j, GLint *k) +{ + const struct gl_texture_image *img = texObj->Image[0][level]; + const GLint width = img->Width; + const GLint height = img->Height; + const GLint depth = img->Depth; + + switch (texObj->Target) { + case GL_TEXTURE_RECTANGLE_ARB: + *i = clamp_rect_coord_nearest(texObj->Sampler.WrapS, texcoord[0], width); + *j = clamp_rect_coord_nearest(texObj->Sampler.WrapT, texcoord[1], height); + *k = 0; + break; + case GL_TEXTURE_1D: + *i = nearest_texel_location(texObj->Sampler.WrapS, img, width, texcoord[0]); + *j = 0; + *k = 0; + break; + case GL_TEXTURE_2D: + *i = nearest_texel_location(texObj->Sampler.WrapS, img, width, texcoord[0]); + *j = nearest_texel_location(texObj->Sampler.WrapT, img, height, texcoord[1]); + *k = 0; + break; + case GL_TEXTURE_1D_ARRAY_EXT: + *i = nearest_texel_location(texObj->Sampler.WrapS, img, width, texcoord[0]); + *j = tex_array_slice(texcoord[1], height); + *k = 0; + break; + case GL_TEXTURE_2D_ARRAY_EXT: + *i = nearest_texel_location(texObj->Sampler.WrapS, img, width, texcoord[0]); + *j = nearest_texel_location(texObj->Sampler.WrapT, img, height, texcoord[1]); + *k = tex_array_slice(texcoord[2], depth); + break; + default: + *i = *j = *k = 0; + } +} + + +/** + * Compute linear integer texcoords for given texobj and coordinate. + * NOTE: only used for depth texture sampling. + */ +static INLINE void +linear_texcoord(const struct gl_texture_object *texObj, + GLuint level, + const GLfloat texcoord[4], + GLint *i0, GLint *i1, GLint *j0, GLint *j1, GLint *slice, + GLfloat *wi, GLfloat *wj) +{ + const struct gl_texture_image *img = texObj->Image[0][level]; + const GLint width = img->Width; + const GLint height = img->Height; + const GLint depth = img->Depth; + + switch (texObj->Target) { + case GL_TEXTURE_RECTANGLE_ARB: + clamp_rect_coord_linear(texObj->Sampler.WrapS, texcoord[0], + width, i0, i1, wi); + clamp_rect_coord_linear(texObj->Sampler.WrapT, texcoord[1], + height, j0, j1, wj); + *slice = 0; + break; + + case GL_TEXTURE_1D: + case GL_TEXTURE_2D: + linear_texel_locations(texObj->Sampler.WrapS, img, width, + texcoord[0], i0, i1, wi); + linear_texel_locations(texObj->Sampler.WrapT, img, height, + texcoord[1], j0, j1, wj); + *slice = 0; + break; + + case GL_TEXTURE_1D_ARRAY_EXT: + linear_texel_locations(texObj->Sampler.WrapS, img, width, + texcoord[0], i0, i1, wi); + *j0 = tex_array_slice(texcoord[1], height); + *j1 = *j0; + *slice = 0; + break; + + case GL_TEXTURE_2D_ARRAY_EXT: + linear_texel_locations(texObj->Sampler.WrapS, img, width, + texcoord[0], i0, i1, wi); + linear_texel_locations(texObj->Sampler.WrapT, img, height, + texcoord[1], j0, j1, wj); + *slice = tex_array_slice(texcoord[2], depth); + break; + + default: + *slice = 0; + } +} + + + +/** + * For linear interpolation between mipmap levels N and N+1, this function + * computes N. + */ +static INLINE GLint +linear_mipmap_level(const struct gl_texture_object *tObj, GLfloat lambda) +{ + if (lambda < 0.0F) + return tObj->BaseLevel; + else if (lambda > tObj->_MaxLambda) + return (GLint) (tObj->BaseLevel + tObj->_MaxLambda); + else + return (GLint) (tObj->BaseLevel + lambda); +} + + +/** + * Compute the nearest mipmap level to take texels from. + */ +static INLINE GLint +nearest_mipmap_level(const struct gl_texture_object *tObj, GLfloat lambda) +{ + GLfloat l; + GLint level; + if (lambda <= 0.5F) + l = 0.0F; + else if (lambda > tObj->_MaxLambda + 0.4999F) + l = tObj->_MaxLambda + 0.4999F; + else + l = lambda; + level = (GLint) (tObj->BaseLevel + l + 0.5F); + if (level > tObj->_MaxLevel) + level = tObj->_MaxLevel; + return level; +} + + + +/* + * Bitflags for texture border color sampling. + */ +#define I0BIT 1 +#define I1BIT 2 +#define J0BIT 4 +#define J1BIT 8 +#define K0BIT 16 +#define K1BIT 32 + + + +/** + * The lambda[] array values are always monotonic. Either the whole span + * will be minified, magnified, or split between the two. This function + * determines the subranges in [0, n-1] that are to be minified or magnified. + */ +static INLINE void +compute_min_mag_ranges(const struct gl_texture_object *tObj, + GLuint n, const GLfloat lambda[], + GLuint *minStart, GLuint *minEnd, + GLuint *magStart, GLuint *magEnd) +{ + GLfloat minMagThresh; + + /* we shouldn't be here if minfilter == magfilter */ + ASSERT(tObj->Sampler.MinFilter != tObj->Sampler.MagFilter); + + /* This bit comes from the OpenGL spec: */ + if (tObj->Sampler.MagFilter == GL_LINEAR + && (tObj->Sampler.MinFilter == GL_NEAREST_MIPMAP_NEAREST || + tObj->Sampler.MinFilter == GL_NEAREST_MIPMAP_LINEAR)) { + minMagThresh = 0.5F; + } + else { + minMagThresh = 0.0F; + } + +#if 0 + /* DEBUG CODE: Verify that lambda[] is monotonic. + * We can't really use this because the inaccuracy in the LOG2 function + * causes this test to fail, yet the resulting texturing is correct. + */ + if (n > 1) { + GLuint i; + printf("lambda delta = %g\n", lambda[0] - lambda[n-1]); + if (lambda[0] >= lambda[n-1]) { /* decreasing */ + for (i = 0; i < n - 1; i++) { + ASSERT((GLint) (lambda[i] * 10) >= (GLint) (lambda[i+1] * 10)); + } + } + else { /* increasing */ + for (i = 0; i < n - 1; i++) { + ASSERT((GLint) (lambda[i] * 10) <= (GLint) (lambda[i+1] * 10)); + } + } + } +#endif /* DEBUG */ + + if (lambda[0] <= minMagThresh && (n <= 1 || lambda[n-1] <= minMagThresh)) { + /* magnification for whole span */ + *magStart = 0; + *magEnd = n; + *minStart = *minEnd = 0; + } + else if (lambda[0] > minMagThresh && (n <=1 || lambda[n-1] > minMagThresh)) { + /* minification for whole span */ + *minStart = 0; + *minEnd = n; + *magStart = *magEnd = 0; + } + else { + /* a mix of minification and magnification */ + GLuint i; + if (lambda[0] > minMagThresh) { + /* start with minification */ + for (i = 1; i < n; i++) { + if (lambda[i] <= minMagThresh) + break; + } + *minStart = 0; + *minEnd = i; + *magStart = i; + *magEnd = n; + } + else { + /* start with magnification */ + for (i = 1; i < n; i++) { + if (lambda[i] > minMagThresh) + break; + } + *magStart = 0; + *magEnd = i; + *minStart = i; + *minEnd = n; + } + } + +#if 0 + /* Verify the min/mag Start/End values + * We don't use this either (see above) + */ + { + GLint i; + for (i = 0; i < n; i++) { + if (lambda[i] > minMagThresh) { + /* minification */ + ASSERT(i >= *minStart); + ASSERT(i < *minEnd); + } + else { + /* magnification */ + ASSERT(i >= *magStart); + ASSERT(i < *magEnd); + } + } + } +#endif +} + + +/** + * When we sample the border color, it must be interpreted according to + * the base texture format. Ex: if the texture base format it GL_ALPHA, + * we return (0,0,0,BorderAlpha). + */ +static INLINE void +get_border_color(const struct gl_texture_object *tObj, + const struct gl_texture_image *img, + GLfloat rgba[4]) +{ + switch (img->_BaseFormat) { + case GL_RGB: + rgba[0] = tObj->Sampler.BorderColor.f[0]; + rgba[1] = tObj->Sampler.BorderColor.f[1]; + rgba[2] = tObj->Sampler.BorderColor.f[2]; + rgba[3] = 1.0F; + break; + case GL_ALPHA: + rgba[0] = rgba[1] = rgba[2] = 0.0; + rgba[3] = tObj->Sampler.BorderColor.f[3]; + break; + case GL_LUMINANCE: + rgba[0] = rgba[1] = rgba[2] = tObj->Sampler.BorderColor.f[0]; + rgba[3] = 1.0; + break; + case GL_LUMINANCE_ALPHA: + rgba[0] = rgba[1] = rgba[2] = tObj->Sampler.BorderColor.f[0]; + rgba[3] = tObj->Sampler.BorderColor.f[3]; + break; + case GL_INTENSITY: + rgba[0] = rgba[1] = rgba[2] = rgba[3] = tObj->Sampler.BorderColor.f[0]; + break; + default: + COPY_4V(rgba, tObj->Sampler.BorderColor.f); + } +} + + +/**********************************************************************/ +/* 1-D Texture Sampling Functions */ +/**********************************************************************/ + +/** + * Return the texture sample for coordinate (s) using GL_NEAREST filter. + */ +static INLINE void +sample_1d_nearest(struct gl_context *ctx, + const struct gl_texture_object *tObj, + const struct gl_texture_image *img, + const GLfloat texcoord[4], GLfloat rgba[4]) +{ + const GLint width = img->Width2; /* without border, power of two */ + GLint i; + i = nearest_texel_location(tObj->Sampler.WrapS, img, width, texcoord[0]); + /* skip over the border, if any */ + i += img->Border; + if (i < 0 || i >= (GLint) img->Width) { + /* Need this test for GL_CLAMP_TO_BORDER mode */ + get_border_color(tObj, img, rgba); + } + else { + img->FetchTexelf(img, i, 0, 0, rgba); + } +} + + +/** + * Return the texture sample for coordinate (s) using GL_LINEAR filter. + */ +static INLINE void +sample_1d_linear(struct gl_context *ctx, + const struct gl_texture_object *tObj, + const struct gl_texture_image *img, + const GLfloat texcoord[4], GLfloat rgba[4]) +{ + const GLint width = img->Width2; + GLint i0, i1; + GLbitfield useBorderColor = 0x0; + GLfloat a; + GLfloat t0[4], t1[4]; /* texels */ + + linear_texel_locations(tObj->Sampler.WrapS, img, width, texcoord[0], &i0, &i1, &a); + + if (img->Border) { + i0 += img->Border; + i1 += img->Border; + } + else { + if (i0 < 0 || i0 >= width) useBorderColor |= I0BIT; + if (i1 < 0 || i1 >= width) useBorderColor |= I1BIT; + } + + /* fetch texel colors */ + if (useBorderColor & I0BIT) { + get_border_color(tObj, img, t0); + } + else { + img->FetchTexelf(img, i0, 0, 0, t0); + } + if (useBorderColor & I1BIT) { + get_border_color(tObj, img, t1); + } + else { + img->FetchTexelf(img, i1, 0, 0, t1); + } + + lerp_rgba(rgba, a, t0, t1); +} + + +static void +sample_1d_nearest_mipmap_nearest(struct gl_context *ctx, + const struct gl_texture_object *tObj, + GLuint n, const GLfloat texcoord[][4], + const GLfloat lambda[], GLfloat rgba[][4]) +{ + GLuint i; + ASSERT(lambda != NULL); + for (i = 0; i < n; i++) { + GLint level = nearest_mipmap_level(tObj, lambda[i]); + sample_1d_nearest(ctx, tObj, tObj->Image[0][level], texcoord[i], rgba[i]); + } +} + + +static void +sample_1d_linear_mipmap_nearest(struct gl_context *ctx, + const struct gl_texture_object *tObj, + GLuint n, const GLfloat texcoord[][4], + const GLfloat lambda[], GLfloat rgba[][4]) +{ + GLuint i; + ASSERT(lambda != NULL); + for (i = 0; i < n; i++) { + GLint level = nearest_mipmap_level(tObj, lambda[i]); + sample_1d_linear(ctx, tObj, tObj->Image[0][level], texcoord[i], rgba[i]); + } +} + + +static void +sample_1d_nearest_mipmap_linear(struct gl_context *ctx, + const struct gl_texture_object *tObj, + GLuint n, const GLfloat texcoord[][4], + const GLfloat lambda[], GLfloat rgba[][4]) +{ + GLuint i; + ASSERT(lambda != NULL); + for (i = 0; i < n; i++) { + GLint level = linear_mipmap_level(tObj, lambda[i]); + if (level >= tObj->_MaxLevel) { + sample_1d_nearest(ctx, tObj, tObj->Image[0][tObj->_MaxLevel], + texcoord[i], rgba[i]); + } + else { + GLfloat t0[4], t1[4]; + const GLfloat f = FRAC(lambda[i]); + sample_1d_nearest(ctx, tObj, tObj->Image[0][level ], texcoord[i], t0); + sample_1d_nearest(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1); + lerp_rgba(rgba[i], f, t0, t1); + } + } +} + + +static void +sample_1d_linear_mipmap_linear(struct gl_context *ctx, + const struct gl_texture_object *tObj, + GLuint n, const GLfloat texcoord[][4], + const GLfloat lambda[], GLfloat rgba[][4]) +{ + GLuint i; + ASSERT(lambda != NULL); + for (i = 0; i < n; i++) { + GLint level = linear_mipmap_level(tObj, lambda[i]); + if (level >= tObj->_MaxLevel) { + sample_1d_linear(ctx, tObj, tObj->Image[0][tObj->_MaxLevel], + texcoord[i], rgba[i]); + } + else { + GLfloat t0[4], t1[4]; + const GLfloat f = FRAC(lambda[i]); + sample_1d_linear(ctx, tObj, tObj->Image[0][level ], texcoord[i], t0); + sample_1d_linear(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1); + lerp_rgba(rgba[i], f, t0, t1); + } + } +} + + +/** Sample 1D texture, nearest filtering for both min/magnification */ +static void +sample_nearest_1d( struct gl_context *ctx, + const struct gl_texture_object *tObj, GLuint n, + const GLfloat texcoords[][4], const GLfloat lambda[], + GLfloat rgba[][4] ) +{ + GLuint i; + struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel]; + (void) lambda; + for (i = 0; i < n; i++) { + sample_1d_nearest(ctx, tObj, image, texcoords[i], rgba[i]); + } +} + + +/** Sample 1D texture, linear filtering for both min/magnification */ +static void +sample_linear_1d( struct gl_context *ctx, + const struct gl_texture_object *tObj, GLuint n, + const GLfloat texcoords[][4], const GLfloat lambda[], + GLfloat rgba[][4] ) +{ + GLuint i; + struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel]; + (void) lambda; + for (i = 0; i < n; i++) { + sample_1d_linear(ctx, tObj, image, texcoords[i], rgba[i]); + } +} + + +/** Sample 1D texture, using lambda to choose between min/magnification */ +static void +sample_lambda_1d( struct gl_context *ctx, + const struct gl_texture_object *tObj, GLuint n, + const GLfloat texcoords[][4], + const GLfloat lambda[], GLfloat rgba[][4] ) +{ + GLuint minStart, minEnd; /* texels with minification */ + GLuint magStart, magEnd; /* texels with magnification */ + GLuint i; + + ASSERT(lambda != NULL); + compute_min_mag_ranges(tObj, n, lambda, + &minStart, &minEnd, &magStart, &magEnd); + + if (minStart < minEnd) { + /* do the minified texels */ + const GLuint m = minEnd - minStart; + switch (tObj->Sampler.MinFilter) { + case GL_NEAREST: + for (i = minStart; i < minEnd; i++) + sample_1d_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel], + texcoords[i], rgba[i]); + break; + case GL_LINEAR: + for (i = minStart; i < minEnd; i++) + sample_1d_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel], + texcoords[i], rgba[i]); + break; + case GL_NEAREST_MIPMAP_NEAREST: + sample_1d_nearest_mipmap_nearest(ctx, tObj, m, texcoords + minStart, + lambda + minStart, rgba + minStart); + break; + case GL_LINEAR_MIPMAP_NEAREST: + sample_1d_linear_mipmap_nearest(ctx, tObj, m, texcoords + minStart, + lambda + minStart, rgba + minStart); + break; + case GL_NEAREST_MIPMAP_LINEAR: + sample_1d_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart, + lambda + minStart, rgba + minStart); + break; + case GL_LINEAR_MIPMAP_LINEAR: + sample_1d_linear_mipmap_linear(ctx, tObj, m, texcoords + minStart, + lambda + minStart, rgba + minStart); + break; + default: + _mesa_problem(ctx, "Bad min filter in sample_1d_texture"); + return; + } + } + + if (magStart < magEnd) { + /* do the magnified texels */ + switch (tObj->Sampler.MagFilter) { + case GL_NEAREST: + for (i = magStart; i < magEnd; i++) + sample_1d_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel], + texcoords[i], rgba[i]); + break; + case GL_LINEAR: + for (i = magStart; i < magEnd; i++) + sample_1d_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel], + texcoords[i], rgba[i]); + break; + default: + _mesa_problem(ctx, "Bad mag filter in sample_1d_texture"); + return; + } + } +} + + +/**********************************************************************/ +/* 2-D Texture Sampling Functions */ +/**********************************************************************/ + + +/** + * Return the texture sample for coordinate (s,t) using GL_NEAREST filter. + */ +static INLINE void +sample_2d_nearest(struct gl_context *ctx, + const struct gl_texture_object *tObj, + const struct gl_texture_image *img, + const GLfloat texcoord[4], + GLfloat rgba[]) +{ + const GLint width = img->Width2; /* without border, power of two */ + const GLint height = img->Height2; /* without border, power of two */ + GLint i, j; + (void) ctx; + + i = nearest_texel_location(tObj->Sampler.WrapS, img, width, texcoord[0]); + j = nearest_texel_location(tObj->Sampler.WrapT, img, height, texcoord[1]); + + /* skip over the border, if any */ + i += img->Border; + j += img->Border; + + if (i < 0 || i >= (GLint) img->Width || j < 0 || j >= (GLint) img->Height) { + /* Need this test for GL_CLAMP_TO_BORDER mode */ + get_border_color(tObj, img, rgba); + } + else { + img->FetchTexelf(img, i, j, 0, rgba); + } +} + + +/** + * Return the texture sample for coordinate (s,t) using GL_LINEAR filter. + * New sampling code contributed by Lynn Quam <quam@ai.sri.com>. + */ +static INLINE void +sample_2d_linear(struct gl_context *ctx, + const struct gl_texture_object *tObj, + const struct gl_texture_image *img, + const GLfloat texcoord[4], + GLfloat rgba[]) +{ + const GLint width = img->Width2; + const GLint height = img->Height2; + GLint i0, j0, i1, j1; + GLbitfield useBorderColor = 0x0; + GLfloat a, b; + GLfloat t00[4], t10[4], t01[4], t11[4]; /* sampled texel colors */ + + linear_texel_locations(tObj->Sampler.WrapS, img, width, texcoord[0], &i0, &i1, &a); + linear_texel_locations(tObj->Sampler.WrapT, img, height, texcoord[1], &j0, &j1, &b); + + if (img->Border) { + i0 += img->Border; + i1 += img->Border; + j0 += img->Border; + j1 += img->Border; + } + else { + if (i0 < 0 || i0 >= width) useBorderColor |= I0BIT; + if (i1 < 0 || i1 >= width) useBorderColor |= I1BIT; + if (j0 < 0 || j0 >= height) useBorderColor |= J0BIT; + if (j1 < 0 || j1 >= height) useBorderColor |= J1BIT; + } + + /* fetch four texel colors */ + if (useBorderColor & (I0BIT | J0BIT)) { + get_border_color(tObj, img, t00); + } + else { + img->FetchTexelf(img, i0, j0, 0, t00); + } + if (useBorderColor & (I1BIT | J0BIT)) { + get_border_color(tObj, img, t10); + } + else { + img->FetchTexelf(img, i1, j0, 0, t10); + } + if (useBorderColor & (I0BIT | J1BIT)) { + get_border_color(tObj, img, t01); + } + else { + img->FetchTexelf(img, i0, j1, 0, t01); + } + if (useBorderColor & (I1BIT | J1BIT)) { + get_border_color(tObj, img, t11); + } + else { + img->FetchTexelf(img, i1, j1, 0, t11); + } + + lerp_rgba_2d(rgba, a, b, t00, t10, t01, t11); +} + + +/** + * As above, but we know WRAP_S == REPEAT and WRAP_T == REPEAT. + * We don't have to worry about the texture border. + */ +static INLINE void +sample_2d_linear_repeat(struct gl_context *ctx, + const struct gl_texture_object *tObj, + const struct gl_texture_image *img, + const GLfloat texcoord[4], + GLfloat rgba[]) +{ + const GLint width = img->Width2; + const GLint height = img->Height2; + GLint i0, j0, i1, j1; + GLfloat wi, wj; + GLfloat t00[4], t10[4], t01[4], t11[4]; /* sampled texel colors */ + + (void) ctx; + + ASSERT(tObj->Sampler.WrapS == GL_REPEAT); + ASSERT(tObj->Sampler.WrapT == GL_REPEAT); + ASSERT(img->Border == 0); + ASSERT(img->_IsPowerOfTwo); + + linear_repeat_texel_location(width, texcoord[0], &i0, &i1, &wi); + linear_repeat_texel_location(height, texcoord[1], &j0, &j1, &wj); + + img->FetchTexelf(img, i0, j0, 0, t00); + img->FetchTexelf(img, i1, j0, 0, t10); + img->FetchTexelf(img, i0, j1, 0, t01); + img->FetchTexelf(img, i1, j1, 0, t11); + + lerp_rgba_2d(rgba, wi, wj, t00, t10, t01, t11); +} + + +static void +sample_2d_nearest_mipmap_nearest(struct gl_context *ctx, + const struct gl_texture_object *tObj, + GLuint n, const GLfloat texcoord[][4], + const GLfloat lambda[], GLfloat rgba[][4]) +{ + GLuint i; + for (i = 0; i < n; i++) { + GLint level = nearest_mipmap_level(tObj, lambda[i]); + sample_2d_nearest(ctx, tObj, tObj->Image[0][level], texcoord[i], rgba[i]); + } +} + + +static void +sample_2d_linear_mipmap_nearest(struct gl_context *ctx, + const struct gl_texture_object *tObj, + GLuint n, const GLfloat texcoord[][4], + const GLfloat lambda[], GLfloat rgba[][4]) +{ + GLuint i; + ASSERT(lambda != NULL); + for (i = 0; i < n; i++) { + GLint level = nearest_mipmap_level(tObj, lambda[i]); + sample_2d_linear(ctx, tObj, tObj->Image[0][level], texcoord[i], rgba[i]); + } +} + + +static void +sample_2d_nearest_mipmap_linear(struct gl_context *ctx, + const struct gl_texture_object *tObj, + GLuint n, const GLfloat texcoord[][4], + const GLfloat lambda[], GLfloat rgba[][4]) +{ + GLuint i; + ASSERT(lambda != NULL); + for (i = 0; i < n; i++) { + GLint level = linear_mipmap_level(tObj, lambda[i]); + if (level >= tObj->_MaxLevel) { + sample_2d_nearest(ctx, tObj, tObj->Image[0][tObj->_MaxLevel], + texcoord[i], rgba[i]); + } + else { + GLfloat t0[4], t1[4]; /* texels */ + const GLfloat f = FRAC(lambda[i]); + sample_2d_nearest(ctx, tObj, tObj->Image[0][level ], texcoord[i], t0); + sample_2d_nearest(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1); + lerp_rgba(rgba[i], f, t0, t1); + } + } +} + + +static void +sample_2d_linear_mipmap_linear( struct gl_context *ctx, + const struct gl_texture_object *tObj, + GLuint n, const GLfloat texcoord[][4], + const GLfloat lambda[], GLfloat rgba[][4] ) +{ + GLuint i; + ASSERT(lambda != NULL); + for (i = 0; i < n; i++) { + GLint level = linear_mipmap_level(tObj, lambda[i]); + if (level >= tObj->_MaxLevel) { + sample_2d_linear(ctx, tObj, tObj->Image[0][tObj->_MaxLevel], + texcoord[i], rgba[i]); + } + else { + GLfloat t0[4], t1[4]; /* texels */ + const GLfloat f = FRAC(lambda[i]); + sample_2d_linear(ctx, tObj, tObj->Image[0][level ], texcoord[i], t0); + sample_2d_linear(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1); + lerp_rgba(rgba[i], f, t0, t1); + } + } +} + + +static void +sample_2d_linear_mipmap_linear_repeat(struct gl_context *ctx, + const struct gl_texture_object *tObj, + GLuint n, const GLfloat texcoord[][4], + const GLfloat lambda[], GLfloat rgba[][4]) +{ + GLuint i; + ASSERT(lambda != NULL); + ASSERT(tObj->Sampler.WrapS == GL_REPEAT); + ASSERT(tObj->Sampler.WrapT == GL_REPEAT); + for (i = 0; i < n; i++) { + GLint level = linear_mipmap_level(tObj, lambda[i]); + if (level >= tObj->_MaxLevel) { + sample_2d_linear_repeat(ctx, tObj, tObj->Image[0][tObj->_MaxLevel], + texcoord[i], rgba[i]); + } + else { + GLfloat t0[4], t1[4]; /* texels */ + const GLfloat f = FRAC(lambda[i]); + sample_2d_linear_repeat(ctx, tObj, tObj->Image[0][level ], + texcoord[i], t0); + sample_2d_linear_repeat(ctx, tObj, tObj->Image[0][level+1], + texcoord[i], t1); + lerp_rgba(rgba[i], f, t0, t1); + } + } +} + + +/** Sample 2D texture, nearest filtering for both min/magnification */ +static void +sample_nearest_2d(struct gl_context *ctx, + const struct gl_texture_object *tObj, GLuint n, + const GLfloat texcoords[][4], + const GLfloat lambda[], GLfloat rgba[][4]) +{ + GLuint i; + struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel]; + (void) lambda; + for (i = 0; i < n; i++) { + sample_2d_nearest(ctx, tObj, image, texcoords[i], rgba[i]); + } +} + + +/** Sample 2D texture, linear filtering for both min/magnification */ +static void +sample_linear_2d(struct gl_context *ctx, + const struct gl_texture_object *tObj, GLuint n, + const GLfloat texcoords[][4], + const GLfloat lambda[], GLfloat rgba[][4]) +{ + GLuint i; + struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel]; + (void) lambda; + if (tObj->Sampler.WrapS == GL_REPEAT && + tObj->Sampler.WrapT == GL_REPEAT && + image->_IsPowerOfTwo && + image->Border == 0) { + for (i = 0; i < n; i++) { + sample_2d_linear_repeat(ctx, tObj, image, texcoords[i], rgba[i]); + } + } + else { + for (i = 0; i < n; i++) { + sample_2d_linear(ctx, tObj, image, texcoords[i], rgba[i]); + } + } +} + + +/** + * Optimized 2-D texture sampling: + * S and T wrap mode == GL_REPEAT + * GL_NEAREST min/mag filter + * No border, + * RowStride == Width, + * Format = GL_RGB + */ +static void +opt_sample_rgb_2d(struct gl_context *ctx, + const struct gl_texture_object *tObj, + GLuint n, const GLfloat texcoords[][4], + const GLfloat lambda[], GLfloat rgba[][4]) +{ + const struct gl_texture_image *img = tObj->Image[0][tObj->BaseLevel]; + const GLfloat width = (GLfloat) img->Width; + const GLfloat height = (GLfloat) img->Height; + const GLint colMask = img->Width - 1; + const GLint rowMask = img->Height - 1; + const GLint shift = img->WidthLog2; + GLuint k; + (void) ctx; + (void) lambda; + ASSERT(tObj->Sampler.WrapS==GL_REPEAT); + ASSERT(tObj->Sampler.WrapT==GL_REPEAT); + ASSERT(img->Border==0); + ASSERT(img->TexFormat == MESA_FORMAT_RGB888); + ASSERT(img->_IsPowerOfTwo); + + for (k=0; k<n; k++) { + GLint i = IFLOOR(texcoords[k][0] * width) & colMask; + GLint j = IFLOOR(texcoords[k][1] * height) & rowMask; + GLint pos = (j << shift) | i; + GLubyte *texel = ((GLubyte *) img->Data) + 3*pos; + rgba[k][RCOMP] = UBYTE_TO_FLOAT(texel[2]); + rgba[k][GCOMP] = UBYTE_TO_FLOAT(texel[1]); + rgba[k][BCOMP] = UBYTE_TO_FLOAT(texel[0]); + rgba[k][ACOMP] = 1.0F; + } +} + + +/** + * Optimized 2-D texture sampling: + * S and T wrap mode == GL_REPEAT + * GL_NEAREST min/mag filter + * No border + * RowStride == Width, + * Format = GL_RGBA + */ +static void +opt_sample_rgba_2d(struct gl_context *ctx, + const struct gl_texture_object *tObj, + GLuint n, const GLfloat texcoords[][4], + const GLfloat lambda[], GLfloat rgba[][4]) +{ + const struct gl_texture_image *img = tObj->Image[0][tObj->BaseLevel]; + const GLfloat width = (GLfloat) img->Width; + const GLfloat height = (GLfloat) img->Height; + const GLint colMask = img->Width - 1; + const GLint rowMask = img->Height - 1; + const GLint shift = img->WidthLog2; + GLuint i; + (void) ctx; + (void) lambda; + ASSERT(tObj->Sampler.WrapS==GL_REPEAT); + ASSERT(tObj->Sampler.WrapT==GL_REPEAT); + ASSERT(img->Border==0); + ASSERT(img->TexFormat == MESA_FORMAT_RGBA8888); + ASSERT(img->_IsPowerOfTwo); + + for (i = 0; i < n; i++) { + const GLint col = IFLOOR(texcoords[i][0] * width) & colMask; + const GLint row = IFLOOR(texcoords[i][1] * height) & rowMask; + const GLint pos = (row << shift) | col; + const GLuint texel = *((GLuint *) img->Data + pos); + rgba[i][RCOMP] = UBYTE_TO_FLOAT( (texel >> 24) ); + rgba[i][GCOMP] = UBYTE_TO_FLOAT( (texel >> 16) & 0xff ); + rgba[i][BCOMP] = UBYTE_TO_FLOAT( (texel >> 8) & 0xff ); + rgba[i][ACOMP] = UBYTE_TO_FLOAT( (texel ) & 0xff ); + } +} + + +/** Sample 2D texture, using lambda to choose between min/magnification */ +static void +sample_lambda_2d(struct gl_context *ctx, + const struct gl_texture_object *tObj, + GLuint n, const GLfloat texcoords[][4], + const GLfloat lambda[], GLfloat rgba[][4]) +{ + const struct gl_texture_image *tImg = tObj->Image[0][tObj->BaseLevel]; + GLuint minStart, minEnd; /* texels with minification */ + GLuint magStart, magEnd; /* texels with magnification */ + + const GLboolean repeatNoBorderPOT = (tObj->Sampler.WrapS == GL_REPEAT) + && (tObj->Sampler.WrapT == GL_REPEAT) + && (tImg->Border == 0 && (tImg->Width == tImg->RowStride)) + && tImg->_IsPowerOfTwo; + + ASSERT(lambda != NULL); + compute_min_mag_ranges(tObj, n, lambda, + &minStart, &minEnd, &magStart, &magEnd); + + if (minStart < minEnd) { + /* do the minified texels */ + const GLuint m = minEnd - minStart; + switch (tObj->Sampler.MinFilter) { + case GL_NEAREST: + if (repeatNoBorderPOT) { + switch (tImg->TexFormat) { + case MESA_FORMAT_RGB888: + opt_sample_rgb_2d(ctx, tObj, m, texcoords + minStart, + NULL, rgba + minStart); + break; + case MESA_FORMAT_RGBA8888: + opt_sample_rgba_2d(ctx, tObj, m, texcoords + minStart, + NULL, rgba + minStart); + break; + default: + sample_nearest_2d(ctx, tObj, m, texcoords + minStart, + NULL, rgba + minStart ); + } + } + else { + sample_nearest_2d(ctx, tObj, m, texcoords + minStart, + NULL, rgba + minStart); + } + break; + case GL_LINEAR: + sample_linear_2d(ctx, tObj, m, texcoords + minStart, + NULL, rgba + minStart); + break; + case GL_NEAREST_MIPMAP_NEAREST: + sample_2d_nearest_mipmap_nearest(ctx, tObj, m, + texcoords + minStart, + lambda + minStart, rgba + minStart); + break; + case GL_LINEAR_MIPMAP_NEAREST: + sample_2d_linear_mipmap_nearest(ctx, tObj, m, texcoords + minStart, + lambda + minStart, rgba + minStart); + break; + case GL_NEAREST_MIPMAP_LINEAR: + sample_2d_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart, + lambda + minStart, rgba + minStart); + break; + case GL_LINEAR_MIPMAP_LINEAR: + if (repeatNoBorderPOT) + sample_2d_linear_mipmap_linear_repeat(ctx, tObj, m, + texcoords + minStart, lambda + minStart, rgba + minStart); + else + sample_2d_linear_mipmap_linear(ctx, tObj, m, texcoords + minStart, + lambda + minStart, rgba + minStart); + break; + default: + _mesa_problem(ctx, "Bad min filter in sample_2d_texture"); + return; + } + } + + if (magStart < magEnd) { + /* do the magnified texels */ + const GLuint m = magEnd - magStart; + + switch (tObj->Sampler.MagFilter) { + case GL_NEAREST: + if (repeatNoBorderPOT) { + switch (tImg->TexFormat) { + case MESA_FORMAT_RGB888: + opt_sample_rgb_2d(ctx, tObj, m, texcoords + magStart, + NULL, rgba + magStart); + break; + case MESA_FORMAT_RGBA8888: + opt_sample_rgba_2d(ctx, tObj, m, texcoords + magStart, + NULL, rgba + magStart); + break; + default: + sample_nearest_2d(ctx, tObj, m, texcoords + magStart, + NULL, rgba + magStart ); + } + } + else { + sample_nearest_2d(ctx, tObj, m, texcoords + magStart, + NULL, rgba + magStart); + } + break; + case GL_LINEAR: + sample_linear_2d(ctx, tObj, m, texcoords + magStart, + NULL, rgba + magStart); + break; + default: + _mesa_problem(ctx, "Bad mag filter in sample_lambda_2d"); + } + } +} + + +/* For anisotropic filtering */ +#define WEIGHT_LUT_SIZE 1024 + +static GLfloat *weightLut = NULL; + +/** + * Creates the look-up table used to speed-up EWA sampling + */ +static void +create_filter_table(void) +{ + GLuint i; + if (!weightLut) { + weightLut = (GLfloat *) malloc(WEIGHT_LUT_SIZE * sizeof(GLfloat)); + + for (i = 0; i < WEIGHT_LUT_SIZE; ++i) { + GLfloat alpha = 2; + GLfloat r2 = (GLfloat) i / (GLfloat) (WEIGHT_LUT_SIZE - 1); + GLfloat weight = (GLfloat) exp(-alpha * r2); + weightLut[i] = weight; + } + } +} + + +/** + * Elliptical weighted average (EWA) filter for producing high quality + * anisotropic filtered results. + * Based on the Higher Quality Elliptical Weighted Avarage Filter + * published by Paul S. Heckbert in his Master's Thesis + * "Fundamentals of Texture Mapping and Image Warping" (1989) + */ +static void +sample_2d_ewa(struct gl_context *ctx, + const struct gl_texture_object *tObj, + const GLfloat texcoord[4], + const GLfloat dudx, const GLfloat dvdx, + const GLfloat dudy, const GLfloat dvdy, const GLint lod, + GLfloat rgba[]) +{ + GLint level = lod > 0 ? lod : 0; + GLfloat scaling = 1.0 / (1 << level); + const struct gl_texture_image *img = tObj->Image[0][level]; + const struct gl_texture_image *mostDetailedImage = + tObj->Image[0][tObj->BaseLevel]; + GLfloat tex_u=-0.5 + texcoord[0] * mostDetailedImage->WidthScale * scaling; + GLfloat tex_v=-0.5 + texcoord[1] * mostDetailedImage->HeightScale * scaling; + + GLfloat ux = dudx * scaling; + GLfloat vx = dvdx * scaling; + GLfloat uy = dudy * scaling; + GLfloat vy = dvdy * scaling; + + /* compute ellipse coefficients to bound the region: + * A*x*x + B*x*y + C*y*y = F. + */ + GLfloat A = vx*vx+vy*vy+1; + GLfloat B = -2*(ux*vx+uy*vy); + GLfloat C = ux*ux+uy*uy+1; + GLfloat F = A*C-B*B/4.0; + + /* check if it is an ellipse */ + /* ASSERT(F > 0.0); */ + + /* Compute the ellipse's (u,v) bounding box in texture space */ + GLfloat d = -B*B+4.0*C*A; + GLfloat box_u = 2.0 / d * sqrt(d*C*F); /* box_u -> half of bbox with */ + GLfloat box_v = 2.0 / d * sqrt(A*d*F); /* box_v -> half of bbox height */ + + GLint u0 = floor(tex_u - box_u); + GLint u1 = ceil (tex_u + box_u); + GLint v0 = floor(tex_v - box_v); + GLint v1 = ceil (tex_v + box_v); + + GLfloat num[4] = {0.0F, 0.0F, 0.0F, 0.0F}; + GLfloat newCoord[2]; + GLfloat den = 0.0F; + GLfloat ddq; + GLfloat U = u0 - tex_u; + GLint v; + + /* Scale ellipse formula to directly index the Filter Lookup Table. + * i.e. scale so that F = WEIGHT_LUT_SIZE-1 + */ + double formScale = (double) (WEIGHT_LUT_SIZE - 1) / F; + A *= formScale; + B *= formScale; + C *= formScale; + /* F *= formScale; */ /* no need to scale F as we don't use it below here */ + + /* Heckbert MS thesis, p. 59; scan over the bounding box of the ellipse + * and incrementally update the value of Ax^2+Bxy*Cy^2; when this + * value, q, is less than F, we're inside the ellipse + */ + ddq = 2 * A; + for (v = v0; v <= v1; ++v) { + GLfloat V = v - tex_v; + GLfloat dq = A * (2 * U + 1) + B * V; + GLfloat q = (C * V + B * U) * V + A * U * U; + + GLint u; + for (u = u0; u <= u1; ++u) { + /* Note that the ellipse has been pre-scaled so F = WEIGHT_LUT_SIZE - 1 */ + if (q < WEIGHT_LUT_SIZE) { + /* as a LUT is used, q must never be negative; + * should not happen, though + */ + const GLint qClamped = q >= 0.0F ? q : 0; + GLfloat weight = weightLut[qClamped]; + + newCoord[0] = u / ((GLfloat) img->Width2); + newCoord[1] = v / ((GLfloat) img->Height2); + + sample_2d_nearest(ctx, tObj, img, newCoord, rgba); + num[0] += weight * rgba[0]; + num[1] += weight * rgba[1]; + num[2] += weight * rgba[2]; + num[3] += weight * rgba[3]; + + den += weight; + } + q += dq; + dq += ddq; + } + } + + if (den <= 0.0F) { + /* Reaching this place would mean + * that no pixels intersected the ellipse. + * This should never happen because + * the filter we use always + * intersects at least one pixel. + */ + + /*rgba[0]=0; + rgba[1]=0; + rgba[2]=0; + rgba[3]=0;*/ + /* not enough pixels in resampling, resort to direct interpolation */ + sample_2d_linear(ctx, tObj, img, texcoord, rgba); + return; + } + + rgba[0] = num[0] / den; + rgba[1] = num[1] / den; + rgba[2] = num[2] / den; + rgba[3] = num[3] / den; +} + + +/** + * Anisotropic filtering using footprint assembly as outlined in the + * EXT_texture_filter_anisotropic spec: + * http://www.opengl.org/registry/specs/EXT/texture_filter_anisotropic.txt + * Faster than EWA but has less quality (more aliasing effects) + */ +static void +sample_2d_footprint(struct gl_context *ctx, + const struct gl_texture_object *tObj, + const GLfloat texcoord[4], + const GLfloat dudx, const GLfloat dvdx, + const GLfloat dudy, const GLfloat dvdy, const GLint lod, + GLfloat rgba[]) +{ + GLint level = lod > 0 ? lod : 0; + GLfloat scaling = 1.0F / (1 << level); + const struct gl_texture_image *img = tObj->Image[0][level]; + + GLfloat ux = dudx * scaling; + GLfloat vx = dvdx * scaling; + GLfloat uy = dudy * scaling; + GLfloat vy = dvdy * scaling; + + GLfloat Px2 = ux * ux + vx * vx; /* squared length of dx */ + GLfloat Py2 = uy * uy + vy * vy; /* squared length of dy */ + + GLint numSamples; + GLfloat ds; + GLfloat dt; + + GLfloat num[4] = {0.0F, 0.0F, 0.0F, 0.0F}; + GLfloat newCoord[2]; + GLint s; + + /* Calculate the per anisotropic sample offsets in s,t space. */ + if (Px2 > Py2) { + numSamples = ceil(SQRTF(Px2)); + ds = ux / ((GLfloat) img->Width2); + dt = vx / ((GLfloat) img->Height2); + } + else { + numSamples = ceil(SQRTF(Py2)); + ds = uy / ((GLfloat) img->Width2); + dt = vy / ((GLfloat) img->Height2); + } + + for (s = 0; s<numSamples; s++) { + newCoord[0] = texcoord[0] + ds * ((GLfloat)(s+1) / (numSamples+1) -0.5); + newCoord[1] = texcoord[1] + dt * ((GLfloat)(s+1) / (numSamples+1) -0.5); + + sample_2d_linear(ctx, tObj, img, newCoord, rgba); + num[0] += rgba[0]; + num[1] += rgba[1]; + num[2] += rgba[2]; + num[3] += rgba[3]; + } + + rgba[0] = num[0] / numSamples; + rgba[1] = num[1] / numSamples; + rgba[2] = num[2] / numSamples; + rgba[3] = num[3] / numSamples; +} + + +/** + * Returns the index of the specified texture object in the + * gl_context texture unit array. + */ +static INLINE GLuint +texture_unit_index(const struct gl_context *ctx, + const struct gl_texture_object *tObj) +{ + const GLuint maxUnit + = (ctx->Texture._EnabledCoordUnits > 1) ? ctx->Const.MaxTextureUnits : 1; + GLuint u; + + /* XXX CoordUnits vs. ImageUnits */ + for (u = 0; u < maxUnit; u++) { + if (ctx->Texture.Unit[u]._Current == tObj) + break; /* found */ + } + if (u >= maxUnit) + u = 0; /* not found, use 1st one; should never happen */ + + return u; +} + + +/** + * Sample 2D texture using an anisotropic filter. + * NOTE: the const GLfloat lambda_iso[] parameter does *NOT* contain + * the lambda float array but a "hidden" SWspan struct which is required + * by this function but is not available in the texture_sample_func signature. + * See _swrast_texture_span( struct gl_context *ctx, SWspan *span ) on how + * this function is called. + */ +static void +sample_lambda_2d_aniso(struct gl_context *ctx, + const struct gl_texture_object *tObj, + GLuint n, const GLfloat texcoords[][4], + const GLfloat lambda_iso[], GLfloat rgba[][4]) +{ + const struct gl_texture_image *tImg = tObj->Image[0][tObj->BaseLevel]; + const GLfloat maxEccentricity = + tObj->Sampler.MaxAnisotropy * tObj->Sampler.MaxAnisotropy; + + /* re-calculate the lambda values so that they are usable with anisotropic + * filtering + */ + SWspan *span = (SWspan *)lambda_iso; /* access the "hidden" SWspan struct */ + + /* based on interpolate_texcoords(struct gl_context *ctx, SWspan *span) + * in swrast/s_span.c + */ + + /* find the texture unit index by looking up the current texture object + * from the context list of available texture objects. + */ + const GLuint u = texture_unit_index(ctx, tObj); + const GLuint attr = FRAG_ATTRIB_TEX0 + u; + GLfloat texW, texH; + + const GLfloat dsdx = span->attrStepX[attr][0]; + const GLfloat dsdy = span->attrStepY[attr][0]; + const GLfloat dtdx = span->attrStepX[attr][1]; + const GLfloat dtdy = span->attrStepY[attr][1]; + const GLfloat dqdx = span->attrStepX[attr][3]; + const GLfloat dqdy = span->attrStepY[attr][3]; + GLfloat s = span->attrStart[attr][0] + span->leftClip * dsdx; + GLfloat t = span->attrStart[attr][1] + span->leftClip * dtdx; + GLfloat q = span->attrStart[attr][3] + span->leftClip * dqdx; + + /* from swrast/s_texcombine.c _swrast_texture_span */ + const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[u]; + const GLboolean adjustLOD = + (texUnit->LodBias + tObj->Sampler.LodBias != 0.0F) + || (tObj->Sampler.MinLod != -1000.0 || tObj->Sampler.MaxLod != 1000.0); + + GLuint i; + + /* on first access create the lookup table containing the filter weights. */ + if (!weightLut) { + create_filter_table(); + } + + texW = tImg->WidthScale; + texH = tImg->HeightScale; + + for (i = 0; i < n; i++) { + const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q); + + GLfloat dudx = texW * ((s + dsdx) / (q + dqdx) - s * invQ); + GLfloat dvdx = texH * ((t + dtdx) / (q + dqdx) - t * invQ); + GLfloat dudy = texW * ((s + dsdy) / (q + dqdy) - s * invQ); + GLfloat dvdy = texH * ((t + dtdy) / (q + dqdy) - t * invQ); + + /* note: instead of working with Px and Py, we will use the + * squared length instead, to avoid sqrt. + */ + GLfloat Px2 = dudx * dudx + dvdx * dvdx; + GLfloat Py2 = dudy * dudy + dvdy * dvdy; + + GLfloat Pmax2; + GLfloat Pmin2; + GLfloat e; + GLfloat lod; + + s += dsdx; + t += dtdx; + q += dqdx; + + if (Px2 < Py2) { + Pmax2 = Py2; + Pmin2 = Px2; + } + else { + Pmax2 = Px2; + Pmin2 = Py2; + } + + /* if the eccentricity of the ellipse is too big, scale up the shorter + * of the two vectors to limit the maximum amount of work per pixel + */ + e = Pmax2 / Pmin2; + if (e > maxEccentricity) { + /* GLfloat s=e / maxEccentricity; + minor[0] *= s; + minor[1] *= s; + Pmin2 *= s; */ + Pmin2 = Pmax2 / maxEccentricity; + } + + /* note: we need to have Pmin=sqrt(Pmin2) here, but we can avoid + * this since 0.5*log(x) = log(sqrt(x)) + */ + lod = 0.5 * LOG2(Pmin2); + + if (adjustLOD) { + /* from swrast/s_texcombine.c _swrast_texture_span */ + if (texUnit->LodBias + tObj->Sampler.LodBias != 0.0F) { + /* apply LOD bias, but don't clamp yet */ + const GLfloat bias = + CLAMP(texUnit->LodBias + tObj->Sampler.LodBias, + -ctx->Const.MaxTextureLodBias, + ctx->Const.MaxTextureLodBias); + lod += bias; + + if (tObj->Sampler.MinLod != -1000.0 || + tObj->Sampler.MaxLod != 1000.0) { + /* apply LOD clamping to lambda */ + lod = CLAMP(lod, tObj->Sampler.MinLod, tObj->Sampler.MaxLod); + } + } + } + + /* If the ellipse covers the whole image, we can + * simply return the average of the whole image. + */ + if (lod >= tObj->_MaxLevel) { + sample_2d_linear(ctx, tObj, tObj->Image[0][tObj->_MaxLevel], + texcoords[i], rgba[i]); + } + else { + /* don't bother interpolating between multiple LODs; it doesn't + * seem to be worth the extra running time. + */ + sample_2d_ewa(ctx, tObj, texcoords[i], + dudx, dvdx, dudy, dvdy, floor(lod), rgba[i]); + + /* unused: */ + (void) sample_2d_footprint; + /* + sample_2d_footprint(ctx, tObj, texcoords[i], + dudx, dvdx, dudy, dvdy, floor(lod), rgba[i]); + */ + } + } +} + + + +/**********************************************************************/ +/* 3-D Texture Sampling Functions */ +/**********************************************************************/ + +/** + * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter. + */ +static INLINE void +sample_3d_nearest(struct gl_context *ctx, + const struct gl_texture_object *tObj, + const struct gl_texture_image *img, + const GLfloat texcoord[4], + GLfloat rgba[4]) +{ + const GLint width = img->Width2; /* without border, power of two */ + const GLint height = img->Height2; /* without border, power of two */ + const GLint depth = img->Depth2; /* without border, power of two */ + GLint i, j, k; + (void) ctx; + + i = nearest_texel_location(tObj->Sampler.WrapS, img, width, texcoord[0]); + j = nearest_texel_location(tObj->Sampler.WrapT, img, height, texcoord[1]); + k = nearest_texel_location(tObj->Sampler.WrapR, img, depth, texcoord[2]); + + if (i < 0 || i >= (GLint) img->Width || + j < 0 || j >= (GLint) img->Height || + k < 0 || k >= (GLint) img->Depth) { + /* Need this test for GL_CLAMP_TO_BORDER mode */ + get_border_color(tObj, img, rgba); + } + else { + img->FetchTexelf(img, i, j, k, rgba); + } +} + + +/** + * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter. + */ +static void +sample_3d_linear(struct gl_context *ctx, + const struct gl_texture_object *tObj, + const struct gl_texture_image *img, + const GLfloat texcoord[4], + GLfloat rgba[4]) +{ + const GLint width = img->Width2; + const GLint height = img->Height2; + const GLint depth = img->Depth2; + GLint i0, j0, k0, i1, j1, k1; + GLbitfield useBorderColor = 0x0; + GLfloat a, b, c; + GLfloat t000[4], t010[4], t001[4], t011[4]; + GLfloat t100[4], t110[4], t101[4], t111[4]; + + linear_texel_locations(tObj->Sampler.WrapS, img, width, texcoord[0], &i0, &i1, &a); + linear_texel_locations(tObj->Sampler.WrapT, img, height, texcoord[1], &j0, &j1, &b); + linear_texel_locations(tObj->Sampler.WrapR, img, depth, texcoord[2], &k0, &k1, &c); + + if (img->Border) { + i0 += img->Border; + i1 += img->Border; + j0 += img->Border; + j1 += img->Border; + k0 += img->Border; + k1 += img->Border; + } + else { + /* check if sampling texture border color */ + if (i0 < 0 || i0 >= width) useBorderColor |= I0BIT; + if (i1 < 0 || i1 >= width) useBorderColor |= I1BIT; + if (j0 < 0 || j0 >= height) useBorderColor |= J0BIT; + if (j1 < 0 || j1 >= height) useBorderColor |= J1BIT; + if (k0 < 0 || k0 >= depth) useBorderColor |= K0BIT; + if (k1 < 0 || k1 >= depth) useBorderColor |= K1BIT; + } + + /* Fetch texels */ + if (useBorderColor & (I0BIT | J0BIT | K0BIT)) { + get_border_color(tObj, img, t000); + } + else { + img->FetchTexelf(img, i0, j0, k0, t000); + } + if (useBorderColor & (I1BIT | J0BIT | K0BIT)) { + get_border_color(tObj, img, t100); + } + else { + img->FetchTexelf(img, i1, j0, k0, t100); + } + if (useBorderColor & (I0BIT | J1BIT | K0BIT)) { + get_border_color(tObj, img, t010); + } + else { + img->FetchTexelf(img, i0, j1, k0, t010); + } + if (useBorderColor & (I1BIT | J1BIT | K0BIT)) { + get_border_color(tObj, img, t110); + } + else { + img->FetchTexelf(img, i1, j1, k0, t110); + } + + if (useBorderColor & (I0BIT | J0BIT | K1BIT)) { + get_border_color(tObj, img, t001); + } + else { + img->FetchTexelf(img, i0, j0, k1, t001); + } + if (useBorderColor & (I1BIT | J0BIT | K1BIT)) { + get_border_color(tObj, img, t101); + } + else { + img->FetchTexelf(img, i1, j0, k1, t101); + } + if (useBorderColor & (I0BIT | J1BIT | K1BIT)) { + get_border_color(tObj, img, t011); + } + else { + img->FetchTexelf(img, i0, j1, k1, t011); + } + if (useBorderColor & (I1BIT | J1BIT | K1BIT)) { + get_border_color(tObj, img, t111); + } + else { + img->FetchTexelf(img, i1, j1, k1, t111); + } + + /* trilinear interpolation of samples */ + lerp_rgba_3d(rgba, a, b, c, t000, t100, t010, t110, t001, t101, t011, t111); +} + + +static void +sample_3d_nearest_mipmap_nearest(struct gl_context *ctx, + const struct gl_texture_object *tObj, + GLuint n, const GLfloat texcoord[][4], + const GLfloat lambda[], GLfloat rgba[][4] ) +{ + GLuint i; + for (i = 0; i < n; i++) { + GLint level = nearest_mipmap_level(tObj, lambda[i]); + sample_3d_nearest(ctx, tObj, tObj->Image[0][level], texcoord[i], rgba[i]); + } +} + + +static void +sample_3d_linear_mipmap_nearest(struct gl_context *ctx, + const struct gl_texture_object *tObj, + GLuint n, const GLfloat texcoord[][4], + const GLfloat lambda[], GLfloat rgba[][4]) +{ + GLuint i; + ASSERT(lambda != NULL); + for (i = 0; i < n; i++) { + GLint level = nearest_mipmap_level(tObj, lambda[i]); + sample_3d_linear(ctx, tObj, tObj->Image[0][level], texcoord[i], rgba[i]); + } +} + + +static void +sample_3d_nearest_mipmap_linear(struct gl_context *ctx, + const struct gl_texture_object *tObj, + GLuint n, const GLfloat texcoord[][4], + const GLfloat lambda[], GLfloat rgba[][4]) +{ + GLuint i; + ASSERT(lambda != NULL); + for (i = 0; i < n; i++) { + GLint level = linear_mipmap_level(tObj, lambda[i]); + if (level >= tObj->_MaxLevel) { + sample_3d_nearest(ctx, tObj, tObj->Image[0][tObj->_MaxLevel], + texcoord[i], rgba[i]); + } + else { + GLfloat t0[4], t1[4]; /* texels */ + const GLfloat f = FRAC(lambda[i]); + sample_3d_nearest(ctx, tObj, tObj->Image[0][level ], texcoord[i], t0); + sample_3d_nearest(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1); + lerp_rgba(rgba[i], f, t0, t1); + } + } +} + + +static void +sample_3d_linear_mipmap_linear(struct gl_context *ctx, + const struct gl_texture_object *tObj, + GLuint n, const GLfloat texcoord[][4], + const GLfloat lambda[], GLfloat rgba[][4]) +{ + GLuint i; + ASSERT(lambda != NULL); + for (i = 0; i < n; i++) { + GLint level = linear_mipmap_level(tObj, lambda[i]); + if (level >= tObj->_MaxLevel) { + sample_3d_linear(ctx, tObj, tObj->Image[0][tObj->_MaxLevel], + texcoord[i], rgba[i]); + } + else { + GLfloat t0[4], t1[4]; /* texels */ + const GLfloat f = FRAC(lambda[i]); + sample_3d_linear(ctx, tObj, tObj->Image[0][level ], texcoord[i], t0); + sample_3d_linear(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1); + lerp_rgba(rgba[i], f, t0, t1); + } + } +} + + +/** Sample 3D texture, nearest filtering for both min/magnification */ +static void +sample_nearest_3d(struct gl_context *ctx, + const struct gl_texture_object *tObj, GLuint n, + const GLfloat texcoords[][4], const GLfloat lambda[], + GLfloat rgba[][4]) +{ + GLuint i; + struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel]; + (void) lambda; + for (i = 0; i < n; i++) { + sample_3d_nearest(ctx, tObj, image, texcoords[i], rgba[i]); + } +} + + +/** Sample 3D texture, linear filtering for both min/magnification */ +static void +sample_linear_3d(struct gl_context *ctx, + const struct gl_texture_object *tObj, GLuint n, + const GLfloat texcoords[][4], + const GLfloat lambda[], GLfloat rgba[][4]) +{ + GLuint i; + struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel]; + (void) lambda; + for (i = 0; i < n; i++) { + sample_3d_linear(ctx, tObj, image, texcoords[i], rgba[i]); + } +} + + +/** Sample 3D texture, using lambda to choose between min/magnification */ +static void +sample_lambda_3d(struct gl_context *ctx, + const struct gl_texture_object *tObj, GLuint n, + const GLfloat texcoords[][4], const GLfloat lambda[], + GLfloat rgba[][4]) +{ + GLuint minStart, minEnd; /* texels with minification */ + GLuint magStart, magEnd; /* texels with magnification */ + GLuint i; + + ASSERT(lambda != NULL); + compute_min_mag_ranges(tObj, n, lambda, + &minStart, &minEnd, &magStart, &magEnd); + + if (minStart < minEnd) { + /* do the minified texels */ + GLuint m = minEnd - minStart; + switch (tObj->Sampler.MinFilter) { + case GL_NEAREST: + for (i = minStart; i < minEnd; i++) + sample_3d_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel], + texcoords[i], rgba[i]); + break; + case GL_LINEAR: + for (i = minStart; i < minEnd; i++) + sample_3d_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel], + texcoords[i], rgba[i]); + break; + case GL_NEAREST_MIPMAP_NEAREST: + sample_3d_nearest_mipmap_nearest(ctx, tObj, m, texcoords + minStart, + lambda + minStart, rgba + minStart); + break; + case GL_LINEAR_MIPMAP_NEAREST: + sample_3d_linear_mipmap_nearest(ctx, tObj, m, texcoords + minStart, + lambda + minStart, rgba + minStart); + break; + case GL_NEAREST_MIPMAP_LINEAR: + sample_3d_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart, + lambda + minStart, rgba + minStart); + break; + case GL_LINEAR_MIPMAP_LINEAR: + sample_3d_linear_mipmap_linear(ctx, tObj, m, texcoords + minStart, + lambda + minStart, rgba + minStart); + break; + default: + _mesa_problem(ctx, "Bad min filter in sample_3d_texture"); + return; + } + } + + if (magStart < magEnd) { + /* do the magnified texels */ + switch (tObj->Sampler.MagFilter) { + case GL_NEAREST: + for (i = magStart; i < magEnd; i++) + sample_3d_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel], + texcoords[i], rgba[i]); + break; + case GL_LINEAR: + for (i = magStart; i < magEnd; i++) + sample_3d_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel], + texcoords[i], rgba[i]); + break; + default: + _mesa_problem(ctx, "Bad mag filter in sample_3d_texture"); + return; + } + } +} + + +/**********************************************************************/ +/* Texture Cube Map Sampling Functions */ +/**********************************************************************/ + +/** + * Choose one of six sides of a texture cube map given the texture + * coord (rx,ry,rz). Return pointer to corresponding array of texture + * images. + */ +static const struct gl_texture_image ** +choose_cube_face(const struct gl_texture_object *texObj, + const GLfloat texcoord[4], GLfloat newCoord[4]) +{ + /* + major axis + direction target sc tc ma + ---------- ------------------------------- --- --- --- + +rx TEXTURE_CUBE_MAP_POSITIVE_X_EXT -rz -ry rx + -rx TEXTURE_CUBE_MAP_NEGATIVE_X_EXT +rz -ry rx + +ry TEXTURE_CUBE_MAP_POSITIVE_Y_EXT +rx +rz ry + -ry TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT +rx -rz ry + +rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz + -rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz + */ + const GLfloat rx = texcoord[0]; + const GLfloat ry = texcoord[1]; + const GLfloat rz = texcoord[2]; + const GLfloat arx = FABSF(rx), ary = FABSF(ry), arz = FABSF(rz); + GLuint face; + GLfloat sc, tc, ma; + + if (arx >= ary && arx >= arz) { + if (rx >= 0.0F) { + face = FACE_POS_X; + sc = -rz; + tc = -ry; + ma = arx; + } + else { + face = FACE_NEG_X; + sc = rz; + tc = -ry; + ma = arx; + } + } + else if (ary >= arx && ary >= arz) { + if (ry >= 0.0F) { + face = FACE_POS_Y; + sc = rx; + tc = rz; + ma = ary; + } + else { + face = FACE_NEG_Y; + sc = rx; + tc = -rz; + ma = ary; + } + } + else { + if (rz > 0.0F) { + face = FACE_POS_Z; + sc = rx; + tc = -ry; + ma = arz; + } + else { + face = FACE_NEG_Z; + sc = -rx; + tc = -ry; + ma = arz; + } + } + + { + const float ima = 1.0F / ma; + newCoord[0] = ( sc * ima + 1.0F ) * 0.5F; + newCoord[1] = ( tc * ima + 1.0F ) * 0.5F; + } + + return (const struct gl_texture_image **) texObj->Image[face]; +} + + +static void +sample_nearest_cube(struct gl_context *ctx, + const struct gl_texture_object *tObj, GLuint n, + const GLfloat texcoords[][4], const GLfloat lambda[], + GLfloat rgba[][4]) +{ + GLuint i; + (void) lambda; + for (i = 0; i < n; i++) { + const struct gl_texture_image **images; + GLfloat newCoord[4]; + images = choose_cube_face(tObj, texcoords[i], newCoord); + sample_2d_nearest(ctx, tObj, images[tObj->BaseLevel], + newCoord, rgba[i]); + } +} + + +static void +sample_linear_cube(struct gl_context *ctx, + const struct gl_texture_object *tObj, GLuint n, + const GLfloat texcoords[][4], + const GLfloat lambda[], GLfloat rgba[][4]) +{ + GLuint i; + (void) lambda; + for (i = 0; i < n; i++) { + const struct gl_texture_image **images; + GLfloat newCoord[4]; + images = choose_cube_face(tObj, texcoords[i], newCoord); + sample_2d_linear(ctx, tObj, images[tObj->BaseLevel], + newCoord, rgba[i]); + } +} + + +static void +sample_cube_nearest_mipmap_nearest(struct gl_context *ctx, + const struct gl_texture_object *tObj, + GLuint n, const GLfloat texcoord[][4], + const GLfloat lambda[], GLfloat rgba[][4]) +{ + GLuint i; + ASSERT(lambda != NULL); + for (i = 0; i < n; i++) { + const struct gl_texture_image **images; + GLfloat newCoord[4]; + GLint level; + images = choose_cube_face(tObj, texcoord[i], newCoord); + + /* XXX we actually need to recompute lambda here based on the newCoords. + * But we would need the texcoords of adjacent fragments to compute that + * properly, and we don't have those here. + * For now, do an approximation: subtracting 1 from the chosen mipmap + * level seems to work in some test cases. + * The same adjustment is done in the next few functions. + */ + level = nearest_mipmap_level(tObj, lambda[i]); + level = MAX2(level - 1, 0); + + sample_2d_nearest(ctx, tObj, images[level], newCoord, rgba[i]); + } +} + + +static void +sample_cube_linear_mipmap_nearest(struct gl_context *ctx, + const struct gl_texture_object *tObj, + GLuint n, const GLfloat texcoord[][4], + const GLfloat lambda[], GLfloat rgba[][4]) +{ + GLuint i; + ASSERT(lambda != NULL); + for (i = 0; i < n; i++) { + const struct gl_texture_image **images; + GLfloat newCoord[4]; + GLint level = nearest_mipmap_level(tObj, lambda[i]); + level = MAX2(level - 1, 0); /* see comment above */ + images = choose_cube_face(tObj, texcoord[i], newCoord); + sample_2d_linear(ctx, tObj, images[level], newCoord, rgba[i]); + } +} + + +static void +sample_cube_nearest_mipmap_linear(struct gl_context *ctx, + const struct gl_texture_object *tObj, + GLuint n, const GLfloat texcoord[][4], + const GLfloat lambda[], GLfloat rgba[][4]) +{ + GLuint i; + ASSERT(lambda != NULL); + for (i = 0; i < n; i++) { + const struct gl_texture_image **images; + GLfloat newCoord[4]; + GLint level = linear_mipmap_level(tObj, lambda[i]); + level = MAX2(level - 1, 0); /* see comment above */ + images = choose_cube_face(tObj, texcoord[i], newCoord); + if (level >= tObj->_MaxLevel) { + sample_2d_nearest(ctx, tObj, images[tObj->_MaxLevel], + newCoord, rgba[i]); + } + else { + GLfloat t0[4], t1[4]; /* texels */ + const GLfloat f = FRAC(lambda[i]); + sample_2d_nearest(ctx, tObj, images[level ], newCoord, t0); + sample_2d_nearest(ctx, tObj, images[level+1], newCoord, t1); + lerp_rgba(rgba[i], f, t0, t1); + } + } +} + + +static void +sample_cube_linear_mipmap_linear(struct gl_context *ctx, + const struct gl_texture_object *tObj, + GLuint n, const GLfloat texcoord[][4], + const GLfloat lambda[], GLfloat rgba[][4]) +{ + GLuint i; + ASSERT(lambda != NULL); + for (i = 0; i < n; i++) { + const struct gl_texture_image **images; + GLfloat newCoord[4]; + GLint level = linear_mipmap_level(tObj, lambda[i]); + level = MAX2(level - 1, 0); /* see comment above */ + images = choose_cube_face(tObj, texcoord[i], newCoord); + if (level >= tObj->_MaxLevel) { + sample_2d_linear(ctx, tObj, images[tObj->_MaxLevel], + newCoord, rgba[i]); + } + else { + GLfloat t0[4], t1[4]; + const GLfloat f = FRAC(lambda[i]); + sample_2d_linear(ctx, tObj, images[level ], newCoord, t0); + sample_2d_linear(ctx, tObj, images[level+1], newCoord, t1); + lerp_rgba(rgba[i], f, t0, t1); + } + } +} + + +/** Sample cube texture, using lambda to choose between min/magnification */ +static void +sample_lambda_cube(struct gl_context *ctx, + const struct gl_texture_object *tObj, GLuint n, + const GLfloat texcoords[][4], const GLfloat lambda[], + GLfloat rgba[][4]) +{ + GLuint minStart, minEnd; /* texels with minification */ + GLuint magStart, magEnd; /* texels with magnification */ + + ASSERT(lambda != NULL); + compute_min_mag_ranges(tObj, n, lambda, + &minStart, &minEnd, &magStart, &magEnd); + + if (minStart < minEnd) { + /* do the minified texels */ + const GLuint m = minEnd - minStart; + switch (tObj->Sampler.MinFilter) { + case GL_NEAREST: + sample_nearest_cube(ctx, tObj, m, texcoords + minStart, + lambda + minStart, rgba + minStart); + break; + case GL_LINEAR: + sample_linear_cube(ctx, tObj, m, texcoords + minStart, + lambda + minStart, rgba + minStart); + break; + case GL_NEAREST_MIPMAP_NEAREST: + sample_cube_nearest_mipmap_nearest(ctx, tObj, m, + texcoords + minStart, + lambda + minStart, rgba + minStart); + break; + case GL_LINEAR_MIPMAP_NEAREST: + sample_cube_linear_mipmap_nearest(ctx, tObj, m, + texcoords + minStart, + lambda + minStart, rgba + minStart); + break; + case GL_NEAREST_MIPMAP_LINEAR: + sample_cube_nearest_mipmap_linear(ctx, tObj, m, + texcoords + minStart, + lambda + minStart, rgba + minStart); + break; + case GL_LINEAR_MIPMAP_LINEAR: + sample_cube_linear_mipmap_linear(ctx, tObj, m, + texcoords + minStart, + lambda + minStart, rgba + minStart); + break; + default: + _mesa_problem(ctx, "Bad min filter in sample_lambda_cube"); + } + } + + if (magStart < magEnd) { + /* do the magnified texels */ + const GLuint m = magEnd - magStart; + switch (tObj->Sampler.MagFilter) { + case GL_NEAREST: + sample_nearest_cube(ctx, tObj, m, texcoords + magStart, + lambda + magStart, rgba + magStart); + break; + case GL_LINEAR: + sample_linear_cube(ctx, tObj, m, texcoords + magStart, + lambda + magStart, rgba + magStart); + break; + default: + _mesa_problem(ctx, "Bad mag filter in sample_lambda_cube"); + } + } +} + + +/**********************************************************************/ +/* Texture Rectangle Sampling Functions */ +/**********************************************************************/ + + +static void +sample_nearest_rect(struct gl_context *ctx, + const struct gl_texture_object *tObj, GLuint n, + const GLfloat texcoords[][4], const GLfloat lambda[], + GLfloat rgba[][4]) +{ + const struct gl_texture_image *img = tObj->Image[0][0]; + const GLint width = img->Width; + const GLint height = img->Height; + GLuint i; + + (void) ctx; + (void) lambda; + + ASSERT(tObj->Sampler.WrapS == GL_CLAMP || + tObj->Sampler.WrapS == GL_CLAMP_TO_EDGE || + tObj->Sampler.WrapS == GL_CLAMP_TO_BORDER); + ASSERT(tObj->Sampler.WrapT == GL_CLAMP || + tObj->Sampler.WrapT == GL_CLAMP_TO_EDGE || + tObj->Sampler.WrapT == GL_CLAMP_TO_BORDER); + + for (i = 0; i < n; i++) { + GLint row, col; + col = clamp_rect_coord_nearest(tObj->Sampler.WrapS, texcoords[i][0], width); + row = clamp_rect_coord_nearest(tObj->Sampler.WrapT, texcoords[i][1], height); + if (col < 0 || col >= width || row < 0 || row >= height) + get_border_color(tObj, img, rgba[i]); + else + img->FetchTexelf(img, col, row, 0, rgba[i]); + } +} + + +static void +sample_linear_rect(struct gl_context *ctx, + const struct gl_texture_object *tObj, GLuint n, + const GLfloat texcoords[][4], + const GLfloat lambda[], GLfloat rgba[][4]) +{ + const struct gl_texture_image *img = tObj->Image[0][0]; + const GLint width = img->Width; + const GLint height = img->Height; + GLuint i; + + (void) ctx; + (void) lambda; + + ASSERT(tObj->Sampler.WrapS == GL_CLAMP || + tObj->Sampler.WrapS == GL_CLAMP_TO_EDGE || + tObj->Sampler.WrapS == GL_CLAMP_TO_BORDER); + ASSERT(tObj->Sampler.WrapT == GL_CLAMP || + tObj->Sampler.WrapT == GL_CLAMP_TO_EDGE || + tObj->Sampler.WrapT == GL_CLAMP_TO_BORDER); + + for (i = 0; i < n; i++) { + GLint i0, j0, i1, j1; + GLfloat t00[4], t01[4], t10[4], t11[4]; + GLfloat a, b; + GLbitfield useBorderColor = 0x0; + + clamp_rect_coord_linear(tObj->Sampler.WrapS, texcoords[i][0], width, + &i0, &i1, &a); + clamp_rect_coord_linear(tObj->Sampler.WrapT, texcoords[i][1], height, + &j0, &j1, &b); + + /* compute integer rows/columns */ + if (i0 < 0 || i0 >= width) useBorderColor |= I0BIT; + if (i1 < 0 || i1 >= width) useBorderColor |= I1BIT; + if (j0 < 0 || j0 >= height) useBorderColor |= J0BIT; + if (j1 < 0 || j1 >= height) useBorderColor |= J1BIT; + + /* get four texel samples */ + if (useBorderColor & (I0BIT | J0BIT)) + get_border_color(tObj, img, t00); + else + img->FetchTexelf(img, i0, j0, 0, t00); + + if (useBorderColor & (I1BIT | J0BIT)) + get_border_color(tObj, img, t10); + else + img->FetchTexelf(img, i1, j0, 0, t10); + + if (useBorderColor & (I0BIT | J1BIT)) + get_border_color(tObj, img, t01); + else + img->FetchTexelf(img, i0, j1, 0, t01); + + if (useBorderColor & (I1BIT | J1BIT)) + get_border_color(tObj, img, t11); + else + img->FetchTexelf(img, i1, j1, 0, t11); + + lerp_rgba_2d(rgba[i], a, b, t00, t10, t01, t11); + } +} + + +/** Sample Rect texture, using lambda to choose between min/magnification */ +static void +sample_lambda_rect(struct gl_context *ctx, + const struct gl_texture_object *tObj, GLuint n, + const GLfloat texcoords[][4], const GLfloat lambda[], + GLfloat rgba[][4]) +{ + GLuint minStart, minEnd, magStart, magEnd; + + /* We only need lambda to decide between minification and magnification. + * There is no mipmapping with rectangular textures. + */ + compute_min_mag_ranges(tObj, n, lambda, + &minStart, &minEnd, &magStart, &magEnd); + + if (minStart < minEnd) { + if (tObj->Sampler.MinFilter == GL_NEAREST) { + sample_nearest_rect(ctx, tObj, minEnd - minStart, + texcoords + minStart, NULL, rgba + minStart); + } + else { + sample_linear_rect(ctx, tObj, minEnd - minStart, + texcoords + minStart, NULL, rgba + minStart); + } + } + if (magStart < magEnd) { + if (tObj->Sampler.MagFilter == GL_NEAREST) { + sample_nearest_rect(ctx, tObj, magEnd - magStart, + texcoords + magStart, NULL, rgba + magStart); + } + else { + sample_linear_rect(ctx, tObj, magEnd - magStart, + texcoords + magStart, NULL, rgba + magStart); + } + } +} + + +/**********************************************************************/ +/* 2D Texture Array Sampling Functions */ +/**********************************************************************/ + +/** + * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter. + */ +static void +sample_2d_array_nearest(struct gl_context *ctx, + const struct gl_texture_object *tObj, + const struct gl_texture_image *img, + const GLfloat texcoord[4], + GLfloat rgba[4]) +{ + const GLint width = img->Width2; /* without border, power of two */ + const GLint height = img->Height2; /* without border, power of two */ + const GLint depth = img->Depth; + GLint i, j; + GLint array; + (void) ctx; + + i = nearest_texel_location(tObj->Sampler.WrapS, img, width, texcoord[0]); + j = nearest_texel_location(tObj->Sampler.WrapT, img, height, texcoord[1]); + array = tex_array_slice(texcoord[2], depth); + + if (i < 0 || i >= (GLint) img->Width || + j < 0 || j >= (GLint) img->Height || + array < 0 || array >= (GLint) img->Depth) { + /* Need this test for GL_CLAMP_TO_BORDER mode */ + get_border_color(tObj, img, rgba); + } + else { + img->FetchTexelf(img, i, j, array, rgba); + } +} + + +/** + * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter. + */ +static void +sample_2d_array_linear(struct gl_context *ctx, + const struct gl_texture_object *tObj, + const struct gl_texture_image *img, + const GLfloat texcoord[4], + GLfloat rgba[4]) +{ + const GLint width = img->Width2; + const GLint height = img->Height2; + const GLint depth = img->Depth; + GLint i0, j0, i1, j1; + GLint array; + GLbitfield useBorderColor = 0x0; + GLfloat a, b; + GLfloat t00[4], t01[4], t10[4], t11[4]; + + linear_texel_locations(tObj->Sampler.WrapS, img, width, texcoord[0], &i0, &i1, &a); + linear_texel_locations(tObj->Sampler.WrapT, img, height, texcoord[1], &j0, &j1, &b); + array = tex_array_slice(texcoord[2], depth); + + if (array < 0 || array >= depth) { + COPY_4V(rgba, tObj->Sampler.BorderColor.f); + } + else { + if (img->Border) { + i0 += img->Border; + i1 += img->Border; + j0 += img->Border; + j1 += img->Border; + } + else { + /* check if sampling texture border color */ + if (i0 < 0 || i0 >= width) useBorderColor |= I0BIT; + if (i1 < 0 || i1 >= width) useBorderColor |= I1BIT; + if (j0 < 0 || j0 >= height) useBorderColor |= J0BIT; + if (j1 < 0 || j1 >= height) useBorderColor |= J1BIT; + } + + /* Fetch texels */ + if (useBorderColor & (I0BIT | J0BIT)) { + get_border_color(tObj, img, t00); + } + else { + img->FetchTexelf(img, i0, j0, array, t00); + } + if (useBorderColor & (I1BIT | J0BIT)) { + get_border_color(tObj, img, t10); + } + else { + img->FetchTexelf(img, i1, j0, array, t10); + } + if (useBorderColor & (I0BIT | J1BIT)) { + get_border_color(tObj, img, t01); + } + else { + img->FetchTexelf(img, i0, j1, array, t01); + } + if (useBorderColor & (I1BIT | J1BIT)) { + get_border_color(tObj, img, t11); + } + else { + img->FetchTexelf(img, i1, j1, array, t11); + } + + /* trilinear interpolation of samples */ + lerp_rgba_2d(rgba, a, b, t00, t10, t01, t11); + } +} + + +static void +sample_2d_array_nearest_mipmap_nearest(struct gl_context *ctx, + const struct gl_texture_object *tObj, + GLuint n, const GLfloat texcoord[][4], + const GLfloat lambda[], GLfloat rgba[][4]) +{ + GLuint i; + for (i = 0; i < n; i++) { + GLint level = nearest_mipmap_level(tObj, lambda[i]); + sample_2d_array_nearest(ctx, tObj, tObj->Image[0][level], texcoord[i], + rgba[i]); + } +} + + +static void +sample_2d_array_linear_mipmap_nearest(struct gl_context *ctx, + const struct gl_texture_object *tObj, + GLuint n, const GLfloat texcoord[][4], + const GLfloat lambda[], GLfloat rgba[][4]) +{ + GLuint i; + ASSERT(lambda != NULL); + for (i = 0; i < n; i++) { + GLint level = nearest_mipmap_level(tObj, lambda[i]); + sample_2d_array_linear(ctx, tObj, tObj->Image[0][level], + texcoord[i], rgba[i]); + } +} + + +static void +sample_2d_array_nearest_mipmap_linear(struct gl_context *ctx, + const struct gl_texture_object *tObj, + GLuint n, const GLfloat texcoord[][4], + const GLfloat lambda[], GLfloat rgba[][4]) +{ + GLuint i; + ASSERT(lambda != NULL); + for (i = 0; i < n; i++) { + GLint level = linear_mipmap_level(tObj, lambda[i]); + if (level >= tObj->_MaxLevel) { + sample_2d_array_nearest(ctx, tObj, tObj->Image[0][tObj->_MaxLevel], + texcoord[i], rgba[i]); + } + else { + GLfloat t0[4], t1[4]; /* texels */ + const GLfloat f = FRAC(lambda[i]); + sample_2d_array_nearest(ctx, tObj, tObj->Image[0][level ], + texcoord[i], t0); + sample_2d_array_nearest(ctx, tObj, tObj->Image[0][level+1], + texcoord[i], t1); + lerp_rgba(rgba[i], f, t0, t1); + } + } +} + + +static void +sample_2d_array_linear_mipmap_linear(struct gl_context *ctx, + const struct gl_texture_object *tObj, + GLuint n, const GLfloat texcoord[][4], + const GLfloat lambda[], GLfloat rgba[][4]) +{ + GLuint i; + ASSERT(lambda != NULL); + for (i = 0; i < n; i++) { + GLint level = linear_mipmap_level(tObj, lambda[i]); + if (level >= tObj->_MaxLevel) { + sample_2d_array_linear(ctx, tObj, tObj->Image[0][tObj->_MaxLevel], + texcoord[i], rgba[i]); + } + else { + GLfloat t0[4], t1[4]; /* texels */ + const GLfloat f = FRAC(lambda[i]); + sample_2d_array_linear(ctx, tObj, tObj->Image[0][level ], + texcoord[i], t0); + sample_2d_array_linear(ctx, tObj, tObj->Image[0][level+1], + texcoord[i], t1); + lerp_rgba(rgba[i], f, t0, t1); + } + } +} + + +/** Sample 2D Array texture, nearest filtering for both min/magnification */ +static void +sample_nearest_2d_array(struct gl_context *ctx, + const struct gl_texture_object *tObj, GLuint n, + const GLfloat texcoords[][4], const GLfloat lambda[], + GLfloat rgba[][4]) +{ + GLuint i; + struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel]; + (void) lambda; + for (i = 0; i < n; i++) { + sample_2d_array_nearest(ctx, tObj, image, texcoords[i], rgba[i]); + } +} + + + +/** Sample 2D Array texture, linear filtering for both min/magnification */ +static void +sample_linear_2d_array(struct gl_context *ctx, + const struct gl_texture_object *tObj, GLuint n, + const GLfloat texcoords[][4], + const GLfloat lambda[], GLfloat rgba[][4]) +{ + GLuint i; + struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel]; + (void) lambda; + for (i = 0; i < n; i++) { + sample_2d_array_linear(ctx, tObj, image, texcoords[i], rgba[i]); + } +} + + +/** Sample 2D Array texture, using lambda to choose between min/magnification */ +static void +sample_lambda_2d_array(struct gl_context *ctx, + const struct gl_texture_object *tObj, GLuint n, + const GLfloat texcoords[][4], const GLfloat lambda[], + GLfloat rgba[][4]) +{ + GLuint minStart, minEnd; /* texels with minification */ + GLuint magStart, magEnd; /* texels with magnification */ + GLuint i; + + ASSERT(lambda != NULL); + compute_min_mag_ranges(tObj, n, lambda, + &minStart, &minEnd, &magStart, &magEnd); + + if (minStart < minEnd) { + /* do the minified texels */ + GLuint m = minEnd - minStart; + switch (tObj->Sampler.MinFilter) { + case GL_NEAREST: + for (i = minStart; i < minEnd; i++) + sample_2d_array_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel], + texcoords[i], rgba[i]); + break; + case GL_LINEAR: + for (i = minStart; i < minEnd; i++) + sample_2d_array_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel], + texcoords[i], rgba[i]); + break; + case GL_NEAREST_MIPMAP_NEAREST: + sample_2d_array_nearest_mipmap_nearest(ctx, tObj, m, + texcoords + minStart, + lambda + minStart, + rgba + minStart); + break; + case GL_LINEAR_MIPMAP_NEAREST: + sample_2d_array_linear_mipmap_nearest(ctx, tObj, m, + texcoords + minStart, + lambda + minStart, + rgba + minStart); + break; + case GL_NEAREST_MIPMAP_LINEAR: + sample_2d_array_nearest_mipmap_linear(ctx, tObj, m, + texcoords + minStart, + lambda + minStart, + rgba + minStart); + break; + case GL_LINEAR_MIPMAP_LINEAR: + sample_2d_array_linear_mipmap_linear(ctx, tObj, m, + texcoords + minStart, + lambda + minStart, + rgba + minStart); + break; + default: + _mesa_problem(ctx, "Bad min filter in sample_2d_array_texture"); + return; + } + } + + if (magStart < magEnd) { + /* do the magnified texels */ + switch (tObj->Sampler.MagFilter) { + case GL_NEAREST: + for (i = magStart; i < magEnd; i++) + sample_2d_array_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel], + texcoords[i], rgba[i]); + break; + case GL_LINEAR: + for (i = magStart; i < magEnd; i++) + sample_2d_array_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel], + texcoords[i], rgba[i]); + break; + default: + _mesa_problem(ctx, "Bad mag filter in sample_2d_array_texture"); + return; + } + } +} + + + + +/**********************************************************************/ +/* 1D Texture Array Sampling Functions */ +/**********************************************************************/ + +/** + * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter. + */ +static void +sample_1d_array_nearest(struct gl_context *ctx, + const struct gl_texture_object *tObj, + const struct gl_texture_image *img, + const GLfloat texcoord[4], + GLfloat rgba[4]) +{ + const GLint width = img->Width2; /* without border, power of two */ + const GLint height = img->Height; + GLint i; + GLint array; + (void) ctx; + + i = nearest_texel_location(tObj->Sampler.WrapS, img, width, texcoord[0]); + array = tex_array_slice(texcoord[1], height); + + if (i < 0 || i >= (GLint) img->Width || + array < 0 || array >= (GLint) img->Height) { + /* Need this test for GL_CLAMP_TO_BORDER mode */ + get_border_color(tObj, img, rgba); + } + else { + img->FetchTexelf(img, i, array, 0, rgba); + } +} + + +/** + * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter. + */ +static void +sample_1d_array_linear(struct gl_context *ctx, + const struct gl_texture_object *tObj, + const struct gl_texture_image *img, + const GLfloat texcoord[4], + GLfloat rgba[4]) +{ + const GLint width = img->Width2; + const GLint height = img->Height; + GLint i0, i1; + GLint array; + GLbitfield useBorderColor = 0x0; + GLfloat a; + GLfloat t0[4], t1[4]; + + linear_texel_locations(tObj->Sampler.WrapS, img, width, texcoord[0], &i0, &i1, &a); + array = tex_array_slice(texcoord[1], height); + + if (img->Border) { + i0 += img->Border; + i1 += img->Border; + } + else { + /* check if sampling texture border color */ + if (i0 < 0 || i0 >= width) useBorderColor |= I0BIT; + if (i1 < 0 || i1 >= width) useBorderColor |= I1BIT; + } + + if (array < 0 || array >= height) useBorderColor |= K0BIT; + + /* Fetch texels */ + if (useBorderColor & (I0BIT | K0BIT)) { + get_border_color(tObj, img, t0); + } + else { + img->FetchTexelf(img, i0, array, 0, t0); + } + if (useBorderColor & (I1BIT | K0BIT)) { + get_border_color(tObj, img, t1); + } + else { + img->FetchTexelf(img, i1, array, 0, t1); + } + + /* bilinear interpolation of samples */ + lerp_rgba(rgba, a, t0, t1); +} + + +static void +sample_1d_array_nearest_mipmap_nearest(struct gl_context *ctx, + const struct gl_texture_object *tObj, + GLuint n, const GLfloat texcoord[][4], + const GLfloat lambda[], GLfloat rgba[][4]) +{ + GLuint i; + for (i = 0; i < n; i++) { + GLint level = nearest_mipmap_level(tObj, lambda[i]); + sample_1d_array_nearest(ctx, tObj, tObj->Image[0][level], texcoord[i], + rgba[i]); + } +} + + +static void +sample_1d_array_linear_mipmap_nearest(struct gl_context *ctx, + const struct gl_texture_object *tObj, + GLuint n, const GLfloat texcoord[][4], + const GLfloat lambda[], GLfloat rgba[][4]) +{ + GLuint i; + ASSERT(lambda != NULL); + for (i = 0; i < n; i++) { + GLint level = nearest_mipmap_level(tObj, lambda[i]); + sample_1d_array_linear(ctx, tObj, tObj->Image[0][level], + texcoord[i], rgba[i]); + } +} + + +static void +sample_1d_array_nearest_mipmap_linear(struct gl_context *ctx, + const struct gl_texture_object *tObj, + GLuint n, const GLfloat texcoord[][4], + const GLfloat lambda[], GLfloat rgba[][4]) +{ + GLuint i; + ASSERT(lambda != NULL); + for (i = 0; i < n; i++) { + GLint level = linear_mipmap_level(tObj, lambda[i]); + if (level >= tObj->_MaxLevel) { + sample_1d_array_nearest(ctx, tObj, tObj->Image[0][tObj->_MaxLevel], + texcoord[i], rgba[i]); + } + else { + GLfloat t0[4], t1[4]; /* texels */ + const GLfloat f = FRAC(lambda[i]); + sample_1d_array_nearest(ctx, tObj, tObj->Image[0][level ], texcoord[i], t0); + sample_1d_array_nearest(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1); + lerp_rgba(rgba[i], f, t0, t1); + } + } +} + + +static void +sample_1d_array_linear_mipmap_linear(struct gl_context *ctx, + const struct gl_texture_object *tObj, + GLuint n, const GLfloat texcoord[][4], + const GLfloat lambda[], GLfloat rgba[][4]) +{ + GLuint i; + ASSERT(lambda != NULL); + for (i = 0; i < n; i++) { + GLint level = linear_mipmap_level(tObj, lambda[i]); + if (level >= tObj->_MaxLevel) { + sample_1d_array_linear(ctx, tObj, tObj->Image[0][tObj->_MaxLevel], + texcoord[i], rgba[i]); + } + else { + GLfloat t0[4], t1[4]; /* texels */ + const GLfloat f = FRAC(lambda[i]); + sample_1d_array_linear(ctx, tObj, tObj->Image[0][level ], texcoord[i], t0); + sample_1d_array_linear(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1); + lerp_rgba(rgba[i], f, t0, t1); + } + } +} + + +/** Sample 1D Array texture, nearest filtering for both min/magnification */ +static void +sample_nearest_1d_array(struct gl_context *ctx, + const struct gl_texture_object *tObj, GLuint n, + const GLfloat texcoords[][4], const GLfloat lambda[], + GLfloat rgba[][4]) +{ + GLuint i; + struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel]; + (void) lambda; + for (i = 0; i < n; i++) { + sample_1d_array_nearest(ctx, tObj, image, texcoords[i], rgba[i]); + } +} + + +/** Sample 1D Array texture, linear filtering for both min/magnification */ +static void +sample_linear_1d_array(struct gl_context *ctx, + const struct gl_texture_object *tObj, GLuint n, + const GLfloat texcoords[][4], + const GLfloat lambda[], GLfloat rgba[][4]) +{ + GLuint i; + struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel]; + (void) lambda; + for (i = 0; i < n; i++) { + sample_1d_array_linear(ctx, tObj, image, texcoords[i], rgba[i]); + } +} + + +/** Sample 1D Array texture, using lambda to choose between min/magnification */ +static void +sample_lambda_1d_array(struct gl_context *ctx, + const struct gl_texture_object *tObj, GLuint n, + const GLfloat texcoords[][4], const GLfloat lambda[], + GLfloat rgba[][4]) +{ + GLuint minStart, minEnd; /* texels with minification */ + GLuint magStart, magEnd; /* texels with magnification */ + GLuint i; + + ASSERT(lambda != NULL); + compute_min_mag_ranges(tObj, n, lambda, + &minStart, &minEnd, &magStart, &magEnd); + + if (minStart < minEnd) { + /* do the minified texels */ + GLuint m = minEnd - minStart; + switch (tObj->Sampler.MinFilter) { + case GL_NEAREST: + for (i = minStart; i < minEnd; i++) + sample_1d_array_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel], + texcoords[i], rgba[i]); + break; + case GL_LINEAR: + for (i = minStart; i < minEnd; i++) + sample_1d_array_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel], + texcoords[i], rgba[i]); + break; + case GL_NEAREST_MIPMAP_NEAREST: + sample_1d_array_nearest_mipmap_nearest(ctx, tObj, m, texcoords + minStart, + lambda + minStart, rgba + minStart); + break; + case GL_LINEAR_MIPMAP_NEAREST: + sample_1d_array_linear_mipmap_nearest(ctx, tObj, m, + texcoords + minStart, + lambda + minStart, + rgba + minStart); + break; + case GL_NEAREST_MIPMAP_LINEAR: + sample_1d_array_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart, + lambda + minStart, rgba + minStart); + break; + case GL_LINEAR_MIPMAP_LINEAR: + sample_1d_array_linear_mipmap_linear(ctx, tObj, m, + texcoords + minStart, + lambda + minStart, + rgba + minStart); + break; + default: + _mesa_problem(ctx, "Bad min filter in sample_1d_array_texture"); + return; + } + } + + if (magStart < magEnd) { + /* do the magnified texels */ + switch (tObj->Sampler.MagFilter) { + case GL_NEAREST: + for (i = magStart; i < magEnd; i++) + sample_1d_array_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel], + texcoords[i], rgba[i]); + break; + case GL_LINEAR: + for (i = magStart; i < magEnd; i++) + sample_1d_array_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel], + texcoords[i], rgba[i]); + break; + default: + _mesa_problem(ctx, "Bad mag filter in sample_1d_array_texture"); + return; + } + } +} + + +/** + * Compare texcoord against depth sample. Return 1.0 or the ambient value. + */ +static INLINE GLfloat +shadow_compare(GLenum function, GLfloat coord, GLfloat depthSample, + GLfloat ambient) +{ + switch (function) { + case GL_LEQUAL: + return (coord <= depthSample) ? 1.0F : ambient; + case GL_GEQUAL: + return (coord >= depthSample) ? 1.0F : ambient; + case GL_LESS: + return (coord < depthSample) ? 1.0F : ambient; + case GL_GREATER: + return (coord > depthSample) ? 1.0F : ambient; + case GL_EQUAL: + return (coord == depthSample) ? 1.0F : ambient; + case GL_NOTEQUAL: + return (coord != depthSample) ? 1.0F : ambient; + case GL_ALWAYS: + return 1.0F; + case GL_NEVER: + return ambient; + case GL_NONE: + return depthSample; + default: + _mesa_problem(NULL, "Bad compare func in shadow_compare"); + return ambient; + } +} + + +/** + * Compare texcoord against four depth samples. + */ +static INLINE GLfloat +shadow_compare4(GLenum function, GLfloat coord, + GLfloat depth00, GLfloat depth01, + GLfloat depth10, GLfloat depth11, + GLfloat ambient, GLfloat wi, GLfloat wj) +{ + const GLfloat d = (1.0F - (GLfloat) ambient) * 0.25F; + GLfloat luminance = 1.0F; + + switch (function) { + case GL_LEQUAL: + if (coord > depth00) luminance -= d; + if (coord > depth01) luminance -= d; + if (coord > depth10) luminance -= d; + if (coord > depth11) luminance -= d; + return luminance; + case GL_GEQUAL: + if (coord < depth00) luminance -= d; + if (coord < depth01) luminance -= d; + if (coord < depth10) luminance -= d; + if (coord < depth11) luminance -= d; + return luminance; + case GL_LESS: + if (coord >= depth00) luminance -= d; + if (coord >= depth01) luminance -= d; + if (coord >= depth10) luminance -= d; + if (coord >= depth11) luminance -= d; + return luminance; + case GL_GREATER: + if (coord <= depth00) luminance -= d; + if (coord <= depth01) luminance -= d; + if (coord <= depth10) luminance -= d; + if (coord <= depth11) luminance -= d; + return luminance; + case GL_EQUAL: + if (coord != depth00) luminance -= d; + if (coord != depth01) luminance -= d; + if (coord != depth10) luminance -= d; + if (coord != depth11) luminance -= d; + return luminance; + case GL_NOTEQUAL: + if (coord == depth00) luminance -= d; + if (coord == depth01) luminance -= d; + if (coord == depth10) luminance -= d; + if (coord == depth11) luminance -= d; + return luminance; + case GL_ALWAYS: + return 1.0F; + case GL_NEVER: + return ambient; + case GL_NONE: + /* ordinary bilinear filtering */ + return lerp_2d(wi, wj, depth00, depth10, depth01, depth11); + default: + _mesa_problem(NULL, "Bad compare func in sample_compare4"); + return ambient; + } +} + + +/** + * Choose the mipmap level to use when sampling from a depth texture. + */ +static int +choose_depth_texture_level(const struct gl_texture_object *tObj, GLfloat lambda) +{ + GLint level; + + if (tObj->Sampler.MinFilter == GL_NEAREST || tObj->Sampler.MinFilter == GL_LINEAR) { + /* no mipmapping - use base level */ + level = tObj->BaseLevel; + } + else { + /* choose mipmap level */ + lambda = CLAMP(lambda, tObj->Sampler.MinLod, tObj->Sampler.MaxLod); + level = (GLint) lambda; + level = CLAMP(level, tObj->BaseLevel, tObj->_MaxLevel); + } + + return level; +} + + +/** + * Sample a shadow/depth texture. This function is incomplete. It doesn't + * check for minification vs. magnification, etc. + */ +static void +sample_depth_texture( struct gl_context *ctx, + const struct gl_texture_object *tObj, GLuint n, + const GLfloat texcoords[][4], const GLfloat lambda[], + GLfloat texel[][4] ) +{ + const GLint level = choose_depth_texture_level(tObj, lambda[0]); + const struct gl_texture_image *img = tObj->Image[0][level]; + const GLint width = img->Width; + const GLint height = img->Height; + const GLint depth = img->Depth; + const GLuint compare_coord = (tObj->Target == GL_TEXTURE_2D_ARRAY_EXT) + ? 3 : 2; + GLfloat ambient; + GLenum function; + GLfloat result; + + ASSERT(img->_BaseFormat == GL_DEPTH_COMPONENT || + img->_BaseFormat == GL_DEPTH_STENCIL_EXT); + + ASSERT(tObj->Target == GL_TEXTURE_1D || + tObj->Target == GL_TEXTURE_2D || + tObj->Target == GL_TEXTURE_RECTANGLE_NV || + tObj->Target == GL_TEXTURE_1D_ARRAY_EXT || + tObj->Target == GL_TEXTURE_2D_ARRAY_EXT); + + ambient = tObj->Sampler.CompareFailValue; + + /* XXXX if tObj->Sampler.MinFilter != tObj->Sampler.MagFilter, we're ignoring lambda */ + + function = (tObj->Sampler.CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB) ? + tObj->Sampler.CompareFunc : GL_NONE; + + if (tObj->Sampler.MagFilter == GL_NEAREST) { + GLuint i; + for (i = 0; i < n; i++) { + GLfloat depthSample, depthRef; + GLint col, row, slice; + + nearest_texcoord(tObj, level, texcoords[i], &col, &row, &slice); + + if (col >= 0 && row >= 0 && col < width && row < height && + slice >= 0 && slice < depth) { + img->FetchTexelf(img, col, row, slice, &depthSample); + } + else { + depthSample = tObj->Sampler.BorderColor.f[0]; + } + + depthRef = CLAMP(texcoords[i][compare_coord], 0.0F, 1.0F); + + result = shadow_compare(function, depthRef, depthSample, ambient); + + switch (tObj->Sampler.DepthMode) { + case GL_LUMINANCE: + ASSIGN_4V(texel[i], result, result, result, 1.0F); + break; + case GL_INTENSITY: + ASSIGN_4V(texel[i], result, result, result, result); + break; + case GL_ALPHA: + ASSIGN_4V(texel[i], 0.0F, 0.0F, 0.0F, result); + break; + case GL_RED: + ASSIGN_4V(texel[i], result, 0.0F, 0.0F, 1.0F); + break; + default: + _mesa_problem(ctx, "Bad depth texture mode"); + } + } + } + else { + GLuint i; + ASSERT(tObj->Sampler.MagFilter == GL_LINEAR); + for (i = 0; i < n; i++) { + GLfloat depth00, depth01, depth10, depth11, depthRef; + GLint i0, i1, j0, j1; + GLint slice; + GLfloat wi, wj; + GLuint useBorderTexel; + + linear_texcoord(tObj, level, texcoords[i], &i0, &i1, &j0, &j1, &slice, + &wi, &wj); + + useBorderTexel = 0; + if (img->Border) { + i0 += img->Border; + i1 += img->Border; + if (tObj->Target != GL_TEXTURE_1D_ARRAY_EXT) { + j0 += img->Border; + j1 += img->Border; + } + } + else { + if (i0 < 0 || i0 >= (GLint) width) useBorderTexel |= I0BIT; + if (i1 < 0 || i1 >= (GLint) width) useBorderTexel |= I1BIT; + if (j0 < 0 || j0 >= (GLint) height) useBorderTexel |= J0BIT; + if (j1 < 0 || j1 >= (GLint) height) useBorderTexel |= J1BIT; + } + + if (slice < 0 || slice >= (GLint) depth) { + depth00 = tObj->Sampler.BorderColor.f[0]; + depth01 = tObj->Sampler.BorderColor.f[0]; + depth10 = tObj->Sampler.BorderColor.f[0]; + depth11 = tObj->Sampler.BorderColor.f[0]; + } + else { + /* get four depth samples from the texture */ + if (useBorderTexel & (I0BIT | J0BIT)) { + depth00 = tObj->Sampler.BorderColor.f[0]; + } + else { + img->FetchTexelf(img, i0, j0, slice, &depth00); + } + if (useBorderTexel & (I1BIT | J0BIT)) { + depth10 = tObj->Sampler.BorderColor.f[0]; + } + else { + img->FetchTexelf(img, i1, j0, slice, &depth10); + } + + if (tObj->Target != GL_TEXTURE_1D_ARRAY_EXT) { + if (useBorderTexel & (I0BIT | J1BIT)) { + depth01 = tObj->Sampler.BorderColor.f[0]; + } + else { + img->FetchTexelf(img, i0, j1, slice, &depth01); + } + if (useBorderTexel & (I1BIT | J1BIT)) { + depth11 = tObj->Sampler.BorderColor.f[0]; + } + else { + img->FetchTexelf(img, i1, j1, slice, &depth11); + } + } + else { + depth01 = depth00; + depth11 = depth10; + } + } + + depthRef = CLAMP(texcoords[i][compare_coord], 0.0F, 1.0F); + + result = shadow_compare4(function, depthRef, + depth00, depth01, depth10, depth11, + ambient, wi, wj); + + switch (tObj->Sampler.DepthMode) { + case GL_LUMINANCE: + ASSIGN_4V(texel[i], result, result, result, 1.0F); + break; + case GL_INTENSITY: + ASSIGN_4V(texel[i], result, result, result, result); + break; + case GL_ALPHA: + ASSIGN_4V(texel[i], 0.0F, 0.0F, 0.0F, result); + break; + default: + _mesa_problem(ctx, "Bad depth texture mode"); + } + + } /* for */ + } /* if filter */ +} + + +/** + * We use this function when a texture object is in an "incomplete" state. + * When a fragment program attempts to sample an incomplete texture we + * return black (see issue 23 in GL_ARB_fragment_program spec). + * Note: fragment programs don't observe the texture enable/disable flags. + */ +static void +null_sample_func( struct gl_context *ctx, + const struct gl_texture_object *tObj, GLuint n, + const GLfloat texcoords[][4], const GLfloat lambda[], + GLfloat rgba[][4]) +{ + GLuint i; + (void) ctx; + (void) tObj; + (void) texcoords; + (void) lambda; + for (i = 0; i < n; i++) { + rgba[i][RCOMP] = 0; + rgba[i][GCOMP] = 0; + rgba[i][BCOMP] = 0; + rgba[i][ACOMP] = 1.0; + } +} + + +/** + * Choose the texture sampling function for the given texture object. + */ +texture_sample_func +_swrast_choose_texture_sample_func( struct gl_context *ctx, + const struct gl_texture_object *t ) +{ + if (!t || !t->_Complete) { + return &null_sample_func; + } + else { + const GLboolean needLambda = + (GLboolean) (t->Sampler.MinFilter != t->Sampler.MagFilter); + const GLenum format = t->Image[0][t->BaseLevel]->_BaseFormat; + + switch (t->Target) { + case GL_TEXTURE_1D: + if (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL_EXT) { + return &sample_depth_texture; + } + else if (needLambda) { + return &sample_lambda_1d; + } + else if (t->Sampler.MinFilter == GL_LINEAR) { + return &sample_linear_1d; + } + else { + ASSERT(t->Sampler.MinFilter == GL_NEAREST); + return &sample_nearest_1d; + } + case GL_TEXTURE_2D: + if (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL_EXT) { + return &sample_depth_texture; + } + else if (needLambda) { + /* Anisotropic filtering extension. Activated only if mipmaps are used */ + if (t->Sampler.MaxAnisotropy > 1.0 && + t->Sampler.MinFilter == GL_LINEAR_MIPMAP_LINEAR) { + return &sample_lambda_2d_aniso; + } + return &sample_lambda_2d; + } + else if (t->Sampler.MinFilter == GL_LINEAR) { + return &sample_linear_2d; + } + else { + /* check for a few optimized cases */ + const struct gl_texture_image *img = t->Image[0][t->BaseLevel]; + ASSERT(t->Sampler.MinFilter == GL_NEAREST); + if (t->Sampler.WrapS == GL_REPEAT && + t->Sampler.WrapT == GL_REPEAT && + img->_IsPowerOfTwo && + img->Border == 0 && + img->TexFormat == MESA_FORMAT_RGB888) { + return &opt_sample_rgb_2d; + } + else if (t->Sampler.WrapS == GL_REPEAT && + t->Sampler.WrapT == GL_REPEAT && + img->_IsPowerOfTwo && + img->Border == 0 && + img->TexFormat == MESA_FORMAT_RGBA8888) { + return &opt_sample_rgba_2d; + } + else { + return &sample_nearest_2d; + } + } + case GL_TEXTURE_3D: + if (needLambda) { + return &sample_lambda_3d; + } + else if (t->Sampler.MinFilter == GL_LINEAR) { + return &sample_linear_3d; + } + else { + ASSERT(t->Sampler.MinFilter == GL_NEAREST); + return &sample_nearest_3d; + } + case GL_TEXTURE_CUBE_MAP: + if (needLambda) { + return &sample_lambda_cube; + } + else if (t->Sampler.MinFilter == GL_LINEAR) { + return &sample_linear_cube; + } + else { + ASSERT(t->Sampler.MinFilter == GL_NEAREST); + return &sample_nearest_cube; + } + case GL_TEXTURE_RECTANGLE_NV: + if (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL_EXT) { + return &sample_depth_texture; + } + else if (needLambda) { + return &sample_lambda_rect; + } + else if (t->Sampler.MinFilter == GL_LINEAR) { + return &sample_linear_rect; + } + else { + ASSERT(t->Sampler.MinFilter == GL_NEAREST); + return &sample_nearest_rect; + } + case GL_TEXTURE_1D_ARRAY_EXT: + if (needLambda) { + return &sample_lambda_1d_array; + } + else if (t->Sampler.MinFilter == GL_LINEAR) { + return &sample_linear_1d_array; + } + else { + ASSERT(t->Sampler.MinFilter == GL_NEAREST); + return &sample_nearest_1d_array; + } + case GL_TEXTURE_2D_ARRAY_EXT: + if (needLambda) { + return &sample_lambda_2d_array; + } + else if (t->Sampler.MinFilter == GL_LINEAR) { + return &sample_linear_2d_array; + } + else { + ASSERT(t->Sampler.MinFilter == GL_NEAREST); + return &sample_nearest_2d_array; + } + default: + _mesa_problem(ctx, + "invalid target in _swrast_choose_texture_sample_func"); + return &null_sample_func; + } + } +} diff --git a/mesalib/src/mesa/vbo/vbo_attrib_tmp.h b/mesalib/src/mesa/vbo/vbo_attrib_tmp.h index d6448dfb6..65717eb45 100644 --- a/mesalib/src/mesa/vbo/vbo_attrib_tmp.h +++ b/mesalib/src/mesa/vbo/vbo_attrib_tmp.h @@ -59,12 +59,12 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #define MAT_ATTR( A, N, V ) ATTR( A, N, (V)[0], (V)[1], (V)[2], (V)[3] ) -static inline float conv_ui10_to_norm_float(unsigned ui10) +static INLINE float conv_ui10_to_norm_float(unsigned ui10) { return (float)(ui10) / 1023.0; } -static inline float conv_ui2_to_norm_float(unsigned ui2) +static INLINE float conv_ui2_to_norm_float(unsigned ui2) { return (float)(ui2) / 3.0; } @@ -91,28 +91,28 @@ static inline float conv_ui2_to_norm_float(unsigned ui2) struct attr_bits_10 {signed int x:10;}; struct attr_bits_2 {signed int x:2;}; -static inline float conv_i10_to_i(int i10) +static INLINE float conv_i10_to_i(int i10) { struct attr_bits_10 val; val.x = i10; return (float)val.x; } -static inline float conv_i2_to_i(int i2) +static INLINE float conv_i2_to_i(int i2) { struct attr_bits_2 val; val.x = i2; return (float)val.x; } -static inline float conv_i10_to_norm_float(int i10) +static INLINE float conv_i10_to_norm_float(int i10) { struct attr_bits_10 val; val.x = i10; return (2.0F * (float)val.x + 1.0F) * (1.0F / 511.0F); } -static inline float conv_i2_to_norm_float(int i2) +static INLINE float conv_i2_to_norm_float(int i2) { struct attr_bits_2 val; val.x = i2; |