Update to latest BGFX (nw)

This commit is contained in:
Branimir Karadžić 2016-04-10 09:16:09 +02:00 committed by Miodrag Milanovic
parent a26f4f3428
commit cceb3a32b7
34 changed files with 3578 additions and 175 deletions

32
3rdparty/bgfx/3rdparty/iqa/LICENSE vendored Normal file
View File

@ -0,0 +1,32 @@
/*
* Copyright (c) 2011, Tom Distler (http://tdistler.com)
* All rights reserved.
*
* The BSD License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* - Neither the name of the tdistler.com nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

36
3rdparty/bgfx/3rdparty/iqa/README.txt vendored Normal file
View File

@ -0,0 +1,36 @@
Doxygen documentation can be found at: http://tdistler.com/iqa
BUILD:
All build artifacts end up in build/<configuration>, where <configuration> is
'debug' or 'release'.
Windows:
- Open iqa.sln, select 'Debug' or 'Release', and build. The output is a
static library 'iqa.lib'.
- To run the tests under the debugger, first right-click the 'test' project,
select Properties -> Configuration Properties -> Debugging and set
'Working Directory' to '$(OutDir)'. Then start the application.
Linux:
- Change directories into the root of the IQA branch you want to build.
- Type `make` for a debug build, or `make RELEASE=1` for a release build.
The output is a static library 'libiqa.a'.
- Type `make test` (or `make test RELEASE=1`) to build the unit tests.
- Type `make clean` (or `make clean RELEASE=1`) to delete all build
artifacts.
- To run the tests, `cd` to the build/<configuration> directory and type
`./test`.
USE:
- Include 'iqa.h' in your source file.
- Call iqa_* methods.
- Link against the IQA library.
HELP & SUPPORT:
Further help can be found at: https://sourceforge.net/projects/iqa/support

View File

@ -0,0 +1,111 @@
/*
* Copyright (c) 2011, Tom Distler (http://tdistler.com)
* All rights reserved.
*
* The BSD License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* - Neither the name of the tdistler.com nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _CONVOLVE_H_
#define _CONVOLVE_H_
typedef float (*_iqa_get_pixel)(const float *img, int w, int h, int x, int y, float bnd_const);
/** Out-of-bounds array values are a mirrored reflection of the border values*/
float KBND_SYMMETRIC(const float *img, int w, int h, int x, int y, float bnd_const);
/** Out-of-bounds array values are set to the nearest border value */
float KBND_REPLICATE(const float *img, int w, int h, int x, int y, float bnd_const);
/** Out-of-bounds array values are set to 'bnd_const' */
float KBND_CONSTANT(const float *img, int w, int h, int x, int y, float bnd_const);
/** Defines a convolution kernel */
struct _kernel {
float *kernel; /**< Pointer to the kernel values */
int w; /**< The kernel width */
int h; /**< The kernel height */
int normalized; /**< 1 if the kernel values add up to 1. 0 otherwise */
_iqa_get_pixel bnd_opt; /**< Defines how out-of-bounds image values are handled */
float bnd_const; /**< If 'bnd_opt' is KBND_CONSTANT, this specifies the out-of-bounds value */
};
/**
* @brief Applies the specified kernel to the image.
* The kernel will be applied to all areas where it fits completely within
* the image. The resulting image will be smaller by half the kernel width
* and height (w - kw/2 and h - kh/2).
*
* @param img Image to modify
* @param w Image width
* @param h Image height
* @param k The kernel to apply
* @param result Buffer to hold the resulting image ((w-kw)*(h-kh), where kw
* and kh are the kernel width and height). If 0, the result
* will be written to the original image buffer.
* @param rw Optional. The width of the resulting image will be stored here.
* @param rh Optional. The height of the resulting image will be stored here.
*/
void _iqa_convolve(float *img, int w, int h, const struct _kernel *k, float *result, int *rw, int *rh);
/**
* The same as _iqa_convolve() except the kernel is applied to the entire image.
* In other words, the kernel is applied to all areas where the top-left corner
* of the kernel is in the image. Out-of-bound pixel value (off the right and
* bottom edges) are chosen based on the 'bnd_opt' and 'bnd_const' members of
* the kernel structure. The resulting array is the same size as the input
* image.
*
* @param img Image to modify
* @param w Image width
* @param h Image height
* @param k The kernel to apply
* @param result Buffer to hold the resulting image ((w-kw)*(h-kh), where kw
* and kh are the kernel width and height). If 0, the result
* will be written to the original image buffer.
* @return 0 if successful. Non-zero otherwise.
*/
int _iqa_img_filter(float *img, int w, int h, const struct _kernel *k, float *result);
/**
* Returns the filtered version of the specified pixel. If no kernel is given,
* the raw pixel value is returned.
*
* @param img Source image
* @param w Image width
* @param h Image height
* @param x The x location of the pixel to filter
* @param y The y location of the pixel to filter
* @param k Optional. The convolution kernel to apply to the pixel.
* @param kscale The scale of the kernel (for normalization). 1 for normalized
* kernels. Required if 'k' is not null.
* @return The filtered pixel value.
*/
float _iqa_filter_pixel(const float *img, int w, int h, int x, int y, const struct _kernel *k, const float kscale);
#endif /*_CONVOLVE_H_*/

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 2011, Tom Distler (http://tdistler.com)
* All rights reserved.
*
* The BSD License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* - Neither the name of the tdistler.com nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _DECIMATE_H_
#define _DECIMATE_H_
#include "convolve.h"
/**
* @brief Downsamples (decimates) an image.
*
* @param img Image to modify
* @param w Image width
* @param h Image height
* @param factor Decimation factor
* @param k The kernel to apply (e.g. low-pass filter). Can be 0.
* @param result Buffer to hold the resulting image (w/factor*h/factor). If 0,
* the result will be written to the original image buffer.
* @param rw Optional. The width of the resulting image will be stored here.
* @param rh Optional. The height of the resulting image will be stored here.
* @return 0 on success.
*/
int _iqa_decimate(float *img, int w, int h, int factor, const struct _kernel *k, float *result, int *rw, int *rh);
#endif /*_DECIMATE_H_*/

134
3rdparty/bgfx/3rdparty/iqa/include/iqa.h vendored Normal file
View File

@ -0,0 +1,134 @@
/*
* Copyright (c) 2011, Tom Distler (http://tdistler.com)
* All rights reserved.
*
* The BSD License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* - Neither the name of the tdistler.com nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _IQA_H_
#define _IQA_H_
#include "iqa_os.h"
/**
* Allows fine-grain control of the SSIM algorithm.
*/
struct iqa_ssim_args {
float alpha; /**< luminance exponent */
float beta; /**< contrast exponent */
float gamma; /**< structure exponent */
int L; /**< dynamic range (2^8 - 1)*/
float K1; /**< stabilization constant 1 */
float K2; /**< stabilization constant 2 */
int f; /**< scale factor. 0=default scaling, 1=no scaling */
};
/**
* Allows fine-grain control of the MS-SSIM algorithm.
*/
struct iqa_ms_ssim_args {
int wang; /**< 1=original algorithm by Wang, et al. 0=MS-SSIM* by Rouse/Hemami (default). */
int gaussian; /**< 1=11x11 Gaussian window (default). 0=8x8 linear window. */
int scales; /**< Number of scaled images to use. Default is 5. */
const float *alphas; /**< Pointer to array of alpha values for each scale. Required if 'scales' isn't 5. */
const float *betas; /**< Pointer to array of beta values for each scale. Required if 'scales' isn't 5. */
const float *gammas; /**< Pointer to array of gamma values for each scale. Required if 'scales' isn't 5. */
};
/**
* Calculates the Mean Squared Error between 2 equal-sized 8-bit images.
* @note The images must have the same width, height, and stride.
* @param ref Original reference image
* @param cmp Distorted image
* @param w Width of the images
* @param h Height of the images
* @param stride The length (in bytes) of each horizontal line in the image.
* This may be different from the image width.
* @return The MSE.
*/
float iqa_mse(const unsigned char *ref, const unsigned char *cmp, int w, int h, int stride);
/**
* Calculates the Peak Signal-to-Noise-Ratio between 2 equal-sized 8-bit
* images.
* @note The images must have the same width, height, and stride.
* @param ref Original reference image
* @param cmp Distorted image
* @param w Width of the images
* @param h Height of the images
* @param stride The length (in bytes) of each horizontal line in the image.
* This may be different from the image width.
* @return The PSNR.
*/
float iqa_psnr(const unsigned char *ref, const unsigned char *cmp, int w, int h, int stride);
/**
* Calculates the Structural SIMilarity between 2 equal-sized 8-bit images.
*
* See https://ece.uwaterloo.ca/~z70wang/publications/ssim.html
* @note The images must have the same width, height, and stride.
* @param ref Original reference image
* @param cmp Distorted image
* @param w Width of the images
* @param h Height of the images
* @param stride The length (in bytes) of each horizontal line in the image.
* This may be different from the image width.
* @param gaussian 0 = 8x8 square window, 1 = 11x11 circular-symmetric Gaussian
* weighting.
* @param args Optional SSIM arguments for fine control of the algorithm. 0 for
* defaults. Defaults are a=b=g=1.0, L=255, K1=0.01, K2=0.03
* @return The mean SSIM over the entire image (MSSIM), or INFINITY if error.
*/
float iqa_ssim(const unsigned char *ref, const unsigned char *cmp, int w, int h, int stride,
int gaussian, const struct iqa_ssim_args *args);
/**
* Calculates the Multi-Scale Structural SIMilarity between 2 equal-sized 8-bit
* images. The default algorithm is MS-SSIM* proposed by Rouse/Hemami 2008.
*
* See https://ece.uwaterloo.ca/~z70wang/publications/msssim.pdf and
* http://foulard.ece.cornell.edu/publications/dmr_hvei2008_paper.pdf
*
* @note 1. The images must have the same width, height, and stride.
* @note 2. The minimum image width or height is 2^(scales-1) * filter, where 'filter' is 11
* if a Gaussian window is being used, or 9 otherwise.
* @param ref Original reference image
* @param cmp Distorted image
* @param w Width of the images.
* @param h Height of the images.
* @param stride The length (in bytes) of each horizontal line in the image.
* This may be different from the image width.
* @param args Optional MS-SSIM arguments for fine control of the algorithm. 0
* for defaults. Defaults are wang=0, scales=5, gaussian=1.
* @return The mean MS-SSIM over the entire image, or INFINITY if error.
*/
float iqa_ms_ssim(const unsigned char *ref, const unsigned char *cmp, int w, int h, int stride,
const struct iqa_ms_ssim_args *args);
#endif /*_IQA_H_*/

View File

@ -0,0 +1,68 @@
/*
* Copyright (c) 2011, Tom Distler (http://tdistler.com)
* All rights reserved.
*
* The BSD License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* - Neither the name of the tdistler.com nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _OS_H_
#define _OS_H_
/* Microsoft tends to implement features early, but they have a high legacy
* cost because they won't break existing implementations. As such, certain
* features we take for granted on other platforms (like C99) aren't fully
* implemented. This file is meant to rectify that.
*/
#ifdef WIN32
#include <windows.h>
#include <math.h>
#define IQA_INLINE __inline
#ifndef INFINITY
#define INFINITY (float)HUGE_VAL /**< Defined in C99 (Windows is C89) */
#endif /*INFINITY*/
#ifndef NAN
static const unsigned long __nan[2] = {0xffffffff, 0x7fffffff};
#define NAN (*(const float *) __nan) /**< Defined in C99 (Windows is C99) */
#endif
#define IQA_EXPORT __declspec(dllexport)
#else /* !Windows */
#define IQA_INLINE inline
#define IQA_EXPORT
#endif
#endif /* _OS_H_ */

View File

@ -0,0 +1,64 @@
/*
* Copyright (c) 2011, Tom Distler (http://tdistler.com)
* All rights reserved.
*
* The BSD License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* - Neither the name of the tdistler.com nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _MATH_UTILS_H_
#define _MATH_UTILS_H_
#include "iqa_os.h"
#include <math.h>
/**
* Rounds a float to the nearest integer.
*/
IQA_EXPORT IQA_INLINE int _round(float a);
IQA_EXPORT IQA_INLINE int _max(int x, int y);
IQA_EXPORT IQA_INLINE int _min(int x, int y);
/**
* Compares 2 floats to the specified digit of precision.
* @return 0 if equal, 1 otherwise.
*/
IQA_EXPORT IQA_INLINE int _cmp_float(float a, float b, int digits);
/**
* Compares 2 matrices with the specified precision. 'b' is assumed to be the
* same size as 'a' or smaller.
* @return 0 if equal, 1 otherwise
*/
IQA_EXPORT IQA_INLINE int _matrix_cmp(const float *a, const float *b, int w, int h, int digits);
#endif /*_MATH_UTILS_H_*/

View File

@ -0,0 +1,117 @@
/*
* Copyright (c) 2011, Tom Distler (http://tdistler.com)
* All rights reserved.
*
* The BSD License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* - Neither the name of the tdistler.com nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SSIM_H_
#define _SSIM_H_
#include "convolve.h"
/*
* Circular-symmetric Gaussian weighting.
* h(x,y) = hg(x,y)/SUM(SUM(hg)) , for normalization to 1.0
* hg(x,y) = e^( -0.5*( (x^2+y^2)/sigma^2 ) ) , where sigma was 1.5
*/
#define GAUSSIAN_LEN 11
static const float g_gaussian_window[GAUSSIAN_LEN][GAUSSIAN_LEN] = {
{0.000001f, 0.000008f, 0.000037f, 0.000112f, 0.000219f, 0.000274f, 0.000219f, 0.000112f, 0.000037f, 0.000008f, 0.000001f},
{0.000008f, 0.000058f, 0.000274f, 0.000831f, 0.001619f, 0.002021f, 0.001619f, 0.000831f, 0.000274f, 0.000058f, 0.000008f},
{0.000037f, 0.000274f, 0.001296f, 0.003937f, 0.007668f, 0.009577f, 0.007668f, 0.003937f, 0.001296f, 0.000274f, 0.000037f},
{0.000112f, 0.000831f, 0.003937f, 0.011960f, 0.023294f, 0.029091f, 0.023294f, 0.011960f, 0.003937f, 0.000831f, 0.000112f},
{0.000219f, 0.001619f, 0.007668f, 0.023294f, 0.045371f, 0.056662f, 0.045371f, 0.023294f, 0.007668f, 0.001619f, 0.000219f},
{0.000274f, 0.002021f, 0.009577f, 0.029091f, 0.056662f, 0.070762f, 0.056662f, 0.029091f, 0.009577f, 0.002021f, 0.000274f},
{0.000219f, 0.001619f, 0.007668f, 0.023294f, 0.045371f, 0.056662f, 0.045371f, 0.023294f, 0.007668f, 0.001619f, 0.000219f},
{0.000112f, 0.000831f, 0.003937f, 0.011960f, 0.023294f, 0.029091f, 0.023294f, 0.011960f, 0.003937f, 0.000831f, 0.000112f},
{0.000037f, 0.000274f, 0.001296f, 0.003937f, 0.007668f, 0.009577f, 0.007668f, 0.003937f, 0.001296f, 0.000274f, 0.000037f},
{0.000008f, 0.000058f, 0.000274f, 0.000831f, 0.001619f, 0.002021f, 0.001619f, 0.000831f, 0.000274f, 0.000058f, 0.000008f},
{0.000001f, 0.000008f, 0.000037f, 0.000112f, 0.000219f, 0.000274f, 0.000219f, 0.000112f, 0.000037f, 0.000008f, 0.000001f},
};
/*
* Equal weight square window.
* Each pixel is equally weighted (1/64) so that SUM(x) = 1.0
*/
#define SQUARE_LEN 8
static const float g_square_window[SQUARE_LEN][SQUARE_LEN] = {
{0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f},
{0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f},
{0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f},
{0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f},
{0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f},
{0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f},
{0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f},
{0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f, 0.015625f},
};
/* Holds intermediate SSIM values for map-reduce operation. */
struct _ssim_int {
double l;
double c;
double s;
};
/* Defines the pointers to the map-reduce functions. */
typedef int (*_map)(const struct _ssim_int *, void *);
typedef float (*_reduce)(int, int, void *);
/* Arguments for map-reduce. The 'context' is user-defined. */
struct _map_reduce {
_map map;
_reduce reduce;
void *context;
};
/**
* Private method that calculates the SSIM value on a pre-processed image.
*
* The input images must have stride==width. This method does not scale.
*
* @note Image buffers are modified.
*
* Map-reduce is used for doing the final SSIM calculation. The map function is
* called for every pixel, and the reduce is called at the end. The context is
* caller-defined and *not* modified by this method.
*
* @param ref Original reference image
* @param cmp Distorted image
* @param w Width of the images
* @param h Height of the images
* @param k The kernel used as the window function
* @param mr Optional map-reduce functions to use to calculate SSIM. Required
* if 'args' is not null. Ignored if 'args' is null.
* @param args Optional SSIM arguments for fine control of the algorithm. 0 for defaults.
* Defaults are a=b=g=1.0, L=255, K1=0.01, K2=0.03
* @return The mean SSIM over the entire image (MSSIM), or INFINITY if error.
*/
float _iqa_ssim(float *ref, float *cmp, int w, int h, const struct _kernel *k, const struct _map_reduce *mr, const struct iqa_ssim_args *args);
#endif /* _SSIM_H_ */

View File

@ -0,0 +1,195 @@
/*
* Copyright (c) 2011, Tom Distler (http://tdistler.com)
* All rights reserved.
*
* The BSD License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* - Neither the name of the tdistler.com nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "convolve.h"
#include <stdlib.h>
float KBND_SYMMETRIC(const float *img, int w, int h, int x, int y, float bnd_const)
{
(void)bnd_const;
if (x<0) x=-1-x;
else if (x>=w) x=(w-(x-w))-1;
if (y<0) y=-1-y;
else if (y>=h) y=(h-(y-h))-1;
return img[y*w + x];
}
float KBND_REPLICATE(const float *img, int w, int h, int x, int y, float bnd_const)
{
(void)bnd_const;
if (x<0) x=0;
if (x>=w) x=w-1;
if (y<0) y=0;
if (y>=h) y=h-1;
return img[y*w + x];
}
float KBND_CONSTANT(const float *img, int w, int h, int x, int y, float bnd_const)
{
if (x<0) x=0;
if (y<0) y=0;
if (x>=w || y>=h)
return bnd_const;
return img[y*w + x];
}
static float _calc_scale(const struct _kernel *k)
{
int ii,k_len;
double sum=0.0;
if (k->normalized)
return 1.0f;
else {
k_len = k->w * k->h;
for (ii=0; ii<k_len; ++ii)
sum += k->kernel[ii];
if (sum != 0.0)
return (float)(1.0 / sum);
return 1.0f;
}
}
void _iqa_convolve(float *img, int w, int h, const struct _kernel *k, float *result, int *rw, int *rh)
{
int x,y,kx,ky,u,v;
int uc = k->w/2;
int vc = k->h/2;
int kw_even = (k->w&1)?0:1;
int kh_even = (k->h&1)?0:1;
int dst_w = w - k->w + 1;
int dst_h = h - k->h + 1;
int img_offset,k_offset;
double sum;
float scale, *dst=result;
if (!dst)
dst = img; /* Convolve in-place */
/* Kernel is applied to all positions where the kernel is fully contained
* in the image */
scale = _calc_scale(k);
for (y=0; y < dst_h; ++y) {
for (x=0; x < dst_w; ++x) {
sum = 0.0;
k_offset = 0;
ky = y+vc;
kx = x+uc;
for (v=-vc; v <= vc-kh_even; ++v) {
img_offset = (ky+v)*w + kx;
for (u=-uc; u <= uc-kw_even; ++u, ++k_offset) {
sum += img[img_offset+u] * k->kernel[k_offset];
}
}
dst[y*dst_w + x] = (float)(sum * scale);
}
}
if (rw) *rw = dst_w;
if (rh) *rh = dst_h;
}
int _iqa_img_filter(float *img, int w, int h, const struct _kernel *k, float *result)
{
int x,y;
int img_offset;
float scale, *dst=result;
if (!k || !k->bnd_opt)
return 1;
if (!dst) {
dst = (float*)malloc(w*h*sizeof(float));
if (!dst)
return 2;
}
scale = _calc_scale(k);
/* Kernel is applied to all positions where top-left corner is in the image */
for (y=0; y < h; ++y) {
for (x=0; x < w; ++x) {
dst[y*w + x] = _iqa_filter_pixel(img, w, h, x, y, k, scale);
}
}
/* If no result buffer given, copy results to image buffer */
if (!result) {
for (y=0; y<h; ++y) {
img_offset = y*w;
for (x=0; x<w; ++x, ++img_offset) {
img[img_offset] = dst[img_offset];
}
}
free(dst);
}
return 0;
}
float _iqa_filter_pixel(const float *img, int w, int h, int x, int y, const struct _kernel *k, const float kscale)
{
int u,v,uc,vc;
int kw_even,kh_even;
int x_edge_left,x_edge_right,y_edge_top,y_edge_bottom;
int edge,img_offset,k_offset;
double sum;
if (!k)
return img[y*w + x];
uc = k->w/2;
vc = k->h/2;
kw_even = (k->w&1)?0:1;
kh_even = (k->h&1)?0:1;
x_edge_left = uc;
x_edge_right = w-uc;
y_edge_top = vc;
y_edge_bottom = h-vc;
edge = 0;
if (x < x_edge_left || y < y_edge_top || x >= x_edge_right || y >= y_edge_bottom)
edge = 1;
sum = 0.0;
k_offset = 0;
for (v=-vc; v <= vc-kh_even; ++v) {
img_offset = (y+v)*w + x;
for (u=-uc; u <= uc-kw_even; ++u, ++k_offset) {
if (!edge)
sum += img[img_offset+u] * k->kernel[k_offset];
else
sum += k->bnd_opt(img, w, h, x+u, y+v, k->bnd_const) * k->kernel[k_offset];
}
}
return (float)(sum * kscale);
}

