From c1948b7c5d6ca2b310cf65e81563900336a6dcd3 Mon Sep 17 00:00:00 2001 From: Toad King Date: Mon, 24 Sep 2012 19:30:24 -0400 Subject: [PATCH] remove VGU requirement from VG video driver MESA's libOpenVG does not supply the utility functions --- Makefile | 2 +- gfx/math/matrix_3x3.c | 234 ++++++++++++++++++++++++++++++++++++++++++ gfx/math/matrix_3x3.h | 63 ++++++++++++ gfx/vg.c | 10 +- 4 files changed, 303 insertions(+), 6 deletions(-) create mode 100644 gfx/math/matrix_3x3.c create mode 100644 gfx/math/matrix_3x3.h diff --git a/Makefile b/Makefile index 22030da47c..43c968ec2f 100644 --- a/Makefile +++ b/Makefile @@ -180,7 +180,7 @@ ifeq ($(HAVE_SDL), 1) endif ifeq ($(HAVE_VG), 1) - OBJ += gfx/vg.o + OBJ += gfx/vg.o gfx/math/matrix_3x3.o DEFINES += $(VG_CFLAGS) LIBS += $(VG_LIBS) endif diff --git a/gfx/math/matrix_3x3.c b/gfx/math/matrix_3x3.c new file mode 100644 index 0000000000..fdadab2ef0 --- /dev/null +++ b/gfx/math/matrix_3x3.c @@ -0,0 +1,234 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2012 - Hans-Kristian Arntzen + * Copyright (C) 2012 - Michael Lelli + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#include "matrix_3x3.h" +#include +#include + +#define floatsEqual(x, y) (fabs(x - y) <= 0.00001f * ((x) > (y) ? (y) : (x))) +#define floatIsZero(x) (floatsEqual((x) + 1, 1)) + +void matrix_3x3_identity(math_matrix_3x3 *mat) +{ + memset(mat, 0, sizeof(*mat)); + for (unsigned i = 0; i < 3; i++) + MAT_ELEM_3X3(*mat, i, i) = 1.0f; +} + +void matrix_3x3_inits(math_matrix_3x3 *mat, + const float n11, const float n12, const float n13, + const float n21, const float n22, const float n23, + const float n31, const float n32, const float n33) +{ + MAT_ELEM_3X3(*mat, 0, 0) = n11; + MAT_ELEM_3X3(*mat, 0, 1) = n12; + MAT_ELEM_3X3(*mat, 0, 2) = n13; + MAT_ELEM_3X3(*mat, 1, 0) = n21; + MAT_ELEM_3X3(*mat, 1, 1) = n22; + MAT_ELEM_3X3(*mat, 1, 2) = n23; + MAT_ELEM_3X3(*mat, 2, 0) = n31; + MAT_ELEM_3X3(*mat, 2, 1) = n32; + MAT_ELEM_3X3(*mat, 2, 2) = n33; +} + +void matrix_3x3_transpose(math_matrix_3x3 *out, const math_matrix_3x3 *in) +{ + math_matrix_3x3 mat; + for (unsigned i = 0; i < 3; i++) + for (unsigned j = 0; j < 3; j++) + MAT_ELEM_3X3(mat, j, i) = MAT_ELEM_3X3(*in, i, j); + + *out = mat; +} + +void matrix_3x3_multiply(math_matrix_3x3 *out, + const math_matrix_3x3 *a, const math_matrix_3x3 *b) +{ + math_matrix_3x3 mat; + for (unsigned r = 0; r < 3; r++) + { + for (unsigned c = 0; c < 3; c++) + { + float dot = 0.0f; + for (unsigned k = 0; k < 3; k++) + dot += MAT_ELEM_3X3(*a, r, k) * MAT_ELEM_3X3(*b, k, c); + MAT_ELEM_3X3(mat, r, c) = dot; + } + } + + *out = mat; +} + +void matrix_3x3_divide_scalar(math_matrix_3x3 *mat, const float s) +{ + for (unsigned i = 0; i < 3; i++) + for (unsigned j = 0; j < 3; j++) + MAT_ELEM_3X3(*mat, i, j) /= s; +} + +float matrix_3x3_determinant(const math_matrix_3x3 *mat) +{ + float det = MAT_ELEM_3X3(*mat, 0, 0) * (MAT_ELEM_3X3(*mat, 1, 1) * MAT_ELEM_3X3(*mat, 2, 2) - MAT_ELEM_3X3(*mat, 1, 2) * MAT_ELEM_3X3(*mat, 2, 1)); + det -= MAT_ELEM_3X3(*mat, 0, 1) * (MAT_ELEM_3X3(*mat, 1, 0) * MAT_ELEM_3X3(*mat, 2, 2) - MAT_ELEM_3X3(*mat, 1, 2) * MAT_ELEM_3X3(*mat, 2, 0)); + det += MAT_ELEM_3X3(*mat, 0, 2) * (MAT_ELEM_3X3(*mat, 1, 0) * MAT_ELEM_3X3(*mat, 2, 1) - MAT_ELEM_3X3(*mat, 1, 1) * MAT_ELEM_3X3(*mat, 2, 0)); + + return det; +} + +void matrix_3x3_adjoint(math_matrix_3x3 *mat) +{ + math_matrix_3x3 out; + + MAT_ELEM_3X3(out, 0, 0) = (MAT_ELEM_3X3(*mat, 1, 1) * MAT_ELEM_3X3(*mat, 2, 2) - MAT_ELEM_3X3(*mat, 1, 2) * MAT_ELEM_3X3(*mat, 2, 1)); + MAT_ELEM_3X3(out, 0, 1) = -(MAT_ELEM_3X3(*mat, 0, 1) * MAT_ELEM_3X3(*mat, 2, 2) - MAT_ELEM_3X3(*mat, 0, 2) * MAT_ELEM_3X3(*mat, 2, 1)); + MAT_ELEM_3X3(out, 0, 2) = (MAT_ELEM_3X3(*mat, 0, 1) * MAT_ELEM_3X3(*mat, 1, 1) - MAT_ELEM_3X3(*mat, 0, 2) * MAT_ELEM_3X3(*mat, 1, 1)); + MAT_ELEM_3X3(out, 1, 0) = -(MAT_ELEM_3X3(*mat, 1, 0) * MAT_ELEM_3X3(*mat, 2, 2) - MAT_ELEM_3X3(*mat, 1, 2) * MAT_ELEM_3X3(*mat, 2, 0)); + MAT_ELEM_3X3(out, 1, 1) = (MAT_ELEM_3X3(*mat, 0, 0) * MAT_ELEM_3X3(*mat, 2, 2) - MAT_ELEM_3X3(*mat, 0, 2) * MAT_ELEM_3X3(*mat, 2, 0)); + MAT_ELEM_3X3(out, 1, 2) = -(MAT_ELEM_3X3(*mat, 0, 0) * MAT_ELEM_3X3(*mat, 1, 2) - MAT_ELEM_3X3(*mat, 0, 2) * MAT_ELEM_3X3(*mat, 1, 0)); + MAT_ELEM_3X3(out, 2, 0) = (MAT_ELEM_3X3(*mat, 1, 0) * MAT_ELEM_3X3(*mat, 2, 1) - MAT_ELEM_3X3(*mat, 1, 1) * MAT_ELEM_3X3(*mat, 2, 0)); + MAT_ELEM_3X3(out, 2, 1) = -(MAT_ELEM_3X3(*mat, 0, 0) * MAT_ELEM_3X3(*mat, 2, 1) - MAT_ELEM_3X3(*mat, 0, 1) * MAT_ELEM_3X3(*mat, 2, 0)); + MAT_ELEM_3X3(out, 2, 2) = (MAT_ELEM_3X3(*mat, 0, 0) * MAT_ELEM_3X3(*mat, 1, 1) - MAT_ELEM_3X3(*mat, 0, 1) * MAT_ELEM_3X3(*mat, 1, 0)); + + *mat = out; +} + +bool matrix_3x3_invert(math_matrix_3x3 *mat) +{ + float det = matrix_3x3_determinant(mat); + + if (floatIsZero(det)) + return false; + + matrix_3x3_adjoint(mat); + matrix_3x3_divide_scalar(mat, det); + return true; +} + +/************************************************************************** + * + * the following code is Copyright 2009 VMware, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +bool matrix_3x3_square_to_quad(const float dx0, const float dy0, + const float dx1, const float dy1, + const float dx3, const float dy3, + const float dx2, const float dy2, + math_matrix_3x3 *mat) +{ + float ax = dx0 - dx1 + dx2 - dx3; + float ay = dy0 - dy1 + dy2 - dy3; + + if (floatIsZero(ax) && floatIsZero(ay)) { + /* affine case */ + matrix_3x3_inits(mat, + dx1 - dx0, dy1 - dy0, 0, + dx2 - dx1, dy2 - dy1, 0, + dx0, dy0, 1); + } else { + float a, b, c, d, e, f, g, h; + float ax1 = dx1 - dx2; + float ax2 = dx3 - dx2; + float ay1 = dy1 - dy2; + float ay2 = dy3 - dy2; + + /* determinants */ + float gtop = ax * ay2 - ax2 * ay; + float htop = ax1 * ay - ax * ay1; + float bottom = ax1 * ay2 - ax2 * ay1; + + if (!bottom) + return false; + + g = gtop / bottom; + h = htop / bottom; + + a = dx1 - dx0 + g * dx1; + b = dx3 - dx0 + h * dx3; + c = dx0; + d = dy1 - dy0 + g * dy1; + e = dy3 - dy0 + h * dy3; + f = dy0; + + matrix_3x3_inits(mat, + a, d, g, + b, e, h, + c, f, 1.f); + } + + return true; +} + +bool matrix_3x3_quad_to_square(const float sx0, const float sy0, + const float sx1, const float sy1, + const float sx2, const float sy2, + const float sx3, const float sy3, + math_matrix_3x3 *mat) +{ + if (!matrix_3x3_square_to_quad(sx0, sy0, sx1, sy1, + sx2, sy2, sx3, sy3, + mat)) + return false; + + return matrix_3x3_invert(mat); +} + +bool matrix_3x3_quad_to_quad(const float dx0, const float dy0, + const float dx1, const float dy1, + const float dx2, const float dy2, + const float dx3, const float dy3, + const float sx0, const float sy0, + const float sx1, const float sy1, + const float sx2, const float sy2, + const float sx3, const float sy3, + math_matrix_3x3 *mat) +{ + math_matrix_3x3 quad_to_square, square_to_quad; + + if (!matrix_3x3_square_to_quad(dx0, dy0, dx1, dy1, + dx2, dy2, dx3, dy3, + &square_to_quad)) + return false; + + if (!matrix_3x3_quad_to_square(sx0, sy0, sx1, sy1, + sx2, sy2, sx3, sy3, + &quad_to_square)) + return false; + + matrix_3x3_multiply(mat, &quad_to_square, &square_to_quad); + + return true; +} diff --git a/gfx/math/matrix_3x3.h b/gfx/math/matrix_3x3.h new file mode 100644 index 0000000000..042275341a --- /dev/null +++ b/gfx/math/matrix_3x3.h @@ -0,0 +1,63 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2012 - Hans-Kristian Arntzen + * Copyright (C) 2012 - Michael Lelli + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#ifndef MATH_MATRIX_3X3_H__ +#define MATH_MATRIX_3X3_H__ + +#include "boolean.h" + +typedef struct math_matrix_3x3 +{ + float data[9]; +} math_matrix_3x3; + +#define MAT_ELEM_3X3(mat, r, c) ((mat).data[3 * (r) + (c)]) + +void matrix_3x3_inits(math_matrix_3x3 *mat, + const float n11, const float n12, const float n13, + const float n21, const float n22, const float n23, + const float n31, const float n32, const float n33); +void matrix_3x3_identity(math_matrix_3x3 *mat); +void matrix_3x3_transpose(math_matrix_3x3 *out, const math_matrix_3x3 *in); + +void matrix_3x3_multiply(math_matrix_3x3 *out, + const math_matrix_3x3 *a, const math_matrix_3x3 *b); +void matrix_3x3_divide_scalar(math_matrix_3x3 *mat, float s); +float matrix_3x3_determinant(const math_matrix_3x3 *mat); +void matrix_3x3_adjoint(math_matrix_3x3 *mat); +bool matrix_3x3_invert(math_matrix_3x3 *mat); + +bool matrix_3x3_square_to_quad(const float dx0, const float dy0, + const float dx1, const float dy1, + const float dx3, const float dy3, + const float dx2, const float dy2, + math_matrix_3x3 *mat); +bool matrix_3x3_quad_to_square(const float sx0, const float sy0, + const float sx1, const float sy1, + const float sx2, const float sy2, + const float sx3, const float sy3, + math_matrix_3x3 *mat); +bool matrix_3x3_quad_to_quad(const float dx0, const float dy0, + const float dx1, const float dy1, + const float dx2, const float dy2, + const float dx3, const float dy3, + const float sx0, const float sy0, + const float sx1, const float sy1, + const float sx2, const float sy2, + const float sx3, const float sy3, + math_matrix_3x3 *mat); + +#endif diff --git a/gfx/vg.c b/gfx/vg.c index c87e2d4324..ba2539bbb7 100644 --- a/gfx/vg.c +++ b/gfx/vg.c @@ -16,9 +16,9 @@ #include #include -#include #include #include "gfx_context.h" +#include "math/matrix_3x3.h" #include "../libretro.h" #include "../general.h" #include "../driver.h" @@ -42,7 +42,7 @@ typedef struct unsigned frame_count; VGImageFormat mTexType; VGImage mImage; - VGfloat mTransformMatrix[9]; + math_matrix_3x3 mTransformMatrix; VGint scissor[4]; #ifdef HAVE_FREETYPE @@ -300,13 +300,13 @@ static bool vg_frame(void *data, const void *frame, unsigned width, unsigned hei vg->mRenderWidth = width; vg->mRenderHeight = height; vg_calculate_quad(vg); - vguComputeWarpQuadToQuad( + matrix_3x3_quad_to_quad( vg->x1, vg->y1, vg->x2, vg->y1, vg->x2, vg->y2, vg->x1, vg->y2, // needs to be flipped, Khronos loves their bottom-left origin 0, height, width, height, width, 0, 0, 0, - vg->mTransformMatrix); + &vg->mTransformMatrix); vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE); - vgLoadMatrix(vg->mTransformMatrix); + vgLoadMatrix(vg->mTransformMatrix.data); } vgSeti(VG_SCISSORING, VG_FALSE); vgClear(0, 0, vg->mScreenWidth, vg->mScreenHeight);