Path: blob/21.2-virgl/src/gallium/frontends/wgl/stw_pixelformat.c
4561 views
/**************************************************************************1*2* Copyright 2008 VMware, Inc.3* All Rights Reserved.4*5* Permission is hereby granted, free of charge, to any person obtaining a6* copy of this software and associated documentation files (the7* "Software"), to deal in the Software without restriction, including8* without limitation the rights to use, copy, modify, merge, publish,9* distribute, sub license, and/or sell copies of the Software, and to10* permit persons to whom the Software is furnished to do so, subject to11* the following conditions:12*13* The above copyright notice and this permission notice (including the14* next paragraph) shall be included in all copies or substantial portions15* of the Software.16*17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS18* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF19* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.20* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR21* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,22* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE23* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.24*25**************************************************************************/2627#include "pipe/p_format.h"28#include "pipe/p_defines.h"29#include "pipe/p_screen.h"3031#include "util/format/u_format.h"32#include "util/u_debug.h"33#include "util/u_memory.h"3435#include <GL/gl.h>36#include "gldrv.h"37#include "stw_device.h"38#include "stw_pixelformat.h"39#include "stw_tls.h"40#include "stw_winsys.h"414243struct stw_pf_color_info44{45enum pipe_format format;46struct {47unsigned char red;48unsigned char green;49unsigned char blue;50unsigned char alpha;51} bits;52struct {53unsigned char red;54unsigned char green;55unsigned char blue;56unsigned char alpha;57} shift;58};5960struct stw_pf_depth_info61{62enum pipe_format format;63struct {64unsigned char depth;65unsigned char stencil;66} bits;67};686970/* NOTE: order matters, since in otherwise equal circumstances the first71* format listed will get chosen */7273static const struct stw_pf_color_info74stw_pf_color[] = {75/* no-alpha */76{ PIPE_FORMAT_B8G8R8X8_UNORM, { 8, 8, 8, 0}, {16, 8, 0, 0} },77{ PIPE_FORMAT_X8R8G8B8_UNORM, { 8, 8, 8, 0}, { 8, 16, 24, 0} },78/* alpha */79{ PIPE_FORMAT_B8G8R8A8_UNORM, { 8, 8, 8, 8}, {16, 8, 0, 24} },80{ PIPE_FORMAT_A8R8G8B8_UNORM, { 8, 8, 8, 8}, { 8, 16, 24, 0} },81/* shallow bit depths */82{ PIPE_FORMAT_B5G6R5_UNORM, { 5, 6, 5, 0}, {11, 5, 0, 0} },83#if 084{ PIPE_FORMAT_R10G10B10A2_UNORM, {10, 10, 10, 2}, { 0, 10, 20, 30} },85#endif86{ PIPE_FORMAT_B5G5R5A1_UNORM, { 5, 5, 5, 1}, {10, 5, 0, 15} },87{ PIPE_FORMAT_B4G4R4A4_UNORM, { 4, 4, 4, 4}, {16, 4, 0, 12} }88};8990static const struct stw_pf_color_info91stw_pf_color_extended[] = {92{ PIPE_FORMAT_R32G32B32A32_FLOAT, {32, 32, 32, 32}, {0, 32, 64, 96} }93};9495static const struct stw_pf_depth_info96stw_pf_depth_stencil[] = {97/* pure depth */98{ PIPE_FORMAT_Z32_UNORM, {32, 0} },99{ PIPE_FORMAT_X8Z24_UNORM, {24, 0} },100{ PIPE_FORMAT_Z24X8_UNORM, {24, 0} },101{ PIPE_FORMAT_Z16_UNORM, {16, 0} },102/* combined depth-stencil */103{ PIPE_FORMAT_Z24_UNORM_S8_UINT, {24, 8} },104{ PIPE_FORMAT_S8_UINT_Z24_UNORM, {24, 8} }105};106107108static const boolean109stw_pf_doublebuffer[] = {110FALSE,111TRUE,112};113114115static const stw_pfd_flag116stw_pf_flag[] = {117stw_pfd_double_buffer,118stw_pfd_gdi_support,119};120121122const unsigned123stw_pf_multisample[] = {1240,1254,1268,12716128};129130131static void132stw_pixelformat_add(struct stw_device *stw_dev,133boolean extended,134const struct stw_pf_color_info *color,135const struct stw_pf_depth_info *depth,136unsigned accum,137boolean doublebuffer,138boolean gdi,139unsigned samples)140{141struct stw_pixelformat_info *pfi;142143assert(util_format_get_component_bits(color->format, UTIL_FORMAT_COLORSPACE_RGB, 0) == color->bits.red);144assert(util_format_get_component_bits(color->format, UTIL_FORMAT_COLORSPACE_RGB, 1) == color->bits.green);145assert(util_format_get_component_bits(color->format, UTIL_FORMAT_COLORSPACE_RGB, 2) == color->bits.blue);146assert(util_format_get_component_bits(color->format, UTIL_FORMAT_COLORSPACE_RGB, 3) == color->bits.alpha);147assert(util_format_get_component_bits(depth->format, UTIL_FORMAT_COLORSPACE_ZS, 0) == depth->bits.depth);148assert(util_format_get_component_bits(depth->format, UTIL_FORMAT_COLORSPACE_ZS, 1) == depth->bits.stencil);149150pfi = util_dynarray_grow(&stw_dev->pixelformats,151struct stw_pixelformat_info,1521);153154memset(pfi, 0, sizeof *pfi);155156pfi->pfd.nSize = sizeof pfi->pfd;157pfi->pfd.nVersion = 1;158159pfi->pfd.dwFlags = PFD_SUPPORT_OPENGL;160161/* TODO: also support non-native pixel formats */162if (!extended) {163pfi->pfd.dwFlags |= PFD_DRAW_TO_WINDOW;164}165166/* See http://www.opengl.org/pipeline/article/vol003_7/ */167pfi->pfd.dwFlags |= PFD_SUPPORT_COMPOSITION;168169if (doublebuffer)170pfi->pfd.dwFlags |= PFD_DOUBLEBUFFER | PFD_SWAP_EXCHANGE;171172if (gdi)173pfi->pfd.dwFlags |= PFD_SUPPORT_GDI;174175pfi->pfd.iPixelType = PFD_TYPE_RGBA;176177pfi->pfd.cColorBits =178color->bits.red + color->bits.green + color->bits.blue + color->bits.alpha;179pfi->pfd.cRedBits = color->bits.red;180pfi->pfd.cRedShift = color->shift.red;181pfi->pfd.cGreenBits = color->bits.green;182pfi->pfd.cGreenShift = color->shift.green;183pfi->pfd.cBlueBits = color->bits.blue;184pfi->pfd.cBlueShift = color->shift.blue;185pfi->pfd.cAlphaBits = color->bits.alpha;186pfi->pfd.cAlphaShift = color->shift.alpha;187pfi->pfd.cAccumBits = 4*accum;188pfi->pfd.cAccumRedBits = accum;189pfi->pfd.cAccumGreenBits = accum;190pfi->pfd.cAccumBlueBits = accum;191pfi->pfd.cAccumAlphaBits = accum;192pfi->pfd.cDepthBits = depth->bits.depth;193pfi->pfd.cStencilBits = depth->bits.stencil;194pfi->pfd.cAuxBuffers = 0;195pfi->pfd.iLayerType = 0;196pfi->pfd.bReserved = 0;197pfi->pfd.dwLayerMask = 0;198pfi->pfd.dwVisibleMask = 0;199pfi->pfd.dwDamageMask = 0;200201/*202* since gallium frontend can allocate depth/stencil/accum buffers, we provide203* only color buffers here204*/205pfi->stvis.buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK;206if (doublebuffer)207pfi->stvis.buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK;208209pfi->stvis.color_format = color->format;210pfi->stvis.depth_stencil_format = depth->format;211212pfi->stvis.accum_format = (accum) ?213PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE;214215pfi->stvis.samples = samples;216217/* WGL_ARB_render_texture */218if (color->bits.alpha)219pfi->bindToTextureRGBA = TRUE;220221pfi->bindToTextureRGB = TRUE;222223if (!extended) {224++stw_dev->pixelformat_count;225assert(stw_dev->pixelformat_count ==226util_dynarray_num_elements(&stw_dev->pixelformats,227struct stw_pixelformat_info));228}229}230231232/**233* Add the depth/stencil/accum/ms variants for a list of color formats.234*/235static unsigned236add_color_format_variants(const struct stw_pf_color_info *color_formats,237unsigned num_color_formats, boolean extended)238{239struct pipe_screen *screen = stw_dev->screen;240unsigned cfmt, ms, db, ds, acc, f;241unsigned bind_flags = PIPE_BIND_RENDER_TARGET;242unsigned num_added = 0;243int force_samples = 0;244245unsigned supported_flags = 0;246if (stw_dev->stw_winsys && stw_dev->stw_winsys->get_pfd_flags)247supported_flags = stw_dev->stw_winsys->get_pfd_flags(screen);248249/* Since GLUT for Windows doesn't support MSAA we have an env var250* to force all pixel formats to have a particular number of samples.251*/252{253const char *samples= getenv("SVGA_FORCE_MSAA");254if (samples)255force_samples = atoi(samples);256}257258if (!extended) {259bind_flags |= PIPE_BIND_DISPLAY_TARGET;260}261262for (ms = 0; ms < ARRAY_SIZE(stw_pf_multisample); ms++) {263unsigned samples = stw_pf_multisample[ms];264265if (force_samples && samples != force_samples)266continue;267268for (cfmt = 0; cfmt < num_color_formats; cfmt++) {269if (!screen->is_format_supported(screen, color_formats[cfmt].format,270PIPE_TEXTURE_2D, samples, samples,271bind_flags)) {272continue;273}274275for (db = 0; db < ARRAY_SIZE(stw_pf_doublebuffer); db++) {276unsigned doublebuffer = stw_pf_doublebuffer[db];277278for (ds = 0; ds < ARRAY_SIZE(stw_pf_depth_stencil); ds++) {279const struct stw_pf_depth_info *depth = &stw_pf_depth_stencil[ds];280281if (!screen->is_format_supported(screen, depth->format,282PIPE_TEXTURE_2D, samples,283samples,284PIPE_BIND_DEPTH_STENCIL)) {285continue;286}287288for (f = 0; f < ARRAY_SIZE(stw_pf_flag); f++) {289stw_pfd_flag flag = stw_pf_flag[f];290if (!(supported_flags & flag) || (flag == stw_pfd_double_buffer && !doublebuffer))291continue;292for (acc = 0; acc < 2; acc++) {293stw_pixelformat_add(stw_dev, extended, &color_formats[cfmt],294depth, acc * 16, doublebuffer,295(flag == stw_pfd_gdi_support), samples);296num_added++;297}298}299}300}301}302}303304return num_added;305}306307308void309stw_pixelformat_init(void)310{311unsigned num_formats;312313assert(!stw_dev->pixelformat_count);314315util_dynarray_init(&stw_dev->pixelformats, NULL);316317/* normal, displayable formats */318num_formats = add_color_format_variants(stw_pf_color,319ARRAY_SIZE(stw_pf_color), FALSE);320assert(num_formats > 0);321322/* extended, pbuffer-only formats */323add_color_format_variants(stw_pf_color_extended,324ARRAY_SIZE(stw_pf_color_extended), TRUE);325326assert(stw_dev->pixelformat_count <=327util_dynarray_num_elements(&stw_dev->pixelformats,328struct stw_pixelformat_info));329}330331332uint333stw_pixelformat_get_count(HDC hdc)334{335if (!stw_init_screen(hdc))336return 0;337338return stw_dev->pixelformat_count;339}340341342uint343stw_pixelformat_get_extended_count(HDC hdc)344{345if (!stw_init_screen(hdc))346return 0;347348return util_dynarray_num_elements(&stw_dev->pixelformats,349struct stw_pixelformat_info);350}351352353const struct stw_pixelformat_info *354stw_pixelformat_get_info(int iPixelFormat)355{356unsigned index;357358if (iPixelFormat <= 0) {359return NULL;360}361362index = iPixelFormat - 1;363if (index >= util_dynarray_num_elements(&stw_dev->pixelformats,364struct stw_pixelformat_info)) {365return NULL;366}367368return util_dynarray_element(&stw_dev->pixelformats,369struct stw_pixelformat_info,370index);371}372373374LONG APIENTRY375DrvDescribePixelFormat(HDC hdc, INT iPixelFormat, ULONG cjpfd,376PIXELFORMATDESCRIPTOR *ppfd)377{378uint count;379const struct stw_pixelformat_info *pfi;380381if (!stw_dev)382return 0;383384count = stw_pixelformat_get_count(hdc);385386if (ppfd == NULL)387return count;388389if (cjpfd != sizeof(PIXELFORMATDESCRIPTOR))390return 0;391392pfi = stw_pixelformat_get_info(iPixelFormat);393if (!pfi) {394return 0;395}396397memcpy(ppfd, &pfi->pfd, sizeof(PIXELFORMATDESCRIPTOR));398399return count;400}401402403BOOL APIENTRY404DrvDescribeLayerPlane(HDC hdc, INT iPixelFormat, INT iLayerPlane,405UINT nBytes, LPLAYERPLANEDESCRIPTOR plpd)406{407assert(0);408return FALSE;409}410411412int APIENTRY413DrvGetLayerPaletteEntries(HDC hdc, INT iLayerPlane, INT iStart,414INT cEntries, COLORREF *pcr)415{416assert(0);417return 0;418}419420421int APIENTRY422DrvSetLayerPaletteEntries(HDC hdc, INT iLayerPlane, INT iStart,423INT cEntries, CONST COLORREF *pcr)424{425assert(0);426return 0;427}428429430BOOL APIENTRY431DrvRealizeLayerPalette(HDC hdc, INT iLayerPlane, BOOL bRealize)432{433assert(0);434return FALSE;435}436437438/* Only used by the wgl code, but have it here to avoid exporting the439* pixelformat.h functionality.440*/441int442stw_pixelformat_choose(HDC hdc, CONST PIXELFORMATDESCRIPTOR *ppfd)443{444uint count;445uint index;446uint bestindex;447uint bestdelta;448449count = stw_pixelformat_get_extended_count(hdc);450bestindex = 0;451bestdelta = ~0U;452453for (index = 1; index <= count; index++) {454uint delta = 0;455const struct stw_pixelformat_info *pfi = stw_pixelformat_get_info(index);456457if (!(ppfd->dwFlags & PFD_DOUBLEBUFFER_DONTCARE) &&458!!(ppfd->dwFlags & PFD_DOUBLEBUFFER) !=459!!(pfi->pfd.dwFlags & PFD_DOUBLEBUFFER))460continue;461462/* Selection logic:463* - Enabling a feature (depth, stencil...) is given highest priority.464* - Giving as many bits as requested is given medium priority.465* - Giving no more bits than requested is given lowest priority.466*/467468/* FIXME: Take in account individual channel bits */469if (ppfd->cColorBits && !pfi->pfd.cColorBits)470delta += 10000;471else if (ppfd->cColorBits > pfi->pfd.cColorBits)472delta += 100;473else if (ppfd->cColorBits < pfi->pfd.cColorBits)474delta++;475476if (ppfd->cDepthBits && !pfi->pfd.cDepthBits)477delta += 10000;478else if (ppfd->cDepthBits > pfi->pfd.cDepthBits)479delta += 200;480else if (ppfd->cDepthBits < pfi->pfd.cDepthBits)481delta += 2;482483if (ppfd->cStencilBits && !pfi->pfd.cStencilBits)484delta += 10000;485else if (ppfd->cStencilBits > pfi->pfd.cStencilBits)486delta += 400;487else if (ppfd->cStencilBits < pfi->pfd.cStencilBits)488delta++;489490if (ppfd->cAlphaBits && !pfi->pfd.cAlphaBits)491delta += 10000;492else if (ppfd->cAlphaBits > pfi->pfd.cAlphaBits)493delta += 100;494else if (ppfd->cAlphaBits < pfi->pfd.cAlphaBits)495delta++;496497if (delta < bestdelta) {498bestindex = index;499bestdelta = delta;500if (bestdelta == 0)501break;502}503}504505return bestindex;506}507508509