View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 2011, Tom Distler (http://tdistler.com)
* All rights reserved.
*
* The BSD License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* - Neither the name of the tdistler.com nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "decimate.h"
#include <stdlib.h>
int _iqa_decimate(float *img, int w, int h, int factor, const struct _kernel *k, float *result, int *rw, int *rh)
{
int x,y;
int sw = w/factor + (w&1);
int sh = h/factor + (h&1);
int dst_offset;
float *dst=img;
if (result)
dst = result;
/* Downsample */
for (y=0; y<sh; ++y) {
dst_offset = y*sw;
for (x=0; x<sw; ++x,++dst_offset) {
dst[dst_offset] = _iqa_filter_pixel(img, w, h, x*factor, y*factor, k, 1.0f);
}
}
if (rw) *rw = sw;
if (rh) *rh = sh;
return 0;
}

View File

@ -0,0 +1,82 @@
/*
* Copyright (c) 2011, Tom Distler (http://tdistler.com)
* All rights reserved.
*
* The BSD License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* - Neither the name of the tdistler.com nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "math_utils.h"
#include <math.h>
int _round(float a)
{
int sign_a = a > 0.0f ? 1 : -1;
return a-(int)a >= 0.5 ? (int)a + sign_a : (int)a;
}
int _max(int x, int y)
{
return x >= y ? x : y;
}
int _min(int x, int y)
{
return x <= y ? x : y;
}
int _cmp_float(float a, float b, int digits)
{
/* Round */
int sign_a = a > 0.0f ? 1 : -1;
int sign_b = b > 0.0f ? 1 : -1;
double scale = pow(10.0, (double)digits);
double ax = a * scale;
double bx = b * scale;
int ai = ax-(int)ax >= 0.5 ? (int)ax + sign_a : (int)ax;
int bi = bx-(int)bx >= 0.5 ? (int)bx + sign_b : (int)bx;
/* Compare */
return ai == bi ? 0 : 1;
}
int _matrix_cmp(const float *a, const float *b, int w, int h, int digits)
{
int offset;
int result=0;
int len=w*h;
for (offset=0; offset<len; ++offset) {
if (_cmp_float(a[offset], b[offset], digits)) {
result = 1;
break;
}
}
return result;
}

View File

@ -0,0 +1,277 @@
/*
* Copyright (c) 2011, Tom Distler (http://tdistler.com)
* All rights reserved.
*
* The BSD License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* - Neither the name of the tdistler.com nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "iqa.h"
#include "ssim.h"
#include "decimate.h"
#include <math.h>
#include <stdlib.h>
#include <string.h>
/* Default number of scales */
#define SCALES 5
/* Low-pass filter for down-sampling (9/7 biorthogonal wavelet filter) */
#define LPF_LEN 9
static const float g_lpf[LPF_LEN][LPF_LEN] = {
{ 0.000714f,-0.000450f,-0.002090f, 0.007132f, 0.016114f, 0.007132f,-0.002090f,-0.000450f, 0.000714f},
{-0.000450f, 0.000283f, 0.001316f,-0.004490f,-0.010146f,-0.004490f, 0.001316f, 0.000283f,-0.000450f},
{-0.002090f, 0.001316f, 0.006115f,-0.020867f,-0.047149f,-0.020867f, 0.006115f, 0.001316f,-0.002090f},
{ 0.007132f,-0.004490f,-0.020867f, 0.071207f, 0.160885f, 0.071207f,-0.020867f,-0.004490f, 0.007132f},
{ 0.016114f,-0.010146f,-0.047149f, 0.160885f, 0.363505f, 0.160885f,-0.047149f,-0.010146f, 0.016114f},
{ 0.007132f,-0.004490f,-0.020867f, 0.071207f, 0.160885f, 0.071207f,-0.020867f,-0.004490f, 0.007132f},
{-0.002090f, 0.001316f, 0.006115f,-0.020867f,-0.047149f,-0.020867f, 0.006115f, 0.001316f,-0.002090f},
{-0.000450f, 0.000283f, 0.001316f,-0.004490f,-0.010146f,-0.004490f, 0.001316f, 0.000283f,-0.000450f},
{ 0.000714f,-0.000450f,-0.002090f, 0.007132f, 0.016114f, 0.007132f,-0.002090f,-0.000450f, 0.000714f},
};
/* Alpha, beta, and gamma values for each scale */
static float g_alphas[] = { 0.0000f, 0.0000f, 0.0000f, 0.0000f, 0.1333f };
static float g_betas[] = { 0.0448f, 0.2856f, 0.3001f, 0.2363f, 0.1333f };
static float g_gammas[] = { 0.0448f, 0.2856f, 0.3001f, 0.2363f, 0.1333f };
struct _context {
double l; /* Luminance */
double c; /* Contrast */
double s; /* Structure */
float alpha;
float beta;
float gamma;
};
/* Called for each pixel */
int _ms_ssim_map(const struct _ssim_int *si, void *ctx)
{
struct _context *ms_ctx = (struct _context*)ctx;
ms_ctx->l += si->l;
ms_ctx->c += si->c;
ms_ctx->s += si->s;
return 0;
}
/* Called to calculate the final result */
float _ms_ssim_reduce(int w, int h, void *ctx)
{
double size = (double)(w*h);
struct _context *ms_ctx = (struct _context*)ctx;
ms_ctx->l = pow(ms_ctx->l / size, (double)ms_ctx->alpha);
ms_ctx->c = pow(ms_ctx->c / size, (double)ms_ctx->beta);
ms_ctx->s = pow(fabs(ms_ctx->s / size), (double)ms_ctx->gamma);
return (float)(ms_ctx->l * ms_ctx->c * ms_ctx->s);
}
/* Releases the scaled buffers */
void _free_buffers(float **buf, int scales)
{
int idx;
for (idx=0; idx<scales; ++idx)
free(buf[idx]);
}
/* Allocates the scaled buffers. If error, all buffers are free'd */
int _alloc_buffers(float **buf, int w, int h, int scales)
{
int idx;
int cur_w = w;
int cur_h = h;
for (idx=0; idx<scales; ++idx) {
buf[idx] = (float*)malloc(cur_w*cur_h*sizeof(float));
if (!buf[idx]) {
_free_buffers(buf, idx);
return 1;
}
cur_w = cur_w/2 + (cur_w&1);
cur_h = cur_h/2 + (cur_h&1);
}
return 0;
}
/*
* MS_SSIM(X,Y) = Lm(x,y)^aM * MULT[j=1->M]( Cj(x,y)^bj * Sj(x,y)^gj )
* where,
* L = mean
* C = variance
* S = cross-correlation
*
* b1=g1=0.0448, b2=g2=0.2856, b3=g3=0.3001, b4=g4=0.2363, a5=b5=g5=0.1333
*/
float iqa_ms_ssim(const unsigned char *ref, const unsigned char *cmp, int w, int h,
int stride, const struct iqa_ms_ssim_args *args)
{
int wang=0;
int scales=SCALES;
int gauss=1;
const float *alphas=g_alphas, *betas=g_betas, *gammas=g_gammas;
int idx,x,y,cur_w,cur_h;
int offset,src_offset;
float **ref_imgs, **cmp_imgs; /* Array of pointers to scaled images */
float msssim;
struct _kernel lpf, window;
struct iqa_ssim_args s_args;
struct _map_reduce mr;
struct _context ms_ctx;
if (args) {
wang = args->wang;
gauss = args->gaussian;
scales = args->scales;
if (args->alphas)
alphas = args->alphas;
if (args->betas)
betas = args->betas;
if (args->gammas)
gammas = args->gammas;
}
/* Make sure we won't scale below 1x1 */
cur_w = w;
cur_h = h;
for (idx=0; idx<scales; ++idx) {
if ( gauss ? cur_w<GAUSSIAN_LEN || cur_h<GAUSSIAN_LEN : cur_w<LPF_LEN || cur_h<LPF_LEN )
return INFINITY;
cur_w /= 2;
cur_h /= 2;
}
window.kernel = (float*)g_square_window;
window.w = window.h = SQUARE_LEN;
window.normalized = 1;
window.bnd_opt = KBND_SYMMETRIC;
if (gauss) {
window.kernel = (float*)g_gaussian_window;
window.w = window.h = GAUSSIAN_LEN;
}
mr.map = _ms_ssim_map;
mr.reduce = _ms_ssim_reduce;
/* Allocate the scaled image buffers */
ref_imgs = (float**)malloc(scales*sizeof(float*));
cmp_imgs = (float**)malloc(scales*sizeof(float*));
if (!ref_imgs || !cmp_imgs) {
if (ref_imgs) free(ref_imgs);
if (cmp_imgs) free(cmp_imgs);
return INFINITY;
}
if (_alloc_buffers(ref_imgs, w, h, scales)) {
free(ref_imgs);
free(cmp_imgs);
return INFINITY;
}
if (_alloc_buffers(cmp_imgs, w, h, scales)) {
_free_buffers(ref_imgs, scales);
free(ref_imgs);
free(cmp_imgs);
return INFINITY;
}
/* Copy original images into first scale buffer, forcing stride = width. */
for (y=0; y<h; ++y) {
src_offset = y*stride;
offset = y*w;
for (x=0; x<w; ++x, ++offset, ++src_offset) {
ref_imgs[0][offset] = (float)ref[src_offset];
cmp_imgs[0][offset] = (float)cmp[src_offset];
}
}
/* Create scaled versions of the images */
cur_w=w;
cur_h=h;
lpf.kernel = (float*)g_lpf;
lpf.w = lpf.h = LPF_LEN;
lpf.normalized = 1;
lpf.bnd_opt = KBND_SYMMETRIC;
for (idx=1; idx<scales; ++idx) {
if (_iqa_decimate(ref_imgs[idx-1], cur_w, cur_h, 2, &lpf, ref_imgs[idx], 0, 0) ||
_iqa_decimate(cmp_imgs[idx-1], cur_w, cur_h, 2, &lpf, cmp_imgs[idx], &cur_w, &cur_h))
{
_free_buffers(ref_imgs, scales);
_free_buffers(cmp_imgs, scales);
free(ref_imgs);
free(cmp_imgs);
return INFINITY;
}
}
cur_w=w;
cur_h=h;
msssim = 1.0;
for (idx=0; idx<scales; ++idx) {
ms_ctx.l = 0;
ms_ctx.c = 0;
ms_ctx.s = 0;
ms_ctx.alpha = alphas[idx];
ms_ctx.beta = betas[idx];
ms_ctx.gamma = gammas[idx];
if (!wang) {
/* MS-SSIM* (Rouse/Hemami) */
s_args.alpha = 1.0f;
s_args.beta = 1.0f;
s_args.gamma = 1.0f;
s_args.K1 = 0.0f; /* Force stabilization constants to 0 */
s_args.K2 = 0.0f;
s_args.L = 255;
s_args.f = 1; /* Don't resize */
mr.context = &ms_ctx;
msssim *= _iqa_ssim(ref_imgs[idx], cmp_imgs[idx], cur_w, cur_h, &window, &mr, &s_args);
}
else {
/* MS-SSIM (Wang) */
s_args.alpha = 1.0f;
s_args.beta = 1.0f;
s_args.gamma = 1.0f;
s_args.K1 = 0.01f;
s_args.K2 = 0.03f;
s_args.L = 255;
s_args.f = 1; /* Don't resize */
mr.context = &ms_ctx;
msssim *= _iqa_ssim(ref_imgs[idx], cmp_imgs[idx], cur_w, cur_h, &window, &mr, &s_args);
}
if (msssim == INFINITY)
break;
cur_w = cur_w/2 + (cur_w&1);
cur_h = cur_h/2 + (cur_h&1);
}
_free_buffers(ref_imgs, scales);
_free_buffers(cmp_imgs, scales);
free(ref_imgs);
free(cmp_imgs);
return msssim;
}

50
3rdparty/bgfx/3rdparty/iqa/source/mse.c vendored Normal file
View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2011, Tom Distler (http://tdistler.com)
* All rights reserved.
*
* The BSD License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* - Neither the name of the tdistler.com nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "iqa.h"
/* MSE(a,b) = 1/N * SUM((a-b)^2) */
float iqa_mse(const unsigned char *ref, const unsigned char *cmp, int w, int h, int stride)
{
int error, offset;
unsigned long long sum=0;
int ww,hh;
for (hh=0; hh<h; ++hh) {
offset = hh*stride;
for (ww=0; ww<w; ++ww, ++offset) {
error = ref[offset] - cmp[offset];
sum += error * error;
}
}
return (float)( (double)sum / (double)(w*h) );
}

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 2011, Tom Distler (http://tdistler.com)
* All rights reserved.
*
* The BSD License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* - Neither the name of the tdistler.com nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "iqa.h"
#include <math.h>
/* PSNR(a,b) = 10*log10(L^2 / MSE(a,b)), where L=2^b - 1 (8bit = 255) */
float iqa_psnr(const unsigned char *ref, const unsigned char *cmp, int w, int h, int stride)
{
const int L_sqd = 255 * 255;
return (float)( 10.0 * log10( L_sqd / iqa_mse(ref,cmp,w,h,stride) ) );
}

322
3rdparty/bgfx/3rdparty/iqa/source/ssim.c vendored Normal file
View File

@ -0,0 +1,322 @@
/*
* Copyright (c) 2011, Tom Distler (http://tdistler.com)
* All rights reserved.
*
* The BSD License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* - Neither the name of the tdistler.com nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "iqa.h"
#include "convolve.h"
#include "decimate.h"
#include "math_utils.h"
#include "ssim.h"
#include <stdlib.h>
#include <math.h>
/* Forward declarations. */
IQA_INLINE static double _calc_luminance(float, float, float, float);
IQA_INLINE static double _calc_contrast(double, float, float, float, float);
IQA_INLINE static double _calc_structure(float, double, float, float, float, float);
static int _ssim_map(const struct _ssim_int *, void *);
static float _ssim_reduce(int, int, void *);
/*
* SSIM(x,y)=(2*ux*uy + C1)*(2sxy + C2) / (ux^2 + uy^2 + C1)*(sx^2 + sy^2 + C2)
* where,
* ux = SUM(w*x)
* sx = (SUM(w*(x-ux)^2)^0.5
* sxy = SUM(w*(x-ux)*(y-uy))
*
* Returns mean SSIM. MSSIM(X,Y) = 1/M * SUM(SSIM(x,y))
*/
float iqa_ssim(const unsigned char *ref, const unsigned char *cmp, int w, int h, int stride,
int gaussian, const struct iqa_ssim_args *args)
{
int scale;
int x,y,src_offset,offset;
float *ref_f,*cmp_f;
struct _kernel low_pass;
struct _kernel window;
float result;
double ssim_sum=0.0;
struct _map_reduce mr;
/* Initialize algorithm parameters */
scale = _max( 1, _round( (float)_min(w,h) / 256.0f ) );
if (args) {
if(args->f)
scale = args->f;
mr.map = _ssim_map;
mr.reduce = _ssim_reduce;
mr.context = (void*)&ssim_sum;
}
window.kernel = (float*)g_square_window;
window.w = window.h = SQUARE_LEN;
window.normalized = 1;
window.bnd_opt = KBND_SYMMETRIC;
if (gaussian) {
window.kernel = (float*)g_gaussian_window;
window.w = window.h = GAUSSIAN_LEN;
}
/* Convert image values to floats. Forcing stride = width. */
ref_f = (float*)malloc(w*h*sizeof(float));
cmp_f = (float*)malloc(w*h*sizeof(float));
if (!ref_f || !cmp_f) {
if (ref_f) free(ref_f);
if (cmp_f) free(cmp_f);
return INFINITY;
}
for (y=0; y<h; ++y) {
src_offset = y*stride;
offset = y*w;
for (x=0; x<w; ++x, ++offset, ++src_offset) {
ref_f[offset] = (float)ref[src_offset];
cmp_f[offset] = (float)cmp[src_offset];
}
}
/* Scale the images down if required */
if (scale > 1) {
/* Generate simple low-pass filter */
low_pass.kernel = (float*)malloc(scale*scale*sizeof(float));
if (!low_pass.kernel) {
free(ref_f);
free(cmp_f);
return INFINITY;
}
low_pass.w = low_pass.h = scale;
low_pass.normalized = 0;
low_pass.bnd_opt = KBND_SYMMETRIC;
for (offset=0; offset<scale*scale; ++offset)
low_pass.kernel[offset] = 1.0f/(scale*scale);
/* Resample */
if (_iqa_decimate(ref_f, w, h, scale, &low_pass, 0, 0, 0) ||
_iqa_decimate(cmp_f, w, h, scale, &low_pass, 0, &w, &h)) { /* Update w/h */
free(ref_f);
free(cmp_f);
free(low_pass.kernel);
return INFINITY;
}
free(low_pass.kernel);
}
result = _iqa_ssim(ref_f, cmp_f, w, h, &window, &mr, args);
free(ref_f);
free(cmp_f);
return result;
}
/* _iqa_ssim */
float _iqa_ssim(float *ref, float *cmp, int w, int h, const struct _kernel *k, const struct _map_reduce *mr, const struct iqa_ssim_args *args)
{
float alpha=1.0f, beta=1.0f, gamma=1.0f;
int L=255;
float K1=0.01f, K2=0.03f;
float C1,C2,C3;
int x,y,offset;
float *ref_mu,*cmp_mu,*ref_sigma_sqd,*cmp_sigma_sqd,*sigma_both;
double ssim_sum, numerator, denominator;
double luminance_comp, contrast_comp, structure_comp, sigma_root;
struct _ssim_int sint;
/* Initialize algorithm parameters */
if (args) {
if (!mr)
return INFINITY;
alpha = args->alpha;
beta = args->beta;
gamma = args->gamma;
L = args->L;
K1 = args->K1;
K2 = args->K2;
}
C1 = (K1*L)*(K1*L);
C2 = (K2*L)*(K2*L);
C3 = C2 / 2.0f;
ref_mu = (float*)malloc(w*h*sizeof(float));
cmp_mu = (float*)malloc(w*h*sizeof(float));
ref_sigma_sqd = (float*)malloc(w*h*sizeof(float));
cmp_sigma_sqd = (float*)malloc(w*h*sizeof(float));
sigma_both = (float*)malloc(w*h*sizeof(float));
if (!ref_mu || !cmp_mu || !ref_sigma_sqd || !cmp_sigma_sqd || !sigma_both) {
if (ref_mu) free(ref_mu);
if (cmp_mu) free(cmp_mu);
if (ref_sigma_sqd) free(ref_sigma_sqd);
if (cmp_sigma_sqd) free(cmp_sigma_sqd);
if (sigma_both) free(sigma_both);
return INFINITY;
}
/* Calculate mean */
_iqa_convolve(ref, w, h, k, ref_mu, 0, 0);
_iqa_convolve(cmp, w, h, k, cmp_mu, 0, 0);
for (y=0; y<h; ++y) {
offset = y*w;
for (x=0; x<w; ++x, ++offset) {
ref_sigma_sqd[offset] = ref[offset] * ref[offset];
cmp_sigma_sqd[offset] = cmp[offset] * cmp[offset];
sigma_both[offset] = ref[offset] * cmp[offset];
}
}
/* Calculate sigma */
_iqa_convolve(ref_sigma_sqd, w, h, k, 0, 0, 0);
_iqa_convolve(cmp_sigma_sqd, w, h, k, 0, 0, 0);
_iqa_convolve(sigma_both, w, h, k, 0, &w, &h); /* Update the width and height */
/* The convolution results are smaller by the kernel width and height */
for (y=0; y<h; ++y) {
offset = y*w;
for (x=0; x<w; ++x, ++offset) {
ref_sigma_sqd[offset] -= ref_mu[offset] * ref_mu[offset];
cmp_sigma_sqd[offset] -= cmp_mu[offset] * cmp_mu[offset];
sigma_both[offset] -= ref_mu[offset] * cmp_mu[offset];
}
}
ssim_sum = 0.0;
for (y=0; y<h; ++y) {
offset = y*w;
for (x=0; x<w; ++x, ++offset) {
if (!args) {
/* The default case */
numerator = (2.0 * ref_mu[offset] * cmp_mu[offset] + C1) * (2.0 * sigma_both[offset] + C2);
denominator = (ref_mu[offset]*ref_mu[offset] + cmp_mu[offset]*cmp_mu[offset] + C1) *
(ref_sigma_sqd[offset] + cmp_sigma_sqd[offset] + C2);
ssim_sum += numerator / denominator;
}
else {
/* User tweaked alpha, beta, or gamma */
/* passing a negative number to sqrt() cause a domain error */
if (ref_sigma_sqd[offset] < 0.0f)
ref_sigma_sqd[offset] = 0.0f;
if (cmp_sigma_sqd[offset] < 0.0f)
cmp_sigma_sqd[offset] = 0.0f;
sigma_root = sqrt(ref_sigma_sqd[offset] * cmp_sigma_sqd[offset]);
luminance_comp = _calc_luminance(ref_mu[offset], cmp_mu[offset], C1, alpha);
contrast_comp = _calc_contrast(sigma_root, ref_sigma_sqd[offset], cmp_sigma_sqd[offset], C2, beta);
structure_comp = _calc_structure(sigma_both[offset], sigma_root, ref_sigma_sqd[offset], cmp_sigma_sqd[offset], C3, gamma);
sint.l = luminance_comp;
sint.c = contrast_comp;
sint.s = structure_comp;
if (mr->map(&sint, mr->context))
return INFINITY;
}
}
}
free(ref_mu);
free(cmp_mu);
free(ref_sigma_sqd);
free(cmp_sigma_sqd);
free(sigma_both);
if (!args)
return (float)(ssim_sum / (double)(w*h));
return mr->reduce(w, h, mr->context);
}
/* _ssim_map */
int _ssim_map(const struct _ssim_int *si, void *ctx)
{
double *ssim_sum = (double*)ctx;
*ssim_sum += si->l * si->c * si->s;
return 0;
}
/* _ssim_reduce */
float _ssim_reduce(int w, int h, void *ctx)
{
double *ssim_sum = (double*)ctx;
return (float)(*ssim_sum / (double)(w*h));
}
/* _calc_luminance */
IQA_INLINE static double _calc_luminance(float mu1, float mu2, float C1, float alpha)
{
double result;
float sign;
/* For MS-SSIM* */
if (C1 == 0 && mu1*mu1 == 0 && mu2*mu2 == 0)
return 1.0;
result = (2.0 * mu1 * mu2 + C1) / (mu1*mu1 + mu2*mu2 + C1);
if (alpha == 1.0f)
return result;
sign = result < 0.0 ? -1.0f : 1.0f;
return sign * pow(fabs(result),(double)alpha);
}
/* _calc_contrast */
IQA_INLINE static double _calc_contrast(double sigma_comb_12, float sigma1_sqd, float sigma2_sqd, float C2, float beta)
{
double result;
float sign;
/* For MS-SSIM* */
if (C2 == 0 && sigma1_sqd + sigma2_sqd == 0)
return 1.0;
result = (2.0 * sigma_comb_12 + C2) / (sigma1_sqd + sigma2_sqd + C2);
if (beta == 1.0f)
return result;
sign = result < 0.0 ? -1.0f : 1.0f;
return sign * pow(fabs(result),(double)beta);
}
/* _calc_structure */
IQA_INLINE static double _calc_structure(float sigma_12, double sigma_comb_12, float sigma1, float sigma2, float C3, float gamma)
{
double result;
float sign;
/* For MS-SSIM* */
if (C3 == 0 && sigma_comb_12 == 0) {
if (sigma1 == 0 && sigma2 == 0)
return 1.0;
else if (sigma1 == 0 || sigma2 == 0)
return 0.0;
}
result = (sigma_12 + C3) / (sigma_comb_12 + C3);
if (gamma == 1.0f)
return result;
sign = result < 0.0 ? -1.0f : 1.0f;
return sign * pow(fabs(result),(double)gamma);
}

View File

@ -1,4 +1,4 @@
// dear imgui, v1.48 WIP
// dear imgui, v1.49 WIP
// (main code and documentation)
// See ImGui::ShowTestWindow() in imgui_demo.cpp for demo code.
@ -2341,9 +2341,9 @@ static void AddDrawListToRenderList(ImVector<ImDrawList*>& out_render_list, ImDr
// Check that draw_list doesn't use more vertices than indexable (default ImDrawIdx = 2 bytes = 64K vertices)
// If this assert triggers because you are drawing lots of stuff manually, A) workaround by calling BeginChild()/EndChild() to put your draw commands in multiple draw lists, B) #define ImDrawIdx to a 'unsigned int' in imconfig.h and render accordingly.
IM_ASSERT((int)draw_list->_VtxCurrentIdx == draw_list->VtxBuffer.Size); // Sanity check. Bug or mismatch between PrimReserve() calls and incrementing _VtxCurrentIdx, _VtxWritePtr etc.
IM_ASSERT((unsigned long long int)draw_list->_VtxCurrentIdx <= ((unsigned long long int)1L << (sizeof(ImDrawIdx)*8))); // Too many vertices in same ImDrawList. See comment above.
IM_ASSERT((int)draw_list->_VtxCurrentIdx == draw_list->VtxBuffer.Size); // Sanity check. Bug or mismatch between PrimReserve() calls and incrementing _VtxCurrentIdx, _VtxWritePtr etc.
IM_ASSERT((int64_t)draw_list->_VtxCurrentIdx <= ((int64_t)1L << (sizeof(ImDrawIdx)*8))); // Too many vertices in same ImDrawList. See comment above.
out_render_list.push_back(draw_list);
GImGui->IO.MetricsRenderVertices += draw_list->VtxBuffer.Size;
GImGui->IO.MetricsRenderIndices += draw_list->IdxBuffer.Size;
@ -7101,9 +7101,9 @@ static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, STB_TEXTEDIT_STRING* ob
static bool is_separator(unsigned int c) { return ImCharIsSpace(c) || c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|'; }
static int is_word_boundary_from_right(STB_TEXTEDIT_STRING* obj, int idx) { return idx > 0 ? (is_separator( obj->Text[idx-1] ) && !is_separator( obj->Text[idx] ) ) : 1; }
static int is_word_boundary_from_left(STB_TEXTEDIT_STRING* obj, int idx) { return idx > 0 ? (!is_separator( obj->Text[idx-1] ) && is_separator( obj->Text[idx] ) ) : 1; }
static int STB_TEXTEDIT_MOVEWORDLEFT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { while (idx >= 0 && !is_word_boundary_from_right(obj, idx)) idx--; return idx < 0 ? 0 : idx; }
#ifdef __APPLE__ // FIXME: Move setting to IO structure
static int is_word_boundary_from_left(STB_TEXTEDIT_STRING* obj, int idx) { return idx > 0 ? (!is_separator( obj->Text[idx-1] ) && is_separator( obj->Text[idx] ) ) : 1; }
static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_left(obj, idx)) idx++; return idx > len ? len : idx; }
#else
static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_right(obj, idx)) idx++; return idx > len ? len : idx; }

View File

@ -1,4 +1,4 @@
// dear imgui, v1.48 WIP
// dear imgui, v1.49 WIP
// (headers)
// See imgui.cpp file for documentation.
@ -16,7 +16,7 @@
#include <stddef.h> // ptrdiff_t, NULL
#include <string.h> // memset, memmove, memcpy, strlen, strchr, strcpy, strcmp
#define IMGUI_VERSION "1.48 WIP"
#define IMGUI_VERSION "1.49 WIP"
// Define attributes of all API symbols declarations, e.g. for DLL under Windows.
#ifndef IMGUI_API
@ -315,7 +315,7 @@ namespace ImGui
IMGUI_API void TreePush(const char* str_id = NULL); // already called by TreeNode(), but you can call Push/Pop yourself for layouting purpose
IMGUI_API void TreePush(const void* ptr_id = NULL); // "
IMGUI_API void TreePop();
IMGUI_API void SetNextTreeNodeOpened(bool opened, ImGuiSetCond cond = 0); // set next tree node to be opened.
IMGUI_API void SetNextTreeNodeOpened(bool opened, ImGuiSetCond cond = 0); // set next tree node/collapsing header to be opened.
// Widgets: Selectable / Lists
IMGUI_API bool Selectable(const char* label, bool selected = false, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0,0)); // size.x==0.0: use remaining width, size.x>0.0: specify width. size.y==0.0: use label height, size.y>0.0: specify height
@ -892,6 +892,7 @@ struct ImGuiTextFilter
int CountGrep;
ImGuiTextFilter(const char* default_filter = "");
~ImGuiTextFilter() {}
void Clear() { InputBuf[0] = 0; Build(); }
bool Draw(const char* label = "Filter (inc,-exc)", float width = 0.0f); // Helper calling InputText+Build
bool PassFilter(const char* text, const char* text_end = NULL) const;
@ -1155,7 +1156,7 @@ struct ImDrawList
// Stateful path API, add points then finish with PathFill() or PathStroke()
inline void PathClear() { _Path.resize(0); }
inline void PathLineTo(const ImVec2& pos) { _Path.push_back(pos); }
inline void PathLineToMergeDuplicate(const ImVec2& pos) { if (_Path.Size == 0 || _Path[_Path.Size-1].x != pos.x || _Path[_Path.Size-1].y != pos.y) _Path.push_back(pos); }
inline void PathLineToMergeDuplicate(const ImVec2& pos) { if (_Path.Size == 0 || memcmp(&_Path[_Path.Size-1], &pos, 8) != 0) _Path.push_back(pos); }
inline void PathFill(ImU32 col) { AddConvexPolyFilled(_Path.Data, _Path.Size, col, true); PathClear(); }
inline void PathStroke(ImU32 col, bool closed, float thickness = 1.0f) { AddPolyline(_Path.Data, _Path.Size, col, closed, thickness, true); PathClear(); }
IMGUI_API void PathArcTo(const ImVec2& centre, float radius, float a_min, float a_max, int num_segments = 10);

View File

@ -1,4 +1,4 @@
// dear imgui, v1.48 WIP
// dear imgui, v1.49 WIP
// (demo code)
// Don't remove this file from your project! It is useful reference code that you can execute.
@ -2295,12 +2295,12 @@ static void ShowExampleAppPropertyEditor(bool* p_opened)
{
ImGui::PushID(uid); // Use object uid as identifier. Most commonly you could also use the object pointer as a base ID.
ImGui::AlignFirstTextHeightToWidgets(); // Text and Tree nodes are less high than regular widgets, here we add vertical spacing to make the tree lines equal high.
bool opened = ImGui::TreeNode("Object", "%s_%u", prefix, uid);
bool is_opened = ImGui::TreeNode("Object", "%s_%u", prefix, uid);
ImGui::NextColumn();
ImGui::AlignFirstTextHeightToWidgets();
ImGui::Text("my sailor is rich");
ImGui::NextColumn();
if (opened)
if (is_opened)
{
static float dummy_members[8] = { 0.0f,0.0f,1.0f,3.1416f,100.0f,999.0f };
for (int i = 0; i < 8; i++)

View File

@ -1,4 +1,4 @@
// dear imgui, v1.48 WIP
// dear imgui, v1.49 WIP
// (drawing and font code)
// Contains implementation for

View File

@ -1,4 +1,4 @@
// dear imgui, v1.48 WIP
// dear imgui, v1.49 WIP
// (internals)
// You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility!

File diff suppressed because it is too large Load Diff

View File

@ -14,7 +14,7 @@
#include <string.h> // memcpy
#ifndef ENTRY_CONFIG_USE_NOOP
# define ENTRY_CONFIG_USE_NOOP (BX_PLATFORM_QNX || BX_PLATFORM_XBOXONE)
# define ENTRY_CONFIG_USE_NOOP (BX_PLATFORM_QNX)
#endif // ENTRY_CONFIG_USE_NOOP
#ifndef ENTRY_CONFIG_USE_SDL

View File

@ -5,7 +5,7 @@
#include "entry_p.h"
#if BX_PLATFORM_WINRT
#if BX_PLATFORM_WINRT || BX_PLATFORM_XBOXONE
#include <bgfx/bgfxplatform.h>
#include <bx/thread.h>
@ -17,7 +17,9 @@ using namespace Windows::UI::Core;
using namespace Windows::UI::Input;
using namespace Windows::System;
using namespace Windows::Foundation;
#if BX_PLATFORM_WINRT
using namespace Windows::Graphics::Display;
#endif // BX_PLATFORM_WINRT
using namespace Platform;
static char* g_emptyArgs[] = { "" };
@ -36,13 +38,23 @@ public:
// IFrameworkView Methods.
virtual void Initialize(CoreApplicationView^ applicationView)
{
applicationView->Activated += ref new TypedEventHandler<CoreApplicationView^, IActivatedEventArgs^>(this, &App::OnActivated);
applicationView->Activated += ref new
TypedEventHandler<CoreApplicationView^, IActivatedEventArgs^>(this, &App::OnActivated);
CoreApplication::Suspending += ref new
EventHandler<SuspendingEventArgs^>(this, &App::OnSuspending);
CoreApplication::Resuming += ref new
EventHandler<Platform::Object^>(this, &App::OnResuming);
}
virtual void SetWindow(CoreWindow^ window)
{
window->VisibilityChanged += ref new TypedEventHandler<CoreWindow^, VisibilityChangedEventArgs^>(this, &App::OnVisibilityChanged);
window->Closed += ref new TypedEventHandler<CoreWindow^, CoreWindowEventArgs^>(this, &App::OnWindowClosed);
window->VisibilityChanged += ref new
TypedEventHandler<CoreWindow^, VisibilityChangedEventArgs^>(this, &App::OnVisibilityChanged);
window->Closed += ref new
TypedEventHandler<CoreWindow^, CoreWindowEventArgs^>(this, &App::OnWindowClosed);
bgfx::winrtSetWindow(reinterpret_cast<IUnknown*>(window) );
}
@ -58,13 +70,15 @@ public:
CoreWindow^ window = CoreWindow::GetForCurrentThread();
auto bounds = window->Bounds;
auto dpi = DisplayInformation::GetForCurrentView()->LogicalDpi;
#if BX_PLATFORM_WINRT
auto dpi = DisplayInformation::GetForCurrentView()->LogicalDpi;
static const float dipsPerInch = 96.0f;
g_eventQueue.postSizeEvent(g_defaultWindow
, lround(floorf(bounds.Width * dpi / dipsPerInch + 0.5f) )
, lround(floorf(bounds.Height * dpi / dipsPerInch + 0.5f) )
, lround(bx::ffloor(bounds.Width * dpi / dipsPerInch + 0.5f) )
, lround(bx::ffloor(bounds.Height * dpi / dipsPerInch + 0.5f) )
);
#endif // BX_PLATFORM_WINRT
while (!m_windowClosed)
{
@ -101,6 +115,16 @@ private:
m_windowVisible = args->Visible;
}
void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args)
{
SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral();
BX_UNUSED(deferral);
}
void OnResuming(Platform::Object^ sender, Platform::Object^ args)
{
}
void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args)
{
m_windowClosed = true;
@ -189,4 +213,4 @@ int main(Array<String^>^)
return 0;
}
#endif // BX_PLATFORM_WINRT
#endif // BX_PLATFORM_WINRT || BX_PLATFORM_XBOXONE

View File

@ -13,6 +13,7 @@ project "texturec"
path.join(BGFX_DIR, "src"),
path.join(BGFX_DIR, "3rdparty"),
path.join(BGFX_DIR, "3rdparty/nvtt"),
path.join(BGFX_DIR, "3rdparty/iqa/include"),
}
files {
@ -31,6 +32,8 @@ project "texturec"
path.join(BGFX_DIR, "3rdparty/pvrtc/**.h"),
path.join(BGFX_DIR, "3rdparty/tinyexr/**.cc"),
path.join(BGFX_DIR, "3rdparty/tinyexr/**.h"),
path.join(BGFX_DIR, "3rdparty/iqa/include/**.h"),
path.join(BGFX_DIR, "3rdparty/iqa/source/**.c"),
path.join(BGFX_DIR, "tools/texturec/**.cpp"),
path.join(BGFX_DIR, "tools/texturec/**.h"),
}

View File

@ -10,6 +10,10 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
#if defined(Success)
// X11 defines Success
# undef Success
#endif // defined(Success)
namespace bgfx { namespace gl
{

95
3rdparty/bgfx/src/hmd_openvr.cpp vendored Normal file
View File

@ -0,0 +1,95 @@
/*
* Copyright 2011-2016 Branimir Karadzic. All rights reserved.
* License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
*/
#include "hmd_openvr.h"
BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC("-Wunused-variable")
#include <openvr/openvr_capi.h>
namespace bgfx
{
#if BX_PLATFORM_WINDOWS
# define VR_CALLTYPE __cdecl
#else
# define VR_CALLTYPE
#endif
typedef uint32_t (VR_CALLTYPE *PFN_VR_INITINTERNAL)(EVRInitError* peError, EVRApplicationType eType);
typedef void (VR_CALLTYPE *PFN_VR_SHUTDOWNINTERNAL)();
typedef bool (VR_CALLTYPE *PFN_VR_ISHMDPRESENT)();
typedef void* (VR_CALLTYPE *PFN_VR_GETGENERICINTERFACE)(const char* pchInterfaceVersion, EVRInitError* peError);
typedef bool (VR_CALLTYPE *PFN_VR_ISRUNTIMEINSTALLED)();
typedef bool (VR_CALLTYPE *PFN_VR_ISINTERFACEVERSIONVALID)(const char *pchInterfaceVersion);
typedef uint32_t (VR_CALLTYPE *PFN_VR_GETINITTOKEN)();
typedef const char* (VR_CALLTYPE *PFN_VR_GETVRINITERRORASSYMBOL)(EVRInitError error);
typedef const char* (VR_CALLTYPE *PFN_VR_GETVRINITERRORASENGLISHDESCRIPTION)(EVRInitError error);
PFN_VR_INITINTERNAL VR_InitInternal;
PFN_VR_SHUTDOWNINTERNAL VR_ShutdownInternal;
PFN_VR_ISHMDPRESENT VR_IsHmdPresent;
PFN_VR_GETGENERICINTERFACE VR_GetGenericInterface;
PFN_VR_ISRUNTIMEINSTALLED VR_IsRuntimeInstalled;
PFN_VR_ISINTERFACEVERSIONVALID VR_IsInterfaceVersionValid;
PFN_VR_GETINITTOKEN VR_GetInitToken;
PFN_VR_GETVRINITERRORASSYMBOL VR_GetVRInitErrorAsSymbol;
PFN_VR_GETVRINITERRORASENGLISHDESCRIPTION VR_GetVRInitErrorAsEnglishDescription;
void* loadOpenVR()
{
void* openvrdll = bx::dlopen(
#if BX_PLATFORM_LINUX
"libopenvr_api.so"
#elif BX_PLATFORM_OSX
"libopenvr_api.dylib"
#else
"openvr_api.dll"
#endif // BX_PLATFORM_*
);
if (NULL != openvrdll)
{
VR_InitInternal = (PFN_VR_INITINTERNAL )bx::dlsym(openvrdll, "VR_InitInternal");
VR_ShutdownInternal = (PFN_VR_SHUTDOWNINTERNAL )bx::dlsym(openvrdll, "VR_ShutdownInternal");
VR_IsHmdPresent = (PFN_VR_ISHMDPRESENT )bx::dlsym(openvrdll, "VR_IsHmdPresent");
VR_GetGenericInterface = (PFN_VR_GETGENERICINTERFACE )bx::dlsym(openvrdll, "VR_GetGenericInterface");
VR_IsRuntimeInstalled = (PFN_VR_ISRUNTIMEINSTALLED )bx::dlsym(openvrdll, "VR_IsRuntimeInstalled");
VR_IsInterfaceVersionValid = (PFN_VR_ISINTERFACEVERSIONVALID)bx::dlsym(openvrdll, "VR_IsInterfaceVersionValid");
VR_GetInitToken = (PFN_VR_GETINITTOKEN )bx::dlsym(openvrdll, "VR_GetInitToken");
VR_GetVRInitErrorAsSymbol = (PFN_VR_GETVRINITERRORASSYMBOL )bx::dlsym(openvrdll, "VR_GetVRInitErrorAsSymbol");
VR_GetVRInitErrorAsEnglishDescription = (PFN_VR_GETVRINITERRORASENGLISHDESCRIPTION)bx::dlsym(openvrdll, "VR_GetVRInitErrorAsEnglishDescription");
if (NULL == VR_InitInternal
&& NULL == VR_ShutdownInternal
&& NULL == VR_IsHmdPresent
&& NULL == VR_GetGenericInterface
&& NULL == VR_IsRuntimeInstalled
&& NULL == VR_IsInterfaceVersionValid
&& NULL == VR_GetInitToken
&& NULL == VR_GetVRInitErrorAsSymbol
&& NULL == VR_GetVRInitErrorAsEnglishDescription)
{
bx::dlclose(openvrdll);
return NULL;
}
EVRInitError err;
uint32_t token = VR_InitInternal(&err, EVRApplicationType_VRApplication_Scene);
BX_UNUSED(token);
BX_TRACE("OpenVR: HMD is %spresent, Runtime is %sinstalled."
, VR_IsHmdPresent() ? "" : "not "
, VR_IsRuntimeInstalled() ? "" : "not "
);
}
return openvrdll;
}
void unloadOpenVR(void* _openvrdll)
{
VR_ShutdownInternal();
bx::dlclose(_openvrdll);
}
} // namespace bgfx

18
3rdparty/bgfx/src/hmd_openvr.h vendored Normal file
View File

@ -0,0 +1,18 @@
/*
* Copyright 2011-2016 Branimir Karadzic. All rights reserved.
* License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
*/
#ifndef BGFX_OPENVR_H_HEADER_GUARD
#define BGFX_OPENVR_H_HEADER_GUARD
#include "bgfx_p.h"
namespace bgfx
{
void* loadOpenVR();
void unloadOpenVR(void*);
} // namespace bgfx
#endif // BGFX_OPENVR_H_HEADER_GUARD

View File

@ -17,6 +17,8 @@ namespace bgfx
#if BGFX_CONFIG_DEBUG
# define OVR_CHECK(_call) _OVR_CHECK(_call)
#else
# define OVR_CHECK(_call) _call
#endif // BGFX_CONFIG_DEBUG
OVR::OVR()
@ -152,6 +154,7 @@ namespace bgfx
for (uint32_t ii = 0; ii < 2; ++ii)
{
m_eyeBuffers[ii]->postRender(m_hmd);
result = ovr_CommitTextureSwapChain(m_hmd, m_eyeBuffers[ii]->m_textureSwapChain);
if (!OVR_SUCCESS(result) )
{

View File

@ -31,10 +31,10 @@ namespace bgfx
struct OVRBufferI
{
virtual ~OVRBufferI() {};
virtual void create(const ovrSession& _session, int _eyeIdx) = 0;
virtual void create(const ovrSession& _session, int _eyeIdx, int _msaaSamples) = 0;
virtual void destroy(const ovrSession& _session) = 0;
virtual void render(const ovrSession& _session) = 0;
virtual void postRender(const ovrSession& _session) = 0;
ovrSizei m_eyeTextureSize;
ovrTextureSwapChain m_textureSwapChain;
};

View File

@ -1076,13 +1076,9 @@ BX_PRAGMA_DIAGNOSTIC_POP();
DX_RELEASE(device, 2);
}
memset(&m_adapterDesc, 0, sizeof(m_adapterDesc) );
hr = adapter->GetDesc(&m_adapterDesc);
if (FAILED(hr) )
{
BX_TRACE("Unable to create Direct3D11 device.");
DX_RELEASE(adapter, 2);
goto error;
}
BX_WARN(SUCCEEDED(hr), "Adapter GetDesc failed 0x%08x.", hr);
g_caps.vendorId = 0 == m_adapterDesc.VendorId
? BGFX_PCI_ID_SOFTWARE_RASTERIZER
@ -1354,140 +1350,168 @@ BX_PRAGMA_DIAGNOSTIC_POP();
if (DXGI_FORMAT_UNKNOWN != fmt)
{
struct D3D11_FEATURE_DATA_FORMAT_SUPPORT
if (BX_ENABLED(BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT) )
{
DXGI_FORMAT InFormat;
UINT OutFormatSupport;
};
struct D3D11_FEATURE_DATA_FORMAT_SUPPORT
{
DXGI_FORMAT InFormat;
UINT OutFormatSupport;
};
D3D11_FEATURE_DATA_FORMAT_SUPPORT data; // D3D11_FEATURE_DATA_FORMAT_SUPPORT2
data.InFormat = fmt;
hr = m_device->CheckFeatureSupport(D3D11_FEATURE_FORMAT_SUPPORT, &data, sizeof(data) );
if (SUCCEEDED(hr) )
{
support |= 0 != (data.OutFormatSupport & (0
| D3D11_FORMAT_SUPPORT_TEXTURE2D
| D3D11_FORMAT_SUPPORT_TEXTURE3D
| D3D11_FORMAT_SUPPORT_TEXTURECUBE
) )
? BGFX_CAPS_FORMAT_TEXTURE_2D
: BGFX_CAPS_FORMAT_TEXTURE_NONE
;
support |= 0 != (data.OutFormatSupport & (0
| D3D11_FORMAT_SUPPORT_TEXTURE3D
) )
? BGFX_CAPS_FORMAT_TEXTURE_3D
: BGFX_CAPS_FORMAT_TEXTURE_NONE
;
support |= 0 != (data.OutFormatSupport & (0
| D3D11_FORMAT_SUPPORT_TEXTURECUBE
) )
? BGFX_CAPS_FORMAT_TEXTURE_CUBE
: BGFX_CAPS_FORMAT_TEXTURE_NONE
;
support |= 0 != (data.OutFormatSupport & (0
| D3D11_FORMAT_SUPPORT_BUFFER
| D3D11_FORMAT_SUPPORT_IA_VERTEX_BUFFER
| D3D11_FORMAT_SUPPORT_IA_INDEX_BUFFER
) )
? BGFX_CAPS_FORMAT_TEXTURE_VERTEX
: BGFX_CAPS_FORMAT_TEXTURE_NONE
;
support |= 0 != (data.OutFormatSupport & (0
| D3D11_FORMAT_SUPPORT_SHADER_LOAD
) )
? BGFX_CAPS_FORMAT_TEXTURE_IMAGE
: BGFX_CAPS_FORMAT_TEXTURE_NONE
;
support |= 0 != (data.OutFormatSupport & (0
| D3D11_FORMAT_SUPPORT_RENDER_TARGET
| D3D11_FORMAT_SUPPORT_DEPTH_STENCIL
) )
? BGFX_CAPS_FORMAT_TEXTURE_FRAMEBUFFER
: BGFX_CAPS_FORMAT_TEXTURE_NONE
;
support |= 0 != (data.OutFormatSupport & (0
| D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET
) )
? BGFX_CAPS_FORMAT_TEXTURE_FRAMEBUFFER_MSAA
: BGFX_CAPS_FORMAT_TEXTURE_NONE
;
support |= 0 != (data.OutFormatSupport & (0
| D3D11_FORMAT_SUPPORT_MULTISAMPLE_LOAD
) )
? BGFX_CAPS_FORMAT_TEXTURE_MSAA
: BGFX_CAPS_FORMAT_TEXTURE_NONE
;
}
else
{
BX_TRACE("CheckFeatureSupport failed with %x for format %s.", hr, getName(TextureFormat::Enum(ii) ) );
}
if (0 != (support & BGFX_CAPS_FORMAT_TEXTURE_IMAGE) )
{
// clear image flag for additional testing
support &= ~BGFX_CAPS_FORMAT_TEXTURE_IMAGE;
data.InFormat = s_textureFormat[ii].m_fmt;
hr = m_device->CheckFeatureSupport(D3D11_FEATURE_FORMAT_SUPPORT2, &data, sizeof(data) );
D3D11_FEATURE_DATA_FORMAT_SUPPORT data; // D3D11_FEATURE_DATA_FORMAT_SUPPORT2
data.InFormat = fmt;
hr = m_device->CheckFeatureSupport(D3D11_FEATURE_FORMAT_SUPPORT, &data, sizeof(data) );
if (SUCCEEDED(hr) )
{
support |= 0 != (data.OutFormatSupport & (0
| D3D11_FORMAT_SUPPORT2_UAV_TYPED_LOAD
| D3D11_FORMAT_SUPPORT2_UAV_TYPED_STORE
| D3D11_FORMAT_SUPPORT_TEXTURE2D
| D3D11_FORMAT_SUPPORT_TEXTURE3D
| D3D11_FORMAT_SUPPORT_TEXTURECUBE
) )
? BGFX_CAPS_FORMAT_TEXTURE_2D
: BGFX_CAPS_FORMAT_TEXTURE_NONE
;
support |= 0 != (data.OutFormatSupport & (0
| D3D11_FORMAT_SUPPORT_TEXTURE3D
) )
? BGFX_CAPS_FORMAT_TEXTURE_3D
: BGFX_CAPS_FORMAT_TEXTURE_NONE
;
support |= 0 != (data.OutFormatSupport & (0
| D3D11_FORMAT_SUPPORT_TEXTURECUBE
) )
? BGFX_CAPS_FORMAT_TEXTURE_CUBE
: BGFX_CAPS_FORMAT_TEXTURE_NONE
;
support |= 0 != (data.OutFormatSupport & (0
| D3D11_FORMAT_SUPPORT_BUFFER
| D3D11_FORMAT_SUPPORT_IA_VERTEX_BUFFER
| D3D11_FORMAT_SUPPORT_IA_INDEX_BUFFER
) )
? BGFX_CAPS_FORMAT_TEXTURE_VERTEX
: BGFX_CAPS_FORMAT_TEXTURE_NONE
;
support |= 0 != (data.OutFormatSupport & (0
| D3D11_FORMAT_SUPPORT_SHADER_LOAD
) )
? BGFX_CAPS_FORMAT_TEXTURE_IMAGE
: BGFX_CAPS_FORMAT_TEXTURE_NONE
;
support |= 0 != (data.OutFormatSupport & (0
| D3D11_FORMAT_SUPPORT_RENDER_TARGET
| D3D11_FORMAT_SUPPORT_DEPTH_STENCIL
) )
? BGFX_CAPS_FORMAT_TEXTURE_FRAMEBUFFER
: BGFX_CAPS_FORMAT_TEXTURE_NONE
;
support |= 0 != (data.OutFormatSupport & (0
| D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET
) )
? BGFX_CAPS_FORMAT_TEXTURE_FRAMEBUFFER_MSAA
: BGFX_CAPS_FORMAT_TEXTURE_NONE
;
support |= 0 != (data.OutFormatSupport & (0
| D3D11_FORMAT_SUPPORT_MULTISAMPLE_LOAD
) )
? BGFX_CAPS_FORMAT_TEXTURE_MSAA
: BGFX_CAPS_FORMAT_TEXTURE_NONE
;
}
else
{
BX_TRACE("CheckFeatureSupport failed with %x for format %s.", hr, getName(TextureFormat::Enum(ii) ) );
}
if (0 != (support & BGFX_CAPS_FORMAT_TEXTURE_IMAGE) )
{
// clear image flag for additional testing
support &= ~BGFX_CAPS_FORMAT_TEXTURE_IMAGE;
data.InFormat = s_textureFormat[ii].m_fmt;
hr = m_device->CheckFeatureSupport(D3D11_FEATURE_FORMAT_SUPPORT2, &data, sizeof(data) );
if (SUCCEEDED(hr) )
{
support |= 0 != (data.OutFormatSupport & (0
| D3D11_FORMAT_SUPPORT2_UAV_TYPED_LOAD
| D3D11_FORMAT_SUPPORT2_UAV_TYPED_STORE
) )
? BGFX_CAPS_FORMAT_TEXTURE_IMAGE
: BGFX_CAPS_FORMAT_TEXTURE_NONE
;
}
}
}
else
{
support |= 0
| BGFX_CAPS_FORMAT_TEXTURE_2D
| BGFX_CAPS_FORMAT_TEXTURE_3D
| BGFX_CAPS_FORMAT_TEXTURE_CUBE
| BGFX_CAPS_FORMAT_TEXTURE_IMAGE
| BGFX_CAPS_FORMAT_TEXTURE_VERTEX
| BGFX_CAPS_FORMAT_TEXTURE_IMAGE
| BGFX_CAPS_FORMAT_TEXTURE_FRAMEBUFFER
| BGFX_CAPS_FORMAT_TEXTURE_FRAMEBUFFER_MSAA
| BGFX_CAPS_FORMAT_TEXTURE_MSAA
;
}
}
if (DXGI_FORMAT_UNKNOWN != fmtSrgb)
{
struct D3D11_FEATURE_DATA_FORMAT_SUPPORT
if (BX_ENABLED(BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT) )
{
DXGI_FORMAT InFormat;
UINT OutFormatSupport;
};
struct D3D11_FEATURE_DATA_FORMAT_SUPPORT
{
DXGI_FORMAT InFormat;
UINT OutFormatSupport;
};
D3D11_FEATURE_DATA_FORMAT_SUPPORT data; // D3D11_FEATURE_DATA_FORMAT_SUPPORT2
data.InFormat = fmtSrgb;
hr = m_device->CheckFeatureSupport(D3D11_FEATURE_FORMAT_SUPPORT, &data, sizeof(data) );
if (SUCCEEDED(hr) )
{
support |= 0 != (data.OutFormatSupport & (0
| D3D11_FORMAT_SUPPORT_TEXTURE2D
) )
? BGFX_CAPS_FORMAT_TEXTURE_2D_SRGB
: BGFX_CAPS_FORMAT_TEXTURE_NONE
;
D3D11_FEATURE_DATA_FORMAT_SUPPORT data; // D3D11_FEATURE_DATA_FORMAT_SUPPORT2
data.InFormat = fmtSrgb;
hr = m_device->CheckFeatureSupport(D3D11_FEATURE_FORMAT_SUPPORT, &data, sizeof(data) );
if (SUCCEEDED(hr) )
{
support |= 0 != (data.OutFormatSupport & (0
| D3D11_FORMAT_SUPPORT_TEXTURE2D
) )
? BGFX_CAPS_FORMAT_TEXTURE_2D_SRGB
: BGFX_CAPS_FORMAT_TEXTURE_NONE
;
support |= 0 != (data.OutFormatSupport & (0
| D3D11_FORMAT_SUPPORT_TEXTURE3D
) )
? BGFX_CAPS_FORMAT_TEXTURE_3D_SRGB
: BGFX_CAPS_FORMAT_TEXTURE_NONE
;
support |= 0 != (data.OutFormatSupport & (0
| D3D11_FORMAT_SUPPORT_TEXTURE3D
) )
? BGFX_CAPS_FORMAT_TEXTURE_3D_SRGB
: BGFX_CAPS_FORMAT_TEXTURE_NONE
;
support |= 0 != (data.OutFormatSupport & (0
| D3D11_FORMAT_SUPPORT_TEXTURECUBE
) )
? BGFX_CAPS_FORMAT_TEXTURE_CUBE_SRGB
: BGFX_CAPS_FORMAT_TEXTURE_NONE
;
support |= 0 != (data.OutFormatSupport & (0
| D3D11_FORMAT_SUPPORT_TEXTURECUBE
) )
? BGFX_CAPS_FORMAT_TEXTURE_CUBE_SRGB
: BGFX_CAPS_FORMAT_TEXTURE_NONE
;
}
else
{
BX_TRACE("CheckFeatureSupport failed with %x for sRGB format %s.", hr, getName(TextureFormat::Enum(ii) ) );
}
}
else
{
BX_TRACE("CheckFeatureSupport failed with %x for sRGB format %s.", hr, getName(TextureFormat::Enum(ii) ) );
support |= 0
| BGFX_CAPS_FORMAT_TEXTURE_2D_SRGB
| BGFX_CAPS_FORMAT_TEXTURE_3D_SRGB
| BGFX_CAPS_FORMAT_TEXTURE_CUBE_SRGB
;
}
}
@ -2132,7 +2156,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
ovrPostReset();
// If OVR doesn't create separate depth stencil view, create default one.
if (NULL == m_backBufferDepthStencil)
if (!m_ovr.isEnabled() && NULL == m_backBufferDepthStencil)
{
D3D11_TEXTURE2D_DESC dsd;
dsd.Width = getBufferWidth();
@ -3096,13 +3120,15 @@ BX_PRAGMA_DIAGNOSTIC_POP();
{
if (m_ovr.postReset() )
{
const uint32_t msaaSamples = 1 << ((m_resolution.m_flags&BGFX_RESET_MSAA_MASK) >> BGFX_RESET_MSAA_SHIFT);
for (uint32_t ii = 0; ii < 2; ++ii)
{
// eye buffers need to be initialized only once during application lifetime
if (NULL == m_ovr.m_eyeBuffers[ii])
{
m_ovr.m_eyeBuffers[ii] = &m_ovrBuffers[ii];
m_ovr.m_eyeBuffers[ii]->create(m_ovr.m_hmd, ii);
m_ovr.m_eyeBuffers[ii]->create(m_ovr.m_hmd, ii, msaaSamples);
}
}
@ -3566,10 +3592,13 @@ BX_PRAGMA_DIAGNOSTIC_POP();
}
#if BGFX_CONFIG_USE_OVR
void OVRBufferD3D11::create(const ovrSession& _session, int _eyeIdx)
void OVRBufferD3D11::create(const ovrSession& _session, int _eyeIdx, int _msaaSamples)
{
ovrHmdDesc hmdDesc = ovr_GetHmdDesc(_session);
m_eyeTextureSize = ovr_GetFovTextureSize(_session, (ovrEyeType)_eyeIdx, hmdDesc.DefaultEyeFov[_eyeIdx], 1.0f);
m_msaaTexture = NULL;
m_msaaRtv = NULL;
m_msaaSv = NULL;
ovrTextureSwapChainDesc desc = {};
desc.Type = ovrTexture_2D;
@ -3617,7 +3646,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
dbDesc.MipLevels = 1;
dbDesc.ArraySize = 1;
dbDesc.Format = DXGI_FORMAT_D32_FLOAT;
dbDesc.SampleDesc.Count = 1;
dbDesc.SampleDesc.Count = _msaaSamples;
dbDesc.SampleDesc.Quality = 0;
dbDesc.Usage = D3D11_USAGE_DEFAULT;
dbDesc.CPUAccessFlags = 0;
@ -3627,29 +3656,74 @@ BX_PRAGMA_DIAGNOSTIC_POP();
DX_CHECK(device->CreateTexture2D(&dbDesc, NULL, &tex) );
DX_CHECK(device->CreateDepthStencilView(tex, NULL, &m_depthBuffer) );
DX_RELEASE(tex, 0);
// create MSAA render target
if (_msaaSamples > 1)
{
D3D11_TEXTURE2D_DESC dsDesc;
dsDesc.Width = m_eyeTextureSize.w;
dsDesc.Height = m_eyeTextureSize.h;
dsDesc.MipLevels = 1;
dsDesc.ArraySize = 1;
dsDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
dsDesc.SampleDesc.Count = _msaaSamples;
dsDesc.SampleDesc.Quality = 0;
dsDesc.Usage = D3D11_USAGE_DEFAULT;
dsDesc.CPUAccessFlags = 0;
dsDesc.MiscFlags = 0;
dsDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
ID3D11Device* device = s_renderD3D11->m_device;
DX_CHECK(device->CreateTexture2D(&dsDesc, NULL, &m_msaaTexture));
DX_CHECK(device->CreateShaderResourceView(m_msaaTexture, NULL, &m_msaaSv));
DX_CHECK(device->CreateRenderTargetView(m_msaaTexture, NULL, &m_msaaRtv));
}
}
void OVRBufferD3D11::render(const ovrSession& _session)
{
// Clear and set up rendertarget
int texIndex = 0;
ovr_GetTextureSwapChainCurrentIndex(_session, m_textureSwapChain, &texIndex);
ID3D11DeviceContext* deviceCtx = s_renderD3D11->m_deviceCtx;
float black[] = { 0.0f, 0.0f, 0.0f, 0.0f }; // Important that alpha=0, if want pixels to be transparent, for manual layers
deviceCtx->OMSetRenderTargets(1, &m_eyeRtv[texIndex], m_depthBuffer);
deviceCtx->ClearRenderTargetView(m_eyeRtv[texIndex], black);
deviceCtx->ClearDepthStencilView(m_depthBuffer, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1, 0);
D3D11_VIEWPORT D3Dvp;
D3Dvp.TopLeftX = 0;
D3Dvp.TopLeftY = 0;
D3Dvp.Width = (FLOAT)m_eyeTextureSize.w;
D3Dvp.Height = (FLOAT)m_eyeTextureSize.h;
D3Dvp.MinDepth = 0;
D3Dvp.MaxDepth = 1;
deviceCtx->RSSetViewports(1, &D3Dvp);
// render to MSAA target
if (NULL != m_msaaTexture)
{
deviceCtx->OMSetRenderTargets(1, &m_msaaRtv, m_depthBuffer);
deviceCtx->ClearRenderTargetView(m_msaaRtv, black);
deviceCtx->ClearDepthStencilView(m_depthBuffer, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1, 0);
}
else // MSAA disabled? render directly to eye buffer
{
int texIndex = 0;
ovr_GetTextureSwapChainCurrentIndex(_session, m_textureSwapChain, &texIndex);
deviceCtx->OMSetRenderTargets(1, &m_eyeRtv[texIndex], m_depthBuffer);
deviceCtx->ClearRenderTargetView(m_eyeRtv[texIndex], black);
deviceCtx->ClearDepthStencilView(m_depthBuffer, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1, 0);
D3D11_VIEWPORT D3Dvp;
D3Dvp.TopLeftX = 0;
D3Dvp.TopLeftY = 0;
D3Dvp.Width = (FLOAT)m_eyeTextureSize.w;
D3Dvp.Height = (FLOAT)m_eyeTextureSize.h;
D3Dvp.MinDepth = 0;
D3Dvp.MaxDepth = 1;
deviceCtx->RSSetViewports(1, &D3Dvp);
}
}
void OVRBufferD3D11::postRender(const ovrSession& _session)
{
if (NULL != m_msaaTexture)
{
ID3D11DeviceContext* deviceCtx = s_renderD3D11->m_deviceCtx;
int destIndex = 0;
ovr_GetTextureSwapChainCurrentIndex(_session, m_textureSwapChain, &destIndex);
ID3D11Resource* dstTex = NULL;
ovr_GetTextureSwapChainBufferDX(_session, m_textureSwapChain, destIndex, IID_PPV_ARGS(&dstTex));
deviceCtx->ResolveSubresource(dstTex, 0, m_msaaTexture, 0, DXGI_FORMAT_R8G8B8A8_UNORM);
dstTex->Release();
}
}
void OVRBufferD3D11::destroy(const ovrSession& _session)
@ -3661,6 +3735,24 @@ BX_PRAGMA_DIAGNOSTIC_POP();
ovr_DestroyTextureSwapChain(_session, m_textureSwapChain);
m_depthBuffer->Release();
if (NULL != m_msaaTexture)
{
m_msaaTexture->Release();
m_msaaTexture = NULL;
}
if (NULL != m_msaaSv)
{
m_msaaSv->Release();
m_msaaSv = NULL;
}
if (NULL != m_msaaRtv)
{
m_msaaRtv->Release();
m_msaaRtv = NULL;
}
}
void OVRMirrorD3D11::create(const ovrSession& _session, int _width, int _height)

View File

@ -33,6 +33,7 @@ BX_PRAGMA_DIAGNOSTIC_POP()
#include "renderer_d3d.h"
#include "shader_dxbc.h"
#include "hmd_ovr.h"
#include "hmd_openvr.h"
#include "debug_renderdoc.h"
#ifndef D3DCOLOR_ARGB
@ -62,12 +63,16 @@ namespace bgfx { namespace d3d11
#if BGFX_CONFIG_USE_OVR
struct OVRBufferD3D11 : public OVRBufferI
{
virtual void create(const ovrSession& _session, int _eyeIdx) BX_OVERRIDE;
virtual void create(const ovrSession& _session, int _eyeIdx, int _msaaSamples) BX_OVERRIDE;
virtual void destroy(const ovrSession& _session) BX_OVERRIDE;
virtual void render(const ovrSession& _session) BX_OVERRIDE;
virtual void postRender(const ovrSession& _session) BX_OVERRIDE;
ID3D11RenderTargetView* m_eyeRtv[4];
ID3D11DepthStencilView* m_depthBuffer;
ID3D11Texture2D* m_msaaTexture;
ID3D11ShaderResourceView* m_msaaSv;
ID3D11RenderTargetView* m_msaaRtv;
};
struct OVRMirrorD3D11 : public OVRMirrorI

View File

@ -2864,13 +2864,15 @@ namespace bgfx { namespace gl
{
if (m_ovr.postReset() )
{
const uint32_t msaaSamples = 1 << ((m_resolution.m_flags&BGFX_RESET_MSAA_MASK) >> BGFX_RESET_MSAA_SHIFT);
for (uint32_t ii = 0; ii < 2; ++ii)
{
// eye buffers need to be initialized only once during application lifetime
if (NULL == m_ovr.m_eyeBuffers[ii])
{
m_ovr.m_eyeBuffers[ii] = &m_ovrBuffers[ii];
m_ovr.m_eyeBuffers[ii]->create(m_ovr.m_hmd, ii);
m_ovr.m_eyeBuffers[ii]->create(m_ovr.m_hmd, ii, msaaSamples);
}
}
@ -3332,8 +3334,15 @@ namespace bgfx { namespace gl
}
#if BGFX_CONFIG_USE_OVR
void OVRBufferGL::create(const ovrSession& _session, int _eyeIdx)
void OVRBufferGL::create(const ovrSession& _session, int _eyeIdx, int _msaaSamples)
{
m_eyeFbo = 0;
m_eyeTexId = 0;
m_depthBuffer = 0;
m_msaaEyeFbo = 0;
m_msaaEyeTexId = 0;
m_msaaDepthBuffer = 0;
ovrHmdDesc hmdDesc = ovr_GetHmdDesc(_session);
m_eyeTextureSize = ovr_GetFovTextureSize(_session, ovrEyeType(_eyeIdx), hmdDesc.DefaultEyeFov[_eyeIdx], 1.0f);
@ -3375,6 +3384,35 @@ namespace bgfx { namespace gl
GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE) );
GL_CHECK(glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, m_eyeTextureSize.w, m_eyeTextureSize.h, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL) );
// create MSAA buffers
if (_msaaSamples > 1)
{
GL_CHECK(glGenFramebuffers(1, &m_msaaEyeFbo) );
// create color MSAA texture
GL_CHECK(glGenTextures(1, &m_msaaEyeTexId) );
GL_CHECK(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_msaaEyeTexId) );
GL_CHECK(glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, _msaaSamples, GL_RGBA, m_eyeTextureSize.w, m_eyeTextureSize.h, false) );
GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER) );
GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER) );
GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR) );
GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) );
GL_CHECK(glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MAX_LEVEL, 0) );
// create MSAA depth buffer
GL_CHECK(glGenTextures(1, &m_msaaDepthBuffer) );
GL_CHECK(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_msaaDepthBuffer) );
GL_CHECK(glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, _msaaSamples, GL_DEPTH_COMPONENT, m_eyeTextureSize.w, m_eyeTextureSize.h, false) );
GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT) );
GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT) );
GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR) );
GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) );
GL_CHECK(glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MAX_LEVEL, 0) );
}
}
void OVRBufferGL::render(const ovrSession& _session)
@ -3384,20 +3422,74 @@ namespace bgfx { namespace gl
ovr_GetTextureSwapChainCurrentIndex(_session, m_textureSwapChain, &curIndex);
ovr_GetTextureSwapChainBufferGL(_session, m_textureSwapChain, curIndex, &m_eyeTexId);
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_eyeFbo) );
GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_eyeTexId, 0) );
GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthBuffer, 0) );
if (0 != m_msaaEyeFbo)
{
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_msaaEyeFbo) );
GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, m_msaaEyeTexId, 0) );
GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE, m_msaaDepthBuffer, 0) );
}
else // MSAA disabled? render directly to eye buffer
{
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_eyeFbo) );
GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_eyeTexId, 0) );
GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthBuffer, 0) );
}
GL_CHECK(glViewport(0, 0, m_eyeTextureSize.w, m_eyeTextureSize.h) );
GL_CHECK(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) );
}
void OVRBufferGL::postRender(const ovrSession& /*_sesion*/)
{
if (0 != m_msaaEyeFbo && 0 != m_eyeTexId)
{
// blit the contents of MSAA FBO to the regular eye buffer "connected" to the HMD
GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, m_msaaEyeFbo));
GL_CHECK(glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, m_msaaEyeTexId, 0) );
GL_CHECK(glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0) );
BX_CHECK(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_READ_FRAMEBUFFER)
, "glCheckFramebufferStatus failed 0x%08x"
, glCheckFramebufferStatus(GL_READ_FRAMEBUFFER) );
GL_CHECK(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_eyeFbo));
GL_CHECK(glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_eyeTexId, 0) );
GL_CHECK(glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0) );
BX_CHECK(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER)
, "glCheckFramebufferStatus failed 0x%08x"
, glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) );
GL_CHECK(glBlitFramebuffer(0, 0, m_eyeTextureSize.w, m_eyeTextureSize.h,
0, 0, m_eyeTextureSize.w, m_eyeTextureSize.h, GL_COLOR_BUFFER_BIT, GL_NEAREST) );
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0) );
}
}
void OVRBufferGL::destroy(const ovrSession& _session)
{
GL_CHECK(glDeleteFramebuffers(1, &m_eyeFbo) );
GL_CHECK(glDeleteTextures(1, &m_depthBuffer) );
ovr_DestroyTextureSwapChain(_session, m_textureSwapChain);
if (0 != m_msaaEyeFbo)
{
GL_CHECK(glDeleteFramebuffers(1, &m_msaaEyeFbo) );
m_msaaEyeFbo = 0;
}
if (0 != m_msaaEyeTexId)
{
GL_CHECK(glDeleteTextures(1, &m_msaaEyeTexId));
m_msaaEyeTexId = 0;
}
if (0 != m_msaaDepthBuffer)
{
GL_CHECK(glDeleteTextures(1, &m_msaaDepthBuffer));
m_msaaDepthBuffer = 0;
}
}
void OVRMirrorGL::create(const ovrSession& _session, int _width, int _height)

View File

@ -108,6 +108,7 @@ typedef uint64_t GLuint64;
#include "renderer.h"
#include "hmd_ovr.h"
#include "hmd_openvr.h"
#include "debug_renderdoc.h"
#ifndef GL_LUMINANCE
@ -904,13 +905,17 @@ namespace bgfx { namespace gl
#if BGFX_CONFIG_USE_OVR
struct OVRBufferGL : public OVRBufferI
{
virtual void create(const ovrSession& _session, int _eyeIdx) BX_OVERRIDE;
virtual void create(const ovrSession& _session, int _eyeIdx, int _msaaSamples) BX_OVERRIDE;
virtual void destroy(const ovrSession& _session) BX_OVERRIDE;
virtual void render(const ovrSession& _session) BX_OVERRIDE;
virtual void postRender(const ovrSession& _sesion) BX_OVERRIDE;
GLuint m_eyeFbo;
GLuint m_eyeTexId;
GLuint m_depthBuffer;
GLuint m_msaaEyeFbo;
GLuint m_msaaEyeTexId;
GLuint m_msaaDepthBuffer;
};
struct OVRMirrorGL : public OVRMirrorI
@ -1284,8 +1289,8 @@ namespace bgfx { namespace gl
void create(const ShaderGL& _vsh, const ShaderGL& _fsh);
void destroy();
void init();
void bindAttributes(const VertexDecl& _vertexDecl, uint32_t _baseVertex = 0) const;
void init();
void bindAttributes(const VertexDecl& _vertexDecl, uint32_t _baseVertex = 0) const;
void bindInstanceData(uint32_t _stride, uint32_t _baseVertex = 0) const;
void add(uint32_t _hash)
@ -1299,8 +1304,8 @@ namespace bgfx { namespace gl
GLint m_attributes[Attrib::Count]; // sparse
GLint m_instanceData[BGFX_CONFIG_MAX_INSTANCE_DATA_COUNT+1];
GLint m_sampler[BGFX_CONFIG_MAX_TEXTURE_SAMPLERS];
uint8_t m_numSamplers;
GLint m_sampler[BGFX_CONFIG_MAX_TEXTURE_SAMPLERS];
uint8_t m_numSamplers;
UniformBuffer* m_constantBuffer;
PredefinedUniform m_predefined[PredefinedUniform::Count];

View File

@ -801,6 +801,7 @@ end
MAME_DIR .. "3rdparty/bgfx/src/glcontext_wgl.cpp",
MAME_DIR .. "3rdparty/bgfx/src/image.cpp",
MAME_DIR .. "3rdparty/bgfx/src/hmd_ovr.cpp",
MAME_DIR .. "3rdparty/bgfx/src/hmd_openvr.cpp",
MAME_DIR .. "3rdparty/bgfx/src/renderer_d3d12.cpp",
MAME_DIR .. "3rdparty/bgfx/src/renderer_d3d11.cpp",
MAME_DIR .. "3rdparty/bgfx/src/renderer_d3d9.cpp",