./0000755000004100000410000000000013313171755011251 5ustar www-datawww-data./NEWS0000644000004100000410000000000213313171754011737 0ustar www-datawww-data ./doxygen-include.am0000644000004100000410000001304513313171755014671 0ustar www-datawww-data# --------------------------------------------------------------------------- # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # --------------------------------------------------------------------------- # Copyright (C) 2004 Oren Ben-Kiki # This file is distributed under the same terms as the Automake macro files. # Generate automatic documentation using Doxygen. Goals and variables values # are controlled by the various DX_COND_??? conditionals set by autoconf. # # The provided goals are: # doxygen-doc: Generate all doxygen documentation. # doxygen-run: Run doxygen, which will generate some of the documentation # (HTML, CHM, CHI, MAN, RTF, XML) but will not do the post # processing required for the rest of it (PS, PDF, and some MAN). # doxygen-man: Rename some doxygen generated man pages. # doxygen-ps: Generate doxygen PostScript documentation. # doxygen-pdf: Generate doxygen PDF documentation. # # Note that by default these are not integrated into the automake goals. If # doxygen is used to generate man pages, you can achieve this integration by # setting man3_MANS to the list of man pages generated and then adding the # dependency: # # $(man3_MANS): doxygen-doc # # This will cause make to run doxygen and generate all the documentation. # # The following variable is intended for use in Makefile.am: # # DX_CLEANFILES = everything to clean. # # This is usually added to MOSTLYCLEANFILES. ## --------------------------------- ## ## Format-independent Doxygen rules. ## ## --------------------------------- ## if DX_COND_doc ## ------------------------------- ## ## Rules specific for HTML output. ## ## ------------------------------- ## if DX_COND_html DX_CLEAN_HTML = @DX_DOCDIR@/html endif DX_COND_html ## ------------------------------ ## ## Rules specific for CHM output. ## ## ------------------------------ ## if DX_COND_chm DX_CLEAN_CHM = @DX_DOCDIR@/chm if DX_COND_chi DX_CLEAN_CHI = @DX_DOCDIR@/@PACKAGE@.chi endif DX_COND_chi endif DX_COND_chm ## ------------------------------ ## ## Rules specific for MAN output. ## ## ------------------------------ ## if DX_COND_man DX_CLEAN_MAN = @DX_DOCDIR@/man endif DX_COND_man ## ------------------------------ ## ## Rules specific for RTF output. ## ## ------------------------------ ## if DX_COND_rtf DX_CLEAN_RTF = @DX_DOCDIR@/rtf endif DX_COND_rtf ## ------------------------------ ## ## Rules specific for XML output. ## ## ------------------------------ ## if DX_COND_xml DX_CLEAN_XML = @DX_DOCDIR@/xml endif DX_COND_xml ## ----------------------------- ## ## Rules specific for PS output. ## ## ----------------------------- ## if DX_COND_ps DX_CLEAN_PS = @DX_DOCDIR@/@PACKAGE@.ps DX_PS_GOAL = doxygen-ps doxygen-ps: @DX_DOCDIR@/@PACKAGE@.ps @DX_DOCDIR@/@PACKAGE@.ps: @DX_DOCDIR@/@PACKAGE@.tag cd @DX_DOCDIR@/latex; \ rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \ $(DX_LATEX) refman.tex; \ $(MAKEINDEX_PATH) refman.idx; \ $(DX_LATEX) refman.tex; \ countdown=5; \ while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \ refman.log > /dev/null 2>&1 \ && test $$countdown -gt 0; do \ $(DX_LATEX) refman.tex; \ countdown=`expr $$countdown - 1`; \ done; \ $(DX_DVIPS) -o ../@PACKAGE@.ps refman.dvi endif DX_COND_ps ## ------------------------------ ## ## Rules specific for PDF output. ## ## ------------------------------ ## if DX_COND_pdf DX_CLEAN_PDF = @DX_DOCDIR@/@PACKAGE@.pdf DX_PDF_GOAL = doxygen-pdf doxygen-pdf: @DX_DOCDIR@/@PACKAGE@.pdf @DX_DOCDIR@/@PACKAGE@.pdf: @DX_DOCDIR@/@PACKAGE@.tag cd @DX_DOCDIR@/latex; \ rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \ $(DX_PDFLATEX) refman.tex; \ $(DX_MAKEINDEX) refman.idx; \ $(DX_PDFLATEX) refman.tex; \ countdown=5; \ while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \ refman.log > /dev/null 2>&1 \ && test $$countdown -gt 0; do \ $(DX_PDFLATEX) refman.tex; \ countdown=`expr $$countdown - 1`; \ done; \ mv refman.pdf ../@PACKAGE@.pdf endif DX_COND_pdf ## ------------------------------------------------- ## ## Rules specific for LaTeX (shared for PS and PDF). ## ## ------------------------------------------------- ## if DX_COND_latex DX_CLEAN_LATEX = @DX_DOCDIR@/latex endif DX_COND_latex .PHONY: doxygen-run doxygen-doc $(DX_PS_GOAL) $(DX_PDF_GOAL) .INTERMEDIATE: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL) doxygen-run: @DX_DOCDIR@/@PACKAGE@.tag doxygen-doc: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL) @DX_DOCDIR@/@PACKAGE@.tag: $(DX_CONFIG) $(pkginclude_HEADERS) rm -rf @DX_DOCDIR@ $(DX_ENV) $(DX_DOXYGEN) $(srcdir)/$(DX_CONFIG) DX_CLEANFILES = \ @DX_DOCDIR@/@PACKAGE@.tag \ -r \ $(DX_CLEAN_HTML) \ $(DX_CLEAN_CHM) \ $(DX_CLEAN_CHI) \ $(DX_CLEAN_MAN) \ $(DX_CLEAN_RTF) \ $(DX_CLEAN_XML) \ $(DX_CLEAN_PS) \ $(DX_CLEAN_PDF) \ $(DX_CLEAN_LATEX) endif DX_COND_doc ./INSTALL0000644000004100000410000003661013313171754012307 0ustar www-datawww-dataInstallation Instructions ************************* Copyright (C) 1994-1996, 1999-2002, 2004-2013 Free Software Foundation, Inc. Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. This file is offered as-is, without warranty of any kind. Basic Installation ================== Briefly, the shell command `./configure && make && make install' should configure, build, and install this package. The following more-detailed instructions are generic; see the `README' file for instructions specific to this package. Some packages provide this `INSTALL' file but do not implement all of the features documented below. The lack of an optional feature in a given package is not necessarily a bug. More recommendations for GNU packages can be found in *note Makefile Conventions: (standards)Makefile Conventions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). It can also use an optional file (typically called `config.cache' and enabled with `--cache-file=config.cache' or simply `-C') that saves the results of its tests to speed up reconfiguring. Caching is disabled by default to prevent problems with accidental use of stale cache files. If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If you are using the cache, and at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.ac' (or `configure.in') is used to create `configure' by a program called `autoconf'. You need `configure.ac' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. Running `configure' might take a while. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package, generally using the just-built uninstalled binaries. 4. Type `make install' to install the programs and any data files and documentation. When installing into a prefix owned by root, it is recommended that the package be configured and built as a regular user, and only the `make install' phase executed with root privileges. 5. Optionally, type `make installcheck' to repeat any self-tests, but this time using the binaries in their final installed location. This target does not install anything. Running this target as a regular user, particularly if the prior `make install' required root privileges, verifies that the installation completed correctly. 6. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. 7. Often, you can also type `make uninstall' to remove the installed files again. In practice, not all packages have tested that uninstallation works correctly, even though it is required by the GNU Coding Standards. 8. Some packages, particularly those that use Automake, provide `make distcheck', which can by used by developers to test that all other targets like `make install' and `make uninstall' work correctly. This target is generally not run by end users. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. Run `./configure --help' for details on some of the pertinent environment variables. You can give `configure' initial values for configuration parameters by setting variables in the command line or in the environment. Here is an example: ./configure CC=c99 CFLAGS=-g LIBS=-lposix *Note Defining Variables::, for more details. Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you can use GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. This is known as a "VPATH" build. With a non-GNU `make', it is safer to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. On MacOS X 10.5 and later systems, you can create libraries and executables that work on multiple system types--known as "fat" or "universal" binaries--by specifying multiple `-arch' options to the compiler but only a single `-arch' option to the preprocessor. Like this: ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CPP="gcc -E" CXXCPP="g++ -E" This is not guaranteed to produce working output in all cases, you may have to build one architecture at a time and combine the results using the `lipo' tool if you have problems. Installation Names ================== By default, `make install' installs the package's commands under `/usr/local/bin', include files under `/usr/local/include', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PREFIX', where PREFIX must be an absolute file name. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you pass the option `--exec-prefix=PREFIX' to `configure', the package uses PREFIX as the prefix for installing programs and libraries. Documentation and other data files still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=DIR' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. In general, the default for these options is expressed in terms of `${prefix}', so that specifying just `--prefix' will affect all of the other directory specifications that were not explicitly provided. The most portable way to affect installation locations is to pass the correct locations to `configure'; however, many packages provide one or both of the following shortcuts of passing variable assignments to the `make install' command line to change installation locations without having to reconfigure or recompile. The first method involves providing an override variable for each affected directory. For example, `make install prefix=/alternate/directory' will choose an alternate location for all directory configuration variables that were expressed in terms of `${prefix}'. Any directories that were specified during `configure', but not in terms of `${prefix}', must each be overridden at install time for the entire installation to be relocated. The approach of makefile variable overrides for each directory variable is required by the GNU Coding Standards, and ideally causes no recompilation. However, some platforms have known limitations with the semantics of shared libraries that end up requiring recompilation when using this method, particularly noticeable in packages that use GNU Libtool. The second method involves providing the `DESTDIR' variable. For example, `make install DESTDIR=/alternate/directory' will prepend `/alternate/directory' before all installation names. The approach of `DESTDIR' overrides is not required by the GNU Coding Standards, and does not work on platforms that have drive letters. On the other hand, it does better at avoiding recompilation issues, and works well even when some directory options were not specified in terms of `${prefix}' at `configure' time. Optional Features ================= If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Some packages offer the ability to configure how verbose the execution of `make' will be. For these packages, running `./configure --enable-silent-rules' sets the default to minimal output, which can be overridden with `make V=1'; while running `./configure --disable-silent-rules' sets the default to verbose, which can be overridden with `make V=0'. Particular systems ================== On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC is not installed, it is recommended to use the following options in order to use an ANSI C compiler: ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" and if that doesn't work, install pre-built binaries of GCC for HP-UX. HP-UX `make' updates targets which have the same time stamps as their prerequisites, which makes it generally unusable when shipped generated files such as `configure' are involved. Use GNU `make' instead. On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot parse its `' header file. The option `-nodtk' can be used as a workaround. If GNU CC is not installed, it is therefore recommended to try ./configure CC="cc" and if that doesn't work, try ./configure CC="cc -nodtk" On Solaris, don't put `/usr/ucb' early in your `PATH'. This directory contains several dysfunctional programs; working variants of these programs are available in `/usr/bin'. So, if you need `/usr/ucb' in your `PATH', put it _after_ `/usr/bin'. On Haiku, software installed for all users goes in `/boot/common', not `/usr/local'. It is recommended to use the following options: ./configure --prefix=/boot/common Specifying the System Type ========================== There may be some features `configure' cannot figure out automatically, but needs to determine by the type of machine the package will run on. Usually, assuming the package is built to be run on the _same_ architectures, `configure' can figure that out, but if it prints a message saying it cannot guess the machine type, give it the `--build=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name which has the form: CPU-COMPANY-SYSTEM where SYSTEM can have one of these forms: OS KERNEL-OS See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the machine type. If you are _building_ compiler tools for cross-compiling, you should use the option `--target=TYPE' to select the type of system they will produce code for. If you want to _use_ a cross compiler, that generates code for a platform different from the build platform, you should specify the "host" platform (i.e., that on which the generated programs will eventually be run) with `--host=TYPE'. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Defining Variables ================== Variables not defined in a site shell script can be set in the environment passed to `configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set them in the `configure' command line, using `VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc causes the specified `gcc' to be used as the C compiler (unless it is overridden in the site shell script). Unfortunately, this technique does not work for `CONFIG_SHELL' due to an Autoconf limitation. Until the limitation is lifted, you can use this workaround: CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash `configure' Invocation ====================== `configure' recognizes the following options to control how it operates. `--help' `-h' Print a summary of all of the options to `configure', and exit. `--help=short' `--help=recursive' Print a summary of the options unique to this package's `configure', and exit. The `short' variant lists options used only in the top level, while the `recursive' variant lists options also present in any nested packages. `--version' `-V' Print the version of Autoconf used to generate the `configure' script, and exit. `--cache-file=FILE' Enable the cache: use and save the results of the tests in FILE, traditionally `config.cache'. FILE defaults to `/dev/null' to disable caching. `--config-cache' `-C' Alias for `--cache-file=config.cache'. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `--prefix=DIR' Use DIR as the installation prefix. *note Installation Names:: for more details, including other options available for fine-tuning the installation locations. `--no-create' `-n' Run the configure checks, but stop before creating any output files. `configure' also accepts some other, not widely useful, options. Run `configure --help' for more details. ./configure.ac0000644000004100000410000003574213313171755013552 0ustar www-datawww-data# # Based on Clutter's autofoo. Here's how this goes down: # # api_version = The soname version "libnux-1.0.so" # version = The package version "1.2.2" # # Making a point release: # - Increase micro_version to the next even number # - Increase interface_age to the next even number UNLESS there was an API # addition/deprecation, at which point you should set it to 0 # # After the release: # - Increase micro_version to the next odd number # - Increase interface_version to the next odd number # m4_define([nux_major_version], [4]) m4_define([nux_minor_version], [0]) m4_define([nux_micro_version], [8]) m4_define([nux_api_version], [4.0]) # Increase the number (to the current date) everytime you propose a branch that breaks the API or ABI # The number format is : year/month/day # e.g.: december 5th, 2011 is: 20111205 # To make more than one API change in a day, add a number to the date. Like 20111205.xx m4_define([nux_abi_version], [20140307.0]) m4_define([nux_version], [nux_major_version.nux_minor_version.nux_micro_version]) # increase the interface age by 1 for each release; if the API changes, # set to 0. interface_age and binary_age are used to create the soname # of the shared object: # # ( * 100 + ) - # # this allows using the same soname for different micro-releases in case # no API was added or deprecated. for instance: # # nux 1.2.0 -> 100 * 2 + 0 = 200, interface age = 0 -> 200 # nux 1.2.2 -> 100 * 2 + 2 = 202, interface age = 2 -> 200 # nux 1.2.4 -> 100 * 2 + 4 = 204, interface age = 4 -> 200 # [ API addition, deprecation ] # nux 1.2.6 -> 100 * 2 + 6 = 206, interface age = 0 -> 206 # nux 1.2.8 -> 100 * 2 + 8 = 208, interface age = 2 -> 206 # nux 1.2.10 -> 100 * 2 + 10 = 210, interface age = 4 -> 206 # ... # m4_define([nux_interface_age], [0]) m4_define([nux_binary_age], [m4_eval(100 * nux_minor_version + nux_micro_version)]) AC_PREREQ(2.59) AC_INIT([nux], [nux_version], [https://bugs.launchpad.net/nux]) AC_COPYRIGHT([Copyright 2010-2013 Inalogic Inc.]) m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) AC_CONFIG_SRCDIR([Makefile.am]) AM_CONFIG_HEADER([config.h]) AM_INIT_AUTOMAKE([1.10]) NUX_MAJOR_VERSION=nux_major_version NUX_MINOR_VERSION=nux_minor_version NUX_MICRO_VERSION=nux_micro_version NUX_VERSION=nux_version NUX_API_VERSION=nux_api_version NUX_ABI_VERSION=nux_abi_version AC_SUBST(NUX_MAJOR_VERSION) AC_SUBST(NUX_MINOR_VERSION) AC_SUBST(NUX_MICRO_VERSION) AC_SUBST(NUX_VERSION) AC_SUBST(NUX_API_VERSION) AC_SUBST(NUX_ABI_VERSION) m4_define([lt_current], [m4_eval(100 * nux_minor_version + nux_micro_version - nux_interface_age)]) m4_define([lt_revision], [nux_interface_age]) m4_define([lt_age], [m4_eval(nux_binary_age - nux_interface_age)]) NUX_LT_CURRENT=lt_current NUX_LT_REV=lt_revision NUX_LT_AGE=lt_age NUX_LT_VERSION="$NUX_LT_CURRENT:$NUX_LT_REV:$NUX_LT_AGE" NUX_LT_LDFLAGS="-version-info $NUX_LT_VERSION" AC_SUBST(NUX_LT_VERSION) AC_SUBST(NUX_LT_LDFLAGS) AC_CONFIG_MACRO_DIR([m4]) dnl =========================================================================== # Checks for programs AM_CXXFLAGS-"$CXXFLAGS -std=c++0x" AC_PROG_CC_C99 AC_PROG_CXX AM_PROG_CC_C_O # require libtool >= 2.2 LT_PREREQ([2.2.6]) LT_INIT([disable-static]) # Checks for header files AC_HEADER_STDC # Checks for typedefs, structures and compiler charecteristics AC_C_CONST # Checks for library functions AC_FUNC_MALLOC AC_FUNC_MMAP AC_CHECK_FUNCS([memset munmap strcasecmp strdup]) PKG_PROG_PKG_CONFIG dnl =========================================================================== GL_PKGS="gl glu glewmx xext x11" MAINTAINER_CFLAGS="" # X11 build AC_ARG_ENABLE([x_support], [AC_HELP_STRING([--enable-x-support=@<:@no/yes@:>@], [Enable X11 code path @<:@default=yes@:>@])], [], [enable_x_support=yes]) AS_IF([test "x$enable_x_support" = "xyes"], [ MAINTAINER_CFLAGS+=" -DUSE_X11" ]) AS_IF([test "x$enable_x_support" = "xno"], [ MAINTAINER_CFLAGS+=" -DNO_X11" ]) AM_CONDITIONAL(USE_X11, [test "x$enable_x_support" = "xyes"]) # Enable opengl es 20 code path AC_ARG_ENABLE([opengles_20], [AC_HELP_STRING([--enable-opengles-20=@<:@no/yes@:>@], [Enable OpenGL ES 20 code path @<:@default=no@:>@])], [], [enable_opengles_20=no]) AS_IF([test "x$enable_opengles_20" = "xyes"], [ MAINTAINER_CFLAGS+=" -DNUX_OPENGLES_20" GL_PKGS="egl glesv2" ] ) AM_CONDITIONAL(NUX_OPENGLES_20, [test "x$enable_opengles_20" = "xyes"]) # Minimal builds AC_ARG_ENABLE([minimal_build], [AC_HELP_STRING([--enable-minimal-build=@<:@no/yes@:>@], [Enable minimal builds @<:@default=no@:>@])], [], [enable_minimal_build=no]) AS_IF([test "x$enable_minimal_build" = "xyes"], [ MAINTAINER_CFLAGS+=" -DNUX_MINIMAL" ]) AM_CONDITIONAL(NUX_MINIMAL, [test "x$enable_minimal_build" = "xyes"]) AC_SUBST(GL_PKGS) AC_SUBST(MAINTAINER_CFLAGS) dnl =========================================================================== PKG_CHECK_MODULES(NUX_CORE, glib-2.0 >= 2.25.14 gthread-2.0 sigc++-2.0 gio-2.0 ) AC_SUBST(NUX_CORE_CFLAGS) AC_SUBST(NUX_CORE_LIBS) PKG_CHECK_MODULES(NUX_GRAPHICS, glib-2.0 >= 2.25.14 gdk-pixbuf-2.0 cairo >= 1.9.14 libpng >= 1.2.44 $GL_PKGS xxf86vm sigc++-2.0 xinerama ) AC_SUBST(NUX_GRAPHICS_CFLAGS) AC_SUBST(NUX_GRAPHICS_LIBS) PKG_CHECK_MODULES(NUX, glib-2.0 >= 2.25.14 gdk-pixbuf-2.0 gthread-2.0 $GL_PKGS sigc++-2.0 pango pangocairo libpcre ) AC_SUBST(NUX_CFLAGS) AC_SUBST(NUX_LIBS) PKG_CHECK_MODULES(UNITY_SUPPORT_TEST, x11 $GL_PKGS xcomposite xdamage libpci ) AC_SUBST(UNITY_SUPPORT_TEST_CFLAGS) AC_SUBST(UNITY_SUPPORT_TEST_LIBS) PKG_CHECK_MODULES(IBUS, glib-2.0 >= 2.25.14 gio-2.0 ibus-1.0 gobject-2.0 ) AC_SUBST(IBUS_CFLAGS) AC_SUBST(IBUS_LIBS) dnl ********************************************************* dnl Enable/disable gestures (geis, from Open Input Framework) dnl ********************************************************* GEIS_PKGS="libgeis" AC_ARG_ENABLE(gestures, AC_HELP_STRING(--disable-gestures, Disables multitouch gestures support (default: auto-detect)), [], [enable_gestures=auto]) # Check for geis as an optional dependency AS_IF([test "x$enable_gestures" = "xauto"], [ PKG_CHECK_MODULES(GEIS, [libgeis >= 2.2.10], [have_geis=yes], [have_geis=no]) ]) AS_IF([test "x$enable_gestures" = "xyes"], [ PKG_CHECK_MODULES(GEIS, [libgeis >= 2.2.10], [have_geis=yes], [ AC_MSG_ERROR([libgeis not found!]) have_geis=no ]) ]) AS_IF([test "x$enable_gestures" = "xno"], [have_geis=no]) AS_IF([test "x$have_geis" = "xyes"], [ NUX_GESTURES_SUPPORT="NUX_GESTURES_SUPPORT" AM_CONDITIONAL(HAVE_GEIS, true) ], [ NUX_GESTURES_SUPPORT="NUX_NO_GESTURES_SUPPORT" AM_CONDITIONAL(HAVE_GEIS, false) GEIS_PKGS="" ]) AC_SUBST(NUX_GESTURES_SUPPORT) AC_SUBST(GEIS_CFLAGS) AC_SUBST(GEIS_LIBS) AC_SUBST(GEIS_PKGS) dnl ************************************ dnl Enable/disable tests dnl ************************************ AC_ARG_ENABLE([tests], [AC_HELP_STRING([--enable-tests=@<:@no/yes@:>@], [Enable Nux Testing @<:@default=yes@:>@])], [], [enable_tests=yes]) AS_IF([test "x$enable_tests" = "xyes"], [ # Check for google gtest CHECK_GTEST AS_IF([test "x$have_gtest" != "xyes"], [AC_MSG_WARN([you are missing google-test, apt-get install google-mock])]) #Check for libboost AC_LANG_PUSH([C++]) AC_CHECK_HEADER([boost/filesystem.hpp], [have_boost=yes], [AC_MSG_WARN([you are missing boost, apt-get install libboost-dev])]) AC_LANG_POP([C++]) #Check for libboost-system AC_LANG_PUSH([C++]) AC_CHECK_HEADER([boost/system/config.hpp], [have_boost_system=yes], [AC_MSG_WARN([you are missing boost-system, apt-get install libboost-system-dev])]) AC_LANG_POP([C++]) #Check for libboost-filesystem AC_LANG_PUSH([C++]) AC_CHECK_HEADER([boost/filesystem/fstream.hpp], [have_boost_fs=yes], [AC_MSG_WARN([you are missing boost-filesystem, apt-get install libboost-filesystem-dev])]) AC_LANG_POP([C++]) #Check for libxtst AC_CHECK_HEADER([X11/extensions/XTest.h], [have_xtest=yes], [AC_MSG_WARN([you are missing libxtst-dev, apt-get install libxtst-dev])]) ] ) AS_IF([test "x$have_xtest" = "xyes" && test "x$have_boost" = "xyes" && test "x$have_boost_system" = "xyes" && test "x$have_boost_fs" = "xyes" && test "x$have_gmock" = "xyes" && test "x$have_gtest" = "xyes"], [], [enable_tests=no] ) AM_CONDITIONAL(BUILD_TESTS, [test "x$enable_tests" = "xyes"]) AS_IF([test "x$enable_tests" = "xyes" && test "x$enable_x_support" = "xyes"], [ PKG_CHECK_MODULES(NUX_TESTS, x11) ], [] ) AC_SUBST(NUX_TESTS_CFLAGS) AC_SUBST(NUX_TESTS_LIBS) ########################### # gcov coverage reporting ########################### m4_include([m4/gcov.m4]) AC_TDD_GCOV AM_CONDITIONAL([HAVE_GCOV], [test "x$ac_cv_check_gcov" = xyes]) AM_CONDITIONAL([HAVE_LCOV], [test "x$ac_cv_check_lcov" = xyes]) AM_CONDITIONAL([HAVE_GCOVR], [test "x$ac_cv_check_gcovr" = xyes]) AC_SUBST(COVERAGE_CFLAGS) AC_SUBST(COVERAGE_LDFLAGS) dnl =========================================================================== # sets up doxygen m4_include([m4/ac_doxygen.m4]) DX_DOXYGEN_FEATURE(ON) DX_HTML_FEATURE(ON) DX_CHM_FEATURE(OFF) DX_CHI_FEATURE(OFF) DX_MAN_FEATURE(OFF) DX_RTF_FEATURE(OFF) DX_XML_FEATURE(OFF) DX_PDF_FEATURE(OFF) DX_PS_FEATURE(OFF) DX_INIT_DOXYGEN(nux, doxygen.cfg, doc) AC_ARG_ENABLE([documentation], [AC_HELP_STRING([--enable-documentation=@<:@no/yes@:>@], [Enable building of documentation @<:@default=no@:>@])], [], [enable_documentation=no]) AM_CONDITIONAL(BUILD_DOCUMENTATION, [test "x$enable_documentation" = "xyes"]) dnl ========================================================================== if test "x$GCC" = "xyes"; then GCC_FLAGS="-g -Werror -Wall -Wextra -Wno-unused-parameter -std=c++0x" fi # gcc flags for building the tests. GCC_TESTS_FLAGS="-g -O0 -Wall -Wextra -std=c++0x" # use strict compiler flags only on development releases AC_ARG_ENABLE([maintainer-mode], [AC_HELP_STRING([--enable-maintainer-mode=@<:@no/yes@:>@], [Use strict compiler flags @<:@default=no@:>@])], [], [enable_maintainer_mode=no]) AS_IF([test "x$enable_maintainer_mode" = "xyes" && test "x$GCC" = "xyes"], [ MAINTAINER_CFLAGS+="-Werror -Wall -Wextra -Wcast-align -Wno-uninitialized -Wempty-body -Wformat-security -Winit-self -Wno-unused-parameter" ] ) # This enables lots of useful debugging output in Nux. # In debug mode, relax the number of build failures due to -Werror. AC_ARG_ENABLE([debug], [AC_HELP_STRING([--enable-debug=@<:@no/yes@:>@], [Enable Nux debugging @<:@default=no@:>@])], [], [enable_debug=no]) AS_IF([test "x$enable_debug" = "xyes"], [ MAINTAINER_CFLAGS+=" -DNUX_DEBUG" GCC_FLAGS="-g -O0 -Wall -Wextra -Wno-unused-parameter -std=c++0x" ] ) AC_SUBST(GCC_FLAGS) AC_SUBST(GCC_TESTS_FLAGS) AC_SUBST(MAINTAINER_CFLAGS) # this enables lots of useful debugging output in Nux AC_ARG_ENABLE([examples], [AC_HELP_STRING([--enable-examples=@<:@no/yes@:>@], [Enable building of examples @<:@default=yes@:>@])], [], [enable_examples=yes]) AM_CONDITIONAL(BUILD_EXAMPLES, [test "x$enable_examples" = "xyes"]) AM_COND_IF([BUILD_EXAMPLES], [ PKG_CHECK_MODULES(NUX_EXAMPLES, x11) AC_SUBST(NUX_EXAMPLES_CFLAGS) AC_SUBST(NUX_EXAMPLES_LIBS) ], ) # this enables gpu tests AC_ARG_ENABLE([gputests], [AC_HELP_STRING([--enable-gputests=@<:@no/yes@:>@], [Enable building of gpu tests @<:@default=yes@:>@])], [], [enable_gputests=yes]) AM_CONDITIONAL(BUILD_GPUTESTS, [test "x$enable_gputests" = "xyes"]) AM_COND_IF([BUILD_GPUTESTS], [ PKG_CHECK_MODULES(NUX_GPUTESTS, x11) AC_SUBST(NUX_GPUTESTS_CFLAGS) AC_SUBST(NUX_GPUTESTS_LIBS) ], ) dnl =========================================================================== AC_CONFIG_FILES([ Makefile data/Makefile NuxCore/Makefile NuxCore/nux-core.pc NuxGraphics/Makefile NuxGraphics/nux-graphics.pc Nux/Makefile Nux/nux.pc Nux/ABI.h Nux/Features.h examples/Makefile tests/Makefile tools/Makefile gputests/Makefile ]) AC_OUTPUT BOLD_GREEN="\033@<:@1;32m" GREEN="\033@<:@0;32m" BOLD_WHITE="\033@<:@1;37m" RESET="\033@<:@0m" echo "" echo -e "${BOLD_GREEN} Nux - $VERSION" echo -e "${RESET}" echo -e "${GREEN} • Global:${RESET}" echo -e " Prefix : ${BOLD_WHITE}${prefix}" echo -e "${RESET}" echo -e "${GREEN} • Compiler Options:${RESET}" echo -e " CFLAGS : ${BOLD_WHITE}${CFLAGS} ${GCC_FLAGS}${RESET}" echo -e " Maintainer CFlags : ${BOLD_WHITE}${MAINTAINER_CFLAGS}${RESET}" echo -e " Debug Mode : ${BOLD_WHITE}${enable_debug}${RESET}" echo -e "${RESET}" echo -e "${GREEN} • Documentation:${RESET}" echo -e " Build Documentation: ${BOLD_WHITE}${enable_documentation}${RESET}" echo -e "${RESET}" echo -e "${GREEN} • Misc Options:${RESET}" echo -e " Build Examples : ${BOLD_WHITE}${enable_examples}${RESET}" echo -e " Build Gpu Tests : ${BOLD_WHITE}${enable_gputests}${RESET}" echo -e " Build Nux Tests : ${BOLD_WHITE}${enable_tests}${RESET}" echo -e " Coverage Reporting : ${BOLD_WHITE}${use_gcov}${RESET}" echo -e " Gestures support : ${BOLD_WHITE}${have_geis}${RESET}" echo -e " X11 build support : ${BOLD_WHITE}${enable_x_support}${RESET}" echo -e " Minimal build : ${BOLD_WHITE}${enable_minimal_build}${RESET}" echo "" echo -e "${RESET}" ./README0000644000004100000410000000460013313171755012131 0ustar www-datawww-dataBuilding Nux ============ Stephen M. Webb 4.0.0, 2013-05-10 Building from Revision Control ------------------------------ A fresh checkout from source control (bzr lp:nux) requires the build infrastructure to be prepared. Unlike most projects that use the GNU autotools, Nux requires the use of the GNOME autotools wrapper to be run in order to pick up some GNOME-specific autoconf macros. Using the GNU autotools tool, autoreconf, for that purpose will not prepare a working build system. Preparing the build system requires that the gnome-common package be installed. The shell command `./autogen.sh` is sufficient to prepare the build system. Normally, Nux is built out-of-source, in other words in a dorectory thatis not the source directory. Running `autogen.sh` in the build directory will generate the configure and Makefile.in files in the _source_ directory. Building from a Source Tarball ------------------------------ After the build system is prepared, ir when building from a source tarball, the shell commands './configure; make; make install' should configure, build, ad install the package. Additional instructions on how to configure and build Nux are found in the INSTALL file included with the source. Interesting Additional Arguments to `autogen.sh` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Atthe least, the installation prefix is usually specified when running `autogen.sh` or `configure`. The default installation prefix will be `/usr/local`, which is most likely not what you want. ------- ./autogen.sh --prefix= <@arguments> ------- Some interesting arguments are: x_support:: enable X11 support (default=YES) opengles_20:: enable OpenGL ES 2.0 (default=NO) minimal_build:: enable minimal builds (default=NO) disable-gestures:: disable multitouch gestures (auto) enable-tests:: enable tests (default=YES) enable-documentation:: enable documentation (default=NO) enable-maintainer-mode:: use strict compiler flags (default=NO) enable-debug:: enable nux debugging (default=NO) enable-examples:: enable building of examples (default=YES) enable-gputests:: enable building of gputests (default=YES) example usage: ------- export PREFIX=/home/user/staging/install/nux ./autogen.sh --prefix=$PREFIX --enable-debug make make install ------- ./COPYING.gpl0000644000004100000410000010437413313171754013075 0ustar www-datawww-data GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program 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 Foundation, either version 3 of the License, or (at your option) any later version. This program 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 this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . ./COPYING.lgpl-v2.10000644000004100000410000006364213313171754013737 0ustar www-datawww-data GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! ./COPYING0000644000004100000410000001672713313171754012320 0ustar www-datawww-data GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. ./gputests/0000755000004100000410000000000013313171755013127 5ustar www-datawww-data./gputests/texture_power_of_2.cpp0000644000004100000410000001077013313171755017461 0ustar www-datawww-data/* * Copyright 2010 Inalogic Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY 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 * version 3 along with this program. If not, see * * * Authored by: Jay Taoko * */ #include "NuxCore/NuxCore.h" #include "NuxGraphics/BitmapFormats.h" #include "NuxGraphics/GraphicsDisplay.h" #include "NuxGraphics/GLWindowManager.h" #include "NuxGraphics/GraphicsEngine.h" /* * Tests: * - load 2d textures of various size from the hard drive * - textures have power of two size 256x256, 128x128, ...., 2x2, 1x1 * - manually load bitmap data into device texture: IOpenGLTexture2D * - Lock/Unlock device texture data pointer * - Use immediate mode rendering with glBegin, glEnd */ void RenderTexturePowerOfTwo () { nux::GraphicsDisplay* m_GLWindow = gGLWindowManager.CreateGLWindow("Window", 570, 270, nux::WINDOWSTYLE_NORMAL, 0, false); nux::GraphicsEngine* m_GraphicsContext = m_GLWindow->GetGraphicsEngine(); m_GLWindow->ShowWindow(); const TCHAR* texture_list [] = { TEXT("./data/mipmap256x256.png"), TEXT("./data/mipmap128x128.png"), TEXT("./data/mipmap64x64.png"), TEXT("./data/mipmap32x32.png"), TEXT("./data/mipmap16x16.png"), TEXT("./data/mipmap8x8.png"), TEXT("./data/mipmap4x4.png"), TEXT("./data/mipmap2x2.png"), TEXT("./data/mipmap1x1.png") }; nux::ObjectPtr tex [9]; for (int i = 0; i < 9; i++) { nux::NBitmapData *bitmap = nux::LoadImageFile(texture_list[i]); nux::ImageSurface surface = bitmap->GetSurface(0); surface.GetFormat(); tex[i] = nux::GetGraphicsDisplay()->GetGpuDevice()->CreateTexture( surface.GetWidth(), surface.GetHeight(), 1, surface.GetFormat()); nux::SURFACE_LOCKED_RECT lockrect; tex[i]->LockRect(0, &lockrect, 0); BYTE *dest = (BYTE *) lockrect.pBits; const BYTE *src = surface.GetPtrRawData(); int RowByteSize = surface.GetPitch(); int num_row = surface.GetBlockHeight(); for (int Y = 0; Y < num_row; Y++ ) { // Take Min(RowByteSize, StrideY): the source and the destination may not have the same Pitch but // they contain the same amount of valid data since they have the same width, height and format. nux::Memcpy (dest + Y * lockrect.Pitch, &src[Y * RowByteSize], nux::Min (RowByteSize, lockrect.Pitch) ); } tex[i]->UnlockRect (0); } int w, h; m_GraphicsContext->GetWindowSize(w, h); m_GraphicsContext->SetViewport(0, 0, w, h); m_GraphicsContext->SetContext(0, 0, w, h); m_GraphicsContext->Push2DWindow(w, h); nux::Event event; memset(&event, 0, sizeof(nux::Event)); do { CHECKGL( glClearColor(0, 0, 0, 1) ); CHECKGL( glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT) ); m_GLWindow->GetSystemEvent(&event); if(event.type == nux::NUX_SIZE_CONFIGURATION) { m_GraphicsContext->DisableAllTextureMode(0); m_GraphicsContext->DisableAllTextureMode(1); m_GraphicsContext->DisableAllTextureMode(2); m_GraphicsContext->DisableAllTextureMode(3); m_GraphicsContext->GetWindowSize(w, h); m_GraphicsContext->SetViewport(0, 0, w, h); m_GraphicsContext->SetScissor(0, 0, w, h); m_GraphicsContext->SetContext(0, 0, w, h); m_GraphicsContext->Push2DWindow(w, h); } int x = 10; int y = 10; for (int i = 0; i < 9; i++) { m_GraphicsContext->SetTexture(GL_TEXTURE0, tex [i]); if (i > 0) x += tex[i-1]->GetWidth () + 5; int width = tex[i]->GetWidth (); int height = tex[i]->GetHeight (); nux::TexCoordXForm texxform; m_GraphicsContext->QRP_GLSL_1Tex(x, y, width, height, tex[i], texxform, nux::color::White); } m_GLWindow->SwapBuffer(); } while(event.type != nux::NUX_TERMINATE_APP); for (int i = 0; i < 9; i++) { tex[i].Release (); } delete m_GLWindow; } int main() { nux::NuxCoreInitialize(0); nux::NuxGraphicsInitialize(); RenderTexturePowerOfTwo (); return 0; } ./gputests/framebufferobject.cpp0000644000004100000410000001143413313171755017311 0ustar www-datawww-data/* * Copyright 2010 Inalogic Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY 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 * version 3 along with this program. If not, see * * * Authored by: Jay Taoko * */ #include "NuxCore/NuxCore.h" #include "NuxGraphics/BitmapFormats.h" #include "NuxGraphics/GraphicsDisplay.h" #include "NuxGraphics/GLWindowManager.h" #include "NuxGraphics/GraphicsEngine.h" /* * Tests: * - frame buffer object * - Set a texture in the fbo * - Set fbo as a render target * - Render Quad to fbo * - Use fbo texture to draw a full screen quad on the default render target */ void RenderToFrameBufferObject () { nux::GraphicsDisplay* graphics_display = gGLWindowManager.CreateGLWindow("Window", 200, 200, nux::WINDOWSTYLE_NORMAL, 0, false); nux::GraphicsEngine* graphics_engine = graphics_display->GetGraphicsEngine(); graphics_display->ShowWindow(); nux::ObjectPtr fbo; nux::ObjectPtr texture_rt; nux::ObjectPtr depth_rt; fbo = graphics_display->GetGpuDevice ()->CreateFrameBufferObject (); texture_rt = graphics_display->GetGpuDevice ()->CreateSystemCapableDeviceTexture (graphics_display->GetWindowWidth(), graphics_display->GetWindowHeight(), 1, nux::BITFMT_R8G8B8A8); depth_rt = graphics_display->GetGpuDevice ()->CreateSystemCapableDeviceTexture (graphics_display->GetWindowWidth(), graphics_display->GetWindowHeight(), 1, nux::BITFMT_D24S8); int w, h; graphics_engine->GetWindowSize(w, h); graphics_engine->SetViewport(0, 0, w, h); graphics_engine->SetContext(0, 0, w, h); graphics_engine->SetScissor(0, 0, w, h); graphics_engine->Push2DWindow(w, h); nux::Event event; memset(&event, 0, sizeof(nux::Event)); bool first_time = true; do { CHECKGL( glClearColor(0, 0, 0, 1) ); CHECKGL( glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT) ); graphics_display->GetSystemEvent(&event); if(first_time || (event.type == nux::NUX_SIZE_CONFIGURATION)) { first_time = false; graphics_engine->DisableAllTextureMode(0); graphics_engine->DisableAllTextureMode(1); graphics_engine->DisableAllTextureMode(2); graphics_engine->DisableAllTextureMode(3); graphics_engine->GetWindowSize(w, h); graphics_engine->SetViewport(0, 0, w, h); graphics_engine->SetScissor(0, 0, w, h); graphics_engine->SetContext(0, 0, w, h); graphics_engine->Push2DWindow(w, h); fbo = graphics_display->GetGpuDevice()->CreateFrameBufferObject (); texture_rt = graphics_display->GetGpuDevice()->CreateSystemCapableDeviceTexture(graphics_display->GetWindowWidth(), graphics_display->GetWindowHeight(), 1, nux::BITFMT_R8G8B8A8); depth_rt = graphics_display->GetGpuDevice()->CreateSystemCapableDeviceTexture (graphics_display->GetWindowWidth(), graphics_display->GetWindowHeight(), 1, nux::BITFMT_D24S8); } fbo->FormatFrameBufferObject (graphics_display->GetWindowWidth(), graphics_display->GetWindowHeight(), nux::BITFMT_R8G8B8A8); if (texture_rt.IsValid()) { fbo->SetRenderTarget(0, texture_rt->GetSurfaceLevel(0)); } if (depth_rt.IsValid()) { fbo->SetDepthSurface(depth_rt->GetSurfaceLevel(0)); } fbo->Activate(); graphics_engine->GetWindowSize(w, h); graphics_engine->SetViewport(0, 0, w, h); graphics_engine->SetContext(0, 0, w, h); graphics_engine->Push2DWindow(w, h); nux::Rect geo (nux::RandomUInt(graphics_display->GetWindowWidth()), nux::RandomUInt(graphics_display->GetWindowHeight()), nux::RandomUInt(200), nux::RandomUInt(200)); graphics_engine->QRP_Color(geo.x, geo.y, geo.width, geo.height, nux::color::RandomColor()); // Restore the back buffer graphics_display->GetGpuDevice()->DeactivateFrameBuffer(); nux::TexCoordXForm texxform; graphics_engine->QRP_1Tex(0, 0, graphics_display->GetWindowWidth(), graphics_display->GetWindowHeight(), texture_rt, texxform, nux::color::White); graphics_display->SwapBuffer(); } while(event.type != nux::NUX_TERMINATE_APP); fbo.Release (); texture_rt.Release (); depth_rt.Release (); delete graphics_display; } int main() { nux::NuxCoreInitialize(0); nux::NuxGraphicsInitialize(); RenderToFrameBufferObject (); return 0; } ./gputests/quad_2texmod.cpp0000755000004100000410000001210613313171755016232 0ustar www-datawww-data/* * Copyright 2010 Inalogic Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY 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 * version 3 along with this program. If not, see * * * Authored by: Jay Taoko * */ #include "NuxCore/NuxCore.h" #include "NuxGraphics/BitmapFormats.h" #include "NuxGraphics/GraphicsDisplay.h" #include "NuxGraphics/GLWindowManager.h" #include "NuxGraphics/GraphicsEngine.h" /* * Tests: * - Create a check board texture * - Create a second texture and fill it manually with color values * - Render full window background quad * - enable blending * - Render the two textures with QRP_2TexMod: result = (Tex0*Color0) * (Tex1*color1) * - Disable blending */ void QuadRendering_2TexMod () { nux::GraphicsDisplay* graphics_display = gGLWindowManager.CreateGLWindow("QuadRendering: 2TexMod", 570, 270, nux::WINDOWSTYLE_NORMAL, 0, false); nux::GraphicsEngine* graphics_engine = graphics_display->GetGraphicsEngine(); graphics_display->ShowWindow(); int size = 256; nux::NTextureData checkboard_texture_data; MakeCheckBoardImage (checkboard_texture_data.GetSurface (0), size, size, nux::Color (0xff000000), nux::color::LightSeaGreen, 4, 4); nux::BaseTexture* checkboard_texture = graphics_display->GetGpuDevice ()->CreateSystemCapableTexture (); checkboard_texture->Update (&checkboard_texture_data); // Create a Texture map of size 256x1 nux::NTextureData texture_data (nux::BITFMT_R8G8B8A8, size, 1, 1); // Get the first surface (mip 0) of the texture map nux::ImageSurface surface = texture_data.GetSurface (0); nux::ObjectPtr gradient_texture = graphics_display->GetGpuDevice ()->CreateSystemCapableDeviceTexture ( texture_data.GetWidth (), texture_data.GetHeight (), 1, texture_data.GetFormat ()); nux::SURFACE_LOCKED_RECT lockrect; gradient_texture->LockRect (0, &lockrect, 0); BYTE *dest = (BYTE *) lockrect.pBits; int num_row = surface.GetBlockHeight (); // Fill the gradient texture with White and an alpha value going from 1.0f to 0.0f for (int y = 0; y < num_row; y++) { // Take Min(RowByteSize, StrideY): the source and the destination may not have the same Pitch but // they contain the same amount of valid data since they have the same width, height and format. for (int x = 0; x < texture_data.GetWidth (); x++) { *(dest + y * lockrect.Pitch + 4*x + 0) = 0xff; //red *(dest + y * lockrect.Pitch + 4*x + 1) = 0xff; //green *(dest + y * lockrect.Pitch + 4*x + 2) = 0xff; //blue *(dest + y * lockrect.Pitch + 4*x + 3) = 255 - 255 * ((float)x/(float)texture_data.GetWidth ()); } } gradient_texture->UnlockRect (0); int w, h; nux::Event event; memset(&event, 0, sizeof(nux::Event)); graphics_engine->GetWindowSize(w, h); graphics_engine->SetViewport(0, 0, w, h); graphics_engine->SetScissor(0, 0, w, h); graphics_engine->SetContext(0, 0, w, h); graphics_engine->Push2DWindow(w, h); do { CHECKGL( glClearColor(0, 0, 0, 1) ); CHECKGL( glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT) ); graphics_display->GetSystemEvent(&event); if(event.type == nux::NUX_SIZE_CONFIGURATION) { graphics_engine->GetWindowSize(w, h); graphics_engine->SetViewport(0, 0, w, h); graphics_engine->SetScissor(0, 0, w, h); graphics_engine->SetContext(0, 0, w, h); graphics_engine->Push2DWindow(w, h); } nux::Rect geo ( ((int)graphics_display->GetWindowWidth() - size) /2, ((int)graphics_display->GetWindowHeight() - size) /2, size, size); // Paint a rectangular quad over the entire window graphics_engine->QRP_Color(0, 0, graphics_display->GetWindowWidth(), graphics_display->GetWindowHeight(), nux::color::Aubergine); // Enable blending graphics_display->GetGraphicsEngine()->GetRenderStates ().SetBlend(true, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); nux::TexCoordXForm texxform0; nux::TexCoordXForm texxform1; // Modulate the checkboard and the gradient texture graphics_engine->QRP_2TexMod(geo.x, geo.y, geo.width, geo.height, gradient_texture, texxform0, nux::color::White, checkboard_texture->GetDeviceTexture (), texxform1, nux::color::White); graphics_display->GetGraphicsEngine()->GetRenderStates ().SetBlend(false); graphics_display->SwapBuffer(); } while(event.type != nux::NUX_TERMINATE_APP); gradient_texture.Release (); checkboard_texture->UnReference (); delete graphics_display; } int main() { nux::NuxCoreInitialize(0); nux::NuxGraphicsInitialize(); QuadRendering_2TexMod (); return 0; } ./gputests/texture_copy_blur.cpp0000644000004100000410000001375013313171755017417 0ustar www-datawww-data/* * Copyright 2010 Inalogic Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY 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 * version 3 along with this program. If not, see * * * Authored by: Jay Taoko * */ #include "NuxCore/NuxCore.h" #include "NuxGraphics/BitmapFormats.h" #include "NuxGraphics/GraphicsDisplay.h" #include "NuxGraphics/GLWindowManager.h" #include "NuxGraphics/GraphicsEngine.h" /* * Tests: * - Frame buffer object * - Set a texture in the fbo * - Set fbo as a render target * - Render Quad to fbo * - Make a copy of the render target: CreateTextureFromBackBuffer * - Deactivate fbo * - Blur the copied render target texture * - Render to default back buffer */ void RenderBlurredCopyOfRenderTarget () { nux::GraphicsDisplay* graphics_display = gGLWindowManager.CreateGLWindow("Window", 600, 300, nux::WINDOWSTYLE_NORMAL, 0, false); nux::GraphicsEngine* graphics_engine = graphics_display->GetGraphicsEngine(); graphics_display->ShowWindow(); nux::ObjectPtr fbo; nux::ObjectPtr texture_rt; nux::ObjectPtr depth_rt; fbo = graphics_display->GetGpuDevice ()->CreateFrameBufferObject (); texture_rt = graphics_display->GetGpuDevice ()->CreateSystemCapableDeviceTexture (graphics_display->GetWindowWidth(), graphics_display->GetWindowHeight(), 1, nux::BITFMT_R8G8B8A8); depth_rt = graphics_display->GetGpuDevice ()->CreateSystemCapableDeviceTexture (graphics_display->GetWindowWidth(), graphics_display->GetWindowHeight(), 1, nux::BITFMT_D24S8); int w, h; graphics_engine->GetWindowSize(w, h); graphics_engine->SetViewport(0, 0, w, h); graphics_engine->SetContext(0, 0, w, h); graphics_engine->Push2DWindow(w, h); nux::Event event; memset(&event, 0, sizeof(nux::Event)); /*char fps [25]; int frame_counter = 0; int frame_periode = 0; float frame_rate = 0; float periode_time = 0; */ bool first_time = true; do { CHECKGL( glClearColor(0, 0, 0, 1) ); CHECKGL( glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT) ); graphics_display->GetSystemEvent(&event); if(first_time || (event.type == nux::NUX_SIZE_CONFIGURATION)) { first_time = false; graphics_engine->DisableAllTextureMode(0); graphics_engine->DisableAllTextureMode(1); graphics_engine->DisableAllTextureMode(2); graphics_engine->DisableAllTextureMode(3); graphics_engine->GetWindowSize(w, h); graphics_engine->SetViewport(0, 0, w, h); graphics_engine->SetScissor(0, 0, w, h); graphics_engine->SetContext(0, 0, w, h); graphics_engine->Push2DWindow(w, h); fbo = graphics_display->GetGpuDevice ()->CreateFrameBufferObject (); texture_rt = graphics_display->GetGpuDevice ()->CreateSystemCapableDeviceTexture (graphics_display->GetWindowWidth(), graphics_display->GetWindowHeight(), 1, nux::BITFMT_R8G8B8A8); depth_rt = graphics_display->GetGpuDevice ()->CreateSystemCapableDeviceTexture (graphics_display->GetWindowWidth(), graphics_display->GetWindowHeight(), 1, nux::BITFMT_D24S8); } fbo->FormatFrameBufferObject (graphics_display->GetWindowWidth(), graphics_display->GetWindowHeight(), nux::BITFMT_R8G8B8A8); fbo->SetRenderTarget (0, texture_rt->GetSurfaceLevel (0)); fbo->SetDepthSurface (depth_rt->GetSurfaceLevel (0)); fbo->Activate(); for (int i = 0; i < 1; i++) { nux::Rect geo (nux::RandomUInt(graphics_display->GetWindowWidth()), nux::RandomUInt(graphics_display->GetWindowHeight()), nux::RandomUInt(200), nux::RandomUInt(200)); graphics_engine->QRP_Color(geo.x, geo.y, geo.width, geo.height, nux::color::RandomColor()); } nux::TexCoordXForm texxform; // Make a copy of the render target nux::ObjectPtr tex_copy = graphics_engine->CreateTextureFromBackBuffer (0, 0, graphics_display->GetWindowWidth (), graphics_display->GetWindowHeight ()); // Restore the back buffer graphics_display->GetGpuDevice ()->DeactivateFrameBuffer (); // Make a blurred version of the back buffer nux::ObjectPtr tex_blur = graphics_engine->QRP_GetBlurTexture ( 0, 0, tex_copy->GetWidth (), tex_copy->GetHeight (), tex_copy, texxform, nux::color::White, 1.0f); // Render the blurred texture graphics_engine->QRP_1Tex(0, 0, tex_blur->GetWidth(), tex_blur->GetHeight(), tex_blur, texxform, nux::color::White); /*sprintf(fps, "FPS: %3.2f", frame_rate); nux::PageBBox page; page.xmin = 0; page.xmax = 100; page.ymin = 0; page.ymax = 20; page.x_margin = 0; page.y_margin = 0; graphics_engine->RenderColorTextLineStatic(graphics_engine->GetBoldFont (), page, fps, nux::color::White, false, nux::eAlignTextLeft); graphics_display->SwapBuffer(); float frame_time = graphics_display->GetFrameTime(); graphics_display->ResetFrameTime(); periode_time += frame_time; frame_counter++; frame_periode++; if (frame_periode >= 100) { frame_rate = frame_periode * 1000.0f / periode_time; periode_time = 0.0f; frame_periode = 0; } */ graphics_display->SwapBuffer(); } while((event.type != nux::NUX_TERMINATE_APP) && (event.GetVirtualKeyState(NUX_VK_ESCAPE) == 0)); fbo.Release (); texture_rt.Release (); depth_rt.Release (); delete graphics_display; } int main() { nux::NuxCoreInitialize(0); nux::NuxGraphicsInitialize(); RenderBlurredCopyOfRenderTarget (); return 0; } ./gputests/texture_data.cpp0000644000004100000410000001101513313171755016322 0ustar www-datawww-data/* * Copyright 2010 Inalogic Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY 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 * version 3 along with this program. If not, see * * * Authored by: Jay Taoko * */ #include "NuxCore/NuxCore.h" #include "NuxGraphics/BitmapFormats.h" #include "NuxGraphics/GraphicsDisplay.h" #include "NuxGraphics/GLWindowManager.h" #include "NuxGraphics/GraphicsEngine.h" #include /* * Tests: * - load 2d textures of various size from the hard drive * - textures have power of two size 256x256, 128x128, ...., 2x2, 1x1 * - manually load bitmap data into device texture: IOpenGLTexture2D * - Lock/Unlock device texture data pointer * - Use immediate mode rendering with glBegin, glEnd */ void RenderTexturePowerOfTwo () { nux::GraphicsDisplay* m_GLWindow = gGLWindowManager.CreateGLWindow("Window", 570, 270, nux::WINDOWSTYLE_NORMAL, 0, false); nux::GraphicsEngine* m_GraphicsContext = m_GLWindow->GetGraphicsEngine(); m_GLWindow->ShowWindow(); const TCHAR* texture_list [] = { TEXT("./data/mipmap256x256.png"), TEXT("./data/mipmap128x128.png"), TEXT("./data/mipmap64x64.png"), TEXT("./data/mipmap32x32.png"), TEXT("./data/mipmap16x16.png"), TEXT("./data/mipmap8x8.png"), TEXT("./data/mipmap4x4.png"), TEXT("./data/mipmap2x2.png"), TEXT("./data/mipmap1x1.png") }; nux::ObjectPtr tex [9]; for (int i = 0; i < 9; i++) { nux::NBitmapData *bitmap = nux::LoadImageFile (texture_list[i]); nux::ImageSurface surface = bitmap->GetSurface (0); surface.GetFormat (); tex[i] = nux::GetGraphicsDisplay()->GetGpuDevice()->CreateTexture ( surface.GetWidth(), surface.GetHeight (), 1, surface.GetFormat ()); nux::SURFACE_LOCKED_RECT lockrect; tex[i]->LockRect(0, &lockrect, 0); BYTE *dest = (BYTE *) lockrect.pBits; const BYTE *src = surface.GetPtrRawData(); int RowByteSize = surface.GetPitch(); int num_row = surface.GetBlockHeight(); for (int Y = 0; Y < num_row; Y++ ) { // Take Min(RowByteSize, StrideY): the source and the destination may not have the same Pitch but // they contain the same amount of valid data since they have the same width, height and format. nux::Memcpy (dest + Y * lockrect.Pitch, &src[Y * RowByteSize], nux::Min (RowByteSize, lockrect.Pitch) ); } tex[i]->UnlockRect (0); } int w, h; m_GraphicsContext->GetWindowSize(w, h); m_GraphicsContext->SetViewport(0, 0, w, h); m_GraphicsContext->SetContext(0, 0, w, h); m_GraphicsContext->Push2DWindow(w, h); nux::Event event; memset(&event, 0, sizeof(nux::Event)); { CHECKGL( glClearColor(0, 0, 0, 1) ); CHECKGL( glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT) ); m_GLWindow->GetSystemEvent(&event); if(event.type == nux::NUX_SIZE_CONFIGURATION) { m_GraphicsContext->DisableAllTextureMode(0); m_GraphicsContext->DisableAllTextureMode(1); m_GraphicsContext->DisableAllTextureMode(2); m_GraphicsContext->DisableAllTextureMode(3); m_GraphicsContext->GetWindowSize(w, h); m_GraphicsContext->SetViewport(0, 0, w, h); m_GraphicsContext->SetScissor(0, 0, w, h); m_GraphicsContext->SetContext(0, 0, w, h); m_GraphicsContext->Push2DWindow(w, h); } int level = 0; int width = 0; int height = 0; int format = 0; unsigned char* data = (unsigned char*) tex [6]->GetSurfaceData (level, width, height, format); cairo_surface_t *surface; surface = cairo_image_surface_create_for_data (data, CAIRO_FORMAT_ARGB32, width, height, width*4); cairo_surface_write_to_png (surface, "tmp.png"); cairo_surface_destroy (surface); nuxDebugMsg (TEXT("size: %dx%d"), width, height); delete data; } for (int i = 0; i < 9; i++) { tex[i].Release (); } delete m_GLWindow; } int main() { nux::NuxCoreInitialize(0); nux::NuxGraphicsInitialize(); RenderTexturePowerOfTwo (); return 0; } ./gputests/texture_blur.cpp0000644000004100000410000001371613313171755016367 0ustar www-datawww-data/* * Copyright 2010 Inalogic Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY 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 * version 3 along with this program. If not, see * * * Authored by: Jay Taoko * */ #include "NuxCore/NuxCore.h" #include "NuxGraphics/BitmapFormats.h" #include "NuxGraphics/GraphicsDisplay.h" #include "NuxGraphics/GLWindowManager.h" #include "NuxGraphics/GraphicsEngine.h" /* * Tests: * - frame buffer object * - Set a texture in the fbo * - Set fbo as a render target * - Render Quad to fbo * - Deactivate fbo * - Blur the render target texture * - Render to default back buffer */ void RenderBlurredTexture () { nux::GraphicsDisplay* graphics_display = gGLWindowManager.CreateGLWindow("Window", 600, 300, nux::WINDOWSTYLE_NORMAL, 0, false); nux::GraphicsEngine* graphics_engine = graphics_display->GetGraphicsEngine(); graphics_display->ShowWindow(); nux::ObjectPtr fbo; nux::ObjectPtr texture_rt; nux::ObjectPtr depth_rt; fbo = graphics_display->GetGpuDevice ()->CreateFrameBufferObject (); texture_rt = graphics_display->GetGpuDevice ()->CreateSystemCapableDeviceTexture (graphics_display->GetWindowWidth(), graphics_display->GetWindowHeight(), 1, nux::BITFMT_R8G8B8A8); depth_rt = graphics_display->GetGpuDevice ()->CreateSystemCapableDeviceTexture (graphics_display->GetWindowWidth(), graphics_display->GetWindowHeight(), 1, nux::BITFMT_D24S8); int w, h; graphics_engine->GetWindowSize(w, h); graphics_engine->SetViewport(0, 0, w, h); graphics_engine->SetContext(0, 0, w, h); graphics_engine->SetScissor(0, 0, w, h); graphics_engine->Push2DWindow(w, h); nux::Event event; memset(&event, 0, sizeof(nux::Event)); /*char fps [25]; int frame_counter = 0; int frame_periode = 0; float frame_rate = 0; float periode_time = 0; */ bool first_time = true; do { CHECKGL( glClearColor(0, 0, 0, 1) ); CHECKGL( glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT) ); graphics_display->GetSystemEvent(&event); if(first_time || (event.type == nux::NUX_SIZE_CONFIGURATION)) { first_time = false; graphics_engine->DisableAllTextureMode(0); graphics_engine->DisableAllTextureMode(1); graphics_engine->DisableAllTextureMode(2); graphics_engine->DisableAllTextureMode(3); graphics_engine->GetWindowSize(w, h); graphics_engine->SetViewport(0, 0, w, h); graphics_engine->SetScissor(0, 0, w, h); graphics_engine->SetContext(0, 0, w, h); graphics_engine->Push2DWindow(w, h); fbo = graphics_display->GetGpuDevice()->CreateFrameBufferObject(); texture_rt = graphics_display->GetGpuDevice()->CreateSystemCapableDeviceTexture(graphics_display->GetWindowWidth(), graphics_display->GetWindowHeight(), 1, nux::BITFMT_R8G8B8A8); depth_rt = graphics_display->GetGpuDevice()->CreateSystemCapableDeviceTexture(graphics_display->GetWindowWidth(), graphics_display->GetWindowHeight(), 1, nux::BITFMT_D24S8); } fbo->FormatFrameBufferObject(graphics_display->GetWindowWidth(), graphics_display->GetWindowHeight(), nux::BITFMT_R8G8B8A8); if (texture_rt.IsValid()) { fbo->SetRenderTarget(0, texture_rt->GetSurfaceLevel (0)); } if (depth_rt.IsValid()) { fbo->SetDepthSurface(depth_rt->GetSurfaceLevel (0)); } fbo->Activate(); graphics_engine->GetWindowSize(w, h); graphics_engine->SetViewport(0, 0, w, h); graphics_engine->SetContext(0, 0, w, h); graphics_engine->Push2DWindow(w, h); for (int i = 0; i < 1; i++) { nux::Rect geo (nux::RandomUInt(graphics_display->GetWindowWidth()), nux::RandomUInt(graphics_display->GetWindowHeight()), nux::RandomUInt(200), nux::RandomUInt(200)); graphics_engine->QRP_Color(geo.x, geo.y, geo.width, geo.height, nux::color::RandomColor()); } // Restore the back buffer graphics_display->GetGpuDevice()->DeactivateFrameBuffer(); nux::ObjectPtr tex_blur; nux::TexCoordXForm texxform; //Make a blurred copy of the previous render target if (texture_rt.IsValid() && graphics_engine) { tex_blur = graphics_engine->QRP_GLSL_GetBlurTexture( 0, 0, texture_rt->GetWidth(), texture_rt->GetHeight(), texture_rt, texxform, nux::color::White, 7.0f); } graphics_engine->QRP_1Tex(0, 0, tex_blur->GetWidth(), tex_blur->GetHeight(), tex_blur, texxform, nux::color::White); /* sprintf(fps, "FPS: %3.2f", frame_rate); nux::PageBBox page; page.xmin = 0; page.xmax = 100; page.ymin = 0; page.ymax = 20; page.x_margin = 0; page.y_margin = 0; graphics_engine->RenderColorTextLineStatic(graphics_engine->GetBoldFont (), page, fps, nux::color::White, false, nux::eAlignTextLeft); float frame_time = graphics_display->GetFrameTime(); graphics_display->ResetFrameTime(); periode_time += frame_time; frame_counter++; frame_periode++; if (frame_periode >= 100) { frame_rate = frame_periode * 1000.0f / periode_time; periode_time = 0.0f; frame_periode = 0; } */ graphics_display->SwapBuffer(); } while((event.type != nux::NUX_TERMINATE_APP)); fbo.Release (); texture_rt.Release (); depth_rt.Release (); delete graphics_display; } int main() { nux::NuxCoreInitialize(0); nux::NuxGraphicsInitialize(); RenderBlurredTexture (); return 0; } ./gputests/arb_programs_limits.cpp0000644000004100000410000003227213313171755017700 0ustar www-datawww-data/* * Copyright 2010 Inalogic Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY 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 * version 3 along with this program. If not, see * * * Authored by: Jay Taoko * */ #include "NuxCore/NuxCore.h" #include "NuxGraphics/BitmapFormats.h" #include "NuxGraphics/GraphicsDisplay.h" #include "NuxGraphics/GLWindowManager.h" #include "NuxGraphics/GraphicsEngine.h" /* * Tests: * - Display arb programs limits */ void ARBProgramLimits () { nux::GraphicsDisplay* graphics_display = gGLWindowManager.CreateGLWindow("Window", 570, 270, nux::WINDOWSTYLE_NORMAL, 0, false); int OPENGL_MAX_PROGRAM_INSTRUCTIONS_ARB; int OPENGL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB; int OPENGL_MAX_PROGRAM_TEMPORARIES_ARB; int OPENGL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB; int OPENGL_MAX_PROGRAM_PARAMETERS_ARB; int OPENGL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB; int OPENGL_MAX_PROGRAM_ATTRIBS_ARB; int OPENGL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB; int OPENGL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB; int OPENGL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB; int OPENGL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB; int OPENGL_MAX_PROGRAM_ENV_PARAMETERS_ARB; int OPENGL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB; int OPENGL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB; int OPENGL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB; int OPENGL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB; int OPENGL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB; int OPENGL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB; CHECKGL (glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &OPENGL_MAX_PROGRAM_INSTRUCTIONS_ARB) ); CHECKGL (glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &OPENGL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB) ); CHECKGL (glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_TEMPORARIES_ARB, &OPENGL_MAX_PROGRAM_TEMPORARIES_ARB) ); CHECKGL (glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &OPENGL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB) ); CHECKGL (glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_PARAMETERS_ARB, &OPENGL_MAX_PROGRAM_PARAMETERS_ARB) ); CHECKGL (glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB, &OPENGL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB) ); CHECKGL (glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ATTRIBS_ARB, &OPENGL_MAX_PROGRAM_ATTRIBS_ARB) ); CHECKGL (glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB, &OPENGL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB) ); CHECKGL (glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB, &OPENGL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB) ); CHECKGL (glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB, &OPENGL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB) ); CHECKGL (glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB, &OPENGL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB) ); CHECKGL (glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &OPENGL_MAX_PROGRAM_ENV_PARAMETERS_ARB) ); CHECKGL (glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB, &OPENGL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB) ); CHECKGL (glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB, &OPENGL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB) ); CHECKGL (glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB, &OPENGL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB) ); CHECKGL (glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB, &OPENGL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB) ); CHECKGL (glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB, &OPENGL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB) ); CHECKGL (glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB, &OPENGL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB) ); nux::LogOutputSeverityMessage(nux::NUX_MSG_SEVERITY_NONE, "---------------------------------------------"); nux::LogOutputSeverityMessage(nux::NUX_MSG_SEVERITY_NONE, "Vertex Program"); nux::LogOutputSeverityMessage(nux::NUX_MSG_SEVERITY_NONE, "---------------------------------------------"); nux::LogOutputSeverityMessage(nux::NUX_MSG_SEVERITY_INFO, "MAX_PROGRAM_INSTRUCTIONS_ARB = %d", OPENGL_MAX_PROGRAM_INSTRUCTIONS_ARB); nux::LogOutputSeverityMessage(nux::NUX_MSG_SEVERITY_INFO, "MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB = %d", OPENGL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB); nux::LogOutputSeverityMessage(nux::NUX_MSG_SEVERITY_INFO, "MAX_PROGRAM_TEMPORARIES_ARB = %d", OPENGL_MAX_PROGRAM_TEMPORARIES_ARB); nux::LogOutputSeverityMessage(nux::NUX_MSG_SEVERITY_INFO, "MAX_PROGRAM_NATIVE_TEMPORARIES_ARB = %d", OPENGL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB); nux::LogOutputSeverityMessage(nux::NUX_MSG_SEVERITY_INFO, "MAX_PROGRAM_PARAMETERS_ARB = %d", OPENGL_MAX_PROGRAM_PARAMETERS_ARB); nux::LogOutputSeverityMessage(nux::NUX_MSG_SEVERITY_INFO, "MAX_PROGRAM_NATIVE_PARAMETERS_ARB = %d", OPENGL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB); nux::LogOutputSeverityMessage(nux::NUX_MSG_SEVERITY_INFO, "MAX_PROGRAM_ATTRIBS_ARB = %d", OPENGL_MAX_PROGRAM_ATTRIBS_ARB); nux::LogOutputSeverityMessage(nux::NUX_MSG_SEVERITY_INFO, "MAX_PROGRAM_NATIVE_ATTRIBS_ARB = %d", OPENGL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB); nux::LogOutputSeverityMessage(nux::NUX_MSG_SEVERITY_INFO, "MAX_PROGRAM_ADDRESS_REGISTERS_ARB = %d", OPENGL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB); nux::LogOutputSeverityMessage(nux::NUX_MSG_SEVERITY_INFO, "MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB = %d", OPENGL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB); nux::LogOutputSeverityMessage(nux::NUX_MSG_SEVERITY_INFO, "MAX_PROGRAM_LOCAL_PARAMETERS_ARB = %d", OPENGL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB); nux::LogOutputSeverityMessage(nux::NUX_MSG_SEVERITY_INFO, "MAX_PROGRAM_ENV_PARAMETERS_ARB = %d", OPENGL_MAX_PROGRAM_ENV_PARAMETERS_ARB); nux::LogOutputSeverityMessage(nux::NUX_MSG_SEVERITY_INFO, "MAX_PROGRAM_ALU_INSTRUCTIONS_ARB = %d", OPENGL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB); nux::LogOutputSeverityMessage(nux::NUX_MSG_SEVERITY_INFO, "MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB = %d", OPENGL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB); nux::LogOutputSeverityMessage(nux::NUX_MSG_SEVERITY_INFO, "MAX_PROGRAM_TEX_INSTRUCTIONS_ARB = %d", OPENGL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB); nux::LogOutputSeverityMessage(nux::NUX_MSG_SEVERITY_INFO, "MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB = %d", OPENGL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB); nux::LogOutputSeverityMessage(nux::NUX_MSG_SEVERITY_INFO, "MAX_PROGRAM_TEX_INDIRECTIONS_ARB = %d", OPENGL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB); nux::LogOutputSeverityMessage(nux::NUX_MSG_SEVERITY_INFO, "MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB = %d", OPENGL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB); CHECKGL (glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &OPENGL_MAX_PROGRAM_INSTRUCTIONS_ARB) ); CHECKGL (glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &OPENGL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB) ); CHECKGL (glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_TEMPORARIES_ARB, &OPENGL_MAX_PROGRAM_TEMPORARIES_ARB) ); CHECKGL (glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &OPENGL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB) ); CHECKGL (glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_PARAMETERS_ARB, &OPENGL_MAX_PROGRAM_PARAMETERS_ARB) ); CHECKGL (glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB, &OPENGL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB) ); CHECKGL (glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ATTRIBS_ARB, &OPENGL_MAX_PROGRAM_ATTRIBS_ARB) ); CHECKGL (glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB, &OPENGL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB) ); CHECKGL (glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB, &OPENGL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB) ); CHECKGL (glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB, &OPENGL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB) ); CHECKGL (glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB, &OPENGL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB) ); CHECKGL (glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &OPENGL_MAX_PROGRAM_ENV_PARAMETERS_ARB) ); CHECKGL (glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB, &OPENGL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB) ); CHECKGL (glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB, &OPENGL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB) ); CHECKGL (glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB, &OPENGL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB) ); CHECKGL (glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB, &OPENGL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB) ); CHECKGL (glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB, &OPENGL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB) ); CHECKGL (glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB, &OPENGL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB) ); nux::LogOutputSeverityMessage(nux::NUX_MSG_SEVERITY_NONE, "---------------------------------------------"); nux::LogOutputSeverityMessage(nux::NUX_MSG_SEVERITY_NONE, "Fragment Program"); nux::LogOutputSeverityMessage(nux::NUX_MSG_SEVERITY_NONE, "---------------------------------------------"); nux::LogOutputSeverityMessage(nux::NUX_MSG_SEVERITY_INFO, "MAX_PROGRAM_INSTRUCTIONS_ARB = %d", OPENGL_MAX_PROGRAM_INSTRUCTIONS_ARB); nux::LogOutputSeverityMessage(nux::NUX_MSG_SEVERITY_INFO, "MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB = %d", OPENGL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB); nux::LogOutputSeverityMessage(nux::NUX_MSG_SEVERITY_INFO, "MAX_PROGRAM_TEMPORARIES_ARB = %d", OPENGL_MAX_PROGRAM_TEMPORARIES_ARB); nux::LogOutputSeverityMessage(nux::NUX_MSG_SEVERITY_INFO, "MAX_PROGRAM_NATIVE_TEMPORARIES_ARB = %d", OPENGL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB); nux::LogOutputSeverityMessage(nux::NUX_MSG_SEVERITY_INFO, "MAX_PROGRAM_PARAMETERS_ARB = %d", OPENGL_MAX_PROGRAM_PARAMETERS_ARB); nux::LogOutputSeverityMessage(nux::NUX_MSG_SEVERITY_INFO, "MAX_PROGRAM_NATIVE_PARAMETERS_ARB = %d", OPENGL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB); nux::LogOutputSeverityMessage(nux::NUX_MSG_SEVERITY_INFO, "MAX_PROGRAM_ATTRIBS_ARB = %d", OPENGL_MAX_PROGRAM_ATTRIBS_ARB); nux::LogOutputSeverityMessage(nux::NUX_MSG_SEVERITY_INFO, "MAX_PROGRAM_NATIVE_ATTRIBS_ARB = %d", OPENGL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB); nux::LogOutputSeverityMessage(nux::NUX_MSG_SEVERITY_INFO, "MAX_PROGRAM_ADDRESS_REGISTERS_ARB = %d", OPENGL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB); nux::LogOutputSeverityMessage(nux::NUX_MSG_SEVERITY_INFO, "MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB = %d", OPENGL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB); nux::LogOutputSeverityMessage(nux::NUX_MSG_SEVERITY_INFO, "MAX_PROGRAM_LOCAL_PARAMETERS_ARB = %d", OPENGL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB); nux::LogOutputSeverityMessage(nux::NUX_MSG_SEVERITY_INFO, "MAX_PROGRAM_ENV_PARAMETERS_ARB = %d", OPENGL_MAX_PROGRAM_ENV_PARAMETERS_ARB); nux::LogOutputSeverityMessage(nux::NUX_MSG_SEVERITY_INFO, "MAX_PROGRAM_ALU_INSTRUCTIONS_ARB = %d", OPENGL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB); nux::LogOutputSeverityMessage(nux::NUX_MSG_SEVERITY_INFO, "MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB = %d", OPENGL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB); nux::LogOutputSeverityMessage(nux::NUX_MSG_SEVERITY_INFO, "MAX_PROGRAM_TEX_INSTRUCTIONS_ARB = %d", OPENGL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB); nux::LogOutputSeverityMessage(nux::NUX_MSG_SEVERITY_INFO, "MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB = %d", OPENGL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB); nux::LogOutputSeverityMessage(nux::NUX_MSG_SEVERITY_INFO, "MAX_PROGRAM_TEX_INDIRECTIONS_ARB = %d", OPENGL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB); nux::LogOutputSeverityMessage(nux::NUX_MSG_SEVERITY_INFO, "MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB = %d", OPENGL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB); delete graphics_display; } int main() { nux::NuxCoreInitialize(0); nux::NuxGraphicsInitialize(); ARBProgramLimits(); return 0; } ./gputests/Makefile.am0000644000004100000410000000415713313171755015172 0ustar www-datawww-dataCLEANFILES = DISTCLEANFILES = EXTRA_DIST = data if BUILD_GPUTESTS # This tells automake that we want to build binaries, but they shouldn't be # installed. For each individual test, add it's binary name here noinst_PROGRAMS = texture_power_of_2 framebufferobject quad_2texmod texture_copy_blur texture_blur texture_data if !NUX_OPENGLES_20 noinst_PROGRAMS += arb_programs_limits endif # We only have to do this AM_ once to affect all the binaries we build from # this Makefile AM_CPPFLAGS = \ -I$(srcdir) \ -I$(top_srcdir) \ -DPREFIX=\""$(prefix)"\" \ -DLIBDIR=\""$(libdir)"\" \ -DDATADIR=\""$(datadir)"\" \ -DG_LOG_DOMAIN=\"NuxGpuTests\" \ $(GCC_FLAGS) \ $(NUX_CORE_CFLAGS) \ $(NUX_GPUTESTS_CFLAGS) \ $(NUX_CFLAGS) \ $(MAINTAINER_CFLAGS) ALL_LIBS = \ $(top_builddir)/NuxCore/libnux-core-@NUX_API_VERSION@.la \ $(top_builddir)/NuxGraphics/libnux-graphics-@NUX_API_VERSION@.la \ $(top_builddir)/Nux/libnux-@NUX_API_VERSION@.la \ $(NUX_GPUTESTS_LIBS) \ $(NUX_LIBS) # This is the individual executable build. For every $exe in noinst_PROGRAMS # you need a $exe_SOURCES and $exe_LDADD so it builds texture_power_of_2_SOURCES = texture_power_of_2.cpp texture_power_of_2_LDADD = $(ALL_LIBS) framebufferobject_SOURCES = framebufferobject.cpp framebufferobject_LDADD = $(ALL_LIBS) quad_2texmod_SOURCES = quad_2texmod.cpp quad_2texmod_LDADD = $(ALL_LIBS) texture_copy_blur_SOURCES = texture_copy_blur.cpp texture_copy_blur_LDADD = $(ALL_LIBS) texture_blur_SOURCES = texture_blur.cpp texture_blur_LDADD = $(ALL_LIBS) texture_data_SOURCES = texture_data.cpp texture_data_LDADD = $(ALL_LIBS) arb_programs_limits_SOURCES = arb_programs_limits.cpp arb_programs_limits_LDADD = $(ALL_LIBS) # distribute source along to the documentation sourcegputestsdir = $(pkgdatadir)/gputests sourcegputests_DATA = $(texture_power_of_2_SOURCES) \ $(framebufferobject_SOURCES) \ $(quad_2texmod) \ $(texture_copy_blur_SOURCES) \ $(texture_blur_SOURCES) \ $(texture_data_SOURCES) \ $(arb_programs_limits_SOURCES) endif ./gputests/data/0000755000004100000410000000000013313171755014040 5ustar www-datawww-data./gputests/data/mipmap8x8.png0000755000004100000410000000536213313171755016412 0ustar www-datawww-dataPNG  IHDR pHYsnu> OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FIDATxbd?@  92(IENDB`./gputests/data/mipmap4x4.png0000755000004100000410000000536113313171755016401 0ustar www-datawww-dataPNG  IHDR~ pHYsnu> OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FIDATxb?`b@aIENDB`./gputests/data/mipmap16x16.png0000755000004100000410000000537113313171755016550 0ustar www-datawww-dataPNG  IHDRa pHYsnu> OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_F$IDATxb?B0j aIENDB`./gputests/data/mipmap128x128.png0000755000004100000410000000571113313171755016716 0ustar www-datawww-dataPNG  IHDR>a pHYsnu> OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FIDATx ð`V²d[-0` 0` 0` 0` 0` 0` 0` 0` 0` 0` 0` 0` 0` 0` 0` 0ܰ_Vb3%IENDB`./gputests/data/mipmap32x32.png0000755000004100000410000000540713313171755016544 0ustar www-datawww-dataPNG  IHDR szz pHYsnu> OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_F2IDATx1i3$`46?=)8IENDB`./gputests/data/mipmap64x64.png0000755000004100000410000000547613313171755016564 0ustar www-datawww-dataPNG  IHDR@@iq pHYsnu> OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FiIDATxӿ3=" OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FIDATxbl` %ώ IENDB`./gputests/data/mipmap1x1.png0000755000004100000410000000535113313171755016372 0ustar www-datawww-dataPNG  IHDRĉ pHYsnu> OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FIDATxb ?&HIENDB`./gputests/data/mipmap256x256.png0000755000004100000410000000646713313171755016733 0ustar www-datawww-dataPNG  IHDR\rf pHYsnu> OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FbIDATx1ð`$z&/``````````````````````````````````````````````````````````````pYqIENDB`./autogen.sh0000755000004100000410000000021013313171755013243 0ustar www-datawww-data#!/bin/sh srcdir=`dirname $0` which gnome-autogen.sh || { echo "You need gnome-common from GNOME SVN" exit 1 } . gnome-autogen.sh ./ChangeLog0000644000004100000410000000000113313171754013011 0ustar www-datawww-data ./Makefile.am.coverage0000644000004100000410000000257213313171754015104 0ustar www-datawww-data # Coverage targets .PHONY: clean-gcno clean-gcda \ coverage-html generate-coverage-html clean-coverage-html \ coverage-gcovr generate-coverage-gcovr clean-coverage-gcovr clean-local: clean-gcno clean-coverage-html clean-coverage-gcovr if HAVE_GCOV clean-gcno: @echo Removing old coverage instrumentation -find -name '*.gcno' -print | xargs -r rm clean-gcda: @echo Removing old coverage results -find -name '*.gcda' -print | xargs -r rm coverage-html: -$(MAKE) $(AM_MAKEFLAGS) -k check $(MAKE) $(AM_MAKEFLAGS) generate-coverage-html generate-coverage-html: @echo Collecting coverage data $(LCOV) --directory $(top_builddir) --capture --output-file coverage.info --no-checksum --compat-libtool $(LCOV) --extract coverage.info "$(abs_top_srcdir)/*" -o coverage.info LANG=C $(GENHTML) --prefix $(top_builddir) --output-directory coveragereport --title "Code Coverage" --legend --show-details coverage.info clean-coverage-html: clean-gcda -$(LCOV) --directory $(top_builddir) -z -rm -rf coverage.info coveragereport if HAVE_GCOVR coverage-gcovr: -$(MAKE) $(AM_MAKEFLAGS) -k check $(MAKE) $(AM_MAKEFLAGS) generate-coverage-gcovr generate-coverage-gcovr: @echo Generating coverage GCOVR report $(GCOVR) --xml -r $(top_builddir) -o $(top_builddir)/coverage.xml clean-coverage-gcovr: clean-gcda -rm -rf $(top_builddir)/coverage.xml endif # HAVE_GCOVR endif # HAVE_GCOV ./NuxGraphics/0000755000004100000410000000000013313171755013504 5ustar www-datawww-data./NuxGraphics/IOpenGLSurface.h0000644000004100000410000001005213313171755016421 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef IOPENGLSURFACE_H #define IOPENGLSURFACE_H namespace nux { class IOpenGLResource; class IOpenGLSurface: public IOpenGLResource { NUX_DECLARE_OBJECT_TYPE(IOpenGLSurface, IOpenGLResource); public: virtual int RefCount() const; int LockRect( SURFACE_LOCKED_RECT *pLockedRect, const SURFACE_RECT *pRect); int UnlockRect(); BitmapFormat GetPixelFormat() const; int GetWidth() const; int GetHeight() const; int GetMipLevel() const; int GetSurfaceTarget() const; int GetDesc(SURFACE_DESC *pDesc); //! Copy the render target into the texture mip level. void CopyRenderTarget(int x, int y, int width, int height); //! Return the mipmap data. /*! Return the mipmap data. @param width Returns the width in pixel of the image data. @param height Returns the height in pixel of the image data. @param stride Returns the row stride of the image data. */ unsigned char* GetSurfaceData(int &width, int &height, int &stride); private: virtual ~IOpenGLSurface(); int InitializeLevel(); // By Default, the surface refers to the face 0 of the texture and to the mip level 0 of that face. // IOpenGLSurface(IOpenGLBaseTexture* DeviceBaseTexture, GLenum OpenGLID) // : _STextureTarget(GL_TEXTURE_2D) // , _SSurfaceTarget(GL_TEXTURE_2D) // , _SMipLevel(0) // , _BaseTexture(DeviceBaseTexture) // , IOpenGLResource(RTSURFACE) // { // // IOpenGLSurface surfaces are created inside a IOpenGLTexture2D, IOpenGLCubeTexture and IOpenGLVolumeTexture. // // They reside within those classes. The reference counting starts once a call to GetSurfaceLevel, // // GetCubeMapSurface or GetVolumeLevel is made to the container object. // _RefCount = 0; // _OpenGLID = OpenGLID; // } IOpenGLSurface(IOpenGLBaseTexture *DeviceBaseTexture , GLenum OpenGLID , GLenum TextureTarget , GLenum SurfaceTarget , int MipLevel , int Slice = 0 /*for volume textures*/ , NUX_FILE_LINE_PROTO); // _STextureTarget may be // GL_TEXTURE_2D // GL_TEXTURE_RECTANGLE_ARB // GL_TEXTURE_CUBE_MAP // GL_TEXTURE_3D GLenum _STextureTarget; // _SSurfaceTarget may be // GL_TEXTURE_2D // GL_TEXTURE_3D // GL_TEXTURE_RECTANGLE_ARB // GL_TEXTURE_CUBE_MAP_POSITIVE_X // GL_TEXTURE_CUBE_MAP_NEGATIVE_X // GL_TEXTURE_CUBE_MAP_POSITIVE_Y // GL_TEXTURE_CUBE_MAP_NEGATIVE_Y // GL_TEXTURE_CUBE_MAP_POSITIVE_Z // GL_TEXTURE_CUBE_MAP_NEGATIVE_Z GLenum _SSurfaceTarget; int _SMipLevel; int _SSlice; // for volume texture SURFACE_LOCKED_RECT _LockedRect; SURFACE_RECT _Rect; int _CompressedDataSize; IOpenGLBaseTexture *_BaseTexture; bool _Initialized; int _AllocatedUnpackBuffer; friend class IOpenGLTexture2D; friend class IOpenGLRectangleTexture; friend class IOpenGLCubeTexture; friend class IOpenGLVolumeTexture; friend class IOpenGLAnimatedTexture; friend class ObjectPtr; }; } #endif // IOPENGLSURFACE_H ./NuxGraphics/IOpenGLCgShader.h0000644000004100000410000000531713313171755016521 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef ICGSHADER_H #define ICGSHADER_H namespace nux { class IOpenGLResource; class ICgShader: public IOpenGLResource { NUX_DECLARE_OBJECT_TYPE(ICgShader, IOpenGLResource); public: ICgShader(std::string ShaderName, OpenGLResourceType ResourceType); virtual ~ICgShader(); virtual void CreateProgram(const ANSICHAR *ShaderCode, const ANSICHAR *EntryPoint) = 0; virtual void CreateProgramFromFileShaderCode(const char *Filename, const char *EntryPoint) = 0; virtual void BindProgram() = 0; const char *GetProgramString(); const char *GetProgramBinary(); virtual bool Compile() = 0; virtual bool IsValid() = 0; CGparameter GetNamedParameter(const char *parameter); std::string _ShaderName; std::string _ShaderCode; std::string _EntryPoint; CGprogram _CgProgram; }; class ICgVertexShader: public ICgShader { NUX_DECLARE_OBJECT_TYPE(ICgVertexShader, ICgShader); public: virtual ~ICgVertexShader(); virtual void CreateProgram(const ANSICHAR *ShaderCode, const ANSICHAR *EntryPoint); virtual void CreateProgramFromFileShaderCode(const char *Filename, const char *EntryPoint); virtual void BindProgram(); virtual bool Compile(); virtual bool IsValid(); private: ICgVertexShader(std::string ShaderName = std::string("VertexProgram")); int _ready; friend class GpuDevice; }; class ICgPixelShader: public ICgShader { NUX_DECLARE_OBJECT_TYPE(ICgPixelShader, ICgShader); public: virtual ~ICgPixelShader(); virtual void CreateProgram(const ANSICHAR *ShaderCode, const ANSICHAR *EntryPoint); virtual void CreateProgramFromFileShaderCode(const char *Filename, const char *EntryPoint); virtual void BindProgram(); virtual bool Compile(); virtual bool IsValid(); private: ICgPixelShader(std::string ShaderName = std::string("PixelProgram")); int _ready; friend class GpuDevice; }; } #endif // ICGSHADER_H ./NuxGraphics/MeshData.h0000644000004100000410000000137713313171755015353 0ustar www-datawww-data#ifndef MESHDATA_H #define MESHDATA_H namespace nux { enum NuxMeshPrimitiveType { NUX_MESH_PRIMITIVE_UNKNOWN = 0, NUX_MESH_TRIANGLE, NUX_MESH_TRIANGLE_STRIP, NUX_MESH_TRIANGLE_FAN, NUX_MESH_LINE, NUX_MESH_LINE_STRIP, NUX_MESH_LINE_LOOP, NUX_MESH_POINT, NUX_MESH_QUAD, NUX_MESH_QUAD_STRIP, }; class MeshData { public: MeshData(); ~MeshData(); bool Allocate(int num_mesh_primitive, NuxMeshPrimitiveType primitive_type, int num_elements, int element_size); public: unsigned char* _vertex_data; unsigned char* _index_data; NuxMeshPrimitiveType _mesh_primitive_type; int _num_element; int _element_size; int _num_index; int _index_size; }; } #endif // MESHDATA_H ./NuxGraphics/FontTexture.cpp0000644000004100000410000002435613313171755016511 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "GLResource.h" #include "GLResourceManager.h" #include "GLTextureResourceManager.h" #include "GraphicsEngine.h" #include "FontTexture.h" namespace nux { NUX_IMPLEMENT_OBJECT_TYPE(FontTexture); FontTexture::FontTexture(const char *FontFile, NUX_FILE_LINE_DECL) : Object(true, NUX_FILE_LINE_PARAM) { std::string FontPath = GNuxGraphicsResources.FindResourceLocation(FontFile); std::filebuf fb; fb.open(FontPath.c_str(), std::ios::in); std::istream is(&fb); BMFontParseFNT(is); } FontTexture::FontTexture(int /* width */, int /* height */, BYTE * /* Texture */) { } FontTexture::~FontTexture() { std::vector::iterator it; for (it = TextureArray.begin(); it != TextureArray.end(); ++it) { (*it)->UnReference(); } TextureArray.clear(); } int FontTexture::GetCharWidth(const char &c) const { int ascii = c & 0xff; nuxAssert(ascii < m_Charset.NumChar); if (ascii >= m_Charset.NumChar) return 0; // XAdvance = abcA + abcB + abcC return m_Charset.Chars[ascii].XAdvance; } int FontTexture::GetStringWidth(const std::string &str) const { // unsigned int total = 0; // for (unsigned int i = 0; i != (unsigned int)str.size(); ++i) // { // total += GetCharWidth(str[i]); // } // return total; return GetCharStringWidth(str.c_str()); } int FontTexture::GetCharStringWidth(const char *str) const { if (str == 0 || *str == '\0') return 0; unsigned int total = 0; for (int i = 0; ; ++i) { if (str[i] == 0) return total; total += GetCharWidth(str[i]); } return total; } int FontTexture::GetStringWidth(const std::string &str, int num_char_to_compute) const { return GetCharStringWidth(str.c_str(), num_char_to_compute); } int FontTexture::GetCharStringWidth(const char *str, int num_char_to_compute) const { if (str == 0 || *str == '\0') return 0; int num_chars = num_char_to_compute; if (num_chars <= 0) { return 0; } int total = 0; for (int i = 0; i < num_chars; ++i) { if (str[i] == 0) return total; total += GetCharWidth(str[i]); } return total; } int FontTexture::GetFontHeight() { return m_Charset.FontHeight; } bool FontTexture::BMFontParseFNT( std::istream &Stream ) { std::string Line; int KerningIndex = 0; while ( !Stream.eof()) { std::getline( Stream, Line ); unsigned int line_size = (unsigned int) Line.length(); char *tc = new char[line_size+1]; const char *stream = tc; Memcpy(tc, Line.c_str(), line_size + 1); tc[line_size] = 0; if ( ParseCommand(&stream, "common") /*Read == "common"*/) { Parse_bool(tc, "Bold=", m_Charset.bold); Parse_bool(tc, "Italic=", m_Charset.italic); Parse_u16(tc, "base=", m_Charset.Base); Parse_u16(tc, "scaleW=", m_Charset.Width); Parse_u16(tc, "scaleH=", m_Charset.Height); Parse_u16(tc, "NumPages=", m_Charset.Pages); Parse_u16(tc, "FontHeight=", m_Charset.FontHeight); Parse_u16(tc, "Ascent=", m_Charset.Ascent); Parse_u16(tc, "Descent=", m_Charset.Descent); Parse_int(tc, "AvgCharWidth=", m_Charset.AvgCharWidth); Parse_int(tc, "MaxCharWidth=", m_Charset.MaxCharWidth); Parse_int(tc, "InternalLeading=", m_Charset.InternalLeading); Parse_int(tc, "ExternalLeading=", m_Charset.ExternalLeading); // Constant for now... Should be read from the font file m_Charset.NumChar = 256; } else if (ParseCommand(&stream, "char")) { unsigned short CharID = 0; Parse_u16(tc, "id=", CharID); Parse_u16(tc, "x=", m_Charset.Chars[CharID].x); Parse_u16(tc, "y=", m_Charset.Chars[CharID].y); Parse_u16(tc, "width=", m_Charset.Chars[CharID].Width); Parse_u16(tc, "height=", m_Charset.Chars[CharID].Height); Parse_s16(tc, "xoffset=", m_Charset.Chars[CharID].XOffset); Parse_s16(tc, "yoffset=", m_Charset.Chars[CharID].YOffset); Parse_s16(tc, "xadvance=", m_Charset.Chars[CharID].XAdvance); Parse_s16(tc, "abcA=", m_Charset.Chars[CharID].abcA); Parse_s16(tc, "abcB=", m_Charset.Chars[CharID].abcB); Parse_s16(tc, "abcC=", m_Charset.Chars[CharID].abcC); Parse_u16(tc, "page=", m_Charset.Chars[CharID].page); } else if ( ParseCommand(&stream, "Kerning")) { Parse_u16(tc, "count=", m_Charset.NumKerningPairs); if (m_Charset.NumKerningPairs > 0) m_Charset.Kerning = new KerningPair[m_Charset.NumKerningPairs]; } else if ( ParseCommand(&stream, "KerningPair")) { if (KerningIndex < m_Charset.NumKerningPairs) { Parse_u16(tc, "first=", m_Charset.Kerning[KerningIndex].first); Parse_u16(tc, "second=", m_Charset.Kerning[KerningIndex].second); Parse_s16(tc, "amount=", m_Charset.Kerning[KerningIndex].amount); KerningIndex++; } } else if ( ParseCommand(&stream, "Texture")) { char texture[256]; if (ParseLine(&stream, texture, 256)) { // FilePath FontPath; // FontPath.AddSearchPath(""); // for case where fully qualified path is given // FontPath.AddSearchPath("."); // FontPath.AddSearchPath("../Fonts"); std::string font_texture_file = GNuxGraphicsResources.FindResourceLocation(texture); #ifdef NUX_OPENGLES_20 Texture2D *Texture = new Texture2D(NUX_TRACKER_LOCATION); #else TextureRectangle *Texture = new TextureRectangle(NUX_TRACKER_LOCATION); #endif NBitmapData* bitmap_data = LoadImageFile(font_texture_file.c_str()); if (bitmap_data) Texture->Update(bitmap_data, false); delete bitmap_data; TextureArray.push_back(Texture); } } delete [] tc; } return true; } // CursorPosToX(similar to ScriptStringCPtoX from Microsoft UniScript) // The CursorPosToX function returns the x-coordinate for the leading or trailing edge of a character position. // Parameters // icp // [in] Character position in the string. // fTrailing // [in] Indicates the edge of the icp that corresponds to the x coordinate. If TRUE, it indicates the trailing edge. If FALSE, it indicates the leading edge. // pX // [out] Pointer to a variable that receives the corresponding x coordinate for the icp. // // Return Values // If the function succeeds, it returns S_OK. // If the function fails, it returns an HRESULT. // The return value can be tested with the SUCCEEDED and FAILED macros. bool FontTexture::CursorPosToX(const std::string &Str, int icp, bool fTrailing, int *pX) { if (icp > (int) Str.size()) return false; if (fTrailing) // get pX at the right of the character at position icp *pX = GetStringWidth(Str, icp + 1); else // get pX at the left of the character at position icp *pX = GetStringWidth(Str, icp); return true; } // XToCursorPosition(similar to ScriptStringXtoCP from Microsoft UniScript) // The XToCursorPosition function converts an x-coordinate to a character position. // // Parameters // iX // [in] Specifies the x coordinate. // FirstVisibleCharIndex, // [in] Index of the first visible character in the text box // piCh // [out] Pointer to a variable that receives the character position corresponding to iX. // piTrailing // [out] Pointer to a variable that receives an indicator whether the position is the leading or trailing edge of the character. // // Return Values // If the function is successful, it returns S_OK. // If the function fails, it returns an HRESULT. // The return value can be tested with the SUCCEEDED and FAILED macros. bool FontTexture::XToCursorPosition(const std::string &Str, int iX, unsigned int FirstVisibleCharIndex, int *piCh, int *piTrailing) { unsigned int num_chars; num_chars = (unsigned int) Str.size(); nuxAssert(FirstVisibleCharIndex < num_chars); *piCh = 0; *piTrailing = 0; unsigned int total = 0; if (iX == 0) { *piCh = 0; *piTrailing = 0; return true; } unsigned int X = iX; for (unsigned int i = 0; i < FirstVisibleCharIndex; ++i) { X += GetCharWidth(Str[i]); } for (unsigned int i = 0; i < num_chars; ++i) { unsigned int s = GetCharWidth(Str[i]); if (i >= FirstVisibleCharIndex) { if (total == X) { *piCh = i; *piTrailing = 0; return true; } else if (total + s / 2 > X) { *piCh = i; *piTrailing = 0; return true; } else if (total + GetCharWidth(Str[i+1]) / 2 > X) { *piCh = i + 1; *piTrailing = 0; return true; } } total += s; } return false; } const Charset &FontTexture::GetFontInfo() const { return m_Charset; } } ./NuxGraphics/IOpenGLVolume.h0000644000004100000410000000601613313171755016305 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef IOPENGLVOLUME_H #define IOPENGLVOLUME_H namespace nux { class IOpenGLResource; class IOpenGLVolumeTexture; class IOpenGLVolume: public IOpenGLResource { NUX_DECLARE_OBJECT_TYPE(IOpenGLVolume, IOpenGLResource); public: virtual int RefCount() const; int LockBox( VOLUME_LOCKED_BOX *pLockedVolume, const VOLUME_BOX *pBox); int UnlockBox(); BitmapFormat GetPixelFormat() const; int GetWidth() const; int GetHeight() const; int GetDepth() const; int GetMipLevel() const { return _SMipLevel; } int GetSurfaceTarget() const { return _SSurfaceTarget; } int GetLevelDesc(VOLUME_DESC *pDesc) { pDesc->Width = GetWidth(); pDesc->Height = GetHeight(); pDesc->Depth = GetDepth(); pDesc->PixelFormat = GetPixelFormat(); pDesc->Type = _ResourceType; return OGL_OK; } private: virtual ~IOpenGLVolume(); int InitializeLevel(); IOpenGLVolume(IOpenGLVolumeTexture *VolumeTexture, GLenum OpenGLID, GLenum TextureTarget, GLenum SurfaceTarget, unsigned int MipLevel) : IOpenGLResource(RTVOLUME) , _STextureTarget(TextureTarget) , _SSurfaceTarget(SurfaceTarget) , _SMipLevel(MipLevel) , _VolumeTexture(VolumeTexture) , _AllocatedUnpackBuffer(0xFFFFFFFF) { // IOpenGLVolume surfaces are created inside a IOpenGLVolumeTexture. // They reside within this class. The reference counting starts once a call to GetVolumeLevel is made to the container object. _RefCount = 0; _OpenGLID = OpenGLID; _LockedBox.pBits = 0; _LockedBox.RowPitch = 0; _CompressedDataSize = 0; _Initialized = 0; } // _STextureTarget may be // GL_TEXTURE_3D GLenum _STextureTarget; // _SSurfaceTarget may be // GL_TEXTURE_3D GLenum _SSurfaceTarget; int _SMipLevel; VOLUME_LOCKED_BOX _LockedBox; VOLUME_BOX _Box; int _CompressedDataSize; IOpenGLVolumeTexture *_VolumeTexture; bool _Initialized; int _AllocatedUnpackBuffer; friend class IOpenGLVolumeTexture; friend class ObjectPtr; }; } #endif // IOPENGLVOLUME_H ./NuxGraphics/GLDeviceObjects.h0000644000004100000410000000321213313171755016607 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef GLDEVICEOBJECT_H #define GLDEVICEOBJECT_H #include "GLResource.h" #include "NuxGraphics.h" #include "GLDeviceFrameBufferObject.h" #include "GLShaderParameter.h" #include "GLTextureStates.h" #include "IOpenGLResource.h" #include "IOpenGLVertexBuffer.h" #include "IOpenGLIndexBuffer.h" #include "IOpenGLPixelBufferOject.h" #include "IOpenGLBaseTexture.h" #include "IOpenGLSurface.h" #include "IOpenGLVolume.h" #include "IOpenGLVolumeTexture.h" #include "IOpenGLCubeTexture.h" #include "IOpenGLRectangleTexture.h" #include "IOpenGLTexture2D.h" #include "IOpenGLAnimatedTexture.h" #include "IOpenGLGLSLShader.h" #ifndef NUX_OPENGLES_20 #include "IOpenGLAsmShader.h" #endif #include "IOpenGLQuery.h" #include "IOpenGLVertexDeclaration.h" #include "IOpenGLFrameBufferObject.h" #if (NUX_ENABLE_CG_SHADERS) #include "IOpenGLCgShader.h" #endif #endif // GLDEVICEOBJECT_H ./NuxGraphics/Gfx_Interface.h0000644000004100000410000000245013313171755016362 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef GRAPHICINTERFACE_H #define GRAPHICINTERFACE_H #if defined(NUX_OS_WINDOWS) #include "Events.h" #elif defined(NUX_OS_LINUX) #include "Events.h" #else #error Undefined GfxEvents for this platform #endif namespace nux { typedef struct _DeviceModes { int width; int height; int format; bool fullscreen; int refresh_rate; } DeviceModes; class GraphicSystem { public: int m_num_gfx_device_modes; std::vector m_gfx_device_modes; }; } #endif //GRAPHICINTERFACE_H ./NuxGraphics/NuxGraphicsResources.h0000644000004100000410000000337213313171755020010 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef NUXGRAPHICSRESOURCES_H #define NUXGRAPHICSRESOURCES_H namespace nux { class FontTexture; class NResourceCache; class NuxGraphicsResources { NUX_DECLARE_GLOBAL_OBJECT(NuxGraphicsResources, NuxGraphicsGlobalSingletonInitializer); public: void InitializeResources(); std::string FindResourceLocation(const char *ResourceFileName, bool ErrorOnFail = false); std::string FindUITextureLocation(const char *ResourceFileName, bool ErrorOnFail = false); std::string FindShaderLocation(const char *ResourceFileName, bool ErrorOnFail = false); std::string FindFontLocation(const char *ResourceFileName, bool ErrorOnFail = false); private: std::vector m_FontSearchPath; std::vector m_ShaderSearchPath; std::vector m_UITextureSearchPath; FilePath m_ResourcePathLocation; }; } #define GNuxGraphicsResources NUX_GLOBAL_OBJECT_INSTANCE(nux::NuxGraphicsResources) #endif // NUXGRAPHICSRESOURCES_H ./NuxGraphics/GLDeviceFrameBufferObject.h0000644000004100000410000001671413313171755020544 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef GLDEVICEFRAMEBUFFEROBJECT_H #define GLDEVICEFRAMEBUFFEROBJECT_H /*! FramebufferObject Class. This class encapsulates the FramebufferObject (FBO) OpenGL spec. See the official spec at: http://oss.sgi.com/projects/ogl-sample/registry/EXT/framebuffer_object.txt for details. A framebuffer object(FBO) is conceptually a structure containing pointers to GPU memory. The memory pointed to is either an OpenGL texture or an OpenGL RenderBuffer. FBOs can be used to render to one or more textures, share depth buffers between multiple sets of color buffers/textures and are a complete replacement for pbuffers. Performance Notes: 1) It is more efficient(but not required) to call Bind() on an FBO before making multiple method calls. For example: FramebufferObject fbo; fbo.Bind(); fbo.AttachTexture(GL_COLOR_ATTACHMENT0_EXT, texId0); fbo.AttachTexture(GL_COLOR_ATTACHMENT1_EXT, texId1); fbo.IsValid(); To provide a complete encapsulation, the following usage pattern works correctly but is less efficient: FramebufferObject fbo; // NOTE : No Bind() call fbo.AttachTexture(GL_COLOR_ATTACHMENT0_EXT, texId0); fbo.AttachTexture(GL_COLOR_ATTACHMENT1_EXT, texId1); fbo.IsValid(); The first usage pattern binds the FBO only once, whereas the second usage binds/unbinds the FBO for each method call. 2) Use FramebufferObject::Disable() sparingly. We have intentionally left out an "Unbind()" method because it is largely unnecessary and encourages rendundant Bind/Unbind coding. Binding an FBO is usually much faster than enabling/disabling a pbuffer, but is still a costly operation. When switching between multiple FBOs and a visible OpenGL framebuffer, the following usage pattern is recommended: FramebufferObject fbo1, fbo2; fbo1.Bind(); ... Render ... // NOTE : No Unbind/Disable here... fbo2.Bind(); ... Render ... // Disable FBO rendering and return to visible window // OpenGL framebuffer. FramebufferObject::Disable(); */ namespace nux { class GLFramebufferObject { public: /// Ctor/Dtor GLFramebufferObject(); virtual ~GLFramebufferObject(); /// Bind this FBO as current render target void Bind(); /// Bind a texture to the "attachment" point of this FBO virtual void AttachTexture( GLenum attachment, GLenum texType, GLuint texId, int mipLevel = 0, int zSlice = 0); /// Bind an array of textures to multiple "attachment" points of this FBO /// - By default, the first 'numTextures' attachments are used, /// starting with GL_COLOR_ATTACHMENT0_EXT virtual void AttachTextures( int numTextures, GLenum texTarget[], GLuint texId[], GLenum attachment[] = NULL, int mipLevel[] = NULL, int zSlice[] = NULL ); /// Bind a render buffer to the "attachment" point of this FBO virtual void AttachRenderBuffer( GLenum attachment, GLuint buffId ); /// Free any resource bound to the "attachment" point of this FBO void Unattach( GLenum attachment ); /// Is this FBO currently a valid render target? /// - Sends output to std::cerr by default but can /// be a user-defined C++ stream /// /// NOTE : This function works correctly in debug build /// mode but always returns "true" if NDEBUG is /// is defined(optimized builds) bool IsValid(); /// BEGIN : Accessors /// Is attached type GL_RENDERBUFFER_EXT or GL_TEXTURE? GLenum GetAttachedType( GLenum attachment ); /// What is the Id of Renderbuffer/texture currently /// attached to "attachement?" GLuint GetAttachedId( GLenum attachment ); /// Which mipmap level is currently attached to "attachement?" GLint GetAttachedMipLevel( GLenum attachment ); /// Which cube face is currently attached to "attachment?" GLint GetAttachedCubeFace( GLenum attachment ); /// Which z-slice is currently attached to "attachment?" GLint GetAttachedZSlice( GLenum attachment ); /// END : Accessors /// BEGIN : Static methods global to all FBOs /// Return number of color attachments permitted static int GetMaxColorAttachments(); /// Disable all FBO rendering and return to traditional, /// windowing-system controlled framebuffer /// NOTE: /// This is NOT an "unbind" for this specific FBO, but rather /// disables all FBO rendering. This call is intentionally "static" /// and named "Disable" instead of "Unbind" for this reason. The /// motivation for this strange semantic is performance. Providing "Unbind" /// would likely lead to a large number of unnecessary FBO enablings/disabling. static void Disable(); /// END : Static methods global to all FBOs private: GLint m_fboId; GLint m_savedFboId; void _GuardedBind(); void _GuardedUnbind(); void _FramebufferTextureND( GLenum attachment, GLenum texType, GLuint texId, int mipLevel, int zSlice ); static GLuint _GenerateFboId(); }; /*! Renderbuffer Class. This class encapsulates the Renderbuffer OpenGL object described in the FramebufferObject(FBO) OpenGL spec. See the official spec at: http://oss.sgi.com/projects/ogl-sample/registry/EXT/framebuffer_object.txt for complete details. A "Renderbuffer" is a chunk of GPU memory used by FramebufferObjects to represent "traditional" framebuffer memory(depth, stencil, and color buffers). By "traditional," we mean that the memory cannot be bound as a texture. With respect to GPU shaders, Renderbuffer memory is "write-only." Framebuffer operations such as alpha blending, depth test, alpha test, stencil test, etc. read from this memory in post-fragement-shader(ROP) operations. The most common use of Renderbuffers is to create depth and stencil buffers. Note that as of 7/1/05, NVIDIA drivers to do not support stencil Renderbuffers. Usage Notes: 1) "internalFormat" can be any of the following: Valid OpenGL internal formats beginning with: RGB, RGBA, DEPTH_COMPONENT or a stencil buffer format(not currently supported in NVIDIA drivers as of 7/1/05). STENCIL_INDEX1_EXT STENCIL_INDEX4_EXT STENCIL_INDEX8_EXT STENCIL_INDEX16_EXT */ class GLRenderbuffer { public: /// Ctors/Dtors GLRenderbuffer(); GLRenderbuffer(GLenum internalFormat, int width, int height); ~GLRenderbuffer(); void Bind(); void Unbind(); void Set(GLenum internalFormat, int width, int height); GLuint GetId() const; static GLint GetMaxSize(); private: GLuint m_bufId; static GLuint _CreateBufferId(); }; } #endif // GLDEVICEFRAMEBUFFEROBJECT_H ./NuxGraphics/IOpenGLSurface.cpp0000644000004100000410000006170713313171755016771 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "GLResource.h" #include "GraphicsDisplay.h" #include "GpuDevice.h" #include "GLDeviceObjects.h" #include "IOpenGLSurface.h" namespace nux { NUX_IMPLEMENT_OBJECT_TYPE(IOpenGLSurface); IOpenGLSurface::IOpenGLSurface(IOpenGLBaseTexture *DeviceBaseTexture , GLenum OpenGLID , GLenum TextureTarget , GLenum SurfaceTarget , int MipLevel , int Slice , NUX_FILE_LINE_DECL) : IOpenGLResource(RTSURFACE, NUX_FILE_LINE_PARAM) , _STextureTarget(TextureTarget) , _SSurfaceTarget(SurfaceTarget) , _SMipLevel(MipLevel) , _SSlice(Slice) , _BaseTexture(DeviceBaseTexture) , _AllocatedUnpackBuffer(0xFFFFFFFF) { // IOpenGLSurface surfaces are created inside a IOpenGLTexture2D, IOpenGLCubeTexture and IOpenGLVolumeTexture. // They reside within those classes. The reference counting starts once a call to GetSurfaceLevel, // GetCubeMapSurface or GetVolumeLevel is made to the container object. _RefCount = 0; _OpenGLID = OpenGLID; _LockedRect.pBits = 0; _LockedRect.Pitch = 0; _CompressedDataSize = 0; _Initialized = 0; } IOpenGLSurface::~IOpenGLSurface() { } BitmapFormat IOpenGLSurface::GetPixelFormat() const { if (_BaseTexture == 0) { nuxAssert(0); // should not happen return BITFMT_UNKNOWN; } return _BaseTexture->GetPixelFormat(); } int IOpenGLSurface::GetWidth() const { if (_BaseTexture == 0) { nuxAssert(0); // should not happen return 0; } return ImageSurface::GetLevelDim(_BaseTexture->_PixelFormat, _BaseTexture->_Width, _SMipLevel); } int IOpenGLSurface::GetHeight() const { if (_BaseTexture == 0) { nuxAssert(0); // should not happen return 0; } return ImageSurface::GetLevelDim(_BaseTexture->_PixelFormat, _BaseTexture->_Height, _SMipLevel); } int IOpenGLSurface::GetMipLevel() const { return _SMipLevel; } int IOpenGLSurface::GetSurfaceTarget() const { return _SSurfaceTarget; } int IOpenGLSurface::GetDesc(SURFACE_DESC *pDesc) { pDesc->Width = GetWidth(); pDesc->Height = GetHeight(); pDesc->PixelFormat = GetPixelFormat(); pDesc->Type = _ResourceType; return OGL_OK; } int IOpenGLSurface::RefCount() const { if (_BaseTexture) return _BaseTexture->RefCount(); nuxAssert(0); // Surface with no underlying texture. That should not happen. return 0; } int IOpenGLSurface::LockRect( SURFACE_LOCKED_RECT *pLockedRect, const SURFACE_RECT *pRect) { // If _LockedRect.pBits or _LockedRect.Pitch are not equal to zero, then we have already Locked the buffer // Unlock it before locking again. nuxAssert(_LockedRect.pBits == 0); nuxAssert(_LockedRect.Pitch == 0); nuxAssert(_CompressedDataSize == 0); if ((_LockedRect.pBits != 0) || (_LockedRect.Pitch != 0) || (_CompressedDataSize != 0)) { // already locked; return OGL_INVALID_LOCK; } _Rect.bottom = _Rect.left = _Rect.right = _Rect.top = 0; GLint unpack_alignment = GPixelFormats[_BaseTexture->_PixelFormat].RowMemoryAlignment; unsigned int halfUnpack = Log2(unpack_alignment); CHECKGL(glBindTexture(_STextureTarget, _BaseTexture->_OpenGLID)); unsigned int surface_size = 0; unsigned int BytePerPixel = 0; IOpenGLBaseTexture *texture = _BaseTexture; if (!((_BaseTexture->_ResourceType == RTTEXTURE) || (_BaseTexture->_ResourceType == RTTEXTURERECTANGLE) || (_BaseTexture->_ResourceType == RTCUBETEXTURE) || (_BaseTexture->_ResourceType == RTVOLUMETEXTURE) || (_BaseTexture->_ResourceType == RTANIMATEDTEXTURE))) { nuxAssertMsg(0, "Unknown resource type"); } int texwidth, texheight; texwidth = ImageSurface::GetLevelDim(texture->_PixelFormat, texture->_Width, _SMipLevel); texheight = ImageSurface::GetLevelDim(texture->_PixelFormat, texture->_Height, _SMipLevel); if ( texture->_PixelFormat == BITFMT_DXT1 || texture->_PixelFormat == BITFMT_DXT2 || texture->_PixelFormat == BITFMT_DXT3 || texture->_PixelFormat == BITFMT_DXT4 || texture->_PixelFormat == BITFMT_DXT5) { if (texture->_PixelFormat == BITFMT_DXT1) { // We can conceive a 4x4 DXT1 block as if each texel uses 4 bits. // Actually, for DXT, we have 2 16-bits colors(5:6:5), and each texel uses 2 bits to interpolate // between the 2 colors. // --------------------- // | COLOR0 | 16 bits // --------------------- // | COLOR1 | 16 bits // --------------------- // | xx | xx | xx | xx | xx = 2 bits // --------------------- // | xx | xx | xx | xx | // --------------------- // | xx | xx | xx | xx | // --------------------- // | xx | xx | xx | xx | // --------------------- // A line of n texel DXT1 data uses n/2 bytes(4 bits/texel). So the number of bytes used for a // texwidth texel, is texwidth/2 bytes. // Note that texwidth is divisible by 4(to to the upper rounding to 4), therefore, it is also divisible // by 2. // glCompressedTexImage2DARB, glCompressedTexImage3DARB, // glCompressedTexSubImage2DARB, glCompressedTexSubImage3DARB are not affected by glPixelStorei. surface_size = ImageSurface::GetLevelSize(texture->_PixelFormat, texture->_Width, texture->_Height, _SMipLevel); _CompressedDataSize = surface_size; _LockedRect.Pitch = ImageSurface::GetLevelPitch(texture->_PixelFormat, texture->_Width, texture->_Height, _SMipLevel); if (_Initialized == false) { InitializeLevel(); } } else { // A line of n texel DXT3/5 data uses n bytes(1 byte/texel). So the number of bytes used for a // texwidth texels, is texwidth bytes. // glCompressedTexImage2DARB, glCompressedTexImage3DARB, // glCompressedTexSubImage2DARB, glCompressedTexSubImage3DARB are not affected by glPixelStorei. surface_size = ImageSurface::GetLevelSize(texture->_PixelFormat, texture->_Width, texture->_Height, _SMipLevel); _CompressedDataSize = surface_size; _LockedRect.Pitch = ImageSurface::GetLevelPitch(texture->_PixelFormat, texture->_Width, texture->_Height, _SMipLevel); if (_Initialized == false) { InitializeLevel(); } } } else { _LockedRect.Pitch = ImageSurface::GetLevelPitch(texture->_PixelFormat, texture->_Width, texture->_Height, _SMipLevel); surface_size = ImageSurface::GetLevelSize(texture->_PixelFormat, texture->_Width, texture->_Height, _SMipLevel); if (_Initialized == false) { InitializeLevel(); } } _Rect.left = 0; _Rect.top = 0; _Rect.bottom = texheight; _Rect.right = texwidth; if (GetGraphicsDisplay()->GetGpuDevice()->UsePixelBufferObjects()) { GetGraphicsDisplay()->GetGpuDevice()->AllocateUnpackPixelBufferIndex(&_AllocatedUnpackBuffer); } if (pRect == 0) { if (GetGraphicsDisplay()->GetGpuDevice()->UsePixelBufferObjects()) { // Mapping the entire area of the surface _LockedRect.pBits = GetGraphicsDisplay()->GetGpuDevice()->LockUnpackPixelBufferIndex(_AllocatedUnpackBuffer, surface_size); pLockedRect->pBits = _LockedRect.pBits; pLockedRect->Pitch = _LockedRect.Pitch; } else { //[DEBUGGING - NO PBO] // Mapping the entire area of the surface _LockedRect.pBits = new BYTE[surface_size]; pLockedRect->pBits = _LockedRect.pBits; pLockedRect->Pitch = _LockedRect.Pitch; } } else { //[WARNING] // this section of code is suppose to handle rectangles that are not the size of the entire surface. // It works for uncompressed texture. However it hasn't been tested for compressed texture. // reserve and lock a surface size equal to(RectWidth * RectHeight * BytePerPixel) int RectWidth = pRect->right - pRect->left; int RectHeight = pRect->bottom - pRect->top; nuxAssert(RectWidth >= 0); nuxAssert(RectHeight >= 0); unsigned int RectSize = (((RectWidth * BytePerPixel + (unpack_alignment - 1)) >> (halfUnpack)) << (halfUnpack)) * RectHeight; if (RectSize == 0) { _LockedRect.pBits = NULL; _LockedRect.Pitch = 0; pLockedRect->pBits = NULL; pLockedRect->Pitch = 0; return OGL_INVALID_LOCK; } if (GetGraphicsDisplay()->GetGpuDevice()->UsePixelBufferObjects()) { _LockedRect.pBits = GetGraphicsDisplay()->GetGpuDevice()->LockUnpackPixelBufferIndex(_AllocatedUnpackBuffer, RectSize); pLockedRect->pBits = ((BYTE *) _LockedRect.pBits); pLockedRect->Pitch = (((RectWidth * BytePerPixel + (unpack_alignment - 1)) >> (halfUnpack)) << (halfUnpack)); } else { //[DEBUGGING - NO PBO] _LockedRect.pBits = new BYTE[RectSize]; pLockedRect->pBits = ((BYTE *) _LockedRect.pBits); pLockedRect->Pitch = (((RectWidth * BytePerPixel + (unpack_alignment - 1)) >> (halfUnpack)) << (halfUnpack)); } _Rect.left = pRect->left; _Rect.top = pRect->top; _Rect.bottom = pRect->bottom; _Rect.right = pRect->right; } return OGL_OK; } int IOpenGLSurface::UnlockRect() { if (_LockedRect.pBits == 0) { return OGL_INVALID_UNLOCK; } CHECKGL(glPixelStorei(GL_UNPACK_ALIGNMENT, _BaseTexture->GetFormatRowMemoryAlignment())); #ifndef NUX_OPENGLES_20 if (_STextureTarget == GL_TEXTURE_2D || _STextureTarget == GL_TEXTURE_RECTANGLE_ARB || _STextureTarget == GL_TEXTURE_CUBE_MAP || _STextureTarget == GL_TEXTURE_3D) #else if (_STextureTarget == GL_TEXTURE_2D) #endif { BYTE *DataPtr = 0; int w = _Rect.right - _Rect.left; int h = _Rect.bottom - _Rect.top; CHECKGL(glBindTexture(_STextureTarget, _BaseTexture->_OpenGLID)); #ifndef NUX_OPENGLES_20 if (GetGraphicsDisplay()->GetGpuDevice()->UsePixelBufferObjects()) { // Unmap the texture image buffer GetGraphicsDisplay()->GetGpuDevice()->BindUnpackPixelBufferIndex(_AllocatedUnpackBuffer); CHECKGL(glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB)); DataPtr = NUX_BUFFER_OFFSET(0); } else { CHECKGL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); #endif DataPtr = (BYTE *) _LockedRect.pBits; #ifndef NUX_OPENGLES_20 } #endif IOpenGLTexture2D *texture = (IOpenGLTexture2D *) _BaseTexture; #ifndef NUX_OPENGLES_20 if ( /*texture->_PixelFormat == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||*/ texture->_PixelFormat == BITFMT_DXT1 || texture->_PixelFormat == BITFMT_DXT2 || texture->_PixelFormat == BITFMT_DXT3 || texture->_PixelFormat == BITFMT_DXT4 || texture->_PixelFormat == BITFMT_DXT5) { nuxAssert(_CompressedDataSize != 0); int width = Max (1, texture->_Width >> _SMipLevel); int height = Max (1, texture->_Height >> _SMipLevel); int xoffset = _Rect.left; int yoffset = _Rect.top; if (_STextureTarget != GL_TEXTURE_3D) { glCompressedTexSubImage2DARB(_SSurfaceTarget, _SMipLevel, // level xoffset, yoffset, width, height, GPixelFormats[texture->_PixelFormat].PlatformFormat, _CompressedDataSize, // image Size DataPtr // data ); CHECKGL_MSG(glCompressedTexSubImage2DARB); } else { glCompressedTexSubImage3DARB(_SSurfaceTarget, _SMipLevel, // level xoffset, yoffset, 0, width, height, _SSlice, GPixelFormats[texture->_PixelFormat].PlatformFormat, _CompressedDataSize, // image Size DataPtr // data ); CHECKGL_MSG(glCompressedTexSubImage3DARB); } // We can use glCompressedTexImage2DARB if we are sure we always lock // the entire area of the surface. // glCompressedTexImage2DARB(_SSurfaceTarget, // _SMipLevel, // level // texture->_Format, // width, // height, // 0, // border // _CompressedDataSize, // image Size // _LockedRect.pBits // data // ); // CHECKGL_MSG(glCompressedTexImage2DARB); // { //[DEBUGGING - Red Texture] // // This is going to put some red in the texture. // // The texture is not compressed. // BYTE *color_array = new BYTE[width*height*4]; // for (int i = 0; i < width*height*4; i += 4) // { // color_array[i + 0] = 0xff; // color_array[i + 1] = _SMipLevel * 0x3F; // color_array[i + 2] = 0x0; // color_array[i + 3] = 0xFF; // } // glTexImage2D(GL_TEXTURE_2D, // _SMipLevel, // GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, color_array); // CHECKGL_MSG(glTexImage2D); // delete [] color_array; // } } else { //CHECKGL(glPixelStorei(GL_UNPACK_ROW_LENGTH, w)); if (_STextureTarget != GL_TEXTURE_3D) { #endif CHECKGL(glTexSubImage2D(_SSurfaceTarget, _SMipLevel, _Rect.left, _Rect.top, w, h, GPixelFormats[texture->_PixelFormat].Format, GPixelFormats[texture->_PixelFormat].type, DataPtr )); #ifndef NUX_OPENGLES_20 } else { CHECKGL(glTexSubImage3D(_SSurfaceTarget, _SMipLevel, _Rect.left, _Rect.top, _SSlice, // z offset w, h, 1, GPixelFormats[texture->_PixelFormat].Format, GPixelFormats[texture->_PixelFormat].type, DataPtr )); } //CHECKGL(glPixelStorei(GL_UNPACK_ROW_LENGTH, 0)); // CHECKGL(glTexImage2D(_SSurfaceTarget, // _SMipLevel, // GPixelFormats[texture->_PixelFormat].PlatformFormat, // w, // h, // 0, // //### todo: // // - find the correct format matching the internal format // // - find the correct type matching the internal format // GPixelFormats[texture->_PixelFormat].Format, // GPixelFormats[texture->_PixelFormat].type, // DataPtr // )); } #endif } else { nuxDebugMsg("[IOpenGLSurface::UnlockRect] Incorrect Texture Target."); } #ifndef NUX_OPENGLES_20 if (GetGraphicsDisplay()->GetGpuDevice()->UsePixelBufferObjects()) { CHECKGL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); GetGraphicsDisplay()->GetGpuDevice()->FreeUnpackPixelBufferIndex(_AllocatedUnpackBuffer); } else { #endif //[DEBUGGING - NO PBO] if (_LockedRect.pBits) { delete [] ((BYTE *) _LockedRect.pBits); } #ifndef NUX_OPENGLES_20 } #endif CHECKGL(glPixelStorei(GL_UNPACK_ALIGNMENT, GetGraphicsDisplay()->GetGpuDevice()->GetPixelStoreAlignment())); _LockedRect.pBits = 0; _LockedRect.Pitch = 0; _CompressedDataSize = 0; return OGL_OK; } int IOpenGLSurface::InitializeLevel() { // Because we use SubImage when unlocking surfaces, we must first get some dummy data in the surface before we can make a lock. int texwidth = ImageSurface::GetLevelWidth(_BaseTexture->_PixelFormat, _BaseTexture->_Width, _SMipLevel); int texheight = ImageSurface::GetLevelHeight(_BaseTexture->_PixelFormat, _BaseTexture->_Height, _SMipLevel); int MemAlignment = ImageSurface::GetMemAlignment(_BaseTexture->_PixelFormat); nuxAssert( texwidth > 0 ); // Should never happen nuxAssert( texheight > 0 ); // Should never happen CHECKGL(glPixelStorei(GL_UNPACK_ALIGNMENT, MemAlignment)); #ifndef NUX_OPENGLES_20 int size = ImageSurface::GetLevelSize(_BaseTexture->_PixelFormat, _BaseTexture->_Width, _BaseTexture->_Height, _SMipLevel); nuxAssert( size > 0 ); // Should never happen if ( _BaseTexture->_PixelFormat == BITFMT_DXT1 || _BaseTexture->_PixelFormat == BITFMT_DXT2 || _BaseTexture->_PixelFormat == BITFMT_DXT3 || _BaseTexture->_PixelFormat == BITFMT_DXT4 || _BaseTexture->_PixelFormat == BITFMT_DXT5) { if (_STextureTarget != GL_TEXTURE_3D) { glCompressedTexImage2DARB( _SSurfaceTarget, _SMipLevel, // level GPixelFormats[_BaseTexture->_PixelFormat].PlatformFormat, texwidth, texheight, 0, // border size, // image Size NULL // data ); CHECKGL_MSG(glCompressedTexImage2DARB); } else { // glCompressedTexImage3DARB( // _SSurfaceTarget, // _SMipLevel, // level // GPixelFormats[_BaseTexture->_PixelFormat].PlatformFormat, // texwidth, // texheight, // _SSlice, // 0, // border // size, // image Size // DummyBuffer // data // ); // CHECKGL_MSG(glCompressedTexImage3DARB); } } else { if (_STextureTarget != GL_TEXTURE_3D) { #endif glTexImage2D( _SSurfaceTarget, _SMipLevel, // level GPixelFormats[_BaseTexture->_PixelFormat].PlatformFormat, texwidth, texheight, 0, // border GPixelFormats[_BaseTexture->_PixelFormat].Format, GPixelFormats[_BaseTexture->_PixelFormat].type, NULL); CHECKGL_MSG(glTexImage2D); #ifndef NUX_OPENGLES_20 } else { // glTexImage3D( // _SSurfaceTarget, // _SMipLevel, // level // GPixelFormats[PixelFormat].PlatformFormat, // texwidth, // texheight, // _SSlice, // 0, // border // GPixelFormats[PixelFormat].Format, // GPixelFormats[PixelFormat].type, // DummyBuffer); // CHECKGL_MSG(glTexImage3D); } } #endif // { //[DEBUGGING - Red Texture] // // This is going to put some red in the texture. // // The texture is not compressed. // BYTE *color_array = new BYTE[texwidth*texheight*4]; // for (unsigned int i = 0; i < texwidth*texheight*4; i += 4) // { // color_array[i + 0] = 0xff; // color_array[i + 1] = _SMipLevel * 0x3F; // color_array[i + 2] = 0x0; // color_array[i + 3] = 0xFF; // } // glTexImage2D(GL_TEXTURE_2D, // _SMipLevel, // GL_RGBA8, texwidth, texheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, color_array); // CHECKGL_MSG(glTexImage2D); // delete [] color_array; // } CHECKGL(glPixelStorei(GL_UNPACK_ALIGNMENT, GetGraphicsDisplay()->GetGpuDevice()->GetPixelStoreAlignment())); _Initialized = true; return OGL_OK; } void IOpenGLSurface::CopyRenderTarget(int x, int y, int width, int height) { CHECKGL(glPixelStorei(GL_UNPACK_ALIGNMENT, _BaseTexture->GetFormatRowMemoryAlignment())); #ifndef NUX_OPENGLES_20 if (_STextureTarget == GL_TEXTURE_2D || _STextureTarget == GL_TEXTURE_RECTANGLE_ARB || _STextureTarget == GL_TEXTURE_CUBE_MAP || _STextureTarget == GL_TEXTURE_3D) #else if (_STextureTarget == GL_TEXTURE_2D) #endif { CHECKGL(glBindTexture(_STextureTarget, _BaseTexture->_OpenGLID)); #ifndef NUX_OPENGLES_20 if (_STextureTarget != GL_TEXTURE_3D) { CHECKGL(glCopyTexImage2D(_SSurfaceTarget, _SMipLevel, GPixelFormats [_BaseTexture->_PixelFormat].Format, x, y, width, height, 0)); } else { CHECKGL(glCopyTexSubImage3D(_SSurfaceTarget, _SMipLevel, 0, 0, 0, x, y, width, height)); } #else CHECKGL(glCopyTexImage2D(_SSurfaceTarget, _SMipLevel, GPixelFormats [_BaseTexture->_PixelFormat].Format, x, y, width, height, 0)); #endif } } unsigned char* IOpenGLSurface::GetSurfaceData(int &width, int &height, int &stride) { width = 0; height = 0; stride = 0; if (_BaseTexture->_OpenGLID == 0) { return NULL; } #ifndef NUX_OPENGLES_20 CHECKGL(glBindTexture(_STextureTarget, _BaseTexture->_OpenGLID)); // Despite a 1 byte pack alignment not being the most optimum, do it for simplicity. CHECKGL(glPixelStorei(GL_PACK_ALIGNMENT, 1)); // We want RGBA data int mip_level_size = GetWidth() * GetHeight() * 4; unsigned char* img = new unsigned char[mip_level_size]; // Internal OpenGL textures are in the RGBA format. // If the selected texture image does not contain four components, the following mappings are applied: // - Single-component textures are treated as RGBA buffers with red set to the single-component value, green set to 0, blue set to 0, and alpha set to 1. // - red set to component zero // - green set to 0 // - blue set to 0 // - alpha set to 1.0 // - Two-component textures are treated as RGBA buffers with: // - red set to component zero // - green set to 0 // - blue set to 0 // - alpha set to component one // // - Three-component textures are treated as RGBA buffers with: // - red set to component zero // - green set to component one // - blue set to component two // - alpha set to 1.0 CHECKGL(glGetTexImage(_STextureTarget, _SMipLevel, GL_RGBA, GL_UNSIGNED_BYTE, img)); width = GetWidth(); height = GetHeight(); stride = width * 4; return img; #else //FIXME: need to render to framebuffer and use glReadPixels return NULL; #endif } } ./NuxGraphics/FontRenderer.h0000644000004100000410000000775013313171755016263 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef FONTRENDERER_H #define FONTRENDERER_H #include #include "GLResource.h" class IOpenGLPixelShader; namespace nux { class GraphicsEngine; class TextureRectangle; class ICgPixelShader; class ICgVertexShader; class TemplateQuadBuffer; class FontTexture; class FontRenderer { public: FontRenderer(GraphicsEngine &OpenGLEngine); ~FontRenderer(); void PositionString(ObjectPtr const& Font, std::string const& str, PageBBox const&, StringBBox&, TextAlignment align = eAlignTextCenter, int NumCharacter = 0); int RenderColorText(ObjectPtr const& Font, int x, int y, std::string const& Str, Color const& color, bool WriteAlphaChannel, int NumCharacter); int RenderColorTextLineStatic(ObjectPtr const& Font, PageBBox const& pageSize, std::string const& Str, Color const& color, bool WriteAlphaChannel, TextAlignment alignment); int RenderColorTextLineEdit(ObjectPtr const& Font, PageBBox const& pageSize, std::string const& Str, Color const& TextColor, bool WriteAlphaChannel, Color const& SelectedTextColor, Color const& SelectedTextBackgroundColor, Color const& TextBlinkColor, Color const& CursorColor, bool ShowCursor, unsigned int CursorPosition, int offset = 0, int selection_start = 0, int selection_end = 0); private: int RenderText(ObjectPtr const& Font, int x, int y, std::string const& str, Color const& color, bool WriteAlphaChannel, int StartCharacter = 0, int NumCharacters = 0); // TODO: delete this int RenderTextToBuffer(float *VertexBuffer, int VBSize, ObjectPtr const& Font, Rect const& geo, std::string const& str, Color const& color, TextAlignment alignment = eAlignTextCenter, int NumCharacter = 0); private: GraphicsEngine& _graphics_engine; ObjectPtr _pixel_shader_prog; ObjectPtr _vertex_shader_prog; ObjectPtr _shader_prog; #ifndef NUX_OPENGLES_20 ObjectPtr _asm_shader_prog; ObjectPtr _asm_font_texture_rect_prog; #endif }; } #endif //FONTRENDERER_H ./NuxGraphics/IOpenGLAsmShader.h0000644000004100000410000001133713313171755016707 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef IOPENGLASMSHADER_H #define IOPENGLASMSHADER_H namespace nux { typedef enum { VTXATTRIB_INVALID = -1, VTXATTRIB_POSITION = 0, VTXATTRIB_WEIGHT = 1, VTXATTRIB_NORMAL = 2, VTXATTRIB_COLOR = 3, VTXATTRIB_COLOR_PRIMARY = 3, VTXATTRIB_COLOR_SECONDARY = 4, VTXATTRIB_FOGCOORD = 5, VTXATTRIB_TEXCOORD = 8, VTXATTRIB_TEXCOORD0 = 8, VTXATTRIB_TEXCOORD1 = 9, VTXATTRIB_TEXCOORD2 = 10, VTXATTRIB_TEXCOORD3 = 11, VTXATTRIB_TEXCOORD4 = 12, VTXATTRIB_TEXCOORD5 = 13, VTXATTRIB_TEXCOORD6 = 14, VTXATTRIB_TEXCOORD7 = 15, } VtxAttributeIndex; class IOpenGLResource; class IOpenGLAsmShader: public IOpenGLResource { NUX_DECLARE_OBJECT_TYPE(IOpenGLAsmShader, IOpenGLResource); IOpenGLAsmShader(std::string const& shader_name, GLint shader_type, OpenGLResourceType ResourceType); virtual ~IOpenGLAsmShader(); public: void SetShaderCode(std::string const& shader_code); bool Compile(); bool IsValid(); protected: std::string shader_name_; std::string shader_code_; GLint shader_type_; bool compiled_and_ready_; }; class IOpenGLAsmVertexShader : public IOpenGLAsmShader { NUX_DECLARE_OBJECT_TYPE(IOpenGLAsmVertexShader, IOpenGLAsmShader); public: IOpenGLAsmVertexShader(); }; class IOpenGLAsmPixelShader : public IOpenGLAsmShader { NUX_DECLARE_OBJECT_TYPE(IOpenGLAsmPixelShader, IOpenGLAsmShader); public: IOpenGLAsmPixelShader(); }; class IOpenGLAsmShaderProgram : public IOpenGLResource { NUX_DECLARE_OBJECT_TYPE(IOpenGLAsmShaderProgram, IOpenGLResource); public: virtual ~IOpenGLAsmShaderProgram(); void LoadVertexShader(const char *glslshader); void LoadPixelShader(const char *glslshader); void LoadIShaderFile(const char *ShaderFileName); void LoadIShader(const char *ShaderCode); void Link(); bool IsValid(); void Begin(); void End(); void SetVertexEnvParameter4dARB (unsigned int index, double x, double y, double z, double w); void SetVertexEnvParameter4dvARB (unsigned int index, const double *params); void SetVertexEnvParameter4fARB (unsigned int index, float x, float y, float z, float w); void SetVertexEnvParameter4fvARB (unsigned int index, const float *params); void SetVertexLocalParameter4dARB (unsigned int index, double x, double y, double z, double w); void SetVertexLocalParameter4dvARB (unsigned int index, const double *params); void SetVertexLocalParameter4fARB (unsigned int index, float x, float y, float z, float w); void SetVertexLocalParameter4fvARB (unsigned int index, const float *params); void SetFragmentEnvParameter4dARB (unsigned int index, double x, double y, double z, double w); void SetFragmentEnvParameter4dvARB (unsigned int index, const double *params); void SetFragmentEnvParameter4fARB (unsigned int index, float x, float y, float z, float w); void SetFragmentEnvParameter4fvARB (unsigned int index, const float *params); void SetFragmentLocalParameter4dARB (unsigned int index, double x, double y, double z, double w); void SetFragmentLocalParameter4dvARB (unsigned int index, const double *params); void SetFragmentLocalParameter4fARB (unsigned int index, float x, float y, float z, float w); void SetFragmentLocalParameter4fvARB (unsigned int index, const float *params); private: IOpenGLAsmShaderProgram(std::string ShaderProgramName = std::string("AsmShaderProgram")); std::vector > ShaderObjectList; std::string _ShaderProgramName; ObjectPtr m_AsmVertexProgram; ObjectPtr m_AsmFragmentProgram; friend class GpuDevice; }; } #endif // IOPENGLASMSHADER_H ./NuxGraphics/RenderingPipeAsm.cpp0000644000004100000410000034213713313171755017416 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef NUX_OPENGLES_20 #include "GLResource.h" #include "IOpenGLBaseTexture.h" #include "RenderingPipe.h" #include "GraphicsEngine.h" namespace nux { // Conventional Attribute Binding Generic Attribute Binding // ------------------------------ ------------------------- // vertex.position vertex.attrib[0] // vertex.weight vertex.attrib[1] // vertex.weight[0] vertex.attrib[1] // vertex.normal vertex.attrib[2] // vertex.color vertex.attrib[3] // vertex.color.primary vertex.attrib[3] // vertex.color.secondary vertex.attrib[4] // vertex.fogcoord vertex.attrib[5] // vertex.texcoord vertex.attrib[8] // vertex.texcoord[0] vertex.attrib[8] // vertex.texcoord[1] vertex.attrib[9] // vertex.texcoord[2] vertex.attrib[10] // vertex.texcoord[3] vertex.attrib[11] // vertex.texcoord[4] vertex.attrib[12] // vertex.texcoord[5] vertex.attrib[13] // vertex.texcoord[6] vertex.attrib[14] // vertex.texcoord[7] vertex.attrib[15] // vertex.texcoord[n] vertex.attrib[8+n] // # Vertex Attribute Registers // # attribute Register Components Underlying State // # vertex.position (x,y,z,w) object position // # vertex.weight (w,w,w,w) vertex weights 0-3 // # vertex.weight[n] (w,w,w,w) vertex weights n-n+3 // # vertex.normal (x,y,z,1) NORMAL // # vertex.color (r,g,b,a) primary color // # vertex.color.primary (r,g,b,a) primary color // # vertex.color.secondary (r,g,b,a) secondary color // # vertex.fogcoord (f,0,0,1) fog coordinate // # vertex.texcoord (s,t,r,q) texture coordinate, unit 0 // # vertex.texcoord[n] (s,t,r,q) texture coordinate, unit n // # vertex.matrixindex (i,i,i,i) vertex matrix indices 0-3 // # vertex.matrixindex[n] (i,i,i,i) vertex matrix indices n-n+3 // # vertex.attrib[n] (x,y,z,w) generic vertex attribute n // // // # Result Register Components Description // # result.position (x,y,z,w) position in clip coordinates // # result.color (r,g,b,a) front-facing, primary color // # result.color.primary (r,g,b,a) front-facing, primary color // # result.color.front (r,g,b,a) front-facing, primary color // # result.color.front.primary (r,g,b,a) front-facing, primary color // # result.color.front.secondary (r,g,b,a) front-facing, secondary color // # result.color.back (r,g,b,a) back-facing, primary color // # result.color.back.primary (r,g,b,a) back-facing, primary color // # result.color.back.secondary (r,g,b,a) back-facing, secondary color // # result.fogcoord (f,*,*,*) fog coordinate // # result.pointsize (s,*,*,*) point size // # result.texcoord (s,t,r,q) texture coordinate, unit 0 // # result.color.secondary (r,g,b,a) front-facing, secondary color // # result.texcoord[n] (s,t,r,q) texture coordinate, unit n // # Fragment Attribute Binding Components Underlying State // # -------------------------- ---------- ---------------------------- // # fragment.color (r,g,b,a) primary color // # fragment.color.primary (r,g,b,a) primary color // # fragment.color.secondary (r,g,b,a) secondary color // # fragment.texcoord (s,t,r,q) texture coordinate, unit 0 // # fragment.texcoord[n] (s,t,r,q) texture coordinate, unit n // # fragment.fogcoord (f,0,0,1) fog distance/coordinate // # fragment.position (x,y,z,1/w) window position // # Fragment Program Results Components Description // # ----------------------------- ---------- ---------------------------- // # result.color (r,g,b,a) color // # result.depth (*,*,d,*) depth coordinate void GraphicsEngine::InitAsmColorShader() { const char* AsmVtx = "!!ARBvp1.0 \n\ ATTRIB iPos = vertex.position; \n\ ATTRIB iColor = vertex.attrib[3]; \n\ PARAM mvp[4] = {state.matrix.mvp}; \n\ OUTPUT oPos = result.position; \n\ OUTPUT oColor = result.color; \n\ # Transform the vertex to clip coordinates. \n\ DP4 oPos.x, mvp[0], iPos; \n\ DP4 oPos.y, mvp[1], iPos; \n\ DP4 oPos.z, mvp[2], iPos; \n\ DP4 oPos.w, mvp[3], iPos; \n\ MOV oColor, iColor; \n\ END"; const char* AsmFrg = "!!ARBfp1.0 \n\ MOV result.color, fragment.color; \n\ END"; m_AsmColor = GetGraphicsDisplay()->GetGpuDevice()->CreateAsmShaderProgram(); m_AsmColor->LoadVertexShader(AsmVtx); m_AsmColor->LoadPixelShader(AsmFrg); m_AsmColor->Link(); } void GraphicsEngine::InitAsmTextureShader() { const char* AsmVtx = "!!ARBvp1.0 \n\ ATTRIB iPos = vertex.position; \n\ ATTRIB iColor = vertex.attrib[3]; \n\ PARAM mvp[4] = {state.matrix.mvp}; \n\ OUTPUT oPos = result.position; \n\ OUTPUT oColor = result.color; \n\ OUTPUT oTexCoord0 = result.texcoord[0]; \n\ # Transform the vertex to clip coordinates. \n\ DP4 oPos.x, mvp[0], iPos; \n\ DP4 oPos.y, mvp[1], iPos; \n\ DP4 oPos.z, mvp[2], iPos; \n\ DP4 oPos.w, mvp[3], iPos; \n\ MOV oColor, iColor; \n\ MOV oTexCoord0, vertex.attrib[8]; \n\ END"; const char* AsmFrg = "!!ARBfp1.0 \n\ TEMP tex0; \n\ TEX tex0, fragment.texcoord[0], texture[0], 2D; \n\ MUL result.color, fragment.color, tex0; \n\ END"; const char* AsmFrgRect = "!!ARBfp1.0 \n\ TEMP tex0; \n\ TEX tex0, fragment.texcoord[0], texture[0], RECT; \n\ MUL result.color, fragment.color, tex0; \n\ END"; m_AsmTextureModColor = GetGraphicsDisplay()->GetGpuDevice()->CreateAsmShaderProgram(); m_AsmTextureModColor->LoadVertexShader(AsmVtx); m_AsmTextureModColor->LoadPixelShader(AsmFrg); m_AsmTextureModColor->Link(); m_AsmTextureRectModColor = GetGraphicsDisplay()->GetGpuDevice()->CreateAsmShaderProgram(); m_AsmTextureRectModColor->LoadVertexShader(AsmVtx); m_AsmTextureRectModColor->LoadPixelShader(AsmFrgRect); m_AsmTextureRectModColor->Link(); } void GraphicsEngine::InitAsmColorModTexMaskAlpha() { const char* AsmVtx = "!!ARBvp1.0 \n\ OUTPUT oPos = result.position; \n\ OUTPUT oColor = result.color; \n\ OUTPUT oTexCoord0 = result.texcoord[0]; \n\ # Transform the vertex to clip coordinates. \n\ DP4 oPos.x, state.matrix.mvp.row[0], vertex.position; \n\ DP4 oPos.y, state.matrix.mvp.row[1], vertex.position; \n\ DP4 oPos.z, state.matrix.mvp.row[2], vertex.position; \n\ DP4 oPos.w, state.matrix.mvp.row[3], vertex.position; \n\ MOV oColor, vertex.attrib[3]; \n\ MOV oTexCoord0, vertex.attrib[8]; \n\ END"; const char* AsmFrg = "!!ARBfp1.0 \n\ TEMP tex0; \n\ TEMP temp; \n\ TEX tex0, fragment.texcoord[0], texture[0], 2D; \n\ MOV temp, fragment.color; \n\ MUL temp.w, fragment.color, tex0.wwww; \n\ MOV result.color, temp; \n\ END"; const char* AsmFrgRect = "!!ARBfp1.0 \n\ TEMP tex0; \n\ TEMP temp; \n\ TEX tex0, fragment.texcoord[0], texture[0], RECT; \n\ MOV temp, fragment.color; \n\ MUL temp.w, fragment.color, tex0.wwww; \n\ MOV result.color, temp; \n\ END"; m_AsmColorModTexMaskAlpha = GetGraphicsDisplay()->GetGpuDevice()->CreateAsmShaderProgram(); m_AsmColorModTexMaskAlpha->LoadVertexShader(AsmVtx); m_AsmColorModTexMaskAlpha->LoadPixelShader(AsmFrg); m_AsmColorModTexMaskAlpha->Link(); m_AsmColorModTexRectMaskAlpha = GetGraphicsDisplay()->GetGpuDevice()->CreateAsmShaderProgram(); m_AsmColorModTexRectMaskAlpha->LoadVertexShader(AsmVtx); m_AsmColorModTexRectMaskAlpha->LoadPixelShader(AsmFrgRect); m_AsmColorModTexRectMaskAlpha->Link(); } void GraphicsEngine::InitAsm2TextureAdd() { const char* AsmVtx = "!!ARBvp1.0 \n\ ATTRIB iPos = vertex.position; \n\ OUTPUT oPos = result.position; \n\ OUTPUT oTexCoord0 = result.texcoord[0]; \n\ OUTPUT oTexCoord1 = result.texcoord[1]; \n\ # Transform the vertex to clip coordinates. \n\ DP4 oPos.x, state.matrix.mvp.row[0], vertex.position; \n\ DP4 oPos.y, state.matrix.mvp.row[1], vertex.position; \n\ DP4 oPos.z, state.matrix.mvp.row[2], vertex.position; \n\ DP4 oPos.w, state.matrix.mvp.row[3], vertex.position; \n\ MOV oTexCoord0, vertex.attrib[8]; \n\ MOV oTexCoord1, vertex.attrib[9]; \n\ END"; const char* AsmFrg = "!!ARBfp1.0 \n\ PARAM color0 = program.local[0]; \n\ PARAM color1 = program.local[1]; \n\ TEMP tex0; \n\ TEMP tex1; \n\ TEMP temp; \n\ TEX tex0, fragment.texcoord[0], texture[0], 2D; \n\ MUL temp, color0, tex0; \n\ TEX tex1, fragment.texcoord[1], texture[1], 2D; \n\ MAD temp, color1, tex1, temp; \n\ MOV result.color, temp; \n\ END"; const char* AsmFrgRect = "!!ARBfp1.0 \n\ PARAM color0 = program.local[0]; \n\ PARAM color1 = program.local[1]; \n\ TEMP tex0; \n\ TEMP tex1; \n\ TEMP temp; \n\ TEX tex0, fragment.texcoord[0], texture[0], RECT; \n\ MUL temp, color0, tex0; \n\ TEX tex1, fragment.texcoord[1], texture[1], RECT; \n\ MAD temp, color1, tex1, temp; \n\ MOV result.color, temp; \n\ END"; m_Asm2TextureAdd = GetGraphicsDisplay()->GetGpuDevice()->CreateAsmShaderProgram(); m_Asm2TextureAdd->LoadVertexShader(AsmVtx); m_Asm2TextureAdd->LoadPixelShader(AsmFrg); m_Asm2TextureAdd->Link(); m_Asm2TextureRectAdd = GetGraphicsDisplay()->GetGpuDevice()->CreateAsmShaderProgram(); m_Asm2TextureRectAdd->LoadVertexShader(AsmVtx); m_Asm2TextureRectAdd->LoadPixelShader(AsmFrgRect); m_Asm2TextureRectAdd->Link(); } void GraphicsEngine::InitAsm2TextureDepRead() { const char* AsmVtx = "!!ARBvp1.0 \n\ ATTRIB iPos = vertex.position; \n\ OUTPUT oPos = result.position; \n\ OUTPUT oTexCoord0 = result.texcoord[0]; \n\ OUTPUT oTexCoord1 = result.texcoord[1]; \n\ # Transform the vertex to clip coordinates. \n\ DP4 oPos.x, state.matrix.mvp.row[0], vertex.position; \n\ DP4 oPos.y, state.matrix.mvp.row[1], vertex.position; \n\ DP4 oPos.z, state.matrix.mvp.row[2], vertex.position; \n\ DP4 oPos.w, state.matrix.mvp.row[3], vertex.position; \n\ MOV oTexCoord0, vertex.attrib[8]; \n\ MOV oTexCoord1, vertex.attrib[9]; \n\ END"; const char* AsmFrg = "!!ARBfp1.0 \n\ PARAM color0 = program.local[0]; \n\ PARAM color1 = program.local[1]; \n\ TEMP tex0; \n\ TEMP tex1; \n\ TEMP temp; \n\ TEMP temp0; \n\ TEMP temp1; \n\ TEX tex0, fragment.texcoord[0], texture[0], 2D; \n\ MAD temp, {2.0, 2.0, 2.0, 2.0}, tex0, {-1.0, -1.0, -1.0, -1.0}; \n\ MUL temp0, color0, temp; \n\ ADD temp1, texture[1]; \n\ TEX tex1, fragment.texcoord[1], texture[1], 2D; \n\ MUL result.color, color1, tex1; \n\ END"; const char* AsmFrgRect = "!!ARBfp1.0 \n\ PARAM color0 = program.local[0]; \n\ PARAM color1 = program.local[1]; \n\ TEMP tex0; \n\ TEMP tex1; \n\ TEMP temp; \n\ TEX tex0, fragment.texcoord[0], texture[0], RECT; \n\ MAD temp, {2.0, 2.0, 2.0, 2.0}, tex0, {-1.0, -1.0, -1.0, -1.0}; \n\ MUL temp, color0, tex0; \n\ TEX tex1, fragment.texcoord[1], temp, RECT; \n\ MUL result.color, color1, tex1; \n\ END"; m_ASM2TextureDepRead = GetGraphicsDisplay()->GetGpuDevice()->CreateAsmShaderProgram(); m_ASM2TextureDepRead->LoadVertexShader(AsmVtx); m_ASM2TextureDepRead->LoadPixelShader(AsmFrg); m_ASM2TextureDepRead->Link(); m_ASM2TextureRectDepRead = GetGraphicsDisplay()->GetGpuDevice()->CreateAsmShaderProgram(); m_ASM2TextureRectDepRead->LoadVertexShader(AsmVtx); m_ASM2TextureRectDepRead->LoadPixelShader(AsmFrgRect); m_ASM2TextureRectDepRead->Link(); } void GraphicsEngine::InitAsm2TextureMod() { const char* AsmVtx = "!!ARBvp1.0 \n\ ATTRIB iPos = vertex.position; \n\ OUTPUT oPos = result.position; \n\ OUTPUT oTexCoord0 = result.texcoord[0]; \n\ OUTPUT oTexCoord1 = result.texcoord[1]; \n\ # Transform the vertex to clip coordinates. \n\ DP4 oPos.x, state.matrix.mvp.row[0], vertex.position; \n\ DP4 oPos.y, state.matrix.mvp.row[1], vertex.position; \n\ DP4 oPos.z, state.matrix.mvp.row[2], vertex.position; \n\ DP4 oPos.w, state.matrix.mvp.row[3], vertex.position; \n\ MOV oTexCoord0, vertex.attrib[8]; \n\ MOV oTexCoord1, vertex.attrib[9]; \n\ END"; const char* AsmFrg = "!!ARBfp1.0 \n\ PARAM color0 = program.local[0]; \n\ PARAM color1 = program.local[1]; \n\ TEMP tex0; \n\ TEMP tex1; \n\ TEMP temp0; \n\ TEMP temp1; \n\ TEX tex0, fragment.texcoord[0], texture[0], 2D; \n\ MUL temp0, color0, tex0; \n\ TEX tex1, fragment.texcoord[1], texture[1], 2D; \n\ MUL temp1, color1, tex1; \n\ MUL result.color, temp0, temp1; \n\ END"; const char* AsmFrgRect = "!!ARBfp1.0 \n\ PARAM color0 = program.local[0]; \n\ PARAM color1 = program.local[1]; \n\ TEMP tex0; \n\ TEMP tex1; \n\ TEMP temp0; \n\ TEMP temp1; \n\ TEX tex0, fragment.texcoord[0], texture[0], RECT; \n\ MUL temp0, color0, tex0; \n\ TEX tex1, fragment.texcoord[1], texture[1], RECT; \n\ MUL temp1, color1, tex1; \n\ MUL result.color, temp0, temp1; \n\ END"; m_Asm2TextureMod = GetGraphicsDisplay()->GetGpuDevice()->CreateAsmShaderProgram(); m_Asm2TextureMod->LoadVertexShader(AsmVtx); m_Asm2TextureMod->LoadPixelShader(AsmFrg); m_Asm2TextureMod->Link(); m_Asm2TextureRectMod = GetGraphicsDisplay()->GetGpuDevice()->CreateAsmShaderProgram(); m_Asm2TextureRectMod->LoadVertexShader(AsmVtx); m_Asm2TextureRectMod->LoadPixelShader(AsmFrgRect); m_Asm2TextureRectMod->Link(); } void GraphicsEngine::InitAsm4TextureAdd() { const char* AsmVtx = "!!ARBvp1.0 \n\ ATTRIB iPos = vertex.position; \n\ OUTPUT oPos = result.position; \n\ OUTPUT oTexCoord0 = result.texcoord[0]; \n\ OUTPUT oTexCoord1 = result.texcoord[1]; \n\ OUTPUT oTexCoord2 = result.texcoord[2]; \n\ OUTPUT oTexCoord3 = result.texcoord[3]; \n\ # Transform the vertex to clip coordinates. \n\ DP4 oPos.x, state.matrix.mvp.row[0], vertex.position; \n\ DP4 oPos.y, state.matrix.mvp.row[1], vertex.position; \n\ DP4 oPos.z, state.matrix.mvp.row[2], vertex.position; \n\ DP4 oPos.w, state.matrix.mvp.row[3], vertex.position; \n\ MOV oTexCoord0, vertex.attrib[8]; \n\ MOV oTexCoord1, vertex.attrib[9]; \n\ MOV oTexCoord2, vertex.attrib[10]; \n\ MOV oTexCoord3, vertex.attrib[11]; \n\ END"; const char* AsmFrg = "!!ARBfp1.0 \n\ PARAM color0 = program.local[0]; \n\ PARAM color1 = program.local[1]; \n\ PARAM color2 = program.local[2]; \n\ PARAM color3 = program.local[3]; \n\ TEMP tex0; \n\ TEMP tex1; \n\ TEMP tex2; \n\ TEMP tex3; \n\ TEMP temp; \n\ TEX tex0, fragment.texcoord[0], texture[0], 2D; \n\ MUL temp, color0, tex0; \n\ TEX tex1, fragment.texcoord[1], texture[1], 2D; \n\ MAD temp, color1, tex1, temp; \n\ TEX tex2, fragment.texcoord[2], texture[2], 2D; \n\ MAD temp, color2, tex2, temp; \n\ TEX tex3, fragment.texcoord[3], texture[3], 2D; \n\ MAD temp, color3, tex3, temp; \n\ MOV result.color, temp; \n\ END"; const char* AsmFrgRect = "!!ARBfp1.0 \n\ PARAM color0 = program.local[0]; \n\ PARAM color1 = program.local[1]; \n\ PARAM color2 = program.local[2]; \n\ PARAM color3 = program.local[3]; \n\ TEMP tex0; \n\ TEMP tex1; \n\ TEMP tex2; \n\ TEMP tex3; \n\ TEMP temp; \n\ TEX tex0, fragment.texcoord[0], texture[0], RECT; \n\ MUL temp, color0, tex0; \n\ TEX tex1, fragment.texcoord[1], texture[1], RECT; \n\ MAD temp, color1, tex1, temp; \n\ TEX tex2, fragment.texcoord[2], texture[2], RECT; \n\ MAD temp, color2, tex2, temp; \n\ TEX tex3, fragment.texcoord[3], texture[3], RECT; \n\ MAD temp, color3, tex3, temp; \n\ MOV result.color, temp; \n\ END"; m_Asm4TextureAdd = GetGraphicsDisplay()->GetGpuDevice()->CreateAsmShaderProgram(); m_Asm4TextureAdd->LoadVertexShader(AsmVtx); m_Asm4TextureAdd->LoadPixelShader(AsmFrg); m_Asm4TextureAdd->Link(); m_Asm4TextureRectAdd = GetGraphicsDisplay()->GetGpuDevice()->CreateAsmShaderProgram(); m_Asm4TextureRectAdd->LoadVertexShader(AsmVtx); m_Asm4TextureRectAdd->LoadPixelShader(AsmFrgRect); m_Asm4TextureRectAdd->Link(); } void GraphicsEngine::InitAsmBlendModes() { const char* AsmVtx = "!!ARBvp1.0 \n\ OUTPUT oPos = result.position; \n\ OUTPUT oTexCoord0 = result.texcoord[0]; \n\ OUTPUT oTexCoord1 = result.texcoord[1]; \n\ # Transform the vertex to clip coordinates. \n\ DP4 oPos.x, state.matrix.mvp.row[0], vertex.position; \n\ DP4 oPos.y, state.matrix.mvp.row[1], vertex.position; \n\ DP4 oPos.z, state.matrix.mvp.row[2], vertex.position; \n\ DP4 oPos.w, state.matrix.mvp.row[3], vertex.position; \n\ MOV oTexCoord0, vertex.attrib[8]; \n\ MOV oTexCoord1, vertex.attrib[9]; \n\ END"; const char* AsmPSBNormal = "!!ARBfp1.0 \n\ TEMP tex0; \n\ TEMP tex1; \n\ TEX tex0, fragment.texcoord[0], texture[0], 2D; \n\ TEX tex1, fragment.texcoord[1], texture[1], 2D; \n\ MOV result.color, tex0; \n\ END"; m_AsmPSBNormal = GetGraphicsDisplay()->GetGpuDevice()->CreateAsmShaderProgram(); m_AsmPSBNormal->LoadVertexShader(AsmVtx); m_AsmPSBNormal->LoadPixelShader(AsmPSBNormal); m_AsmPSBNormal->Link(); // Lighten const char* AsmPSBLighten = "!!ARBfp1.0 \n\ TEMP tex0; \n\ TEMP tex1; \n\ TEMP temp; \n\ TEMP cmpres; \n\ TEX tex0, fragment.texcoord[0], texture[0], 2D; \n\ TEX tex1, fragment.texcoord[1], texture[1], 2D; \n\ SUB temp, tex0, tex1; \n\ CMP cmpres, temp, tex1, tex0; \n\ MOV result.color, temp; \n\ END"; m_AsmPSBLighten = GetGraphicsDisplay()->GetGpuDevice()->CreateAsmShaderProgram(); m_AsmPSBLighten->LoadVertexShader(AsmVtx); m_AsmPSBLighten->LoadPixelShader(AsmPSBLighten); m_AsmPSBLighten->Link(); // Darken const char* AsmPSBDarken = "!!ARBfp1.0 \n\ TEMP tex0; \n\ TEMP tex1; \n\ TEMP temp; \n\ TEMP cmpres; \n\ TEX tex0, fragment.texcoord[0], texture[0], 2D; \n\ TEX tex1, fragment.texcoord[1], texture[1], 2D; \n\ SUB temp, tex1, tex0; \n\ CMP cmpres, temp, tex1, tex0; \n\ MOV result.color, temp; \n\ END"; m_AsmPSBDarken = GetGraphicsDisplay()->GetGpuDevice()->CreateAsmShaderProgram(); m_AsmPSBDarken->LoadVertexShader(AsmVtx); m_AsmPSBDarken->LoadPixelShader(AsmPSBDarken); m_AsmPSBDarken->Link(); // Multiply const char* AsmPSBMultiply = "!!ARBfp1.0 \n\ TEMP tex0; \n\ TEMP tex1; \n\ TEMP temp; \n\ TEX tex0, fragment.texcoord[0], texture[0], 2D; \n\ TEX tex1, fragment.texcoord[1], texture[1], 2D; \n\ MUL result.color, tex0, tex1; \n\ END"; m_AsmPSBMultiply = GetGraphicsDisplay()->GetGpuDevice()->CreateAsmShaderProgram(); m_AsmPSBMultiply->LoadVertexShader(AsmVtx); m_AsmPSBMultiply->LoadPixelShader(AsmPSBMultiply); m_AsmPSBMultiply->Link(); } void GraphicsEngine::QRP_ASM_Color(int x, int y, int width, int height, const Color &c0) { QRP_ASM_Color(x, y, width, height, c0, c0, c0, c0); } void GraphicsEngine::QRP_ASM_Color(int x, int y, int width, int height, const Color &c0, const Color &c1, const Color &c2, const Color &c3) { NUX_RETURN_IF_FALSE(m_AsmColor.IsValid()); float fx = x, fy = y; float VtxBuffer[] = { fx, fy, 0.0f, 1.0f, c0.red, c0.green, c0.blue, c0.alpha, fx, fy + height, 0.0f, 1.0f, c1.red, c1.green, c1.blue, c1.alpha, fx + width, fy + height, 0.0f, 1.0f, c2.red, c2.green, c2.blue, c2.alpha, fx + width, fy, 0.0f, 1.0f, c3.red, c3.green, c3.blue, c3.alpha, }; CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); ObjectPtr shader_program = m_AsmColor; shader_program->Begin(); CHECKGL(glMatrixMode(GL_MODELVIEW)); CHECKGL(glLoadIdentity()); CHECKGL(glLoadMatrixf((FLOAT *) GetOpenGLModelViewMatrix().m)); CHECKGL(glMatrixMode(GL_PROJECTION)); CHECKGL(glLoadIdentity()); CHECKGL(glLoadMatrixf((FLOAT *) GetOpenGLProjectionMatrix().m)); int VertexLocation = VTXATTRIB_POSITION; int VertexColorLocation = VTXATTRIB_COLOR; CHECKGL(glEnableVertexAttribArrayARB(VertexLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexLocation, 4, GL_FLOAT, GL_FALSE, 32, VtxBuffer)); if (VertexColorLocation != -1) { CHECKGL(glEnableVertexAttribArrayARB(VertexColorLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexColorLocation, 4, GL_FLOAT, GL_FALSE, 32, VtxBuffer + 4)); } CHECKGL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); CHECKGL(glDisableVertexAttribArrayARB(VertexLocation)); if (VertexColorLocation != -1) CHECKGL(glDisableVertexAttribArrayARB(VertexColorLocation)); shader_program->End(); } void GraphicsEngine::QRP_ASM_1Tex(int x, int y, int width, int height, ObjectPtr device_texture, TexCoordXForm &texxform, const Color &color) { NUX_RETURN_IF_FALSE(m_AsmTextureModColor.IsValid()); NUX_RETURN_IF_FALSE(m_AsmTextureRectModColor.IsValid()); QRP_Compute_Texture_Coord(width, height, device_texture, texxform); float fx = x, fy = y; float VtxBuffer[] = { fx, fy, 0.0f, 1.0f, texxform.u0, texxform.v0, 0, 1.0f, color.red, color.green, color.blue, color.alpha, fx, fy + height, 0.0f, 1.0f, texxform.u0, texxform.v1, 0, 1.0f, color.red, color.green, color.blue, color.alpha, fx + width, fy + height, 0.0f, 1.0f, texxform.u1, texxform.v1, 0, 1.0f, color.red, color.green, color.blue, color.alpha, fx + width, fy, 0.0f, 1.0f, texxform.u1, texxform.v0, 0, 1.0f, color.red, color.green, color.blue, color.alpha, }; CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); ObjectPtr shader_program = m_AsmTextureModColor; if (device_texture->Type().IsDerivedFromType(IOpenGLRectangleTexture::StaticObjectType)) { shader_program = m_AsmTextureRectModColor; } shader_program->Begin(); SetTexture(GL_TEXTURE0, device_texture); CHECKGL(glMatrixMode(GL_MODELVIEW)); CHECKGL(glLoadIdentity()); CHECKGL(glLoadMatrixf((FLOAT *) GetOpenGLModelViewMatrix().m)); CHECKGL(glMatrixMode(GL_PROJECTION)); CHECKGL(glLoadIdentity()); CHECKGL(glLoadMatrixf((FLOAT *) GetOpenGLProjectionMatrix().m)); int VertexLocation = VTXATTRIB_POSITION; int TextureCoord0Location = VTXATTRIB_TEXCOORD0; int VertexColorLocation = VTXATTRIB_COLOR; CHECKGL(glEnableVertexAttribArrayARB(VertexLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexLocation, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer)); if (TextureCoord0Location != -1) { CHECKGL(glEnableVertexAttribArrayARB(TextureCoord0Location)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord0Location, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 4)); } if (VertexColorLocation != -1) { CHECKGL(glEnableVertexAttribArrayARB(VertexColorLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexColorLocation, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 8)); } CHECKGL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); CHECKGL(glDisableVertexAttribArrayARB(VertexLocation)); if (TextureCoord0Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord0Location)); if (VertexColorLocation != -1) CHECKGL(glDisableVertexAttribArrayARB(VertexColorLocation)); shader_program->End(); } void GraphicsEngine::QRP_ASM_ColorModTexAlpha(int x, int y, int width, int height, ObjectPtr device_texture, TexCoordXForm &texxform, const Color &color) { NUX_RETURN_IF_FALSE(m_AsmColorModTexMaskAlpha.IsValid()); NUX_RETURN_IF_FALSE(m_AsmColorModTexRectMaskAlpha.IsValid()); QRP_Compute_Texture_Coord(width, height, device_texture, texxform); float fx = x, fy = y; float VtxBuffer[] = { fx, fy, 0.0f, 1.0f, texxform.u0, texxform.v0, 0, 1.0f, color.red, color.green, color.blue, color.alpha, fx, fy + height, 0.0f, 1.0f, texxform.u0, texxform.v1, 0, 1.0f, color.red, color.green, color.blue, color.alpha, fx + width, fy + height, 0.0f, 1.0f, texxform.u1, texxform.v1, 0, 1.0f, color.red, color.green, color.blue, color.alpha, fx + width, fy, 0.0f, 1.0f, texxform.u1, texxform.v0, 0, 1.0f, color.red, color.green, color.blue, color.alpha, }; CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); ObjectPtr shader_program = m_AsmColorModTexMaskAlpha; if (device_texture->Type().IsDerivedFromType(IOpenGLRectangleTexture::StaticObjectType)) { shader_program = m_AsmColorModTexRectMaskAlpha; } shader_program->Begin(); SetTexture(GL_TEXTURE0, device_texture); CHECKGL(glMatrixMode(GL_MODELVIEW)); CHECKGL(glLoadIdentity()); CHECKGL(glLoadMatrixf((FLOAT *) GetOpenGLModelViewMatrix().m)); CHECKGL(glMatrixMode(GL_PROJECTION)); CHECKGL(glLoadIdentity()); CHECKGL(glLoadMatrixf((FLOAT *) GetOpenGLProjectionMatrix().m)); int VertexLocation = VTXATTRIB_POSITION; int TextureCoord0Location = VTXATTRIB_TEXCOORD0; int VertexColorLocation = VTXATTRIB_COLOR; CHECKGL(glEnableVertexAttribArrayARB(VertexLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexLocation, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer)); if (TextureCoord0Location != -1) { CHECKGL(glEnableVertexAttribArrayARB(TextureCoord0Location)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord0Location, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 4)); } if (VertexColorLocation != -1) { CHECKGL(glEnableVertexAttribArrayARB(VertexColorLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexColorLocation, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 8)); } CHECKGL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); CHECKGL(glDisableVertexAttribArrayARB(VertexLocation)); if (TextureCoord0Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord0Location)); if (VertexColorLocation != -1) CHECKGL(glDisableVertexAttribArrayARB(VertexColorLocation)); shader_program->End(); } void GraphicsEngine::QRP_ASM_2Tex(int x, int y, int width, int height, ObjectPtr device_texture0, TexCoordXForm &texxform0, const Color &color0, ObjectPtr device_texture1, TexCoordXForm &texxform1, const Color &color1) { NUX_RETURN_IF_FALSE(m_Asm2TextureAdd.IsValid()); NUX_RETURN_IF_FALSE(m_Asm2TextureRectAdd.IsValid()); QRP_Compute_Texture_Coord(width, height, device_texture0, texxform0); QRP_Compute_Texture_Coord(width, height, device_texture1, texxform1); float fx = x, fy = y; float VtxBuffer[] = { fx, fy, 0.0f, 1.0f, texxform0.u0, texxform0.v0, 0.0f, 1.0f, texxform1.u0, texxform1.v0, 0.0f, 1.0f, fx, fy + height, 0.0f, 1.0f, texxform0.u0, texxform0.v1, 0.0f, 1.0f, texxform1.u0, texxform1.v1, 0.0f, 1.0f, fx + width, fy + height, 0.0f, 1.0f, texxform0.u1, texxform0.v1, 0.0f, 1.0f, texxform1.u1, texxform1.v1, 0.0f, 1.0f, fx + width, fy, 0.0f, 1.0f, texxform0.u1, texxform0.v0, 0.0f, 1.0f, texxform1.u1, texxform1.v0, 0.0f, 1.0f, }; CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); ObjectPtr shader_program = m_Asm2TextureAdd; if (device_texture0->Type().IsDerivedFromType(IOpenGLRectangleTexture::StaticObjectType)) { shader_program = m_Asm2TextureRectAdd; } shader_program->Begin(); SetTexture(GL_TEXTURE0, device_texture0); SetTexture(GL_TEXTURE1, device_texture1); CHECKGL(glMatrixMode(GL_MODELVIEW)); CHECKGL(glLoadIdentity()); CHECKGL(glLoadMatrixf((FLOAT *) GetOpenGLModelViewMatrix().m)); CHECKGL(glMatrixMode(GL_PROJECTION)); CHECKGL(glLoadIdentity()); CHECKGL(glLoadMatrixf((FLOAT *) GetOpenGLProjectionMatrix().m)); int VertexLocation = VTXATTRIB_POSITION; int TextureCoord0Location = VTXATTRIB_TEXCOORD0; int TextureCoord1Location = VTXATTRIB_TEXCOORD1; CHECKGL(glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, color0.red, color0.green, color0.blue, color0.alpha )); CHECKGL(glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, color1.red, color1.green, color1.blue, color1.alpha )); CHECKGL(glEnableVertexAttribArrayARB(VertexLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexLocation, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer)); if (TextureCoord0Location != -1) { CHECKGL(glEnableVertexAttribArrayARB(TextureCoord0Location)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord0Location, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 4)); } if (TextureCoord1Location != -1) { CHECKGL(glEnableVertexAttribArrayARB(TextureCoord1Location)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord1Location, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 8)); } CHECKGL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); CHECKGL(glDisableVertexAttribArrayARB(VertexLocation)); if (TextureCoord0Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord0Location)); if (TextureCoord1Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord1Location)); shader_program->End(); } void GraphicsEngine::QRP_ASM_DisturbedTexture( int x, int y, int width, int height, ObjectPtr distorsion_texture, TexCoordXForm &texxform0, const Color& c0, ObjectPtr src_device_texture, TexCoordXForm &texxform1, const Color& c1) { NUX_RETURN_IF_FALSE(m_ASM2TextureDepRead.IsValid()); NUX_RETURN_IF_FALSE(m_ASM2TextureRectDepRead.IsValid()); QRP_Compute_Texture_Coord(width, height, distorsion_texture, texxform0); QRP_Compute_Texture_Coord(width, height, src_device_texture, texxform1); float fx = x, fy = y; float VtxBuffer[] = { fx, fy, 0.0f, 1.0f, texxform0.u0, texxform0.v0, 0.0f, 1.0f, texxform1.u0, texxform1.v0, 0.0f, 1.0f, fx, fy + height, 0.0f, 1.0f, texxform0.u0, texxform0.v1, 0.0f, 1.0f, texxform1.u0, texxform1.v1, 0.0f, 1.0f, fx + width, fy + height, 0.0f, 1.0f, texxform0.u1, texxform0.v1, 0.0f, 1.0f, texxform1.u1, texxform1.v1, 0.0f, 1.0f, fx + width, fy, 0.0f, 1.0f, texxform0.u1, texxform0.v0, 0.0f, 1.0f, texxform1.u1, texxform1.v0, 0.0f, 1.0f, }; CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); ObjectPtr shader_program = m_ASM2TextureDepRead; if (src_device_texture->Type().IsDerivedFromType(IOpenGLRectangleTexture::StaticObjectType)) { shader_program = m_ASM2TextureRectDepRead; } shader_program->Begin(); SetTexture(GL_TEXTURE0, distorsion_texture); SetTexture(GL_TEXTURE1, src_device_texture); CHECKGL(glMatrixMode(GL_MODELVIEW)); CHECKGL(glLoadIdentity()); CHECKGL(glLoadMatrixf((FLOAT *) GetOpenGLModelViewMatrix().m)); CHECKGL(glMatrixMode(GL_PROJECTION)); CHECKGL(glLoadIdentity()); CHECKGL(glLoadMatrixf((FLOAT *) GetOpenGLProjectionMatrix().m)); int VertexLocation = VTXATTRIB_POSITION; int TextureCoord0Location = VTXATTRIB_TEXCOORD0; int TextureCoord1Location = VTXATTRIB_TEXCOORD1; CHECKGL(glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, c0.red, c0.green, c0.blue, c0.alpha )); CHECKGL(glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, c1.red, c1.green, c1.blue, c1.alpha )); CHECKGL(glEnableVertexAttribArrayARB(VertexLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexLocation, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer)); if (TextureCoord0Location != -1) { CHECKGL(glEnableVertexAttribArrayARB(TextureCoord0Location)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord0Location, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 4)); } if (TextureCoord1Location != -1) { CHECKGL(glEnableVertexAttribArrayARB(TextureCoord1Location)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord1Location, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 8)); } CHECKGL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); CHECKGL(glDisableVertexAttribArrayARB(VertexLocation)); if (TextureCoord0Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord0Location)); if (TextureCoord1Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord1Location)); shader_program->End(); } void GraphicsEngine::QRP_ASM_2TexMod(int x, int y, int width, int height, ObjectPtr device_texture0, TexCoordXForm &texxform0, const Color &color0, ObjectPtr device_texture1, TexCoordXForm &texxform1, const Color &color1) { NUX_RETURN_IF_FALSE(m_Asm2TextureMod.IsValid()); NUX_RETURN_IF_FALSE(m_Asm2TextureRectMod.IsValid()); QRP_Compute_Texture_Coord(width, height, device_texture0, texxform0); QRP_Compute_Texture_Coord(width, height, device_texture1, texxform1); float fx = x, fy = y; float VtxBuffer[] = { fx, fy, 0.0f, 1.0f, texxform0.u0, texxform0.v0, 0.0f, 1.0f, texxform1.u0, texxform1.v0, 0.0f, 1.0f, fx, fy + height, 0.0f, 1.0f, texxform0.u0, texxform0.v1, 0.0f, 1.0f, texxform1.u0, texxform1.v1, 0.0f, 1.0f, fx + width, fy + height, 0.0f, 1.0f, texxform0.u1, texxform0.v1, 0.0f, 1.0f, texxform1.u1, texxform1.v1, 0.0f, 1.0f, fx + width, fy, 0.0f, 1.0f, texxform0.u1, texxform0.v0, 0.0f, 1.0f, texxform1.u1, texxform1.v0, 0.0f, 1.0f, }; CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); ObjectPtr shader_program = m_Asm2TextureMod; if (device_texture0->Type().IsDerivedFromType(IOpenGLRectangleTexture::StaticObjectType)) { shader_program = m_Asm2TextureRectMod; } shader_program->Begin(); SetTexture(GL_TEXTURE0, device_texture0); SetTexture(GL_TEXTURE1, device_texture1); CHECKGL(glMatrixMode(GL_MODELVIEW)); CHECKGL(glLoadIdentity()); CHECKGL(glLoadMatrixf((FLOAT *) GetOpenGLModelViewMatrix().m)); CHECKGL(glMatrixMode(GL_PROJECTION)); CHECKGL(glLoadIdentity()); CHECKGL(glLoadMatrixf((FLOAT *) GetOpenGLProjectionMatrix().m)); int VertexLocation = VTXATTRIB_POSITION; int TextureCoord0Location = VTXATTRIB_TEXCOORD0; int TextureCoord1Location = VTXATTRIB_TEXCOORD1; CHECKGL(glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, color0.red, color0.green, color0.blue, color0.alpha )); CHECKGL(glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, color1.red, color1.green, color1.blue, color1.alpha )); CHECKGL(glEnableVertexAttribArrayARB(VertexLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexLocation, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer)); if (TextureCoord0Location != -1) { CHECKGL(glEnableVertexAttribArrayARB(TextureCoord0Location)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord0Location, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 4)); } if (TextureCoord1Location != -1) { CHECKGL(glEnableVertexAttribArrayARB(TextureCoord1Location)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord1Location, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 8)); } CHECKGL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); CHECKGL(glDisableVertexAttribArrayARB(VertexLocation)); if (TextureCoord0Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord0Location)); if (TextureCoord1Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord1Location)); shader_program->End(); } void GraphicsEngine::QRP_ASM_4Tex(int x, int y, int width, int height, ObjectPtr device_texture0, TexCoordXForm &texxform0, const Color &color0, ObjectPtr device_texture1, TexCoordXForm &texxform1, const Color &color1, ObjectPtr device_texture2, TexCoordXForm &texxform2, const Color &color2, ObjectPtr device_texture3, TexCoordXForm &texxform3, const Color &color3) { NUX_RETURN_IF_FALSE(m_Asm4TextureAdd.IsValid()); NUX_RETURN_IF_FALSE(m_Asm4TextureRectAdd.IsValid()); QRP_Compute_Texture_Coord(width, height, device_texture0, texxform0); QRP_Compute_Texture_Coord(width, height, device_texture1, texxform1); QRP_Compute_Texture_Coord(width, height, device_texture2, texxform1); QRP_Compute_Texture_Coord(width, height, device_texture3, texxform1); float fx = x, fy = y; float VtxBuffer[] = { fx, fy, 0.0f, 1.0f, texxform0.u0, texxform0.v0, 0, 1.0f, texxform1.u0, texxform1.v0, 0, 1.0f, texxform2.u0, texxform2.v0, 0, 1.0f, texxform3.u0, texxform3.v0, 0, 1.0f, fx, fy + height, 0.0f, 1.0f, texxform0.u0, texxform0.v1, 0, 1.0f, texxform1.u0, texxform1.v1, 0, 1.0f, texxform2.u0, texxform2.v1, 0, 1.0f, texxform3.u0, texxform3.v1, 0, 1.0f, fx + width, fy + height, 0.0f, 1.0f, texxform0.u1, texxform0.v1, 0, 1.0f, texxform1.u1, texxform1.v1, 0, 1.0f, texxform2.u1, texxform2.v1, 0, 1.0f, texxform3.u1, texxform3.v1, 0, 1.0f, fx + width, fy, 0.0f, 1.0f, texxform0.u1, texxform0.v0, 0, 1.0f, texxform1.u1, texxform1.v0, 0, 1.0f, texxform2.u1, texxform2.v0, 0, 1.0f, texxform3.u1, texxform3.v0, 0, 1.0f, }; CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); ObjectPtr shader_program = m_Asm4TextureAdd; if (device_texture0->Type().IsDerivedFromType(IOpenGLRectangleTexture::StaticObjectType)) { shader_program = m_Asm4TextureRectAdd; } shader_program->Begin(); SetTexture(GL_TEXTURE0, device_texture0); SetTexture(GL_TEXTURE1, device_texture1); SetTexture(GL_TEXTURE2, device_texture1); SetTexture(GL_TEXTURE3, device_texture1); CHECKGL(glMatrixMode(GL_MODELVIEW)); CHECKGL(glLoadIdentity()); CHECKGL(glLoadMatrixf((FLOAT *) GetOpenGLModelViewMatrix().m)); CHECKGL(glMatrixMode(GL_PROJECTION)); CHECKGL(glLoadIdentity()); CHECKGL(glLoadMatrixf((FLOAT *) GetOpenGLProjectionMatrix().m)); int VertexLocation = VTXATTRIB_POSITION; int TextureCoord0Location = VTXATTRIB_TEXCOORD0; int TextureCoord1Location = VTXATTRIB_TEXCOORD1; int TextureCoord2Location = VTXATTRIB_TEXCOORD2; int TextureCoord3Location = VTXATTRIB_TEXCOORD3; CHECKGL(glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, color0.red, color0.green, color0.blue, color0.alpha )); CHECKGL(glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, color1.red, color1.green, color1.blue, color1.alpha )); CHECKGL(glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 2, color2.red, color2.green, color2.blue, color2.alpha )); CHECKGL(glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 3, color3.red, color3.green, color3.blue, color3.alpha )); CHECKGL(glEnableVertexAttribArrayARB(VertexLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexLocation, 4, GL_FLOAT, GL_FALSE, 80, VtxBuffer)); if (TextureCoord0Location != -1) { CHECKGL(glEnableVertexAttribArrayARB(TextureCoord0Location)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord0Location, 4, GL_FLOAT, GL_FALSE, 80, VtxBuffer + 4)); } if (TextureCoord1Location != -1) { CHECKGL(glEnableVertexAttribArrayARB(TextureCoord1Location)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord1Location, 4, GL_FLOAT, GL_FALSE, 80, VtxBuffer + 8)); } if (TextureCoord2Location != -1) { CHECKGL(glEnableVertexAttribArrayARB(TextureCoord2Location)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord2Location, 4, GL_FLOAT, GL_FALSE, 80, VtxBuffer + 12)); } if (TextureCoord3Location != -1) { CHECKGL(glEnableVertexAttribArrayARB(TextureCoord3Location)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord3Location, 4, GL_FLOAT, GL_FALSE, 80, VtxBuffer + 16)); } CHECKGL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); CHECKGL(glDisableVertexAttribArrayARB(VertexLocation)); if (TextureCoord0Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord0Location)); if (TextureCoord1Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord1Location)); if (TextureCoord2Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord2Location)); if (TextureCoord3Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord3Location)); shader_program->End(); } //////////////////////////////////////////////////////////////////////////////////// void GraphicsEngine::QRP_ASM_Triangle(int x0, int y0, int x1, int y1, int x2, int y2, Color c0) { QRP_ASM_Triangle(x0, y0, x1, y1, x2, y2, c0, c0, c0); } void GraphicsEngine::QRP_ASM_Triangle(int x0, int y0, int x1, int y1, int x2, int y2, Color c0, Color c1, Color c2) { NUX_RETURN_IF_FALSE(m_AsmColor.IsValid()); float VtxBuffer[] = { static_cast(x0), static_cast(y0), 0.0f, 1.0f, c0.red, c0.green, c0.blue, c0.alpha, static_cast(x1), static_cast(y1), 0.0f, 1.0f, c1.red, c1.green, c1.blue, c1.alpha, static_cast(x2), static_cast(y2), 0.0f, 1.0f, c2.red, c2.green, c2.blue, c2.alpha, }; CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); ObjectPtr ShaderProg = m_AsmColor; ShaderProg->Begin(); CHECKGL(glMatrixMode(GL_MODELVIEW)); CHECKGL(glLoadIdentity()); CHECKGL(glLoadMatrixf((FLOAT *) GetOpenGLModelViewMatrix().m)); CHECKGL(glMatrixMode(GL_PROJECTION)); CHECKGL(glLoadIdentity()); CHECKGL(glLoadMatrixf((FLOAT *) GetOpenGLProjectionMatrix().m)); int VertexLocation = VTXATTRIB_POSITION; int VertexColorLocation = VTXATTRIB_COLOR; CHECKGL(glEnableVertexAttribArrayARB(VertexLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexLocation, 4, GL_FLOAT, GL_FALSE, 32, VtxBuffer)); CHECKGL(glEnableVertexAttribArrayARB(VertexColorLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexColorLocation, 4, GL_FLOAT, GL_FALSE, 32, VtxBuffer + 4)); CHECKGL(glDrawArrays(GL_TRIANGLES, 0, 3)); CHECKGL(glDisableVertexAttribArrayARB(VertexLocation)); CHECKGL(glDisableVertexAttribArrayARB(VertexColorLocation)); ShaderProg->End(); m_triangle_stats++; } ////////////////////// // DRAW LINES // ////////////////////// void GraphicsEngine::QRP_ASM_Line(int x0, int y0, int x1, int y1, Color c0) { QRP_ASM_Line(x0, y0, x1, y1, c0, c0); } void GraphicsEngine::QRP_ASM_Line(int x0, int y0, int x1, int y1, Color c0, Color c1) { NUX_RETURN_IF_FALSE(m_AsmColor.IsValid()); float VtxBuffer[] = { static_cast(x0), static_cast(y0), 0.0f, 1.0f, c0.red, c0.green, c0.blue, c0.alpha, static_cast(x1), static_cast(y1), 0.0f, 1.0f, c1.red, c1.green, c1.blue, c1.alpha, }; ObjectPtr ShaderProg = m_AsmColor; CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); ShaderProg->Begin(); CHECKGL(glMatrixMode(GL_MODELVIEW)); CHECKGL(glLoadIdentity()); CHECKGL(glLoadMatrixf((FLOAT *) GetOpenGLModelViewMatrix().m)); CHECKGL(glMatrixMode(GL_PROJECTION)); CHECKGL(glLoadIdentity()); CHECKGL(glLoadMatrixf((FLOAT *) GetOpenGLProjectionMatrix().m)); int VertexLocation = VTXATTRIB_POSITION; int VertexColorLocation = VTXATTRIB_COLOR; CHECKGL(glEnableVertexAttribArrayARB(VertexLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexLocation, 4, GL_FLOAT, GL_FALSE, 32, VtxBuffer)); if (VertexColorLocation != -1) { CHECKGL(glEnableVertexAttribArrayARB(VertexColorLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexColorLocation, 4, GL_FLOAT, GL_FALSE, 32, VtxBuffer + 4)); } CHECKGL(glDrawArrays(GL_LINES, 0, 2)); CHECKGL(glDisableVertexAttribArrayARB(VertexLocation)); if (VertexColorLocation != -1) CHECKGL(glDisableVertexAttribArrayARB(VertexColorLocation)); ShaderProg->End(); m_line_stats++; } void GraphicsEngine::QRP_ASM_QuadWireframe(int x0, int y0, int width, int height, Color c0, Color c1, Color c2, Color c3) { NUX_RETURN_IF_FALSE(m_AsmColor.IsValid()); float fx0 = x0, fy0 = y0; float VtxBuffer[] = { fx0, fy0, 0.0f, 1.0f, c0.red, c0.green, c0.blue, c0.alpha, fx0, fy0 + height - 1, 0.0f, 1.0f, c1.red, c1.green, c1.blue, c1.alpha, fx0 + width - 1, fy0 + height - 1, 0.0f, 1.0f, c2.red, c2.green, c2.blue, c2.alpha, fx0 + width - 1, fy0, 0.0f, 1.0f, c3.red, c3.green, c3.blue, c3.alpha, fx0, fy0, 0.0f, 1.0f, c0.red, c0.green, c0.blue, c0.alpha, }; ObjectPtr ShaderProg = m_AsmColor; CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); ShaderProg->Begin(); CHECKGL(glMatrixMode(GL_MODELVIEW)); CHECKGL(glLoadIdentity()); CHECKGL(glLoadMatrixf((FLOAT *) GetOpenGLModelViewMatrix().m)); CHECKGL(glMatrixMode(GL_PROJECTION)); CHECKGL(glLoadIdentity()); CHECKGL(glLoadMatrixf((FLOAT *) GetOpenGLProjectionMatrix().m)); int VertexLocation = VTXATTRIB_POSITION; int VertexColorLocation = VTXATTRIB_COLOR; CHECKGL(glEnableVertexAttribArrayARB(VertexLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexLocation, 4, GL_FLOAT, GL_FALSE, 32, VtxBuffer)); if (VertexColorLocation != -1) { CHECKGL(glEnableVertexAttribArrayARB(VertexColorLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexColorLocation, 4, GL_FLOAT, GL_FALSE, 32, VtxBuffer + 4)); } CHECKGL(glDrawArrays(GL_LINE_STRIP, 0, 5)); CHECKGL(glDisableVertexAttribArrayARB(VertexLocation)); if (VertexColorLocation != -1) CHECKGL(glDisableVertexAttribArrayARB(VertexColorLocation)); ShaderProg->End(); m_line_stats++; } void GraphicsEngine::InitAsmPower() { const char* AsmVtx = "!!ARBvp1.0 \n\ ATTRIB iPos = vertex.position; \n\ OUTPUT oPos = result.position; \n\ OUTPUT oTexCoord0 = result.texcoord[0]; \n\ # Transform the vertex to clip coordinates. \n\ DP4 oPos.x, state.matrix.mvp.row[0], vertex.position; \n\ DP4 oPos.y, state.matrix.mvp.row[1], vertex.position; \n\ DP4 oPos.z, state.matrix.mvp.row[2], vertex.position; \n\ DP4 oPos.w, state.matrix.mvp.row[3], vertex.position; \n\ MOV oTexCoord0, vertex.attrib[8]; \n\ END"; const char* AsmFrg = "!!ARBfp1.0 \n\ PARAM color0 = program.local[0]; \n\ PARAM exponent = program.local[1]; \n\ TEMP tex0; \n\ TEMP final; \n\ TEX tex0, fragment.texcoord[0], texture[0], 2D; \n\ POW final.r, tex0.r, exponent.r; \n\ POW final.g, tex0.g, exponent.g; \n\ POW final.b, tex0.b, exponent.b; \n\ MOV final.a, tex0.a; \n\ MUL result.color, color0, final; \n\ END"; _asm_tex_component_exponentiation_prog = GetGraphicsDisplay()->GetGpuDevice()->CreateAsmShaderProgram(); _asm_tex_component_exponentiation_prog->LoadVertexShader(AsmVtx); _asm_tex_component_exponentiation_prog->LoadPixelShader(AsmFrg); _asm_tex_component_exponentiation_prog->Link(); } void GraphicsEngine::QRP_ASM_Power (int x, int y, int width, int height, ObjectPtr device_texture, TexCoordXForm &texxform, const Color &c0, Vector4 exponent) { NUX_RETURN_IF_FALSE(_asm_tex_component_exponentiation_prog.IsValid()); NUX_RETURN_IF_FALSE(_asm_texrect_component_exponentiation_prog.IsValid()); QRP_Compute_Texture_Coord(width, height, device_texture, texxform); float fx = x, fy = y; float VtxBuffer[] = { fx, fy, 0.0f, 1.0f, texxform.u0, texxform.v0, 0, 1.0f, fx, fy + height, 0.0f, 1.0f, texxform.u0, texxform.v1, 0, 1.0f, fx + width, fy + height, 0.0f, 1.0f, texxform.u1, texxform.v1, 0, 1.0f, fx + width, fy, 0.0f, 1.0f, texxform.u1, texxform.v0, 0, 1.0f, }; CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); ObjectPtr shader_program = _asm_tex_component_exponentiation_prog; if (device_texture->Type().IsDerivedFromType(IOpenGLRectangleTexture::StaticObjectType)) { shader_program = _asm_texrect_component_exponentiation_prog; } shader_program->Begin(); SetTexture(GL_TEXTURE0, device_texture); CHECKGL(glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, c0.red, c0.green, c0.blue, c0.alpha)); CHECKGL(glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, exponent.x, exponent.y, exponent.z, exponent.w)); CHECKGL(glMatrixMode(GL_MODELVIEW)); CHECKGL(glLoadIdentity()); CHECKGL(glLoadMatrixf((FLOAT *) GetOpenGLModelViewMatrix().m)); CHECKGL(glMatrixMode(GL_PROJECTION)); CHECKGL(glLoadIdentity()); CHECKGL(glLoadMatrixf((FLOAT *) GetOpenGLProjectionMatrix().m)); int VertexLocation = VTXATTRIB_POSITION; int TextureCoord0Location = VTXATTRIB_TEXCOORD0; CHECKGL(glEnableVertexAttribArrayARB(VertexLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexLocation, 4, GL_FLOAT, GL_FALSE, 32, VtxBuffer)); if (TextureCoord0Location != -1) { CHECKGL(glEnableVertexAttribArrayARB(TextureCoord0Location)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord0Location, 4, GL_FLOAT, GL_FALSE, 32, VtxBuffer + 4)); } CHECKGL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); CHECKGL(glDisableVertexAttribArrayARB(VertexLocation)); if (TextureCoord0Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord0Location)); shader_program->End(); } void GraphicsEngine::InitAsmAlphaReplicate() { const char* AsmVtx = "!!ARBvp1.0 \n\ ATTRIB iPos = vertex.position; \n\ OUTPUT oPos = result.position; \n\ OUTPUT oTexCoord0 = result.texcoord[0]; \n\ # Transform the vertex to clip coordinates. \n\ DP4 oPos.x, state.matrix.mvp.row[0], vertex.position; \n\ DP4 oPos.y, state.matrix.mvp.row[1], vertex.position; \n\ DP4 oPos.z, state.matrix.mvp.row[2], vertex.position; \n\ DP4 oPos.w, state.matrix.mvp.row[3], vertex.position; \n\ MOV oTexCoord0, vertex.attrib[8]; \n\ END"; const char* AsmFrg = "!!ARBfp1.0 \n\ PARAM color0 = program.local[0]; \n\ TEMP tex0; \n\ TEX tex0, fragment.texcoord[0], texture[0], 2D; \n\ MUL result.color, color0, tex0.aaaa; \n\ END"; _asm_tex_alpha_replicate_prog = GetGraphicsDisplay()->GetGpuDevice()->CreateAsmShaderProgram(); _asm_tex_alpha_replicate_prog->LoadVertexShader(AsmVtx); _asm_tex_alpha_replicate_prog->LoadPixelShader(AsmFrg); _asm_tex_alpha_replicate_prog->Link(); } void GraphicsEngine::QRP_ASM_AlphaReplicate(int x, int y, int width, int height, ObjectPtr device_texture, TexCoordXForm &texxform, const Color &c0) { NUX_RETURN_IF_FALSE(_asm_tex_alpha_replicate_prog.IsValid()); NUX_RETURN_IF_FALSE(_asm_texrect_alpha_replicate_prog.IsValid()); QRP_Compute_Texture_Coord(width, height, device_texture, texxform); float fx = x, fy = y; float VtxBuffer[] = { fx, fy, 0.0f, 1.0f, texxform.u0, texxform.v0, 0, 1.0f, fx, fy + height, 0.0f, 1.0f, texxform.u0, texxform.v1, 0, 1.0f, fx + width, fy + height, 0.0f, 1.0f, texxform.u1, texxform.v1, 0, 1.0f, fx + width, fy, 0.0f, 1.0f, texxform.u1, texxform.v0, 0, 1.0f, }; CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); ObjectPtr shader_program = _asm_tex_alpha_replicate_prog; if (device_texture->Type().IsDerivedFromType(IOpenGLRectangleTexture::StaticObjectType)) { shader_program = _asm_texrect_alpha_replicate_prog; } shader_program->Begin(); SetTexture(GL_TEXTURE0, device_texture); CHECKGL(glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, c0.red, c0.green, c0.blue, c0.alpha)); CHECKGL(glMatrixMode(GL_MODELVIEW)); CHECKGL(glLoadIdentity()); CHECKGL(glLoadMatrixf((FLOAT *) GetOpenGLModelViewMatrix().m)); CHECKGL(glMatrixMode(GL_PROJECTION)); CHECKGL(glLoadIdentity()); CHECKGL(glLoadMatrixf((FLOAT *) GetOpenGLProjectionMatrix().m)); int VertexLocation = VTXATTRIB_POSITION; int TextureCoord0Location = VTXATTRIB_TEXCOORD0; CHECKGL(glEnableVertexAttribArrayARB(VertexLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexLocation, 4, GL_FLOAT, GL_FALSE, 32, VtxBuffer)); if (TextureCoord0Location != -1) { CHECKGL(glEnableVertexAttribArrayARB(TextureCoord0Location)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord0Location, 4, GL_FLOAT, GL_FALSE, 32, VtxBuffer + 4)); } CHECKGL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); CHECKGL(glDisableVertexAttribArrayARB(VertexLocation)); if (TextureCoord0Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord0Location)); shader_program->End(); } void GraphicsEngine::InitAsmColorMatrixFilter() { const char* AsmVtx = "!!ARBvp1.0 \n\ ATTRIB iPos = vertex.position; \n\ OUTPUT oPos = result.position; \n\ OUTPUT oTexCoord0 = result.texcoord[0]; \n\ # Transform the vertex to clip coordinates. \n\ DP4 oPos.x, state.matrix.mvp.row[0], vertex.position; \n\ DP4 oPos.y, state.matrix.mvp.row[1], vertex.position; \n\ DP4 oPos.z, state.matrix.mvp.row[2], vertex.position; \n\ DP4 oPos.w, state.matrix.mvp.row[3], vertex.position; \n\ MOV oTexCoord0, vertex.attrib[8]; \n\ END"; const char* AsmFrg = "!!ARBfp1.0 \n\ PARAM color0 = program.local[0]; \n\ PARAM CM0 = program.local[1]; \n\ PARAM CM1 = program.local[2]; \n\ PARAM CM2 = program.local[3]; \n\ PARAM CM3 = program.local[4]; \n\ PARAM offset = program.local[5]; \n\ TEMP tex0; \n\ TEMP final; \n\ TEX tex0, fragment.texcoord[0], texture[0], 2D; \n\ MAD final.r, tex0, CM0, offset.r; \n\ MAD final.g, tex0, CM1, offset.g; \n\ MAD final.b, tex0, CM2, offset.b; \n\ MAD final.a, tex0, CM3, offset.a; \n\ MUL result.color, color0, final; \n\ END"; const char* AsmFrgRect = "!!ARBfp1.0 \n\ PARAM color0 = program.local[0]; \n\ PARAM CM0 = program.local[1]; \n\ PARAM CM1 = program.local[2]; \n\ PARAM CM2 = program.local[3]; \n\ PARAM CM3 = program.local[4]; \n\ PARAM offset = program.local[5]; \n\ TEMP tex0; \n\ TEMP final; \n\ TEX tex0, fragment.texcoord[0], texture[0], 2D; \n\ MAD final.r, tex0, CM0, offset.r; \n\ MAD final.g, tex0, CM1, offset.g; \n\ MAD final.b, tex0, CM2, offset.b; \n\ MAD final.a, tex0, CM3, offset.a; \n\ MUL result.color, color0, final; \n\ END"; _asm_tex_color_matrix_filter_prog = GetGraphicsDisplay()->GetGpuDevice()->CreateAsmShaderProgram(); _asm_tex_color_matrix_filter_prog->LoadVertexShader(AsmVtx); _asm_tex_color_matrix_filter_prog->LoadPixelShader(AsmFrg); _asm_tex_color_matrix_filter_prog->Link(); _asm_texrect_color_matrix_filter_prog = GetGraphicsDisplay()->GetGpuDevice()->CreateAsmShaderProgram(); _asm_texrect_color_matrix_filter_prog->LoadVertexShader(AsmVtx); _asm_texrect_color_matrix_filter_prog->LoadPixelShader(AsmFrgRect); _asm_texrect_color_matrix_filter_prog->Link(); } void GraphicsEngine::QRP_ASM_ColorMatrix (int x, int y, int width, int height, ObjectPtr device_texture, TexCoordXForm &texxform, const Color &c0, Matrix4 color_matrix, Vector4 offset) { NUX_RETURN_IF_FALSE(_asm_tex_color_matrix_filter_prog.IsValid()); NUX_RETURN_IF_FALSE(_asm_texrect_color_matrix_filter_prog.IsValid()); QRP_Compute_Texture_Coord(width, height, device_texture, texxform); float fx = x, fy = y; float VtxBuffer[] = { fx, fy, 0.0f, 1.0f, texxform.u0, texxform.v0, 0, 1.0f, fx, fy + height, 0.0f, 1.0f, texxform.u0, texxform.v1, 0, 1.0f, fx + width, fy + height, 0.0f, 1.0f, texxform.u1, texxform.v1, 0, 1.0f, fx + width, fy, 0.0f, 1.0f, texxform.u1, texxform.v0, 0, 1.0f, }; CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); ObjectPtr shader_program = _asm_tex_color_matrix_filter_prog; if (device_texture->Type().IsDerivedFromType(IOpenGLRectangleTexture::StaticObjectType)) { shader_program = _asm_texrect_color_matrix_filter_prog; } shader_program->Begin(); SetTexture(GL_TEXTURE0, device_texture); CHECKGL(glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, c0.red, c0.green, c0.blue, c0.alpha)); CHECKGL(glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, color_matrix.m[0][0], color_matrix.m[0][1], color_matrix.m[0][2], color_matrix.m[0][3])); CHECKGL(glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 2, color_matrix.m[1][0], color_matrix.m[1][1], color_matrix.m[1][2], color_matrix.m[1][3])); CHECKGL(glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 3, color_matrix.m[2][0], color_matrix.m[2][1], color_matrix.m[2][2], color_matrix.m[2][3])); CHECKGL(glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 4, color_matrix.m[3][0], color_matrix.m[3][1], color_matrix.m[3][2], color_matrix.m[3][3])); CHECKGL(glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 5, offset.x, offset.y, offset.z, offset.w)); CHECKGL(glMatrixMode(GL_MODELVIEW)); CHECKGL(glLoadIdentity()); CHECKGL(glLoadMatrixf((FLOAT *) GetOpenGLModelViewMatrix().m)); CHECKGL(glMatrixMode(GL_PROJECTION)); CHECKGL(glLoadIdentity()); CHECKGL(glLoadMatrixf((FLOAT *) GetOpenGLProjectionMatrix().m)); int VertexLocation = VTXATTRIB_POSITION; int TextureCoord0Location = VTXATTRIB_TEXCOORD0; CHECKGL(glEnableVertexAttribArrayARB(VertexLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexLocation, 4, GL_FLOAT, GL_FALSE, 32, VtxBuffer)); if (TextureCoord0Location != -1) { CHECKGL(glEnableVertexAttribArrayARB(TextureCoord0Location)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord0Location, 4, GL_FLOAT, GL_FALSE, 32, VtxBuffer + 4)); } CHECKGL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); CHECKGL(glDisableVertexAttribArrayARB(VertexLocation)); if (TextureCoord0Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord0Location)); shader_program->End(); } void GraphicsEngine::InitAsmSeparableGaussFilter() { const char* AsmVtx = "!!ARBvp1.0 \n\ ATTRIB iPos = vertex.position; \n\ OUTPUT oPos = result.position; \n\ OUTPUT oTexCoord0 = result.texcoord[0]; \n\ OUTPUT oTexCoord1 = result.texcoord[1]; \n\ OUTPUT oTexCoord2 = result.texcoord[2]; \n\ OUTPUT oTexCoord3 = result.texcoord[3]; \n\ OUTPUT oTexCoord4 = result.texcoord[4]; \n\ OUTPUT oTexCoord5 = result.texcoord[5]; \n\ OUTPUT oTexCoord6 = result.texcoord[6]; \n\ # Transform the vertex to clip coordinates. \n\ DP4 oPos.x, state.matrix.mvp.row[0], vertex.position; \n\ DP4 oPos.y, state.matrix.mvp.row[1], vertex.position; \n\ DP4 oPos.z, state.matrix.mvp.row[2], vertex.position; \n\ DP4 oPos.w, state.matrix.mvp.row[3], vertex.position; \n\ MOV oTexCoord0, vertex.attrib[8]; \n\ MOV oTexCoord1, vertex.attrib[9]; \n\ MOV oTexCoord2, vertex.attrib[10]; \n\ MOV oTexCoord3, vertex.attrib[11]; \n\ MOV oTexCoord4, vertex.attrib[12]; \n\ MOV oTexCoord5, vertex.attrib[13]; \n\ MOV oTexCoord6, vertex.attrib[14]; \n\ END"; const char* AsmFrg = "!!ARBfp1.0 \n\ TEMP tex0; \n\ TEMP final; \n\ MOV final, {0, 0, 0, 0}; \n\ TEX tex0, fragment.texcoord[0], texture[0], 2D; \n\ MAD final, tex0, program.local[0], final; \n\ TEX tex0, fragment.texcoord[1], texture[0], 2D; \n\ MAD final, tex0, program.local[1], final; \n\ TEX tex0, fragment.texcoord[2], texture[0], 2D; \n\ MAD final, tex0, program.local[2], final; \n\ TEX tex0, fragment.texcoord[3], texture[0], 2D; \n\ MAD final, tex0, program.local[3], final; \n\ TEX tex0, fragment.texcoord[4], texture[0], 2D; \n\ MAD final, tex0, program.local[4], final; \n\ TEX tex0, fragment.texcoord[5], texture[0], 2D; \n\ MAD final, tex0, program.local[5], final; \n\ TEX tex0, fragment.texcoord[6], texture[0], 2D; \n\ MAD final, tex0, program.local[6], final; \n\ MOV result.color, final; \n\ END"; const char* AsmFrgRect = "!!ARBfp1.0 \n\ TEMP tex0; \n\ TEMP final; \n\ MOV final, {0, 0, 0, 0}; \n\ TEX tex0, fragment.texcoord[0], texture[0], RECT; \n\ MAD final, tex0, program.local[0], final; \n\ TEX tex0, fragment.texcoord[1], texture[0], RECT; \n\ MAD final, tex0, program.local[1], final; \n\ TEX tex0, fragment.texcoord[2], texture[0], RECT; \n\ MAD final, tex0, program.local[2], final; \n\ TEX tex0, fragment.texcoord[3], texture[0], RECT; \n\ MAD final, tex0, program.local[3], final; \n\ TEX tex0, fragment.texcoord[4], texture[0], RECT; \n\ MAD final, tex0, program.local[4], final; \n\ TEX tex0, fragment.texcoord[5], texture[0], RECT; \n\ MAD final, tex0, program.local[5], final; \n\ TEX tex0, fragment.texcoord[6], texture[0], RECT; \n\ MAD final, tex0, program.local[6], final; \n\ MOV result.color, final; \n\ END"; _asm_tex_separable_gauss_filter_prog = GetGraphicsDisplay()->GetGpuDevice()->CreateAsmShaderProgram(); _asm_tex_separable_gauss_filter_prog->LoadVertexShader(AsmVtx); _asm_tex_separable_gauss_filter_prog->LoadPixelShader(AsmFrg); _asm_tex_separable_gauss_filter_prog->Link(); _asm_texrect_separable_gauss_filter_prog = GetGraphicsDisplay()->GetGpuDevice()->CreateAsmShaderProgram(); _asm_texrect_separable_gauss_filter_prog->LoadVertexShader(AsmVtx); _asm_texrect_separable_gauss_filter_prog->LoadPixelShader(AsmFrgRect); _asm_texrect_separable_gauss_filter_prog->Link(); } void GraphicsEngine::QRP_ASM_HorizontalGauss(int x, int y, int width, int height, ObjectPtr device_texture, TexCoordXForm &texxform, const Color & /* c0 */, float /* sigma */) { NUX_RETURN_IF_FALSE(_asm_tex_separable_gauss_filter_prog.IsValid()); NUX_RETURN_IF_FALSE(_asm_texrect_separable_gauss_filter_prog.IsValid()); QRP_Compute_Texture_Coord(width, height, device_texture, texxform); float delta = 1.0f / device_texture->GetWidth(); float fx = x, fy = y; float VtxBuffer[] = { fx, fy, 0.0f, 1.0f, texxform.u0 - 3.0f * delta, texxform.v0, 0, 1.0f, texxform.u0 - 2.0f * delta, texxform.v0, 0, 1.0f, texxform.u0 - 1.0f * delta, texxform.v0, 0, 1.0f, texxform.u0 + 0.0f * delta, texxform.v0, 0, 1.0f, texxform.u0 + 1.0f * delta, texxform.v0, 0, 1.0f, texxform.u0 + 2.0f * delta, texxform.v0, 0, 1.0f, texxform.u0 + 3.0f * delta, texxform.v0, 0, 1.0f, fx, fy + height, 0.0f, 1.0f, texxform.u0 - 3.0f * delta, texxform.v1, 0, 1.0f, texxform.u0 - 2.0f * delta, texxform.v1, 0, 1.0f, texxform.u0 - 1.0f * delta, texxform.v1, 0, 1.0f, texxform.u0 + 0.0f * delta, texxform.v1, 0, 1.0f, texxform.u0 + 1.0f * delta, texxform.v1, 0, 1.0f, texxform.u0 + 2.0f * delta, texxform.v1, 0, 1.0f, texxform.u0 + 3.0f * delta, texxform.v1, 0, 1.0f, fx + width, fy + height, 0.0f, 1.0f, texxform.u1 - 3.0f * delta, texxform.v1, 0, 1.0f, texxform.u1 - 2.0f * delta, texxform.v1, 0, 1.0f, texxform.u1 - 1.0f * delta, texxform.v1, 0, 1.0f, texxform.u1 + 0.0f * delta, texxform.v1, 0, 1.0f, texxform.u1 + 1.0f * delta, texxform.v1, 0, 1.0f, texxform.u1 + 2.0f * delta, texxform.v1, 0, 1.0f, texxform.u1 + 3.0f * delta, texxform.v1, 0, 1.0f, fx + width, fy, 0.0f, 1.0f, texxform.u1 - 3.0f * delta, texxform.v0, 0, 1.0f, texxform.u1 - 2.0f * delta, texxform.v0, 0, 1.0f, texxform.u1 - 1.0f * delta, texxform.v0, 0, 1.0f, texxform.u1 + 0.0f * delta, texxform.v0, 0, 1.0f, texxform.u1 + 1.0f * delta, texxform.v0, 0, 1.0f, texxform.u1 + 2.0f * delta, texxform.v0, 0, 1.0f, texxform.u1 + 3.0f * delta, texxform.v0, 0, 1.0f, }; CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); ObjectPtr shader_program = _asm_tex_separable_gauss_filter_prog; if (device_texture->Type().IsDerivedFromType(IOpenGLRectangleTexture::StaticObjectType)) { shader_program = _asm_texrect_separable_gauss_filter_prog; } shader_program->Begin(); SetTexture(GL_TEXTURE0, device_texture); // Set the Gaussian weights { float *W; GaussianWeights(&W, 1, 7); for (int i = 0; i < 7; i++) { CHECKGL(glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, i, W[i], W[i], W[i], W[i])); } delete[] W; } CHECKGL(glMatrixMode(GL_MODELVIEW)); CHECKGL(glLoadIdentity()); CHECKGL(glLoadMatrixf((FLOAT *) GetOpenGLModelViewMatrix().m)); CHECKGL(glMatrixMode(GL_PROJECTION)); CHECKGL(glLoadIdentity()); CHECKGL(glLoadMatrixf((FLOAT *) GetOpenGLProjectionMatrix().m)); int VertexLocation = VTXATTRIB_POSITION; int TextureCoord0Location = VTXATTRIB_TEXCOORD0; int TextureCoord1Location = VTXATTRIB_TEXCOORD1; int TextureCoord2Location = VTXATTRIB_TEXCOORD2; int TextureCoord3Location = VTXATTRIB_TEXCOORD3; int TextureCoord4Location = VTXATTRIB_TEXCOORD4; int TextureCoord5Location = VTXATTRIB_TEXCOORD5; int TextureCoord6Location = VTXATTRIB_TEXCOORD6; CHECKGL(glEnableVertexAttribArrayARB(VertexLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexLocation, 4, GL_FLOAT, GL_FALSE, 128, VtxBuffer)); //if(TextureCoord0Location != -1) { CHECKGL(glEnableVertexAttribArrayARB(TextureCoord0Location)); CHECKGL(glEnableVertexAttribArrayARB(TextureCoord1Location)); CHECKGL(glEnableVertexAttribArrayARB(TextureCoord2Location)); CHECKGL(glEnableVertexAttribArrayARB(TextureCoord3Location)); CHECKGL(glEnableVertexAttribArrayARB(TextureCoord4Location)); CHECKGL(glEnableVertexAttribArrayARB(TextureCoord5Location)); CHECKGL(glEnableVertexAttribArrayARB(TextureCoord6Location)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord0Location, 4, GL_FLOAT, GL_FALSE, 128, VtxBuffer + 4)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord1Location, 4, GL_FLOAT, GL_FALSE, 128, VtxBuffer + 8)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord2Location, 4, GL_FLOAT, GL_FALSE, 128, VtxBuffer + 12)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord3Location, 4, GL_FLOAT, GL_FALSE, 128, VtxBuffer + 16)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord4Location, 4, GL_FLOAT, GL_FALSE, 128, VtxBuffer + 20)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord5Location, 4, GL_FLOAT, GL_FALSE, 128, VtxBuffer + 24)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord6Location, 4, GL_FLOAT, GL_FALSE, 128, VtxBuffer + 28)); } CHECKGL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); CHECKGL(glDisableVertexAttribArrayARB(VertexLocation)); if (TextureCoord0Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord0Location)); if (TextureCoord1Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord1Location)); if (TextureCoord2Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord2Location)); if (TextureCoord3Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord3Location)); if (TextureCoord4Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord4Location)); if (TextureCoord5Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord5Location)); if (TextureCoord6Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord6Location)); shader_program->End(); } void GraphicsEngine::QRP_ASM_VerticalGauss(int x, int y, int width, int height, ObjectPtr device_texture, TexCoordXForm &texxform, const Color & /* c0 */, float /* sigma */) { NUX_RETURN_IF_FALSE(_asm_tex_separable_gauss_filter_prog.IsValid()); NUX_RETURN_IF_FALSE(_asm_texrect_separable_gauss_filter_prog.IsValid()); QRP_Compute_Texture_Coord(width, height, device_texture, texxform); float delta = 1.0f / device_texture->GetHeight(); float fx = x, fy = y; float VtxBuffer[] = { fx, fy, 0.0f, 1.0f, texxform.u0, texxform.v0 - 3.0f * delta, 0, 1.0f, texxform.u0, texxform.v0 - 2.0f * delta, 0, 1.0f, texxform.u0, texxform.v0 - 1.0f * delta, 0, 1.0f, texxform.u0, texxform.v0 + 0.0f * delta, 0, 1.0f, texxform.u0, texxform.v0 + 1.0f * delta, 0, 1.0f, texxform.u0, texxform.v0 + 2.0f * delta, 0, 1.0f, texxform.u0, texxform.v0 + 3.0f * delta, 0, 1.0f, fx, fy + height, 0.0f, 1.0f, texxform.u0, texxform.v1 - 3.0f * delta, 0, 1.0f, texxform.u0, texxform.v1 - 2.0f * delta, 0, 1.0f, texxform.u0, texxform.v1 - 1.0f * delta, 0, 1.0f, texxform.u0, texxform.v1 + 0.0f * delta, 0, 1.0f, texxform.u0, texxform.v1 + 1.0f * delta, 0, 1.0f, texxform.u0, texxform.v1 + 2.0f * delta, 0, 1.0f, texxform.u0, texxform.v1 + 3.0f * delta, 0, 1.0f, fx + width, fy + height, 0.0f, 1.0f, texxform.u1, texxform.v1 - 3.0f * delta, 0, 1.0f, texxform.u1, texxform.v1 - 2.0f * delta, 0, 1.0f, texxform.u1, texxform.v1 - 1.0f * delta, 0, 1.0f, texxform.u1, texxform.v1 + 0.0f * delta, 0, 1.0f, texxform.u1, texxform.v1 + 1.0f * delta, 0, 1.0f, texxform.u1, texxform.v1 + 2.0f * delta, 0, 1.0f, texxform.u1, texxform.v1 + 3.0f * delta, 0, 1.0f, fx + width, fy, 0.0f, 1.0f, texxform.u1, texxform.v0 - 3.0f * delta, 0, 1.0f, texxform.u1, texxform.v0 - 2.0f * delta, 0, 1.0f, texxform.u1, texxform.v0 - 1.0f * delta, 0, 1.0f, texxform.u1, texxform.v0 + 0.0f * delta, 0, 1.0f, texxform.u1, texxform.v0 + 1.0f * delta, 0, 1.0f, texxform.u1, texxform.v0 + 2.0f * delta, 0, 1.0f, texxform.u1, texxform.v0 + 3.0f * delta, 0, 1.0f, }; CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); ObjectPtr shader_program = _asm_tex_separable_gauss_filter_prog; if (device_texture->Type().IsDerivedFromType(IOpenGLRectangleTexture::StaticObjectType)) { shader_program = _asm_texrect_separable_gauss_filter_prog; } shader_program->Begin(); SetTexture(GL_TEXTURE0, device_texture); // Set the Gaussian weights { float *W; GaussianWeights(&W, 1, 7); for (int i = 0; i < 7; i++) { CHECKGL(glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, i, W[i], W[i], W[i], W[i])); } delete[] W; } CHECKGL(glMatrixMode(GL_MODELVIEW)); CHECKGL(glLoadIdentity()); CHECKGL(glLoadMatrixf((FLOAT *) GetOpenGLModelViewMatrix().m)); CHECKGL(glMatrixMode(GL_PROJECTION)); CHECKGL(glLoadIdentity()); CHECKGL(glLoadMatrixf((FLOAT *) GetOpenGLProjectionMatrix().m)); int VertexLocation = VTXATTRIB_POSITION; int TextureCoord0Location = VTXATTRIB_TEXCOORD0; int TextureCoord1Location = VTXATTRIB_TEXCOORD1; int TextureCoord2Location = VTXATTRIB_TEXCOORD2; int TextureCoord3Location = VTXATTRIB_TEXCOORD3; int TextureCoord4Location = VTXATTRIB_TEXCOORD4; int TextureCoord5Location = VTXATTRIB_TEXCOORD5; int TextureCoord6Location = VTXATTRIB_TEXCOORD6; CHECKGL(glEnableVertexAttribArrayARB(VertexLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexLocation, 4, GL_FLOAT, GL_FALSE, 128, VtxBuffer)); //if(TextureCoord0Location != -1) { CHECKGL(glEnableVertexAttribArrayARB(TextureCoord0Location)); CHECKGL(glEnableVertexAttribArrayARB(TextureCoord1Location)); CHECKGL(glEnableVertexAttribArrayARB(TextureCoord2Location)); CHECKGL(glEnableVertexAttribArrayARB(TextureCoord3Location)); CHECKGL(glEnableVertexAttribArrayARB(TextureCoord4Location)); CHECKGL(glEnableVertexAttribArrayARB(TextureCoord5Location)); CHECKGL(glEnableVertexAttribArrayARB(TextureCoord6Location)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord0Location, 4, GL_FLOAT, GL_FALSE, 128, VtxBuffer + 4)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord1Location, 4, GL_FLOAT, GL_FALSE, 128, VtxBuffer + 8)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord2Location, 4, GL_FLOAT, GL_FALSE, 128, VtxBuffer + 12)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord3Location, 4, GL_FLOAT, GL_FALSE, 128, VtxBuffer + 16)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord4Location, 4, GL_FLOAT, GL_FALSE, 128, VtxBuffer + 20)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord5Location, 4, GL_FLOAT, GL_FALSE, 128, VtxBuffer + 24)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord6Location, 4, GL_FLOAT, GL_FALSE, 128, VtxBuffer + 28)); } CHECKGL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); CHECKGL(glDisableVertexAttribArrayARB(VertexLocation)); if (TextureCoord0Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord0Location)); if (TextureCoord1Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord1Location)); if (TextureCoord2Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord2Location)); if (TextureCoord3Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord3Location)); if (TextureCoord4Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord4Location)); if (TextureCoord5Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord5Location)); if (TextureCoord6Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord6Location)); shader_program->End(); } ObjectPtr GraphicsEngine::QRP_ASM_GetBlurTexture( int x, int y, int buffer_width, int buffer_height, ObjectPtr device_texture, TexCoordXForm &texxform, const Color& c0, float /* sigma */, int num_pass) { // _offscreen_color_rt0.Release(); // _offscreen_color_rt1.Release(); // _offscreen_depth_rt0.Release(); // _offscreen_depth_rt1.Release(); int quad_width = device_texture->GetWidth(); int quad_height = device_texture->GetHeight(); num_pass = Clamp (num_pass, 1, 5); ObjectPtr prevFBO = GetGraphicsDisplay()->GetGpuDevice()->GetCurrentFrameBufferObject(); int previous_width = 0; int previous_height = 0; if (prevFBO.IsValid()) { previous_width = prevFBO->GetWidth(); previous_height = prevFBO->GetHeight(); } else { previous_width = _graphics_display.GetWindowWidth(); previous_height = _graphics_display.GetWindowHeight(); } CHECKGL(glClearColor(0, 0, 0, 0)); _offscreen_color_rt0->SetWrap(GL_CLAMP, GL_CLAMP, GL_CLAMP); _offscreen_color_rt0->SetFiltering(GL_NEAREST, GL_NEAREST); _offscreen_color_rt1->SetWrap(GL_CLAMP, GL_CLAMP, GL_CLAMP); _offscreen_color_rt1->SetFiltering(GL_NEAREST, GL_NEAREST); SetFrameBufferHelper(_offscreen_fbo, _offscreen_color_rt0, _offscreen_depth_rt0, buffer_width, buffer_height); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); QRP_ASM_1Tex(x, y, quad_width, quad_height, device_texture, texxform, color::White); TexCoordXForm texxform1; for (int i = 0; i < num_pass; i++) { SetFrameBufferHelper(_offscreen_fbo, _offscreen_color_rt1, _offscreen_depth_rt1, buffer_width, buffer_height); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); QRP_ASM_HorizontalGauss(0, 0, buffer_width, buffer_height, _offscreen_color_rt0, texxform1, c0); SetFrameBufferHelper(_offscreen_fbo, _offscreen_color_rt0, _offscreen_depth_rt0, buffer_width, buffer_height); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); QRP_ASM_VerticalGauss(0, 0, buffer_width, buffer_height, _offscreen_color_rt1, texxform1, c0); } _offscreen_fbo->Deactivate(); if (prevFBO.IsValid()) { prevFBO->Activate(true); SetViewport(0, 0, previous_width, previous_height); } else { SetViewport(0, 0, previous_width, previous_height); } SetOrthographicProjectionMatrix(previous_width, previous_height); return _offscreen_color_rt0; } void GraphicsEngine::QRP_ASM_GetBlurTextureFx( int x, int y, int buffer_width, int buffer_height, FxStructure *fx_structure, TexCoordXForm &texxform, const Color& color, float /* sigma */, int num_pass) { int quad_width = fx_structure->src_texture->GetWidth(); int quad_height = fx_structure->src_texture->GetHeight(); num_pass = Clamp (num_pass, 1, 5); ObjectPtr prevFBO = GetGraphicsDisplay()->GetGpuDevice()->GetCurrentFrameBufferObject(); int previous_width = 0; int previous_height = 0; if (prevFBO.IsValid()) { previous_width = prevFBO->GetWidth(); previous_height = prevFBO->GetHeight(); } else { previous_width = _graphics_display.GetWindowWidth(); previous_height = _graphics_display.GetWindowHeight(); } CHECKGL(glClearColor(0, 0, 0, 0)); fx_structure->src_texture->SetWrap(GL_CLAMP, GL_CLAMP, GL_CLAMP); fx_structure->src_texture->SetFiltering(GL_NEAREST, GL_NEAREST); fx_structure->dst_texture->SetWrap(GL_CLAMP, GL_CLAMP, GL_CLAMP); fx_structure->dst_texture->SetFiltering(GL_NEAREST, GL_NEAREST); fx_structure->temp_texture->SetWrap(GL_CLAMP, GL_CLAMP, GL_CLAMP); fx_structure->temp_texture->SetFiltering(GL_NEAREST, GL_NEAREST); SetFrameBufferHelper(_offscreen_fbo, fx_structure->dst_texture, _offscreen_depth_rt0, buffer_width, buffer_height); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); QRP_ASM_1Tex(x, y, quad_width, quad_height, fx_structure->src_texture, texxform, color::White); TexCoordXForm texxform1; for (int i = 0; i < num_pass; i++) { SetFrameBufferHelper(_offscreen_fbo, fx_structure->temp_texture, _offscreen_depth_rt1, buffer_width, buffer_height); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); QRP_ASM_HorizontalGauss(0, 0, buffer_width, buffer_height, fx_structure->dst_texture, texxform1, color); SetFrameBufferHelper(_offscreen_fbo, fx_structure->dst_texture, _offscreen_depth_rt0, buffer_width, buffer_height); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); QRP_ASM_VerticalGauss(0, 0, buffer_width, buffer_height, fx_structure->temp_texture, texxform1, color); } _offscreen_fbo->Deactivate(); if (prevFBO.IsValid()) { prevFBO->Activate(true); SetViewport(0, 0, previous_width, previous_height); } else { SetViewport(0, 0, previous_width, previous_height); } } ObjectPtr GraphicsEngine::QRP_ASM_GetPower( ObjectPtr device_texture, TexCoordXForm &texxform, const Color & c0, const Vector4 &exponent) { int quad_width = device_texture->GetWidth(); int quad_height = device_texture->GetHeight(); ObjectPtr prevFBO = GetGraphicsDisplay()->GetGpuDevice()->GetCurrentFrameBufferObject(); int previous_width = 0; int previous_height = 0; if (prevFBO.IsValid()) { previous_width = prevFBO->GetWidth(); previous_height = prevFBO->GetHeight(); } else { previous_width = _graphics_display.GetWindowWidth(); previous_height = _graphics_display.GetWindowHeight(); } CHECKGL(glClearColor(0, 0, 0, 0)); _offscreen_color_rt0->SetWrap(GL_CLAMP, GL_CLAMP, GL_CLAMP); _offscreen_color_rt0->SetFiltering(GL_NEAREST, GL_NEAREST); _offscreen_color_rt1->SetWrap(GL_CLAMP, GL_CLAMP, GL_CLAMP); _offscreen_color_rt1->SetFiltering(GL_NEAREST, GL_NEAREST); SetFrameBufferHelper(_offscreen_fbo, _offscreen_color_rt0, _offscreen_depth_rt0, quad_width, quad_height); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); QRP_ASM_1Tex(0, 0, quad_width, quad_height, device_texture, texxform, color::White); SetFrameBufferHelper(_offscreen_fbo, _offscreen_color_rt1, _offscreen_depth_rt1, quad_width, quad_height); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); QRP_ASM_Power(0, 0, quad_width, quad_height, _offscreen_color_rt0, texxform, c0, exponent); _offscreen_fbo->Deactivate(); if (prevFBO.IsValid()) { prevFBO->Activate(true); SetViewport(0, 0, previous_width, previous_height); } else { SetViewport(0, 0, previous_width, previous_height); } return _offscreen_color_rt1; } ObjectPtr GraphicsEngine::QRP_ASM_GetAlphaTexture( ObjectPtr device_texture, TexCoordXForm &texxform, const Color & c0) { // _offscreen_color_rt0.Release(); // _offscreen_color_rt1.Release(); // _offscreen_depth_rt0.Release(); // _offscreen_depth_rt1.Release(); int quad_width = device_texture->GetWidth(); int quad_height = device_texture->GetHeight(); ObjectPtr prevFBO = GetGraphicsDisplay()->GetGpuDevice()->GetCurrentFrameBufferObject(); int previous_width = 0; int previous_height = 0; if (prevFBO.IsValid()) { previous_width = prevFBO->GetWidth(); previous_height = prevFBO->GetHeight(); } else { previous_width = _graphics_display.GetWindowWidth(); previous_height = _graphics_display.GetWindowHeight(); } CHECKGL(glClearColor(0, 0, 0, 0)); _offscreen_color_rt0->SetWrap(GL_CLAMP, GL_CLAMP, GL_CLAMP); _offscreen_color_rt0->SetFiltering(GL_NEAREST, GL_NEAREST); _offscreen_color_rt1->SetWrap(GL_CLAMP, GL_CLAMP, GL_CLAMP); _offscreen_color_rt1->SetFiltering(GL_NEAREST, GL_NEAREST); SetFrameBufferHelper(_offscreen_fbo, _offscreen_color_rt0, _offscreen_depth_rt0, quad_width, quad_height); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); QRP_ASM_1Tex(0, 0, quad_width, quad_height, device_texture, texxform, color::White); SetFrameBufferHelper(_offscreen_fbo, _offscreen_color_rt1, _offscreen_depth_rt1, quad_width, quad_height); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); QRP_ASM_AlphaReplicate(0, 0, quad_width, quad_height, _offscreen_color_rt0, texxform, c0); _offscreen_fbo->Deactivate(); if (prevFBO.IsValid()) { prevFBO->Activate(true); SetViewport(0, 0, previous_width, previous_height); } else { SetViewport(0, 0, previous_width, previous_height); } return _offscreen_color_rt1; } ObjectPtr GraphicsEngine::QRP_ASM_GetColorMatrixTexture( ObjectPtr device_texture, TexCoordXForm &texxform, const Color & c0, Matrix4 color_matrix, Vector4 offset) { int quad_width = device_texture->GetWidth(); int quad_height = device_texture->GetHeight(); ObjectPtr prevFBO = GetGraphicsDisplay()->GetGpuDevice()->GetCurrentFrameBufferObject(); int previous_width = 0; int previous_height = 0; if (prevFBO.IsValid()) { previous_width = prevFBO->GetWidth(); previous_height = prevFBO->GetHeight(); } else { previous_width = _graphics_display.GetWindowWidth(); previous_height = _graphics_display.GetWindowHeight(); } CHECKGL(glClearColor(0, 0, 0, 0)); _offscreen_color_rt0->SetWrap(GL_CLAMP, GL_CLAMP, GL_CLAMP); _offscreen_color_rt0->SetFiltering(GL_NEAREST, GL_NEAREST); _offscreen_color_rt1->SetWrap(GL_CLAMP, GL_CLAMP, GL_CLAMP); _offscreen_color_rt1->SetFiltering(GL_NEAREST, GL_NEAREST); SetFrameBufferHelper(_offscreen_fbo, _offscreen_color_rt0, _offscreen_depth_rt0, quad_width, quad_height); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); QRP_ASM_1Tex(0, 0, quad_width, quad_height, device_texture, texxform, color::White); SetFrameBufferHelper(_offscreen_fbo, _offscreen_color_rt1, _offscreen_depth_rt1, quad_width, quad_height); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); QRP_ASM_ColorMatrix(0, 0, quad_width, quad_height, _offscreen_color_rt0, texxform, c0, color_matrix, offset); _offscreen_fbo->Deactivate(); if (prevFBO.IsValid()) { prevFBO->Activate(true); SetViewport(0, 0, previous_width, previous_height); } else { SetViewport(0, 0, previous_width, previous_height); } return _offscreen_color_rt1; } ObjectPtr GraphicsEngine::QRP_ASM_GetLQBlur( int /* x */, int /* y */, int /* buffer_width */, int /* buffer_height */, ObjectPtr device_texture, TexCoordXForm &texxform, const Color& /* c0 */) { // _offscreen_color_rt0.Release(); // _offscreen_color_rt1.Release(); // _offscreen_depth_rt0.Release(); // _offscreen_depth_rt1.Release(); int quad_width = device_texture->GetWidth(); int quad_height = device_texture->GetHeight(); ObjectPtr prevFBO = GetGraphicsDisplay()->GetGpuDevice()->GetCurrentFrameBufferObject(); int previous_width = 0; int previous_height = 0; if (prevFBO.IsValid()) { previous_width = prevFBO->GetWidth(); previous_height = prevFBO->GetHeight(); } else { previous_width = _graphics_display.GetWindowWidth(); previous_height = _graphics_display.GetWindowHeight(); } CHECKGL(glClearColor(0, 0, 0, 0)); _offscreen_color_rt0->SetWrap(GL_CLAMP, GL_CLAMP, GL_CLAMP); _offscreen_color_rt0->SetFiltering(GL_NEAREST, GL_NEAREST); _offscreen_color_rt1->SetWrap(GL_CLAMP, GL_CLAMP, GL_CLAMP); _offscreen_color_rt1->SetFiltering(GL_NEAREST, GL_NEAREST); _offscreen_color_rt2->SetWrap(GL_CLAMP, GL_CLAMP, GL_CLAMP); _offscreen_color_rt2->SetFiltering(GL_NEAREST, GL_NEAREST); _offscreen_color_rt3->SetWrap(GL_CLAMP, GL_CLAMP, GL_CLAMP); _offscreen_color_rt3->SetFiltering(GL_NEAREST, GL_NEAREST); SetFrameBufferHelper(_offscreen_fbo, _offscreen_color_rt0, _offscreen_depth_rt0, quad_width/2, quad_height/2); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); QRP_ASM_1Tex(0, 0, quad_width / 2, quad_height / 2, device_texture, texxform, color::White); SetFrameBufferHelper(_offscreen_fbo, _offscreen_color_rt1, _offscreen_depth_rt1, quad_width/4, quad_height/4); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); QRP_ASM_1Tex(0, 0, quad_width / 4, quad_height / 4, _offscreen_color_rt0, texxform, color::White); SetFrameBufferHelper(_offscreen_fbo, _offscreen_color_rt2, _offscreen_depth_rt2, quad_width/8, quad_height/8); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); QRP_ASM_1Tex(0, 0, quad_width / 8, quad_height / 8, _offscreen_color_rt1, texxform, color::White); SetFrameBufferHelper(_offscreen_fbo, _offscreen_color_rt3, _offscreen_depth_rt3, quad_width, quad_height); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); TexCoordXForm texxform0; TexCoordXForm texxform1; TexCoordXForm texxform2; TexCoordXForm texxform3; texxform0.flip_v_coord = true; texxform2.flip_v_coord = true; QRP_ASM_4Tex(0, 0, quad_width, quad_height, device_texture, texxform0, Color(0.25, 0.25, 0.25, 0.25), _offscreen_color_rt0, texxform1, Color(0.25, 0.25, 0.25, 0.25), _offscreen_color_rt1, texxform2, Color(0.25, 0.25, 0.25, 0.25), _offscreen_color_rt2, texxform3, Color(0.25, 0.25, 0.25, 0.25)); _offscreen_fbo->Deactivate(); if (prevFBO.IsValid()) { prevFBO->Activate(true); SetViewport(0, 0, previous_width, previous_height); } else { SetViewport(0, 0, previous_width, previous_height); } return _offscreen_color_rt3; } void GraphicsEngine::InitAsmPixelateShader() { const char* AsmVtx = "!!ARBvp1.0 \n\ ATTRIB iPos = vertex.position; \n\ ATTRIB iColor = vertex.attrib[3]; \n\ PARAM mvp[4] = {state.matrix.mvp}; \n\ OUTPUT oPos = result.position; \n\ OUTPUT oColor = result.color; \n\ OUTPUT oTexCoord0 = result.texcoord[0]; \n\ # Transform the vertex to clip coordinates. \n\ DP4 oPos.x, mvp[0], iPos; \n\ DP4 oPos.y, mvp[1], iPos; \n\ DP4 oPos.z, mvp[2], iPos; \n\ DP4 oPos.w, mvp[3], iPos; \n\ MOV oColor, iColor; \n\ MOV oTexCoord0, vertex.attrib[8]; \n\ END"; const char* AsmFrg = "!!ARBfp1.0 \n\ TEMP tex0; \n\ TEMP tex_coord; \n\ PARAM pixel_size = program.local [0]; \n\ PARAM pixel_size_inv = program.local [1]; \n\ MUL tex_coord, fragment.texcoord[0], pixel_size_inv; \n\ FLR tex_coord, tex_coord; \n\ MUL tex_coord, tex_coord, pixel_size; \n\ TEX tex0, tex_coord, texture[0], 2D; \n\ MUL result.color, fragment.color, tex0; \n\ END"; const char* AsmFrgRect = "!!ARBfp1.0 \n\ TEMP tex0; \n\ TEMP tex_coord; \n\ PARAM pixel_size = program.local [0]; \n\ PARAM pixel_size_inv = program.local [1]; \n\ MUL tex_coord, fragment.texcoord[0], pixel_size_inv; \n\ FLR tex_coord, tex_coord; \n\ MUL tex_coord, tex_coord, pixel_size; \n\ TEX tex0, tex_coord, texture[0], RECT; \n\ MUL result.color, fragment.color, tex0; \n\ END"; m_AsmPixelate = GetGraphicsDisplay()->GetGpuDevice()->CreateAsmShaderProgram(); m_AsmPixelate->LoadVertexShader(AsmVtx); m_AsmPixelate->LoadPixelShader(AsmFrg); m_AsmPixelate->Link(); m_AsmPixelateRect = GetGraphicsDisplay()->GetGpuDevice()->CreateAsmShaderProgram(); m_AsmPixelateRect->LoadVertexShader(AsmVtx); m_AsmPixelateRect->LoadPixelShader(AsmFrgRect); m_AsmPixelateRect->Link(); } void GraphicsEngine::QRP_ASM_Pixelate(int x, int y, int width, int height, ObjectPtr device_texture, TexCoordXForm &texxform, const Color &color, int pixel_size) { NUX_RETURN_IF_FALSE(m_AsmPixelate.IsValid()); NUX_RETURN_IF_FALSE(m_AsmPixelateRect.IsValid()); if (pixel_size <= 0) pixel_size = 1; QRP_Compute_Texture_Coord(width, height, device_texture, texxform); float fx = x, fy = y; float VtxBuffer[] = { fx, fy, 0.0f, 1.0f, texxform.u0, texxform.v0, 0, 1.0f, color.red, color.green, color.blue, color.alpha, fx, fy + height, 0.0f, 1.0f, texxform.u0, texxform.v1, 0, 1.0f, color.red, color.green, color.blue, color.alpha, fx + width, fy + height, 0.0f, 1.0f, texxform.u1, texxform.v1, 0, 1.0f, color.red, color.green, color.blue, color.alpha, fx + width, fy, 0.0f, 1.0f, texxform.u1, texxform.v0, 0, 1.0f, color.red, color.green, color.blue, color.alpha, }; float tex_width = device_texture->GetWidth(); float tex_height = device_texture->GetHeight(); CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); bool rectangle_texture = false; ObjectPtr shader_program = m_AsmPixelate; if (device_texture->Type().IsDerivedFromType(IOpenGLRectangleTexture::StaticObjectType)) { shader_program = m_AsmPixelateRect; rectangle_texture = true; } shader_program->Begin(); SetTexture(GL_TEXTURE0, device_texture); CHECKGL(glMatrixMode(GL_MODELVIEW)); CHECKGL(glLoadIdentity()); CHECKGL(glLoadMatrixf((FLOAT *) GetOpenGLModelViewMatrix().m)); CHECKGL(glMatrixMode(GL_PROJECTION)); CHECKGL(glLoadIdentity()); CHECKGL(glLoadMatrixf((FLOAT *) GetOpenGLProjectionMatrix().m)); int VertexLocation = VTXATTRIB_POSITION; int TextureCoord0Location = VTXATTRIB_TEXCOORD0; int VertexColorLocation = VTXATTRIB_COLOR; if (rectangle_texture == false) { CHECKGL(glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, (float)pixel_size/(float)tex_width, (float)pixel_size/(float)tex_height, 1.0f, 1.0f)); CHECKGL(glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, (float)tex_width/(float)pixel_size, (float)tex_height/(float)pixel_size, 1.0f, 1.0f)); } else { CHECKGL(glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, pixel_size, pixel_size, 1.0f, 1.0f)); CHECKGL(glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, 1.0f/pixel_size, 1.0f/pixel_size, 1.0f, 1.0f)); } CHECKGL(glEnableVertexAttribArrayARB(VertexLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexLocation, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer)); if (TextureCoord0Location != -1) { CHECKGL(glEnableVertexAttribArrayARB(TextureCoord0Location)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord0Location, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 4)); } if (VertexColorLocation != -1) { CHECKGL(glEnableVertexAttribArrayARB(VertexColorLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexColorLocation, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 8)); } CHECKGL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); CHECKGL(glDisableVertexAttribArrayARB(VertexLocation)); if (TextureCoord0Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord0Location)); if (VertexColorLocation != -1) CHECKGL(glDisableVertexAttribArrayARB(VertexColorLocation)); shader_program->End(); } ObjectPtr GraphicsEngine::QRP_ASM_GetPixelBlocks( ObjectPtr device_texture, TexCoordXForm &texxform0, const Color& c0, int pixel_size) { int quad_width = device_texture->GetWidth(); int quad_height = device_texture->GetHeight(); ObjectPtr prevFBO = GetGraphicsDisplay()->GetGpuDevice()->GetCurrentFrameBufferObject(); int previous_width = 0; int previous_height = 0; if (prevFBO.IsValid()) { previous_width = prevFBO->GetWidth(); previous_height = prevFBO->GetHeight(); } else { previous_width = _graphics_display.GetWindowWidth(); previous_height = _graphics_display.GetWindowHeight(); } CHECKGL(glClearColor(0, 0, 0, 0)); SetFrameBufferHelper(_offscreen_fbo, _offscreen_color_rt0, _offscreen_depth_rt0, quad_width, quad_height); CHECKGL(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)); QRP_ASM_Pixelate(0, 0, quad_width, quad_height, device_texture, texxform0, c0, pixel_size); _offscreen_fbo->Deactivate(); if (prevFBO.IsValid()) { prevFBO->Activate(true); SetViewport(0, 0, previous_width, previous_height); } else { SetViewport(0, 0, previous_width, previous_height); } return _offscreen_color_rt0; } void GraphicsEngine::QRP_ASM_GetCopyTexture( int width, int height, ObjectPtr& dst_device_texture, ObjectPtr& src_device_texture, TexCoordXForm &texxform0, const Color& c0) { if (src_device_texture.IsValid() == false) { return; } ObjectPtr prevFBO = GetGraphicsDisplay()->GetGpuDevice()->GetCurrentFrameBufferObject(); int previous_width = 0; int previous_height = 0; if (prevFBO.IsValid()) { previous_width = prevFBO->GetWidth(); previous_height = prevFBO->GetHeight(); } else { previous_width = _graphics_display.GetWindowWidth(); previous_height = _graphics_display.GetWindowHeight(); } if ((dst_device_texture.IsValid() == false) || (dst_device_texture->GetWidth() != width) || (dst_device_texture->GetHeight() != height) || (dst_device_texture->GetPixelFormat() != src_device_texture->GetPixelFormat())) { dst_device_texture = _graphics_display.GetGpuDevice()->CreateTexture(width, height, 1, src_device_texture->GetPixelFormat()); } CHECKGL(glClearColor(0, 0, 0, 0)); SetFrameBufferHelper(_offscreen_fbo, dst_device_texture, _offscreen_depth_rt0, width, height); CHECKGL(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)); QRP_ASM_1Tex(0, 0, width, height, src_device_texture, texxform0, c0); _offscreen_fbo->Deactivate(); if (prevFBO.IsValid()) { prevFBO->Activate(true); SetViewport(0, 0, previous_width, previous_height); } else { SetViewport(0, 0, previous_width, previous_height); } } void GraphicsEngine::InitAsmTexturePremultiplyShader() { std::string AsmVtx = "!!ARBvp1.0 \n\ ATTRIB iPos = vertex.position; \n\ ATTRIB iColor = vertex.attrib[3]; \n\ PARAM mvp[4] = {state.matrix.mvp}; \n\ OUTPUT oPos = result.position; \n\ OUTPUT oColor = result.color; \n\ OUTPUT oTexCoord0 = result.texcoord[0]; \n\ # Transform the vertex to clip coordinates. \n\ DP4 oPos.x, mvp[0], iPos; \n\ DP4 oPos.y, mvp[1], iPos; \n\ DP4 oPos.z, mvp[2], iPos; \n\ DP4 oPos.w, mvp[3], iPos; \n\ MOV oColor, iColor; \n\ MOV oTexCoord0, vertex.attrib[8]; \n\ END"; std::string AsmFrg = "!!ARBfp1.0 \n\ TEMP tex0; \n\ TEMP temp; \n\ TEX tex0, fragment.texcoord[0], texture[0], 2D; \n\ MUL temp.rgb, tex0, tex0.aaaa; \n\ MOV temp.a, tex0.aaaa; \n\ MUL result.color, fragment.color, temp; \n\ END"; std::string AsmFrgRect = "!!ARBfp1.0 \n\ TEMP tex0; \n\ TEMP temp; \n\ TEX tex0, fragment.texcoord[0], texture[0], RECT; \n\ MUL temp.rgb, tex0, tex0.aaaa; \n\ MOV temp.a, tex0.aaaa; \n\ MUL result.color, fragment.color, temp; \n\ END"; m_AsmTexturePremultiplyModColor = GetGraphicsDisplay()->GetGpuDevice()->CreateAsmShaderProgram(); m_AsmTexturePremultiplyModColor->LoadVertexShader(AsmVtx.c_str()); m_AsmTexturePremultiplyModColor->LoadPixelShader(AsmFrg.c_str()); m_AsmTexturePremultiplyModColor->Link(); m_AsmTexturePremultiplyRectModColor = GetGraphicsDisplay()->GetGpuDevice()->CreateAsmShaderProgram(); m_AsmTexturePremultiplyRectModColor->LoadVertexShader(AsmVtx.c_str()); m_AsmTexturePremultiplyRectModColor->LoadPixelShader(AsmFrgRect.c_str()); m_AsmTexturePremultiplyRectModColor->Link(); } void GraphicsEngine::QRP_ASM_1TexPremultiply(int x, int y, int width, int height, ObjectPtr device_texture, TexCoordXForm &texxform, const Color &color) { if (device_texture.IsNull()) return; NUX_RETURN_IF_FALSE(m_AsmTexturePremultiplyModColor.IsValid()); NUX_RETURN_IF_FALSE(m_AsmTexturePremultiplyRectModColor.IsValid()); QRP_Compute_Texture_Coord(width, height, device_texture, texxform); float fx = x, fy = y; float VtxBuffer[] = { fx, fy, 0.0f, 1.0f, texxform.u0, texxform.v0, 0, 1.0f, color.red, color.green, color.blue, color.alpha, fx, fy + height, 0.0f, 1.0f, texxform.u0, texxform.v1, 0, 1.0f, color.red, color.green, color.blue, color.alpha, fx + width, fy + height, 0.0f, 1.0f, texxform.u1, texxform.v1, 0, 1.0f, color.red, color.green, color.blue, color.alpha, fx + width, fy, 0.0f, 1.0f, texxform.u1, texxform.v0, 0, 1.0f, color.red, color.green, color.blue, color.alpha, }; CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); ObjectPtr shader_program = m_AsmTexturePremultiplyModColor; if (device_texture->Type().IsDerivedFromType(IOpenGLRectangleTexture::StaticObjectType)) { shader_program = m_AsmTexturePremultiplyRectModColor; } shader_program->Begin(); SetTexture(GL_TEXTURE0, device_texture); CHECKGL(glMatrixMode(GL_MODELVIEW)); CHECKGL(glLoadIdentity()); CHECKGL(glLoadMatrixf((FLOAT *) GetOpenGLModelViewMatrix().m)); CHECKGL(glMatrixMode(GL_PROJECTION)); CHECKGL(glLoadIdentity()); CHECKGL(glLoadMatrixf((FLOAT *) GetOpenGLProjectionMatrix().m)); int VertexLocation = VTXATTRIB_POSITION; int TextureCoord0Location = VTXATTRIB_TEXCOORD0; int VertexColorLocation = VTXATTRIB_COLOR; CHECKGL(glEnableVertexAttribArrayARB(VertexLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexLocation, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer)); if (TextureCoord0Location != -1) { CHECKGL(glEnableVertexAttribArrayARB(TextureCoord0Location)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord0Location, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 4)); } if (VertexColorLocation != -1) { CHECKGL(glEnableVertexAttribArrayARB(VertexColorLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexColorLocation, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 8)); } CHECKGL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); CHECKGL(glDisableVertexAttribArrayARB(VertexLocation)); if (TextureCoord0Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord0Location)); if (VertexColorLocation != -1) CHECKGL(glDisableVertexAttribArrayARB(VertexColorLocation)); shader_program->End(); } } #endif // NUX_OPENGLES_20 ./NuxGraphics/GLResource.cpp0000644000004100000410000002137113313171755016226 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "GLResource.h" #include "IOpenGLVertexBuffer.h" namespace nux { const char *OGLDeviceErrorMessages[] = { "OGL_OK", "OGL_ERROR_UNKNOWN", "OGL_INVALID_SURFACE_LEVEL", "OGL_INVALID_CALL", "OGL_INVALID_LOCK", "OGL_INVALID_UNLOCK", "OGL_INVALID_TEXTURE", }; /* This table lists the most efficient combinations of internalformat(either generic or specific), format, and type: internalformat format type ------------------------------------------------------------------------------------ GL_ALPHA16 GL_ALPHA GL_UNSIGNED_SHORT GL_ALPHA8 or GL_ALPHA GL_ALPHA GL_UNSIGNED_BYTE GL_INTENSITY16 GL_INTENSITY GL_UNSIGNED_SHORT GL_INTENSITY8 GL_INTENSITY GL_UNSIGNED_BYTE GL_LUMINANCE16 GL_LUMINANCE GL_UNSIGNED_SHORT GL_LUMINANCE8 or GL_LUMINANCE GL_LUMINANCE GL_UNSIGNED_BYTE GL_LUMINANCE16_ALPHA16 GL_LUMINANCE_ALPHA GL_UNSIGNED_INT_16_16_REV GL_LUMINANCE8_ALPHA8 or GL_LUMINANCE_ALPHA GL_LUMINANCE_ALPHA GL_UNSIGNED_SHORT_8_8_REV GL_RGB8 GL_RGBA GL_UNSIGNED_INT_8_8_8_8 GL_RGBA8 or GL_RGBA8 GL_RGBA GL_UNSIGNED_INT_8_8_8_8 GL_ARGB_SCE GL_BGRA GL_UNSIGNED_INT_8_8_8_8_REV GL_RGB16F GL_RGBA GL_HALF_FLOAT_ARB GL_RGBA16F GL_RGBA GL_HALF_FLOAT_ARB GL_LUMINANCE_ALPHA16F_ARB GL_ALPHA_LUMINANCE_SCE GL_HALF_FLOAT_ARB GL_LUMINANCE32F_ARB GL_LUMINANCE GL_FLOAT GL_RGB32F_ARB GL_RGBA GL_FLOAT GL_RGBA32F_ARB GL_RGBA GL_FLOAT GL_DEPTH_COMPONENT24 or GL_DEPTH_COMPONENT GL_DEPTH_COMPONENT GL_UNSIGNED_INT_24_8_SCE */ // //void AddVertexElement(std::vector& Elements, // WORD Stream, // WORD Offset, // //WORD Stride, // ATTRIB_DECL_TYPE Type, // ATTRIB_USAGE_DECL Usage, // BYTE UsageIndex) //{ // VERTEXELEMENT Element; // Element.Stream = Stream; // Element.Offset = Offset; // // We don't want to store ATTRIB_DECL_TYPE. We unpack it here so we don't have to do it every frame. // // Opengl commands such as cgGLSetParameterPointer needs to know how many components there are in // // a vertex attribute and what is the format of each component. // DecomposeTypeDeclaraction(Type, &Element.NumComponent, &Element.Type); // //Element.Stride = Stride; // Element.Usage = Usage; // Element.UsageIndex = UsageIndex; // Elements.AddItem(Element); //} void DecomposeTypeDeclaraction(ATTRIB_DECL_TYPE Type, int &NumComponent, ATTRIB_COMPONENT_TYPE &ComponentType) { switch(Type) { case ATTRIB_DECLTYPE_FLOAT1: { NumComponent = 1; ComponentType = ATTRIB_CT_FLOAT; break; } case ATTRIB_DECLTYPE_FLOAT2: { NumComponent = 2; ComponentType = ATTRIB_CT_FLOAT; break; } case ATTRIB_DECLTYPE_FLOAT3: { NumComponent = 3; ComponentType = ATTRIB_CT_FLOAT; break; } case ATTRIB_DECLTYPE_FLOAT4: { NumComponent = 4; ComponentType = ATTRIB_CT_FLOAT; break; } case ATTRIB_DECLTYPE_COLOR: { NumComponent = 4; ComponentType = ATTRIB_CT_UNSIGNED_BYTE; break; } case ATTRIB_DECLTYPE_UBYTE4: { NumComponent = 4; ComponentType = ATTRIB_CT_UNSIGNED_BYTE; break; } case ATTRIB_DECLTYPE_SHORT2: { NumComponent = 2; ComponentType = ATTRIB_CT_SHORT; break; } case ATTRIB_DECLTYPE_SHORT4: { NumComponent = 4; ComponentType = ATTRIB_CT_SHORT; break; } case ATTRIB_DECLTYPE_UBYTE4N: { NumComponent = 4; ComponentType = ATTRIB_CT_UNSIGNED_BYTE; break; } case ATTRIB_DECLTYPE_SHORT2N: { NumComponent = 2; ComponentType = ATTRIB_CT_SHORT; break; } case ATTRIB_DECLTYPE_SHORT4N: { NumComponent = 4; ComponentType = ATTRIB_CT_SHORT; break; } case ATTRIB_DECLTYPE_USHORT2N: { NumComponent = 2; ComponentType = ATTRIB_CT_UNSIGNED_SHORT; break; } case ATTRIB_DECLTYPE_USHORT4N: { NumComponent = 4; ComponentType = ATTRIB_CT_UNSIGNED_SHORT; break; } #ifndef NUX_OPENGLES_20 case ATTRIB_DECLTYPE_FLOAT16_2: { NumComponent = 2; ComponentType = ATTRIB_CT_HALF_FLOAT; break; } case ATTRIB_DECLTYPE_FLOAT16_4: { NumComponent = 4; ComponentType = ATTRIB_CT_HALF_FLOAT; break; } #endif case ATTRIB_DECLTYPE_UNUSED: default: { NumComponent = 0; ComponentType = ATTRIB_CT_UNKNOWN; nuxError("Unsupported Declaration Type. \n"); } } } UINT GetVertexElementSize(VERTEXELEMENT vtxelement) { ATTRIB_COMPONENT_TYPE type = vtxelement.Type; UINT NumComponent = vtxelement.NumComponent; switch(type) { case ATTRIB_CT_BYTE: case ATTRIB_CT_UNSIGNED_BYTE: return 1 * NumComponent; case ATTRIB_CT_SHORT: case ATTRIB_CT_UNSIGNED_SHORT: return 2 * NumComponent; case ATTRIB_CT_INT: case ATTRIB_CT_UNSIGNED_INT: case ATTRIB_CT_FLOAT: return 4 * NumComponent; #ifndef NUX_OPENGLES_20 case ATTRIB_CT_HALF_FLOAT: return 2 * NumComponent; case ATTRIB_CT_DOUBLE: return 8 * NumComponent; #endif case ATTRIB_CT_UNKNOWN: default: nuxAssert("Unknown Component Type"); return 0; } return 0; } void AddVertexElement(std::vector& Elements, WORD Stream, WORD Offset, //ubiU16 Stride, ATTRIB_DECL_TYPE Type, ATTRIB_USAGE_DECL /* Usage */, BYTE /* UsageIndex */) { VERTEXELEMENT Element; Element.Stream = Stream; Element.Offset = Offset; // We don't want to store ATTRIB_DECL_TYPE. We unpack it here so we don't have to do it every frame. // Opengl commands such as cgGLSetParameterPointer needs to know how many components there are in // a vertex attribute and what is the format of each component. DecomposeTypeDeclaraction(Type, Element.NumComponent, Element.Type); //Element.Stride = Stride; //Element.Usage = Usage; //Element.UsageIndex = UsageIndex; Elements.push_back(Element); } unsigned int GetGLElementCount(PRIMITIVE_TYPE InPrimitiveType, unsigned int InPrimitiveCount) { switch(InPrimitiveType) { case PRIMITIVE_TYPE_POINTLIST: return InPrimitiveCount; case PRIMITIVE_TYPE_LINELIST: return InPrimitiveCount * 2; case PRIMITIVE_TYPE_LINESTRIP: return InPrimitiveCount + 1; case PRIMITIVE_TYPE_TRIANGLELIST: return InPrimitiveCount * 3; case PRIMITIVE_TYPE_TRIANGLESTRIP: return InPrimitiveCount + 2; case PRIMITIVE_TYPE_TRIANGLEFAN: return InPrimitiveCount; #ifndef NUX_OPENGLES_20 case PRIMITIVE_TYPE_QUADLIST: return InPrimitiveCount * 4; case PRIMITIVE_TYPE_QUADSTRIP: return InPrimitiveCount * 2 + 2; #endif default: return 0; } nuxAssertMsg(0, "[GetGLElementCount] Invalid PRIMITIVE_TYPE"); return InPrimitiveCount; } } ./NuxGraphics/IOpenGLTexture2D.h0000644000004100000410000000624213313171755016665 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef IOPENGLTEXTURE2D_H #define IOPENGLTEXTURE2D_H namespace nux { class IOpenGLBaseTexture; class IOpenGLTexture2D: public IOpenGLBaseTexture { NUX_DECLARE_OBJECT_TYPE(IOpenGLTexture2D, IOpenGLBaseTexture); public: virtual ~IOpenGLTexture2D(); void GetSurfaceLevel(int Level, ObjectPtr& surface); ObjectPtr GetSurfaceLevel(int Level); int LockRect( int Level, SURFACE_LOCKED_RECT *pLockedRect, const SURFACE_RECT *pRect); int UnlockRect( int Level ); unsigned int EnableGammaCorrection(bool b); int GetLevelDesc( int Level, SURFACE_DESC *pDesc ) { nuxAssert(Level >= 0 ); nuxAssert(Level < _NumMipLevel); if ((Level < 0) || (Level > _NumMipLevel)) { pDesc->Width = 0; pDesc->Height = 0; pDesc->PixelFormat = BITFMT_UNKNOWN; pDesc->Type = _ResourceType; } else { pDesc->Width = Max (1, _Width >> Level); pDesc->Height = Max (1, _Height >> Level); pDesc->PixelFormat = _PixelFormat; pDesc->Type = _ResourceType; } return OGL_OK; } //! Return a pointer to a mipmap level data. /*! Return a pointer to a mipmap level data. The data is in the RGBA format.\n Inherited from IOpenGLBaseTexture. @param level The requested texture mipmap level data. @param width Returns the width in pixel of the image data. @param height Returns the height in pixel of the image data. @param stride Returns the row stride of the image data. @return A pointer to RGBA data. The caller must dlete the data by calling delete []. */ unsigned char* GetSurfaceData(int level, int &width, int &height, int &stride); private: // The Dummy boolean is used to create a skeletal frame for the default // render target texture and surface; Only GpuDevice uses it in its constructor. // Do not use it otherwise!!! IOpenGLTexture2D( unsigned int Width , unsigned int Height , unsigned int Levels , BitmapFormat PixelFormat, bool Dummy = false, NUX_FILE_LINE_PROTO); std::vector< ObjectPtr > _SurfaceArray; bool external_id_; friend class GpuDevice; friend class IOpenGLSurface; }; } #endif // IOPENGLTEXTURE2D_H ./NuxGraphics/RenderingPipeTextureBlendShaderSource.h0000644000004100000410000005171113313171755023253 0ustar www-datawww-data/* * Copyright 2010-2012 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * Robert Carr */ #ifndef RENDERING_PIPE_TEXTURE_BLEND_SHADER_SOURCE_H #define RENDERING_PIPE_TEXTURE_BLEND_SHADER_SOURCE_H namespace nux { static const std::string BlendNormalShader = " \n\ vec3 BlendNormal(vec3 B /*background layer*/, vec3 L /*foreground layer*/) \n\ { \n\ return L; \n\ }"; static const std::string BlendLightenShader = " \n\ vec3 BlendLighten(vec3 B /*background layer*/, vec3 L /*foreground layer*/) \n\ { \n\ // This mode is commutative \n\ vec3 V = max(L, B); \n\ return V; \n\ }"; static const std::string BlendDarkenShader = " \n\ vec3 BlendDarken(vec3 B /*background layer*/, vec3 L /*foreground layer*/) \n\ { \n\ vec3 V = min(L, B); \n\ return V; \n\ }"; static const std::string BlendMultiplyShader = " \n\ vec3 BlendMultiply(vec3 B /*background layer*/, vec3 L /*foreground layer*/) \n\ { \n\ return(B * L); \n\ }"; static const std::string BlendAverageShader = " \n\ vec3 BlendAverage(vec3 B /*background layer*/, vec3 L /*foreground layer*/) \n\ { \n\ // This mode is commutative \n\ return((B + L) / 2.0); \n\ }"; // *** Additive Modes *** static const std::string BlendAddShader = " \n\ vec3 BlendAdd(vec3 B /*background layer*/, vec3 L /*foreground layer*/) \n\ { \n\ return min(B + L, vec3(1.0)); \n\ }"; static const std::string BlendSubstractShader = " \n\ vec3 BlendSubstract(vec3 B /*background layer*/, vec3 L /*foreground layer*/) \n\ { \n\ return max(B + L - vec3(1.0), vec3(0.0)); \n\ }"; // *** Difference Modes *** static const std::string BlendDifferenceShader = " \n\ vec3 BlendDifference(vec3 B /*background layer*/, vec3 L /*foreground layer*/) \n\ { \n\ return abs(B - L); \n\ }"; static const std::string BlendNegationShader = " \n\ vec3 BlendNegation(vec3 B /*background layer*/, vec3 L /*foreground layer*/) \n\ { \n\ return(vec3(1.0) - abs(vec3(1.0) - B - L)); \n\ }"; static const std::string BlendExclusionShader = " \n\ vec3 BlendExclusion(vec3 B /*background layer*/, vec3 L /*foreground layer*/) \n\ { \n\ return(B + L - 2.0 * B * L); \n\ }"; static const std::string BlendScreenShader = " \n\ vec3 BlendScreen(vec3 B /*background layer*/, vec3 L /*foreground layer*/) \n\ { \n\ return(1.0 - (1.0 - B) * (1.0 - L)); \n\ }"; static const std::string BlendOverlayShader = " \n\ float _BlendOverlay(float B /*background layer*/, float L /*foreground layer*/) \n\ { \n\ if (L < 0.5) \n\ return(2.0 * B * L); \n\ else \n\ return(1.0 - 2.0 * (1.0 - B) * (1.0 - L)); \n\ } \n\ vec3 BlendOverlay(vec3 B /*background layer*/, vec3 L /*foreground layer*/) \n\ { \n\ return vec3(_BlendOverlay(B.r,L.r), _BlendOverlay(B.g ,L.g), _BlendOverlay(B.b,L.b)); \n\ }"; static const std::string BlendSoftLightShader = " \n\ float _BlendSoftLight(float B /*background layer*/, float L /*foreground layer*/) \n\ { \n\ if (L < 0.5) \n\ return(2.0 * B * L + B * B * (1.0 - 2.0 * L)); \n\ else \n\ return sqrt(B) * (2.0 * L - 1.0) + 2.0 * B * (1.0 - L); \n\ } \n\ vec3 BlendSoftLight(vec3 B /*background layer*/, vec3 L /*foreground layer*/) \n\ { \n\ return vec3(_BlendSoftLight(B.r, L.r), _BlendSoftLight(B.g, L.g), _BlendSoftLight(B.b, L.b)); \n\ }"; static const std::string BlendHardLightShader = " \n\ float _BlendHardLight(float B /*background layer*/, float L /*foreground layer*/) \n\ { \n\ if (L < 0.5) \n\ return(2.0 * B * L); \n\ else \n\ return(1.0 - 2.0 * (1.0 - B) * (1.0 - L)); \n\ } \n\ vec3 BlendHardLight(vec3 B /*background layer*/, vec3 L /*foreground layer*/) \n\ { \n\ return vec3(_BlendHardLight(B.r, L.r), _BlendHardLight(B.g, L.g), _BlendHardLight(B.b, L.b)); \n\ }"; static const std::string BlendColorDodgeShader = " \n\ float _BlendColorDodge(float B /*background layer*/, float L /*foreground layer*/) \n\ { \n\ if (L == 1.0) \n\ return 1.0; \n\ else \n\ return min(B / (1.0 - L), 1.0); \n\ } \n\ vec3 BlendColorDodge(vec3 B /*background layer*/, vec3 L /*foreground layer*/) \n\ { \n\ return vec3(_BlendColorDodge(B.r, L.r), _BlendColorDodge(B.g, L.g), _BlendColorDodge(B.b, L.b)); \n\ }"; static const std::string BlendLinearDodgeShader = " \n\ float _BlendLinearDodge(float B /*background layer*/, float L /*foreground layer*/) \n\ { \n\ return min(B + L, 1.0); \n\ } \n\ vec3 BlendLinearDodge(vec3 B /*background layer*/, vec3 L /*foreground layer*/) \n\ { \n\ return vec3(_BlendLinearDodge(B.r, L.r), _BlendLinearDodge(B.g, L.g), _BlendLinearDodge(B.b, L.b)); \n\ }"; static const std::string BlendColorBurnShader = " \n\ float _BlendColorBurn(float B /*background layer*/, float L /*foreground layer*/) \n\ { \n\ if (L == 0.0) \n\ return 0.0; \n\ else \n\ return max(1.0 - ((1.0 - B) / L), 0.0); \n\ } \n\ vec3 BlendColorBurn(vec3 B /*background layer*/, vec3 L /*foreground layer*/) \n\ { \n\ return vec3(_BlendColorBurn(B.r, L.r), _BlendColorBurn(B.g, L.g), _BlendColorBurn(B.b, L.b)); \n\ }"; static const std::string BlendLinearBurnShader = " \n\ float _BlendLinearBurn(float B /*background layer*/, float L /*foreground layer*/) \n\ { \n\ return max(B + L - 1.0, 0.0); \n\ } \n\ vec3 BlendLinearBurn(vec3 B /*background layer*/, vec3 L /*foreground layer*/) \n\ { \n\ return vec3(_BlendLinearBurn(B.r, L.r), _BlendLinearBurn(B.g, L.g), _BlendLinearBurn(B.b, L.b)); \n\ }"; static const std::string BlendLinearLightShader = BlendLinearBurnShader + BlendLinearDodgeShader + "float _BlendLinearLight(float B /*background layer*/, float L /*foreground layer*/) \n\ { \n\ if (L < 0.5) \n\ return _BlendLinearBurn(B, (2.0 * L)); \n\ else \n\ return _BlendLinearDodge(B, (2.0 * (L - 0.5))); \n\ } \n\ vec3 BlendLinearLight(vec3 B /*background layer*/, vec3 L /*foreground layer*/) \n\ { \n\ return vec3(_BlendLinearLight(B.r, L.r), _BlendLinearLight(B.g, L.g), _BlendLinearLight(B.b, L.b)); \n\ }"; static const std::string BlendVividLightShader = BlendColorBurnShader + BlendColorDodgeShader + "float _BlendVividLight(float B /*background layer*/, float L /*foreground layer*/) \n\ { \n\ if (L < 0.5) \n\ return _BlendColorBurn(B, (2.0 * L)); \n\ else \n\ return _BlendColorDodge(B, (2.0 * (L - 0.5))); \n\ } \n\ vec3 BlendVividLight(vec3 B /*background layer*/, vec3 L /*foreground layer*/) \n\ { \n\ return vec3(_BlendVividLight(B.r, L.r), _BlendVividLight(B.g, L.g), _BlendVividLight(B.b, L.b)); \n\ }"; static const std::string BlendPinLightShader = " \n\ float _BlendPinLight(float B /*background layer*/, float L /*foreground layer*/) \n\ { \n\ if (L < 0.5) \n\ return min(B, (2.0 * L)); \n\ else \n\ return max(B, (2.0 * (L - 0.5))); \n\ } \n\ vec3 BlendPinLight(vec3 B /*background layer*/, vec3 L /*foreground layer*/) \n\ { \n\ return vec3(_BlendPinLight(B.r, L.r), _BlendPinLight(B.g, L.g), _BlendPinLight(B.b, L.b)); \n\ }"; static const std::string BlendHardMixShader = BlendVividLightShader + "float _BlendHardMix(float B /*background layer*/, float L /*foreground layer*/) \n\ { \n\ if (_BlendVividLight(B, L) < 0.5) \n\ return 0.0; \n\ else \n\ return 1.0; \n\ } \n\ vec3 BlendHardMix(vec3 B /*background layer*/, vec3 L /*foreground layer*/) \n\ { \n\ return vec3(_BlendHardMix(B.r, L.r), _BlendHardMix(B.g, L.g), _BlendHardMix(B.b, L.b)); \n\ }"; static const std::string BlendReflectShader = " \n\ float _BlendReflect(float B /*background layer*/, float L /*foreground layer*/) \n\ { \n\ if (L == 1.0) \n\ return 1.0; \n\ else \n\ return min(B * B / (1.0 - L), 1.0); \n\ } \n\ vec3 BlendReflect(vec3 B /*background layer*/, vec3 L /*foreground layer*/) \n\ { \n\ return vec3(_BlendReflect(B.r, L.r), _BlendReflect(B.g, L.g), _BlendReflect(B.b, L.b)); \n\ }"; static const std::string BlendGlowShader = " \n\ float _BlendGlow(float B /*background layer*/, float L /*foreground layer*/) \n\ { \n\ if (L == 1.0) \n\ return 1.0; \n\ else \n\ return min(L * L / (1.0 - B), 1.0); \n\ } \n\ vec3 BlendGlow(vec3 B /*background layer*/, vec3 L /*foreground layer*/) \n\ { \n\ return vec3(_BlendGlow(B.r, L.r), _BlendGlow(B.g, L.g), _BlendGlow(B.b, L.b)); \n\ }"; static const std::string BlendPhoenixShader = " \n\ vec3 BlendPhoenix(vec3 B /*background layer*/, vec3 L /*foreground layer*/) \n\ { \n\ return min(B, L) - max(B, L) + vec3(1.0); \n\ }"; static const std::string BlendOpacityShader = " \n\ vec3 BlendOpacity(vec3 B /*background layer*/, vec3 L /*foreground layer*/) \n\ { \n\ return O * L + (1 - O) * B; \n\ }"; } #endif ./NuxGraphics/IOpenGLBaseTexture.h0000644000004100000410000001204613313171755017271 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef IOPENGLBASETEXTURE_H #define IOPENGLBASETEXTURE_H #include "GLResource.h" #include "IOpenGLResource.h" #include "GLShaderParameter.h" #include "GLTextureStates.h" namespace nux { class IOpenGLResource; class IOpenGLBaseTexture; int GetTextureSize(IOpenGLBaseTexture *pTexture); // todo: It should not be possible to create an object of type IOpenGLBaseTexture directly. class IOpenGLBaseTexture: public IOpenGLResource { NUX_DECLARE_OBJECT_TYPE(IOpenGLBaseTexture, IOpenGLResource); public: IOpenGLBaseTexture(OpenGLResourceType ResourceType, unsigned int Width, unsigned int Height, unsigned int Depth, unsigned int NumMipLevel, BitmapFormat PixelFormat, NUX_FILE_LINE_PROTO); virtual ~IOpenGLBaseTexture(); BitmapFormat GetPixelFormat() const { return _PixelFormat; } int GetNumMipLevel() const { return _NumMipLevel; } bool IsPowerOfTwo() const { return _IsPOT; } int GetWidth() const { if (_ResourceType == RTTEXTURE) return _Width; if (_ResourceType == RTTEXTURERECTANGLE) return _Width; if (_ResourceType == RTCUBETEXTURE) return _Width; return 0; } int GetHeight() const { if (_ResourceType == RTTEXTURE) return _Height; if (_ResourceType == RTTEXTURERECTANGLE) return _Height; if (_ResourceType == RTCUBETEXTURE) return _Width; return 0; } int GetDepth() const { if (_ResourceType == RTTEXTURE) return 1; if (_ResourceType == RTTEXTURERECTANGLE) return 1; if (_ResourceType == RTCUBETEXTURE) return 1; if (_ResourceType == RTVOLUMETEXTURE) return _Depth; if (_ResourceType == RTANIMATEDTEXTURE) return _Depth; return 0; } int GetFormatRowMemoryAlignment() const { return _RowMemoryAlignment; } //GLTextureStates& GetTextureStates() {return _TextureStates;} void SetRenderStates(); void SetFiltering(unsigned int MIN = GL_NEAREST, unsigned int MAG = GL_NEAREST/*, unsigned int MIP = GL_NEAREST*/); void SetWrap(unsigned int U = GL_REPEAT, unsigned int V = GL_REPEAT, unsigned int W = GL_REPEAT); void SetLOD(float MinLod = -1000.0f, float MaxLod = +1000.0f); void SetMipLevel(unsigned int MinMip = 0, unsigned int MaxMip = 1000); void SetBorderColor(float R, float G, float B, float A); int BindTexture(); int BindTextureToUnit(int TextureUnitIndex); virtual void GetSurfaceLevel(int Level, ObjectPtr& surface); virtual ObjectPtr GetSurfaceLevel(int Level); virtual int LockRect( int Level, SURFACE_LOCKED_RECT *pLockedRect, const SURFACE_RECT *pRect); virtual int UnlockRect(int Level); //! Return a pointer to a mipmap level data. /*! Return a pointer to a mipmap level data. The data is in the RGBA format.\n @param level The requested texture mipmap level data. @param width Returns the width in pixel of the image data. @param height Returns the height in pixel of the image data. @param stride Returns the row stride of the image data. @return A pointer to RGBA data. The caller must delete the data by calling delete []. */ virtual unsigned char* GetSurfaceData(int level, int &width, int &height, int &stride); void Save(const char* filename); protected: GLTextureStates _TextureStates; bool _IsPOT; // is power of two? int _NumMipLevel; BitmapFormat _PixelFormat; // These parameters are scalable across textures, cube textures and volume textures. // For texture and cube texture _Depth is equal to 1. // For cube texture, _Width = _Height int _Width; int _Height; int _Depth; int _RowMemoryAlignment; friend class IOpenGLSurface; friend class IOpenGLVolume; friend void GetTextureDesc( IOpenGLBaseTexture *pTexture, unsigned int Level, TEXTURE_DESC *pDesc ); friend int GetTextureSize(IOpenGLBaseTexture *pTexture); }; } #endif // IOPENGLBASETEXTURE_H ./NuxGraphics/IOpenGLAnimatedTexture.h0000644000004100000410000000503513313171755020141 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef IOPENGLANIMATEDTEXTURE_H #define IOPENGLANIMATEDTEXTURE_H namespace nux { class IOpenGLBaseTexture; // Note that for Animated texture, the Depth value is the number of frames. // The number of mipmap levels is always 1; class IOpenGLAnimatedTexture: public IOpenGLBaseTexture { NUX_DECLARE_OBJECT_TYPE(IOpenGLAnimatedTexture, IOpenGLBaseTexture); public: virtual ~IOpenGLAnimatedTexture(); void GetSurfaceFrame(int Frame, ObjectPtr& surface); ObjectPtr GetSurfaceFrame(int Level); int LockRect( int Frame, SURFACE_LOCKED_RECT *pLockedRect, const SURFACE_RECT *pRect); int UnlockRect( int Frame ); int GetDepth(int /* MipLevel */) const { return _Depth; } int GetDesc(ANIMATEDTEXTURE_DESC *pDesc) { pDesc->Width = Max (1, _Width); pDesc->Height = Max (1, _Height); pDesc->Depth = _Depth; pDesc->PixelFormat = _PixelFormat; pDesc->Type = _ResourceType; return OGL_OK; } void PresentFirstFrame(); void PresentNextFrame(); void PresentLastFrame(); int GetFrameTime(); unsigned int GetNumFrame(); void SetFrameTime(int Frame, int time_ms); private: IOpenGLAnimatedTexture( int Width , int Height , int Depth , BitmapFormat PixelFormat); // unsigned int _Width; // unsigned int _Height; // unsigned int _Depth; //std::vector _VolumeArray; int _CurrentFrame; std::vector< ObjectPtr > _FrameTextureArray; std::vector< int > _FrameTimeArray; friend class GpuDevice; friend class IOpenGLSurface; }; } #endif // IOPENGLANIMATEDTEXTURE_H ./NuxGraphics/RenderingPipe.h0000644000004100000410000001025113313171755016407 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef RENDERINGPIPE_H #define RENDERINGPIPE_H #include "GLResource.h" namespace nux { //! Graphics wraping modes /*! Defines the wraping modes of TexCoordXForm. The values are matched to OpenGL wraping modes. @sa TexCoordXForm. */ typedef enum { TEXWRAP_UNKNOWN = 0, TEXWRAP_REPEAT, TEXWRAP_CLAMP, TEXWRAP_CLAMP_TO_EDGE, TEXWRAP_CLAMP_TO_BORDER, TEXWRAP_MIRRORED_REPEAT, TEXWRAP_MIRROR_CLAMP_EXT, TEXWRAP_MIRROR_CLAMP_TO_EDGE_EXT, TEXWRAP_MIRROR_CLAMP_TO_BORDER_EXT, } TexWrap; //! Graphics filtering modes /*! Defines the filtering modes of TexCoordXForm. The values are matched to openGL filtering modes. @sa TexCoordXForm. */ typedef enum { TEXFILTER_UNKNOWN = 0, TEXFILTER_LINEAR, TEXFILTER_NEAREST, TEXFILTER_NEAREST_MIPMAP_NEAREST, TEXFILTER_LINEAR_MIPMAP_NEAREST, TEXFILTER_NEAREST_MIPMAP_LINEAR, TEXFILTER_LINEAR_MIPMAP_LINEAR, } TexFilter; //! Graphics blend modes /*! Defines the blending modes. The values are matched to openGL blending modes. */ typedef enum { ROPBLEND_UNKNOWN = 0, ROPBLEND_ZERO, ROPBLEND_ONE, ROPBLEND_SRC_COLOR, ROPBLEND_ONE_MINUS_SRC_COLOR, ROPBLEND_DST_COLOR, ROPBLEND_ONE_MINUS_DST_COLOR, ROPBLEND_SRC_ALPHA, ROPBLEND_ONE_MINUS_SRC_ALPHA, ROPBLEND_DST_ALPHA, ROPBLEND_ONE_MINUS_DST_ALPHA, ROPBLEND_CONSTANT_COLOR, ROPBLEND_ONE_MINUS_CONSTANT_COLOR, ROPBLEND_CONSTANT_ALPHA, ROPBLEND_ONE_MINUS_CONSTANT_ALPHA, ROPBLEND_SRC_ALPHA_SATURATE, } RopBlend; //! Texture parameter and coordinate computation class. /*! Defines the texture coordinate computation, wrapping and filtering modes */ class TexCoordXForm { public: //! Texture coordinates computation mode typedef enum { OFFSET_SCALE_COORD, //!< Texture coordinates are scaled and offset. OFFSET_COORD, //!< Textures coordinates are offset. The scaling factor between the texture size and the quad size is preserved. NORMALIZED_COORD, //!< Provided normalized texture coordinates in u0, v0, u1, v1 UNNORMALIZED_COORD, //!< Provided un-normalized texture coordinates in u0, v0, u1, v1 FIXED_COORD, //!< Provided fix coordinates in u0, v0, u1, v1 } TexCoordType; TexCoordXForm(); void SetTexCoordType(TexCoordType tex_coord_type); void FlipUCoord(bool b); void FlipVCoord(bool b); void FlipUVCoord(bool flip_u, bool flip_v); void SetFilter(TexFilter min_fliter, TexFilter mag_filter); void SetWrap(TexWrap u_wrap, TexWrap v_wrap); //! Texture coordinates are computed automatically by following the TexCoordType policy or provided by the user float u0, v0, u1, v1; float uscale; float vscale; float uoffset; float voffset; TexWrap uwrap; TexWrap vwrap; TexFilter min_filter; TexFilter mag_filter; bool flip_u_coord; bool flip_v_coord; TexCoordType m_tex_coord_type; }; //! Compute texture coordinates and wrapping mode according to TexCoordXForm /*! @param quad_width Quad width. @param quad_height Quad height. @param tex Device texture. @param texxform Texture coordinates computation mode. */ void QRP_Compute_Texture_Coord(int quad_width, int quad_height, ObjectPtr tex, TexCoordXForm &texxform); } #endif // RENDERINGPIPE_H ./NuxGraphics/FreetypeFont.h0000644000004100000410000001201613313171755016267 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef DBM_FONTMGR #define DBM_FONTMGR #if defined WIN32 #include // Header File For Windows #include #include #include // #include // Header File For The OpenGL32 Library // #include // Header File For The GLu32 Library // #include using namespace std; #else #include #include // #include // #include // #include #endif /*#include "fmt_image.h" #include "fmt_tga.h" #include "fmt_bmp.h" #include "dbm_texturemgr.h"*/ #include #include #include #include #include FT_FREETYPE_H typedef int FontID; typedef enum _TextAlignment { eAlignTextNone = 0, eAlignTextLeft = 1, eAlignTextRight = 2, eAlignTextCenter = 3, } TextAlignment; class StringBBox { public: StringBBox() { x = 0; y = 0; width = 0; height = 0; ybearing = 0; downline = 0; }; ~StringBBox() {}; int x; int y; int width; int height; int ybearing; // max ybearing of the string int downline; // max downline of the string (max space below the baseline) }; class PageBBox { public: PageBBox() { xmin = 0; ymin = 0; xmax = 0; ymax = 0; x_margin = 0; y_margin = 0; }; ~PageBBox() {}; int xmin; int ymin; int xmax; int ymax; int x_margin; int y_margin; }; typedef struct _CharData { int hbearingX; int hbearingY; int vbearingX; int vbearingY; int vadvance; int hadvance; int gwidth; int gheight; struct { int xmin, xmax, ymin, ymax; } bbox; int bitmap_left_bearing; int bitmap_top_bearing; int bitmap_width; int bitmap_height; int glyph_index; int gltexid; int glTexWidth; int glTexHeight; } CharData; typedef struct _FontStyle { char *style_name; CharData *charmap; int num_glyph; int ascent; int descent; int texture_width; int texture_height; int line_spacing; } FontStyle; typedef struct _FontFamily { char *font_name; FT_Face m_face; //int num_glyph; list *style_list; } FontFamily; class FontMgr { private: char *current_font; char *current_style; FontMgr(); static FontMgr *pinstance; public: list *m_font_list; static FontMgr *Instance(); int nombre; ~FontMgr(); bool load_font (const char *font_name); int get_character_texture_id (const char *font_name, int encoding, CharData *cd); int get_character_texture_id (int encoding, CharData *cd); void get_style_texture_size (const char *font_name, int *width, int *height); void get_style_texture_size (int *width, int *height); void get_style_line_spacing (const char *font_name, int *line_spacing); void get_style_line_spacing (int *line_spacing); unsigned int get_null_character_texture_id (const char *font_name); unsigned int get_null_character_texture_id(); bool find_font (const char *font_name, const char *style_name); FontFamily *get_font_family (const char *font_name); FontStyle *get_font_style (char *font_name, char *style_name); void set_current_font (char *font_name, char *style_name); void draw_text (int rect_xmin, int rect_ymin, int rect_xmax, int rect_ymax, const char *text, const char *sh_name); void ComputeGlyphString (int x, int y, const char *text); //unsigned int GetStringWidth(const char* text); //unsigned int GetStringHeight(const char* text); unsigned int GetStringWidth (const std::string &text); unsigned int GetStringHeight (const std::string &text); void ComputeStringBBox (StringBBox &stringBBox, const char *text); void PositionString (const PageBBox &, StringBBox &, TextAlignment align = eAlignTextCenter); //void RenderGlyph(int targer_width, int target_height); void RenderGlyph (const PageBBox &pageSize, const char *text, TextAlignment align = eAlignTextCenter); void RenderString (const PageBBox &pageSize, const std::string &Str, TextAlignment alignment, unsigned int CursorPosition, int offset = 0); void RenderTextLineEdit (const PageBBox &pageSize, const std::string &Str, unsigned int CursorPosition, int offset = 0); void RenderTextLineStatic (const PageBBox &pageSize, const std::string &Str, TextAlignment alignment, char trailingchar = 0); }; #endif ./NuxGraphics/IOpenGLGLSLShader.cpp0000644000004100000410000011126513313171755017264 0ustar www-datawww-data/* * Copyright 2010 Inalogic Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "GLResource.h" #include "GraphicsDisplay.h" #include "GpuDevice.h" #include "GLDeviceObjects.h" #include "IOpenGLGLSLShader.h" namespace nux { namespace local { namespace { GLuint last_loaded_shader = 0; bool enable_tracking = false; } } NUX_IMPLEMENT_OBJECT_TYPE(IOpenGLShader); NUX_IMPLEMENT_OBJECT_TYPE(IOpenGLVertexShader); NUX_IMPLEMENT_OBJECT_TYPE(IOpenGLPixelShader); //NUX_IMPLEMENT_OBJECT_TYPE(IOpenGLGeometryShader); NUX_IMPLEMENT_OBJECT_TYPE(IOpenGLShaderProgram); bool ExtractShaderString3(const std::string &ShaderToken, const std::string &ShaderSource, std::string &RetSource, std::string ShaderPreprocessorDefines) { //Loop for all characters in the string if (ShaderToken != "") { size_t lineStart = 0; size_t lineCount = 1; bool startTokenFound = false; size_t shaderStringStart = 0; size_t shaderStartLine = 1; size_t i; for (i = 0; i < ShaderSource.length(); i++) { //Check if the starting character '[' (open bracket) is found at the beginning of the line // i counts the characters in the file. lineStart is equal to i at the beginning of the line. std::string sub_string = ShaderSource.substr(i, std::string::npos); if ((TCharStringNCompare(sub_string.c_str(), "[", 1) == 0) && (lineStart == i)) { if (!startTokenFound) { //Test for the start token if (ShaderSource.find(ShaderToken, 0) == i) { // Found the shader token shaderStringStart = i + ShaderToken.length(); startTokenFound = true; //Set what line the shader was found on shaderStartLine = lineCount; } } else { //Break where the end token was found break; } } //If the character is equal to the new line character, // The next character must be on the new line sub_string = ShaderSource.substr(i, std::string::npos); if ((TCharStringNCompare(sub_string.c_str(), "\r", 1) == 0) || (TCharStringNCompare(sub_string.c_str(), "\n", 1) == 0)) { lineStart = i + 1; } //Count the new lines if (TCharStringNCompare(sub_string.c_str(), "\n", 1) == 0) { lineCount++; } } //If the string was not found, return false if (!startTokenFound || shaderStringStart >= i) { return false; } //Assign the return string RetSource = ShaderSource.substr(shaderStringStart, i - shaderStringStart); //Add the line directive to the shader source. See the documentation for GLSL #line directive. // GLSL spec: The #version directive must occur in a shader before anything else, except for comments and white space. size_t Pos = RetSource.find("#version", 0); while (Pos != std::string::npos && RetSource[Pos] != '\n') { if (RetSource[Pos] == 0) break; ++Pos; } if (RetSource[Pos] != 0) ++Pos; size_t EndOfLinePosition = 0; size_t LinePosition = 0; while ((EndOfLinePosition = RetSource.find('\n', EndOfLinePosition)) < Pos - 1) { ++EndOfLinePosition; ++LinePosition; } std::string s = "#line "; s += std::to_string((unsigned long long)(LinePosition + shaderStartLine)) + "\n"; RetSource.insert(Pos, s); // Insert the preprocessor definitions before the #line directive if (ShaderPreprocessorDefines.length()) RetSource.insert(Pos, ShaderPreprocessorDefines + std::string("\n")); return true; } else { // We are not searching for a start token. Return the whole source. RetSource = ShaderSource; return true; } } static void InsertPreProcessorDefinitions(const std::string &ShaderSource, std::string &RetSource, std::string &ShaderPreprocessorDefines) { RetSource = ShaderSource; if (ShaderPreprocessorDefines.length() == 0) return; // GLSL spec: The #version directive must occur in a shader before anything else, except for comments and white space. size_t Pos = RetSource.find("#version", 0); if (Pos != tstring::npos) { Pos = RetSource.find('\n', Pos); if (Pos == std::string::npos) { // this is most likely an incorrect shader Pos = RetSource.size(); RetSource.insert(Pos, std::string("\n")); Pos = RetSource.size(); } else { // Skip character \n Pos++; } } else { Pos = 0; } if (ShaderPreprocessorDefines.length()) RetSource.insert(Pos, ShaderPreprocessorDefines + std::string("\n")); } IOpenGLShader::IOpenGLShader(std::string ShaderName, OpenGLResourceType ResourceType) : IOpenGLResource(ResourceType) , _ShaderName(ShaderName) { } IOpenGLShader::~IOpenGLShader() { } IOpenGLVertexShader::IOpenGLVertexShader(std::string ShaderName) : IOpenGLShader(ShaderName, RT_GLSL_VERTEXSHADER) , m_CompiledAndReady(false) { _OpenGLID = glCreateShader(GL_VERTEX_SHADER_ARB); CHECKGL_MSG( glCreateShader(GL_VERTEX_SHADER_ARB)); } IOpenGLVertexShader::~IOpenGLVertexShader() { CHECKGL(glDeleteShader(_OpenGLID)); _OpenGLID = 0; m_CompiledAndReady = false; } void IOpenGLVertexShader::SetShaderCode(const char *ShaderCode, const char *VtxShaderPreprocessorDefines) { nuxAssertMsg(ShaderCode, "[IOpenGLVertexShader::SetShaderCode] Invalid shader code."); NUX_RETURN_IF_NULL(ShaderCode); std::string ProcessedShaderSource; std::string Defines(VtxShaderPreprocessorDefines); InsertPreProcessorDefinitions(ShaderCode, ProcessedShaderSource, Defines); m_CompiledAndReady = false; _ShaderCode = ProcessedShaderSource; } bool IOpenGLVertexShader::Compile() { size_t CodeSize = _ShaderCode.size(); if (CodeSize == 0) { nuxDebugMsg("[IOpenGLVertexShader::Compile] Vertex shader source code is empty."); } char *ShaderSource = new char[CodeSize+1]; Memset(ShaderSource, 0, CodeSize + 1); Memcpy(ShaderSource, _ShaderCode.c_str(), CodeSize); CHECKGL(glShaderSource(_OpenGLID, 1, (const GLcharARB **) &ShaderSource, NULL)); delete [] ShaderSource; // compile vertex shader object CHECKGL(glCompileShader(_OpenGLID)); // check if shader compiled m_CompiledAndReady = false; CHECKGL(glGetShaderiv(_OpenGLID, GL_COMPILE_STATUS, &m_CompiledAndReady)); if (!m_CompiledAndReady) { ANSICHAR *InfoLogBuffer = 0; GLint InfoLogBufferSize = 0; GLint InfoLogReturnSize = 0; GLint iLog = 0; glGetShaderiv(_OpenGLID, GL_INFO_LOG_LENGTH, &iLog); InfoLogBuffer = new ANSICHAR[iLog+1]; InfoLogBufferSize = iLog + 1; glGetShaderInfoLog(_OpenGLID, InfoLogBufferSize, &InfoLogReturnSize, InfoLogBuffer); if (InfoLogReturnSize != 0) { nuxError("[IOpenGLVertexShader::Compile] glCompileShader: %s", InfoLogBuffer); } delete[] InfoLogBuffer; } return m_CompiledAndReady; } bool IOpenGLVertexShader::IsValid() { return m_CompiledAndReady; } IOpenGLPixelShader::IOpenGLPixelShader(std::string ShaderName) : IOpenGLShader(ShaderName, RT_GLSL_PIXELSHADER) , m_CompiledAndReady(false) { _OpenGLID = glCreateShader(GL_FRAGMENT_SHADER_ARB); CHECKGL_MSG( glCreateShader(GL_FRAGMENT_SHADER_ARB)); } IOpenGLPixelShader::~IOpenGLPixelShader() { CHECKGL(glDeleteShader(_OpenGLID)); _OpenGLID = 0; m_CompiledAndReady = false; } void IOpenGLPixelShader::SetShaderCode(const char *ShaderCode, const char *FrgShaderPreprocessorDefines) { nuxAssertMsg(ShaderCode, "[IOpenGLPixelShader::SetShaderCode] Invalid shader code."); NUX_RETURN_IF_NULL(ShaderCode); std::string ProcessedShaderSource; std::string Defines(FrgShaderPreprocessorDefines); InsertPreProcessorDefinitions(ShaderCode, ProcessedShaderSource, Defines); m_CompiledAndReady = false; _ShaderCode = ProcessedShaderSource; } bool IOpenGLPixelShader::Compile() { GLint CodeSize = (GLint) _ShaderCode.size(); if (CodeSize == 0) { nuxDebugMsg("[IOpenGLPixelShader::Compile] Pixel shader source code is empty."); } char *ShaderSource = new char[CodeSize+1]; Memset(ShaderSource, 0, CodeSize + 1); Memcpy(ShaderSource, _ShaderCode.c_str(), CodeSize); CHECKGL(glShaderSource(_OpenGLID, 1, (const GLcharARB **) &ShaderSource, &CodeSize)); delete [] ShaderSource; // compile pixel shader object CHECKGL(glCompileShader(_OpenGLID)); // check if shader compiled m_CompiledAndReady = false; CHECKGL(glGetShaderiv(_OpenGLID, GL_COMPILE_STATUS, &m_CompiledAndReady)); if (!m_CompiledAndReady) { ANSICHAR *InfoLogBuffer = 0; GLint InfoLogBufferSize = 0; GLint InfoLogReturnSize = 0; GLint iLog = 0; glGetShaderiv(_OpenGLID, GL_INFO_LOG_LENGTH, &iLog); InfoLogBuffer = new ANSICHAR[iLog+1]; InfoLogBufferSize = iLog + 1; glGetShaderInfoLog(_OpenGLID, InfoLogBufferSize, &InfoLogReturnSize, InfoLogBuffer); if (InfoLogReturnSize != 0) { nuxError("[IOpenGLPixelShader::Compile] glCompileShader: %s", InfoLogBuffer); } printf("Error: %s \n COMPILE \n", InfoLogBuffer); delete[] InfoLogBuffer; } return m_CompiledAndReady; } bool IOpenGLPixelShader::IsValid() { return m_CompiledAndReady; } #if 0 IOpenGLGeometryShader::IOpenGLGeometryShader(std::string ShaderName) : IOpenGLShader(ShaderName, RT_GLSL_GEOMETRYSHADER) , m_CompiledAndReady(false) { _OpenGLID = glCreateShader(GL_GEOMETRY_SHADER); CHECKGL_MSG(glCreateShader(GL_GEOMETRY_SHADER)); } IOpenGLGeometryShader::~IOpenGLGeometryShader() { CHECKGL(glDeleteShader(_OpenGLID)); _OpenGLID = 0; m_CompiledAndReady = false; } void IOpenGLGeometryShader::SetShaderCode(const char *ShaderCode, const char *GeometryShaderPreprocessorDefines) { nuxAssertMsg(ShaderCode, "[IOpenGLGeometryShader::SetShaderCode] Invalid shader code."); NUX_RETURN_IF_NULL(ShaderCode); std::string ProcessedShaderSource; std::string Defines(GeometryShaderPreprocessorDefines); InsertPreProcessorDefinitions(ShaderCode, ProcessedShaderSource, Defines); m_CompiledAndReady = false; _ShaderCode = ProcessedShaderSource; } bool IOpenGLGeometryShader::Compile() { GLint CodeSize = (GLint) _ShaderCode.Size(); if (CodeSize == 0) { nuxDebugMsg("[IOpenGLGeometryShader::Compile] Pixel shader source code is empty."); } char *ShaderSource = new char[CodeSize+1]; Memset(ShaderSource, 0, CodeSize + 1); Memcpy(ShaderSource, _ShaderCode.m_string.c_str(), CodeSize); CHECKGL(glShaderSource(_OpenGLID, 1, (const GLcharARB **) &ShaderSource, &CodeSize)); delete [] ShaderSource; // compile pixel shader object CHECKGL(glCompileShader(_OpenGLID)); // check if shader compiled m_CompiledAndReady = false; CHECKGL(glGetShaderiv(_OpenGLID, GL_COMPILE_STATUS, &m_CompiledAndReady)); if (!m_CompiledAndReady) { ANSICHAR *InfoLogBuffer = 0; GLint InfoLogBufferSize = 0; GLint InfoLogReturnSize = 0; GLint iLog = 0; glGetShaderiv(_OpenGLID, GL_INFO_LOG_LENGTH, &iLog); InfoLogBuffer = new ANSICHAR[iLog+1]; InfoLogBufferSize = iLog + 1; glGetShaderInfoLog(_OpenGLID, InfoLogBufferSize, &InfoLogReturnSize, InfoLogBuffer); if (InfoLogReturnSize != 0) { nuxError("[IOpenGLGeometryShader::Compile] glCompileShader: %s", InfoLogBuffer); } delete InfoLogBuffer; } return m_CompiledAndReady; } bool IOpenGLGeometryShader::IsValid() { return m_CompiledAndReady; } void IOpenGLGeometryShader::SetInputPrimitiveType(GLenum type) { CHECKGL(glProgramParameteri(_OpenGLID, GL_GEOMETRY_INPUT_TYPE_EXT, type)); } void IOpenGLGeometryShader::SetOutputPrimitiveType(GLenum type) { CHECKGL(glProgramParameteri(_OpenGLID, GL_GEOMETRY_OUTPUT_TYPE_EXT, type)); } void IOpenGLGeometryShader::SetMaxVertexOutput(int max_vertex_output) { CHECKGL(glProgramParameteri(_OpenGLID, GL_GEOMETRY_VERTICES_OUT_EXT, max_vertex_output)); } #endif IOpenGLShaderProgram::IOpenGLShaderProgram(std::string ShaderProgramName) : IOpenGLResource(RT_GLSL_SHADERPROGRAM) , _FirstParameter(0) , m_CompiledAndReady(false) , _ShaderProgramName(ShaderProgramName) { _OpenGLID = glCreateProgram(); CHECKGL_MSG( glCreateProgram()); } IOpenGLShaderProgram::~IOpenGLShaderProgram() { if (local::last_loaded_shader == _OpenGLID) { CHECKGL(glUseProgramObjectARB(0)); local::last_loaded_shader = 0; } CHECKGL(glDeleteProgram(_OpenGLID)); _OpenGLID = 0; m_CompiledAndReady = false; } void IOpenGLShaderProgram::LoadIShaderFile(const char *ShaderFileName, const char *VtxShaderPreprocessorDefines, const char *FrgShaderPreprocessorDefines) { nuxAssertMsg(ShaderFileName, "[IOpenGLShaderProgram::LoadIShaderFile] Invalid shader file name."); NUX_RETURN_IF_NULL(ShaderFileName); std::string SourceCode; LoadFileToString(SourceCode, ShaderFileName); LoadIShader(&SourceCode[0], VtxShaderPreprocessorDefines, FrgShaderPreprocessorDefines); } void IOpenGLShaderProgram::LoadIShader(const char *ShaderCode, const char *VtxShaderPreprocessorDefines, const char *FrgShaderPreprocessorDefines) { nuxAssertMsg(ShaderCode, "[IOpenGLShaderProgram::LoadIShader] Invalid shader code."); NUX_RETURN_IF_NULL(ShaderCode); std::string VertexShaderSource; ExtractShaderString3("[Vertex Shader]", ShaderCode, VertexShaderSource, std::string(VtxShaderPreprocessorDefines)); std::string PixelShaderSource; ExtractShaderString3("[Fragment Shader]", ShaderCode, PixelShaderSource, std::string(FrgShaderPreprocessorDefines)); ObjectPtr vs = GetGraphicsDisplay()->GetGpuDevice()->CreateVertexShader(); //new IOpenGLVertexShader; ObjectPtr ps = GetGraphicsDisplay()->GetGpuDevice()->CreatePixelShader(); //new IOpenGLPixelShader; vs->SetShaderCode(VertexShaderSource.c_str()); ps->SetShaderCode(PixelShaderSource.c_str()); vs->Compile(); ps->Compile(); ShaderObjectList.clear(); AddShaderObject(vs); AddShaderObject(ps); } void IOpenGLShaderProgram::LoadVertexShader(const char *glslshader, const char *VtxShaderPreprocessorDefines) { nuxAssertMsg(glslshader, "[IOpenGLShaderProgram::LoadVertexShader] Invalid shader code."); NUX_RETURN_IF_NULL(glslshader); ObjectPtr vs = GetGraphicsDisplay()->GetGpuDevice()->CreateVertexShader(); //new IOpenGLVertexShader; std::string ProcessedShaderSource; if(!VtxShaderPreprocessorDefines) { VtxShaderPreprocessorDefines = ""; } std::string Defines(VtxShaderPreprocessorDefines); InsertPreProcessorDefinitions(glslshader, ProcessedShaderSource, Defines); vs->SetShaderCode(glslshader); vs->Compile(); AddShaderObject(vs); } void IOpenGLShaderProgram::LoadPixelShader(const char *glslshader, const char *FrgShaderPreprocessorDefines) { nuxAssertMsg(glslshader, "[IOpenGLShaderProgram::LoadPixelShader] Invalid shader code."); NUX_RETURN_IF_NULL(glslshader); ObjectPtr ps = GetGraphicsDisplay()->GetGpuDevice()->CreatePixelShader(); //new IOpenGLPixelShader; std::string ProcessedShaderSource; if (!FrgShaderPreprocessorDefines) { FrgShaderPreprocessorDefines = ""; } std::string Defines(FrgShaderPreprocessorDefines); InsertPreProcessorDefinitions(glslshader, ProcessedShaderSource, Defines); ps->SetShaderCode(glslshader); ps->Compile(); AddShaderObject(ps); } void IOpenGLShaderProgram::AddShaderObject(ObjectPtr ShaderObject) { ShaderObjectList.push_back(ShaderObject); } void IOpenGLShaderProgram::AddShaderParameter(GLShaderParameter* parameter) { GLShaderParameter* temp = _FirstParameter; while (temp) { if (temp == parameter) { // Parameter already added return; } temp = temp->m_NextParameter; } parameter->m_NextParameter = _FirstParameter; _FirstParameter = parameter; // If we add shader parameters after the program is linked, we need to call CheckUniformLocation(). CheckUniformLocation(); } void IOpenGLShaderProgram::RemoveShaderObject(ObjectPtr ShaderObject) { std::vector< ObjectPtr >::iterator it = find(ShaderObjectList.begin(), ShaderObjectList.end(), ShaderObject); if (it != ShaderObjectList.end()) { ShaderObjectList.erase(it); } } void IOpenGLShaderProgram::ClearShaderObjects() { ShaderObjectList.clear(); } bool IOpenGLShaderProgram::Link() { // Get the number of attached shaders. GLint NumAttachedShaders; CHECKGL(glGetProgramiv(_OpenGLID, GL_ATTACHED_SHADERS, &NumAttachedShaders)); GLuint *ShaderObjects = 0; if (NumAttachedShaders) { ShaderObjects = new GLuint[NumAttachedShaders]; } CHECKGL(glGetAttachedShaders(_OpenGLID, NumAttachedShaders, NULL, ShaderObjects)); // Detach everything first for (int i = 0; i < (int) NumAttachedShaders; i++) { unsigned int obj = ShaderObjects[i]; CHECKGL(glDetachShader(_OpenGLID, obj)); } if (NumAttachedShaders) { delete[] ShaderObjects; } for (int i = 0; i < (int) ShaderObjectList.size(); i++) { if (!ShaderObjectList[i]->IsValid()) { if (ShaderObjectList[i]->Compile() == false) { nuxDebugMsg("[IOpenGLShaderProgram::Link] Attached shader %s does not compile with program: %s.", ShaderObjectList[i]->_ShaderName.c_str(), _ShaderProgramName.c_str()); } } unsigned int obj = ShaderObjectList[i]->GetOpenGLID(); CHECKGL(glAttachShader(_OpenGLID, obj)); } GLint linked; CHECKGL(glLinkProgram(_OpenGLID)); CHECKGL(glGetProgramiv(_OpenGLID, GL_LINK_STATUS, &linked)); if (linked == GL_FALSE) { ANSICHAR *InfoLogBuffer = 0; GLint InfoLogBufferSize = 0; GLint InfoLogReturnSize = 0; GLint iLog = 0; glGetProgramiv(_OpenGLID, GL_INFO_LOG_LENGTH, &iLog); InfoLogBuffer = new ANSICHAR[iLog+1]; InfoLogBufferSize = iLog + 1; glGetProgramInfoLog(_OpenGLID, InfoLogBufferSize, &InfoLogReturnSize, InfoLogBuffer); if (InfoLogReturnSize != 0) { nuxError("[IOpenGLShaderProgram::Link] glLinkProgram: %s", InfoLogBuffer); } delete[] InfoLogBuffer; m_CompiledAndReady = false; return m_CompiledAndReady; } GLint validated; // glValidateProgram checks to see whether the executables contained in program can execute given the current OpenGL state. CHECKGL(glValidateProgram(_OpenGLID)); CHECKGL(glGetProgramiv(_OpenGLID, GL_VALIDATE_STATUS, &validated)); if (validated == GL_FALSE) { ANSICHAR *InfoLogBuffer = 0; GLint InfoLogBufferSize = 0; GLint InfoLogReturnSize = 0; GLint iLog = 0; glGetProgramiv(_OpenGLID, GL_INFO_LOG_LENGTH, &iLog); InfoLogBuffer = new ANSICHAR[iLog+1]; InfoLogBufferSize = iLog + 1; glGetProgramInfoLog(_OpenGLID, InfoLogBufferSize, &InfoLogReturnSize, InfoLogBuffer); if (InfoLogReturnSize != 0) { nuxError("[IOpenGLShaderProgram::Link] glValidateProgram: %s", InfoLogBuffer); } delete [] InfoLogBuffer; } m_CompiledAndReady = true; Begin(); CheckUniformLocation(); CheckAttributeLocation(); End(); return m_CompiledAndReady; } void IOpenGLShaderProgram::SetShaderTracking(bool enabled) { local::enable_tracking = enabled; local::last_loaded_shader = 0; CHECKGL(glUseProgramObjectARB(0)); } void IOpenGLShaderProgram::Begin(void) { if (local::last_loaded_shader == _OpenGLID && local::enable_tracking) return; local::last_loaded_shader = _OpenGLID; CHECKGL(glUseProgramObjectARB(_OpenGLID)); } void IOpenGLShaderProgram::End(void) { if (!local::enable_tracking) CHECKGL(glUseProgramObjectARB(0)); } void IOpenGLShaderProgram::CheckAttributeLocation() { //ResetAttributeVariable(m_ProgramAttributeDefinition); for (int i = 0; i < NUM_VERTEX_SHADER_INPUT_ATTRIBUTE; i++) { m_ProgramAttributeDefinition[i].attribute_index = -1; m_ProgramAttributeDefinition[i].attribute_name = ""; m_ProgramAttributeDefinition[i].type = VAT_UNDEFINED; m_ProgramAttributeDefinition[i].valid = false; } char active_attribute_name[256]; GLsizei length; GLint size; GLenum type; GLint num_active_attributes; CHECKGL(glGetObjectParameterivARB(_OpenGLID, GL_OBJECT_ACTIVE_ATTRIBUTES_ARB, &num_active_attributes)); // Vertex Attribute Aliasing // GLSL attempts to eliminate aliasing of vertex attributes but this is integral to NVIDIA's hardware // approach and necessary for maintaining compatibility with existing OpenGL applications that NVIDIA customers rely on. // NVIDIA's GLSL implementation therefore does not allow built-in vertex attributes to collide with a // generic vertex attributes that is assigned to a particular vertex attribute index with glBindAttribLocation. // For example, you should not use gl_Normal(a built-in vertex attribute) and also use glBindAttribLocation to // bind a generic vertex attribute named "whatever" to vertex attribute index 2 because gl_Normal aliases to index 2. // // Built-in vertex attribute name Incompatible aliased vertex attribute index // gl_Vertex 0 // gl_Normal 2 // gl_Color 3 // gl_SecondaryColor 4 // gl_FogCoord 5 // gl_MultiTexCoord0 8 // gl_MultiTexCoord1 9 // gl_MultiTexCoord2 10 // gl_MultiTexCoord3 11 // gl_MultiTexCoord4 12 // gl_MultiTexCoord5 13 // gl_MultiTexCoord6 14 // gl_MultiTexCoord7 15 // The compiler will automatically assign vertex shader attribute variables not pre-assigned // by glBindAttribLocation to locations that do not collide with any built-in attribute variables // used by the vertex shader. The assigned locations can be queries with glGetAttribLocation. // This means that a developer only needs to worry about collisions when they are explicitly requesting // an attribute to be bound to a specific location. for (int index = 0; index < num_active_attributes; index++) { glGetActiveAttribARB(_OpenGLID, index, 256, &length, &size, &type, active_attribute_name); CHECKGL_MSG( glGetActiveAttribARB ); m_ProgramAttributeDefinition[index].attribute_index = glGetAttribLocationARB(_OpenGLID, active_attribute_name); CHECKGL_MSG( glGetAttribLocationARB ); m_ProgramAttributeDefinition[index].attribute_name = active_attribute_name; m_ProgramAttributeDefinition[index].valid = true; switch(type) { case GL_FLOAT: m_ProgramAttributeDefinition[index].type = VAT_FLOAT; break; case GL_FLOAT_VEC2: m_ProgramAttributeDefinition[index].type = VAT_FLOAT2; break; case GL_FLOAT_VEC3: m_ProgramAttributeDefinition[index].type = VAT_FLOAT3; break; case GL_FLOAT_VEC4: m_ProgramAttributeDefinition[index].type = VAT_FLOAT4; break; case GL_FLOAT_MAT2: case GL_FLOAT_MAT3: case GL_FLOAT_MAT4: default: //todo nuxAssert(0); } } } void IOpenGLShaderProgram::CheckUniformLocation() { GLShaderParameter *parameter = _FirstParameter; while (m_CompiledAndReady && parameter) { int location = glGetUniformLocationARB(_OpenGLID, parameter->m_Name.c_str()); CHECKGL_MSG(glGetUniformLocationARB(_OpenGLID, parameter->m_Name.c_str())); //nuxDebugMsg("[IOpenGLShaderProgram::CheckUniformLocation] prog: %d, name: %s, location index: %d", _OpenGLID, parameter->m_Name.c_str(), location); if ((location == -1) && (!parameter->m_bIsOptional)) { nuxDebugMsg("[IOpenGLShaderProgram::CheckUniformLocation] Couldn't find shader program parameter %s \n", parameter->m_Name.c_str()); nuxAssert(0); } parameter->m_Index = location; parameter = parameter->m_NextParameter; } } int IOpenGLShaderProgram::GetAttributeLocation(const char *AttributeName) { for (int i = 0; i < 16 /*NUM_VERTEX_SHADER_INPUT_ATTRIBUTE*/; i++) { if (m_ProgramAttributeDefinition[i].attribute_name == AttributeName) return m_ProgramAttributeDefinition[i].attribute_index; } return -1; } bool IOpenGLShaderProgram::SetUniform1f(char *varname, GLfloat v0) { GLint loc = GetUniformLocationARB(varname); if (loc == -1) return false; // can't find variable glUniform1fARB(loc, v0); return true; } bool IOpenGLShaderProgram::SetUniform1f(GLint loc, GLfloat v0) { if (loc == -1) return false; // can't find variable glUniform1fARB(loc, v0); return true; } bool IOpenGLShaderProgram::SetUniform2f(char *varname, GLfloat v0, GLfloat v1) { GLint loc = GetUniformLocationARB(varname); if (loc == -1) return false; // can't find variable glUniform2fARB(loc, v0, v1); return true; } bool IOpenGLShaderProgram::SetUniform2f(GLint loc, GLfloat v0, GLfloat v1) { if (loc == -1) return false; // can't find variable glUniform2fARB(loc, v0, v1); return true; } bool IOpenGLShaderProgram::SetUniform3f(char *varname, GLfloat v0, GLfloat v1, GLfloat v2) { GLint loc = GetUniformLocationARB(varname); if (loc == -1) return false; // can't find variable glUniform3fARB(loc, v0, v1, v2); return true; } bool IOpenGLShaderProgram::SetUniform3f(GLint loc, GLfloat v0, GLfloat v1, GLfloat v2) { if (loc == -1) return false; // can't find variable glUniform3fARB(loc, v0, v1, v2); return true; } bool IOpenGLShaderProgram::SetUniform4f(char *varname, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) { GLint loc = GetUniformLocationARB(varname); if (loc == -1) return false; // can't find variable glUniform4fARB(loc, v0, v1, v2, v3); return true; } bool IOpenGLShaderProgram::SetUniform4f(GLint loc, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) { if (loc == -1) return false; // can't find variable glUniform4fARB(loc, v0, v1, v2, v3); return true; } bool IOpenGLShaderProgram::SetUniform1i(char *varname, GLint v0) { GLint loc = GetUniformLocationARB(varname); if (loc == -1) return false; // can't find variable glUniform1iARB(loc, v0); return true; } bool IOpenGLShaderProgram::SetUniform1i(GLint loc, GLint v0) { if (loc == -1) return false; // can't find variable glUniform1iARB(loc, v0); return true; } bool IOpenGLShaderProgram::SetUniform2i(char *varname, GLint v0, GLint v1) { GLint loc = GetUniformLocationARB(varname); if (loc == -1) return false; // can't find variable glUniform2iARB(loc, v0, v1); return true; } bool IOpenGLShaderProgram::SetUniform2i(GLint loc, GLint v0, GLint v1) { if (loc == -1) return false; // can't find variable glUniform2iARB(loc, v0, v1); return true; } bool IOpenGLShaderProgram::SetUniform3i(char *varname, GLint v0, GLint v1, GLint v2) { GLint loc = GetUniformLocationARB(varname); if (loc == -1) return false; // can't find variable glUniform3iARB(loc, v0, v1, v2); return true; } bool IOpenGLShaderProgram::SetUniform3i(GLint loc, GLint v0, GLint v1, GLint v2) { if (loc == -1) return false; // can't find variable glUniform3iARB(loc, v0, v1, v2); return true; } bool IOpenGLShaderProgram::SetUniform4i(char *varname, GLint v0, GLint v1, GLint v2, GLint v3) { GLint loc = GetUniformLocationARB(varname); if (loc == -1) return false; // can't find variable glUniform4iARB(loc, v0, v1, v2, v3); return true; } bool IOpenGLShaderProgram::SetUniform4i(GLint loc, GLint v0, GLint v1, GLint v2, GLint v3) { if (loc == -1) return false; // can't find variable glUniform4iARB(loc, v0, v1, v2, v3); return true; } bool IOpenGLShaderProgram::SetUniform1fv(char *varname, GLsizei count, GLfloat *value) { GLint loc = GetUniformLocationARB(varname); if (loc == -1) return false; // can't find variable glUniform1fvARB(loc, count, value); return true; } bool IOpenGLShaderProgram::SetUniform1fv(GLint loc, GLsizei count, GLfloat *value) { if (loc == -1) return false; // can't find variable glUniform1fvARB(loc, count, value); return true; } bool IOpenGLShaderProgram::SetUniform2fv(char *varname, GLsizei count, GLfloat *value) { GLint loc = GetUniformLocationARB(varname); if (loc == -1) return false; // can't find variable glUniform2fvARB(loc, count, value); return true; } bool IOpenGLShaderProgram::SetUniform2fv(GLint loc, GLsizei count, GLfloat *value) { if (loc == -1) return false; // can't find variable glUniform2fvARB(loc, count, value); return true; } bool IOpenGLShaderProgram::SetUniform3fv(char *varname, GLsizei count, GLfloat *value) { GLint loc = GetUniformLocationARB(varname); if (loc == -1) return false; // can't find variable glUniform3fvARB(loc, count, value); return true; } bool IOpenGLShaderProgram::SetUniform3fv(GLint loc, GLsizei count, GLfloat *value) { if (loc == -1) return false; // can't find variable glUniform3fvARB(loc, count, value); return true; } bool IOpenGLShaderProgram::SetUniform4fv(char *varname, GLsizei count, GLfloat *value) { GLint loc = GetUniformLocationARB(varname); if (loc == -1) return false; // can't find variable glUniform4fvARB(loc, count, value); return true; } bool IOpenGLShaderProgram::SetUniform4fv(GLint loc, GLsizei count, GLfloat *value) { if (loc == -1) return false; // can't find variable glUniform4fvARB(loc, count, value); return true; } bool IOpenGLShaderProgram::SetUniform1iv(char *varname, GLsizei count, GLint *value) { GLint loc = GetUniformLocationARB(varname); if (loc == -1) return false; // can't find variable glUniform1ivARB(loc, count, value); return true; } bool IOpenGLShaderProgram::SetUniform1iv(GLint loc, GLsizei count, GLint *value) { if (loc == -1) return false; // can't find variable glUniform1ivARB(loc, count, value); return true; } bool IOpenGLShaderProgram::SetUniform2iv(char *varname, GLsizei count, GLint *value) { GLint loc = GetUniformLocationARB(varname); if (loc == -1) return false; // can't find variable glUniform2ivARB(loc, count, value); return true; } bool IOpenGLShaderProgram::SetUniform2iv(GLint loc, GLsizei count, GLint *value) { if (loc == -1) return false; // can't find variable glUniform2ivARB(loc, count, value); return true; } bool IOpenGLShaderProgram::SetUniform3iv(char *varname, GLsizei count, GLint *value) { GLint loc = GetUniformLocationARB(varname); if (loc == -1) return false; // can't find variable glUniform3ivARB(loc, count, value); return true; } bool IOpenGLShaderProgram::SetUniform3iv(GLint loc, GLsizei count, GLint *value) { if (loc == -1) return false; // can't find variable glUniform3ivARB(loc, count, value); return true; } bool IOpenGLShaderProgram::SetUniform4iv(char *varname, GLsizei count, GLint *value) { GLint loc = GetUniformLocationARB(varname); if (loc == -1) return false; // can't find variable glUniform4ivARB(loc, count, value); return true; } bool IOpenGLShaderProgram::SetUniform4iv(GLint loc, GLsizei count, GLint *value) { if (loc == -1) return false; // can't find variable glUniform4ivARB(loc, count, value); return true; } bool IOpenGLShaderProgram::SetUniformMatrix2fv(char *varname, GLsizei count, GLboolean transpose, GLfloat *value) { GLint loc = GetUniformLocationARB(varname); if (loc == -1) return false; // can't find variable glUniformMatrix2fvARB(loc, count, transpose, value); return true; } bool IOpenGLShaderProgram::SetUniformLocMatrix2fv(GLint loc, GLsizei count, GLboolean transpose, GLfloat *value) { if (loc == -1) return false; // can't find variable glUniformMatrix2fvARB(loc, count, transpose, value); return true; } bool IOpenGLShaderProgram::SetUniformMatrix3fv(char *varname, GLsizei count, GLboolean transpose, GLfloat *value) { GLint loc = GetUniformLocationARB(varname); if (loc == -1) return false; // can't find variable glUniformMatrix3fvARB(loc, count, transpose, value); return true; } bool IOpenGLShaderProgram::SetUniformLocMatrix3fv(GLint loc, GLsizei count, GLboolean transpose, GLfloat *value) { if (loc == -1) return false; // can't find variable glUniformMatrix3fvARB(loc, count, transpose, value); return true; } bool IOpenGLShaderProgram::SetUniformMatrix4fv(char *varname, GLsizei count, GLboolean transpose, GLfloat *value) { GLint loc = GetUniformLocationARB(varname); if (loc == -1) return false; // can't find variable glUniformMatrix4fvARB(loc, count, transpose, value); return true; } bool IOpenGLShaderProgram::SetUniformLocMatrix4fv(GLint loc, GLsizei count, GLboolean transpose, GLfloat *value) { if (loc == -1) return false; // can't find variable glUniformMatrix4fvARB(loc, count, transpose, value); return true; } void IOpenGLShaderProgram::GetUniformfv(char *name, GLfloat *values) { GLint loc; loc = glGetUniformLocationARB(_OpenGLID, name); CHECKGL_MSG( glGetUniformLocationARB ); if (loc == -1) { std::cout << "Error: can't find uniform variable \"" << name << "\"\n"; } CHECKGL(glGetUniformfvARB(_OpenGLID, loc, values)); } void IOpenGLShaderProgram::GetUniformiv(char *name, GLint *values) { GLint loc; loc = glGetUniformLocationARB(_OpenGLID, name); CHECKGL_MSG( glGetUniformLocationARB ); if (loc == -1) { std::cout << "Error: can't find uniform variable \"" << name << "\"\n"; } CHECKGL(glGetUniformivARB(_OpenGLID, loc, values)); } int IOpenGLShaderProgram::GetUniformLocationARB(const GLcharARB *name) { GLint loc; loc = glGetUniformLocationARB(_OpenGLID, name); CHECKGL_MSG( glGetUniformLocationARB ); return loc; } void IOpenGLShaderProgram::GetActiveUniformARB( GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name) { glGetActiveUniformARB(_OpenGLID, index, maxLength, length, size, type, name); CHECKGL_MSG(glGetActiveUniformARB); } void IOpenGLShaderProgram::GetObjectParameterfvARB(GLenum pname, GLfloat *params) { #ifndef NUX_OPENGLES_20 glGetObjectParameterfvARB(_OpenGLID, pname, params); CHECKGL_MSG(glGetObjectParameterfvARB); #endif } bool IOpenGLShaderProgram::SetSampler(char *name, int texture_unit) { GLint loc = GetUniformLocationARB(name); if (loc == -1) return false; // can't find variable glUniform1iARB(loc, texture_unit); return true; } } ./NuxGraphics/RunTimeStats.h0000644000004100000410000000424413313171755016263 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef RUNTIMESTATS_H #define RUNTIMESTATS_H namespace nux { class RenderingStats { NUX_DECLARE_GLOBAL_OBJECT(RenderingStats, NuxGraphicsGlobalSingletonInitializer); public: static unsigned int m_NumTex2D; static unsigned int m_GPUSizeTex2D; static unsigned int m_NumTexRectangle; static unsigned int m_GPUSizeTexRectangle; static unsigned int m_NumTexCube; static unsigned int m_GPUSizeTexCube; static unsigned int m_NumTexVolume; static unsigned int m_GPUSizeTexVolume; static unsigned int m_NumTexAnimated; static unsigned int m_GPUSizeTexAnimated; static unsigned int m_NumPBO; static unsigned int m_GPUSizePBO; static unsigned int m_NumFrameBufferObject; static unsigned int m_NumQueryObject; static unsigned int m_NumVertexBuffer; static unsigned int m_GPUSizeVertexBuffer; static unsigned int m_NumIndexBuffer; static unsigned int m_GPUSizeIndexBuffer; static unsigned int m_NumVertexShader; static unsigned int m_NumPixelShader; static unsigned int m_NumShaderProgram; static unsigned int m_TotalGPUSize; void Register(IOpenGLResource *GraphicsObject); void UnRegister(IOpenGLResource *GraphicsObject); std::vector _texture_2d_array; std::vector _texture_rect_array; }; } #define GRunTimeStats NUX_GLOBAL_OBJECT_INSTANCE(nux::RenderingStats) #endif // RUNTIMESTATS_H ./NuxGraphics/RenderingPipeTextureBlend.cpp0000644000004100000410000006721213313171755021301 0ustar www-datawww-data/* * Copyright 2010-2012 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * Robert Carr */ #include "NuxCore/NuxCore.h" #include "ImageSurface.h" #include "GpuDevice.h" #include "GLDeviceObjects.h" #include "GLResourceManager.h" #include "GLTextureResourceManager.h" #include "GLVertexResourceManager.h" #include "GraphicsEngine.h" #include "RenderingPipeTextureBlendShaderSource.h" namespace nux { std::string GraphicsEngine::GetBlendModeBlendFunc(LayerBlendMode layer_blend_mode) { switch (layer_blend_mode) { case LAYER_BLEND_MODE_NORMAL: return BlendNormalShader; case LAYER_BLEND_MODE_DARKEN: return BlendDarkenShader; case LAYER_BLEND_MODE_MULTIPLY: return BlendMultiplyShader; case LAYER_BLEND_MODE_COLOR_BURN: return BlendColorBurnShader; case LAYER_BLEND_MODE_LINEAR_BURN: return BlendLinearBurnShader; case LAYER_BLEND_MODE_LIGHTEN: return BlendLightenShader; case LAYER_BLEND_MODE_SCREEN: return BlendScreenShader; case LAYER_BLEND_MODE_COLOR_DODGE: return BlendColorDodgeShader; case LAYER_BLEND_MODE_LINEAR_DODGE: return BlendLinearDodgeShader; case LAYER_BLEND_MODE_OVERLAY: return BlendOverlayShader; case LAYER_BLEND_MODE_SOFT_LIGHT: return BlendSoftLightShader; case LAYER_BLEND_MODE_HARD_LIGHT: return BlendHardLightShader; case LAYER_BLEND_MODE_VIVID_LIGHT: return BlendVividLightShader; case LAYER_BLEND_MODE_LINEAR_LIGHT: return BlendLinearLightShader; case LAYER_BLEND_MODE_PIN_LIGHT: return BlendPinLightShader; case LAYER_BLEND_MODE_HARD_MIX: return BlendHardMixShader; case LAYER_BLEND_MODE_DIFFERENCE: return BlendDifferenceShader; case LAYER_BLEND_MODE_EXCLUSION: return BlendExclusionShader; case LAYER_BLEND_MODE_SUBTRACT: return BlendSubstractShader; case LAYER_BLEND_MODE_AVERAGE: return BlendAverageShader; case LAYER_BLEND_MODE_ADD: return BlendAddShader; case LAYER_BLEND_MODE_NEGATION: return BlendNegationShader; case LAYER_BLEND_MODE_REFLECT: return BlendReflectShader; case LAYER_BLEND_MODE_GLOW: return BlendGlowShader; case LAYER_BLEND_MODE_PHOENIX: return BlendPhoenixShader; case LAYER_BLEND_MODE_LAST: return BlendNormalShader; default: return BlendNormalShader; } } std::string GraphicsEngine::GetBlendModeString(LayerBlendMode layer_blend_mode) { switch (layer_blend_mode) { case LAYER_BLEND_MODE_NORMAL: return std::string("BlendNormal"); case LAYER_BLEND_MODE_DARKEN: return std::string("BlendDarken"); case LAYER_BLEND_MODE_MULTIPLY: return std::string("BlendMultiply"); case LAYER_BLEND_MODE_COLOR_BURN: return std::string("BlendColorBurn"); case LAYER_BLEND_MODE_LINEAR_BURN: return std::string("BlendLinearBurn"); case LAYER_BLEND_MODE_LIGHTEN: return std::string("BlendLighten"); case LAYER_BLEND_MODE_SCREEN: return std::string("BlendScreen"); case LAYER_BLEND_MODE_COLOR_DODGE: return std::string("BlendColorDodge"); case LAYER_BLEND_MODE_LINEAR_DODGE: return std::string("BlendLinearDodge"); case LAYER_BLEND_MODE_OVERLAY: return std::string("BlendOverlay"); case LAYER_BLEND_MODE_SOFT_LIGHT: return std::string("BlendSoftLight"); case LAYER_BLEND_MODE_HARD_LIGHT: return std::string("BlendHardLight"); case LAYER_BLEND_MODE_VIVID_LIGHT: return std::string("BlendVividLight"); case LAYER_BLEND_MODE_LINEAR_LIGHT: return std::string("BlendLinearLight"); case LAYER_BLEND_MODE_PIN_LIGHT: return std::string("BlendPinLight"); case LAYER_BLEND_MODE_HARD_MIX: return std::string("BlendHardMix"); case LAYER_BLEND_MODE_DIFFERENCE: return std::string("BlendDifference"); case LAYER_BLEND_MODE_EXCLUSION: return std::string("BlendExclusion"); case LAYER_BLEND_MODE_SUBTRACT: return std::string("BlendSubstract"); case LAYER_BLEND_MODE_AVERAGE: return std::string("BlendAverage"); case LAYER_BLEND_MODE_ADD: return std::string("BlendAdd"); case LAYER_BLEND_MODE_NEGATION: return std::string("BlendNegation"); case LAYER_BLEND_MODE_REFLECT: return std::string("BlendReflect"); case LAYER_BLEND_MODE_GLOW: return std::string("BlendGlow"); case LAYER_BLEND_MODE_PHOENIX: return std::string("BlendPhoenix"); case LAYER_BLEND_MODE_LAST: return std::string("BlendNormal"); default: return std::string("BlendNormal"); } } ObjectPtr GraphicsEngine::GetColorBlendOverTexProgram(LayerBlendMode layer_blend_mode) { if (blend_tex_color_prog_[layer_blend_mode].IsValid()) { return blend_tex_color_prog_[layer_blend_mode]; } ObjectPtr VS = _graphics_display.m_DeviceFactory->CreateVertexShader(); ObjectPtr PS = _graphics_display.m_DeviceFactory->CreatePixelShader(); const std::string vertex_code = NUX_VERTEX_SHADER_HEADER "uniform mat4 view_projection_matrix; \n\ attribute vec4 in_vertex; \n\ attribute vec4 in_bkg_tex_coord; \n\ varying vec4 bkg_tex_coord; \n\ void main() \n\ { \n\ gl_Position = view_projection_matrix * (in_vertex); \n\ bkg_tex_coord = in_bkg_tex_coord; \n\ }"; const std::string pixel_code = NUX_FRAGMENT_SHADER_HEADER "uniform vec4 bkg_color; \n\ uniform sampler2D bkg_texture; \n\ uniform vec4 frg_color; \n\ varying vec4 bkg_tex_coord; \n\ %s \n\ void main() \n\ { \n\ vec4 tex = texture2D(bkg_texture, bkg_tex_coord.st) * bkg_color; \n\ gl_FragColor.rgb = mix(tex.rgb,%s(tex.rgb, frg_color.rgb), frg_color.a); \n\ gl_FragColor.a = 1.0; \n\ }"; int safe_area = 10; int code_buffer_size = pixel_code.length(); code_buffer_size += GetBlendModeBlendFunc(layer_blend_mode).length(); code_buffer_size += GetBlendModeString(layer_blend_mode).length() + safe_area; char* shader_prog = new char[code_buffer_size]; std::memset(shader_prog, 0, code_buffer_size); sprintf(shader_prog, pixel_code.c_str(), GetBlendModeBlendFunc(layer_blend_mode).c_str(), GetBlendModeString(layer_blend_mode).c_str()); blend_tex_color_prog_[layer_blend_mode] = _graphics_display.m_DeviceFactory->CreateShaderProgram(); VS->SetShaderCode(vertex_code.c_str()); PS->SetShaderCode(shader_prog); delete [] shader_prog; blend_tex_color_prog_[layer_blend_mode]->ClearShaderObjects(); blend_tex_color_prog_[layer_blend_mode]->AddShaderObject(VS); blend_tex_color_prog_[layer_blend_mode]->AddShaderObject(PS); CHECKGL(glBindAttribLocation(blend_tex_color_prog_[layer_blend_mode]->GetOpenGLID(), 0, "in_vertex")); blend_tex_color_prog_[layer_blend_mode]->Link(); return blend_tex_color_prog_[layer_blend_mode]; } void GraphicsEngine::QRP_GLSL_ColorLayerOverTexture(int x, int y, int width, int height, ObjectPtr bkg_device_texture, TexCoordXForm& bkg_texxform, const Color& bkg_color, const Color& frg_color, LayerBlendMode layer_blend_mode) { if (!UsingGLSLCodePath()) return; ObjectPtr ShaderProg = GetColorBlendOverTexProgram(layer_blend_mode); m_quad_tex_stats++; QRP_Compute_Texture_Coord(width, height, bkg_device_texture, bkg_texxform); float fx = x, fy = y; float vtx_buffer[] = { fx, fy, 0.0f, 1.0f, bkg_texxform.u0, bkg_texxform.v0, 0, 0, fx, fy + height, 0.0f, 1.0f, bkg_texxform.u0, bkg_texxform.v1, 0, 0, fx + width, fy + height, 0.0f, 1.0f, bkg_texxform.u1, bkg_texxform.v1, 0, 0, fx + width, fy, 0.0f, 1.0f, bkg_texxform.u1, bkg_texxform.v0, 0, 0, }; CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); ShaderProg->Begin(); int in_vertex_loc = ShaderProg->GetAttributeLocation("in_vertex"); int in_bkg_tex_coord_loc = ShaderProg->GetAttributeLocation("in_bkg_tex_coord"); int bkg_texture_loc = ShaderProg->GetUniformLocationARB("bkg_texture"); int bkg_color_loc = ShaderProg->GetUniformLocationARB("bkg_color"); int frg_color_loc = ShaderProg->GetUniformLocationARB("frg_color"); SetTexture(GL_TEXTURE0, bkg_device_texture); CHECKGL(glUniform1iARB(bkg_texture_loc, 0)); if (bkg_color_loc != -1) { CHECKGL(glUniform4fARB(bkg_color_loc, bkg_color.red, bkg_color.green, bkg_color.blue, bkg_color.alpha)); } if (frg_color_loc != -1) { CHECKGL(glUniform4fARB(frg_color_loc, frg_color.red, frg_color.green, frg_color.blue, frg_color.alpha)); } int view_projection_matrix_loc = ShaderProg->GetUniformLocationARB("view_projection_matrix"); Matrix4 mvp_matrix = GetOpenGLModelViewProjectionMatrix(); ShaderProg->SetUniformLocMatrix4fv((GLint) view_projection_matrix_loc, 1, false, (GLfloat*) & (mvp_matrix.m)); if (in_vertex_loc != -1) { CHECKGL(glEnableVertexAttribArrayARB(in_vertex_loc)); CHECKGL(glVertexAttribPointerARB((GLuint) in_vertex_loc, 4, GL_FLOAT, GL_FALSE, 32, vtx_buffer)); } if (in_bkg_tex_coord_loc != -1) { CHECKGL(glEnableVertexAttribArrayARB(in_bkg_tex_coord_loc)); CHECKGL(glVertexAttribPointerARB((GLuint) in_bkg_tex_coord_loc, 4, GL_FLOAT, GL_FALSE, 32, vtx_buffer + 4)); } CHECKGL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); if (in_vertex_loc != -1) CHECKGL(glDisableVertexAttribArrayARB(in_vertex_loc)); if (in_bkg_tex_coord_loc != -1) CHECKGL(glDisableVertexAttribArrayARB(in_bkg_tex_coord_loc)); ShaderProg->End();; } ObjectPtr GraphicsEngine::GetTextureLayerOverColorProgram(LayerBlendMode layer_blend_mode) { if (blend_color_tex_prog_[layer_blend_mode].IsValid()) { return blend_color_tex_prog_[layer_blend_mode]; } ObjectPtr VS = _graphics_display.m_DeviceFactory->CreateVertexShader(); ObjectPtr PS = _graphics_display.m_DeviceFactory->CreatePixelShader(); std::string vertex_code = NUX_VERTEX_SHADER_HEADER "uniform mat4 view_projection_matrix; \n\ attribute vec4 in_vertex; \n\ attribute vec4 in_frg_tex_coord; \n\ varying vec4 frg_tex_coord; \n\ void main() \n\ { \n\ gl_Position = view_projection_matrix * (in_vertex); \n\ frg_tex_coord = in_frg_tex_coord; \n\ }"; std::string pixel_code = NUX_FRAGMENT_SHADER_HEADER "uniform vec4 frg_color; \n\ uniform sampler2D frg_texture; \n\ uniform vec4 bkg_color; \n\ varying vec4 frg_tex_coord; \n\ %s \n\ void main() \n\ { \n\ vec3 tex = texture2D(frg_texture, frg_tex_coord.st).rgb * frg_color.rgb; \n\ gl_FragColor.rgb = %s(bkg_color.rgb * bkg_color.aaa, tex.rgb * frg_color.aaa); \n\ gl_FragColor.a = 1.0; \n\ }"; int safe_area = 10; int code_buffer_size = pixel_code.length(); code_buffer_size += GetBlendModeBlendFunc(layer_blend_mode).length(); code_buffer_size += GetBlendModeString(layer_blend_mode).length() + safe_area; char* shader_prog = new char[code_buffer_size]; std::memset(shader_prog, 0, code_buffer_size); sprintf(shader_prog, pixel_code.c_str(), GetBlendModeBlendFunc(layer_blend_mode).c_str(), GetBlendModeString(layer_blend_mode).c_str()); blend_color_tex_prog_[layer_blend_mode] = _graphics_display.m_DeviceFactory->CreateShaderProgram(); VS->SetShaderCode(vertex_code.c_str()); PS->SetShaderCode(shader_prog); delete [] shader_prog; blend_color_tex_prog_[layer_blend_mode]->ClearShaderObjects(); blend_color_tex_prog_[layer_blend_mode]->AddShaderObject(VS); blend_color_tex_prog_[layer_blend_mode]->AddShaderObject(PS); CHECKGL(glBindAttribLocation(blend_color_tex_prog_[layer_blend_mode]->GetOpenGLID(), 0, "in_vertex")); blend_color_tex_prog_[layer_blend_mode]->Link(); return blend_color_tex_prog_[layer_blend_mode]; } void GraphicsEngine::QRP_GLSL_TextureLayerOverColor(int x, int y, int width, int height, const Color& bkg_color, ObjectPtr frg_device_texture, TexCoordXForm& frg_texxform, const Color& frg_color, LayerBlendMode layer_blend_mode) { if (!UsingGLSLCodePath()) return; ObjectPtr ShaderProg = GetTextureLayerOverColorProgram(layer_blend_mode); m_quad_tex_stats++; QRP_Compute_Texture_Coord(width, height, frg_device_texture, frg_texxform); float fx = x, fy = y; float vtx_buffer[] = { fx, fy, 0.0f, 1.0f, frg_texxform.u0, frg_texxform.v0, 0, 0, fx, fy + height, 0.0f, 1.0f, frg_texxform.u0, frg_texxform.v1, 0, 0, fx + width, fy + height, 0.0f, 1.0f, frg_texxform.u1, frg_texxform.v1, 0, 0, fx + width, fy, 0.0f, 1.0f, frg_texxform.u1, frg_texxform.v0, 0, 0, }; CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); ShaderProg->Begin(); int frg_texture_loc = ShaderProg->GetUniformLocationARB("frg_texture"); int frg_color_loc = ShaderProg->GetUniformLocationARB("frg_color"); int bkg_color_loc = ShaderProg->GetUniformLocationARB("bkg_color"); int in_vertex_loc = ShaderProg->GetAttributeLocation("in_vertex"); int in_frg_tex_coord_loc = ShaderProg->GetAttributeLocation("in_frg_tex_coord"); SetTexture(GL_TEXTURE0, frg_device_texture); CHECKGL(glUniform1iARB(frg_texture_loc, 0)); int view_projection_matrix_loc = ShaderProg->GetUniformLocationARB("view_projection_matrix"); Matrix4 mvp_matrix = GetOpenGLModelViewProjectionMatrix(); ShaderProg->SetUniformLocMatrix4fv((GLint) view_projection_matrix_loc, 1, false, (GLfloat*) & (mvp_matrix.m)); if (in_vertex_loc != -1) { CHECKGL(glEnableVertexAttribArrayARB(in_vertex_loc)); CHECKGL(glVertexAttribPointerARB((GLuint) in_vertex_loc, 4, GL_FLOAT, GL_FALSE, 32, vtx_buffer)); } if (in_frg_tex_coord_loc != -1) { CHECKGL(glEnableVertexAttribArrayARB(in_frg_tex_coord_loc)); CHECKGL(glVertexAttribPointerARB((GLuint) in_frg_tex_coord_loc, 4, GL_FLOAT, GL_FALSE, 32, vtx_buffer + 4)); } if (frg_color_loc != -1) { CHECKGL(glUniform4fARB(frg_color_loc, frg_color.red, frg_color.green, frg_color.blue, frg_color.alpha)); } if (bkg_color_loc != -1) { CHECKGL(glUniform4fARB(bkg_color_loc, bkg_color.red, bkg_color.green, bkg_color.blue, bkg_color.alpha)); } CHECKGL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); if (in_vertex_loc != -1) CHECKGL(glDisableVertexAttribArrayARB(in_vertex_loc)); if (in_frg_tex_coord_loc != -1) CHECKGL(glDisableVertexAttribArrayARB(in_frg_tex_coord_loc)); ShaderProg->End(); } ObjectPtr GraphicsEngine::GetColorLayerOverColorProgram(LayerBlendMode layer_blend_mode) { if (blend_color_color_prog_[layer_blend_mode].IsValid()) return blend_color_color_prog_[layer_blend_mode]; ObjectPtr vertexShader = _graphics_display.m_DeviceFactory->CreateVertexShader(); ObjectPtr pixelShader = _graphics_display.m_DeviceFactory->CreatePixelShader(); std::string vertex_code = NUX_VERTEX_SHADER_HEADER "uniform mat4 view_projection_matrix; \n\ attribute vec4 in_vertex; \n\ void main() \n\ { \n\ gl_Position = view_projection_matrix * in_vertex; \n\ }"; std::string pixel_code = NUX_FRAGMENT_SHADER_HEADER "uniform vec4 bkg_color; \n\ uniform vec4 frg_color; \n\ %s \n\ void main() \n\ { \n\ gl_FragColor.rgb = %s(bkg_color.rgb * bkg_color.aaa, frg_color.rgb * frg_color.aaa); \n\ gl_FragColor.a = 1.0; \n\ }"; int safe_area = 10; int code_buffer_size = pixel_code.length(); code_buffer_size += GetBlendModeBlendFunc(layer_blend_mode).length(); code_buffer_size += GetBlendModeString(layer_blend_mode).length() + safe_area; char* shader_prog = new char[code_buffer_size]; std::memset(shader_prog, 0, code_buffer_size); sprintf(shader_prog, pixel_code.c_str(), GetBlendModeBlendFunc(layer_blend_mode).c_str(), GetBlendModeString(layer_blend_mode).c_str()); blend_color_color_prog_[layer_blend_mode] = _graphics_display.m_DeviceFactory->CreateShaderProgram(); vertexShader->SetShaderCode(vertex_code.c_str()); pixelShader->SetShaderCode(shader_prog); delete [] shader_prog; blend_color_color_prog_[layer_blend_mode]->ClearShaderObjects(); blend_color_color_prog_[layer_blend_mode]->AddShaderObject(vertexShader); blend_color_color_prog_[layer_blend_mode]->AddShaderObject(pixelShader); CHECKGL(glBindAttribLocation(blend_color_color_prog_[layer_blend_mode]->GetOpenGLID(), 0, "in_vertex")); blend_color_color_prog_[layer_blend_mode]->Link(); return blend_color_color_prog_[layer_blend_mode]; } void GraphicsEngine::QRP_GLSL_ColorLayerOverColor(int x, int y, int width, int height, const Color& bkg_color, const Color& frg_color, LayerBlendMode layer_blend_mode) { if (!UsingGLSLCodePath()) return; ObjectPtr shader_prog = GetColorLayerOverColorProgram(layer_blend_mode); float fx = x, fy = y; float vtx_buffer[] = { fx, fy, 0.0f, 1.0f, fx, fy + height, 0.0f, 1.0f, fx + width, fy + height, 0.0f, 1.0f, fx + width, fy, 0.0f, 1.0f, }; CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); shader_prog->Begin(); int in_vertex_loc = shader_prog->GetAttributeLocation("in_vertex"); int bkg_color_loc = shader_prog->GetUniformLocationARB("bkg_color"); int frg_color_loc = shader_prog->GetUniformLocationARB("frg_color"); if (bkg_color_loc != -1) CHECKGL(glUniform4fARB(bkg_color_loc, bkg_color.red, bkg_color.green, bkg_color.blue, bkg_color.alpha)); if (frg_color_loc != -1) CHECKGL(glUniform4fARB(frg_color_loc, frg_color.red, frg_color.green, frg_color.blue, frg_color.alpha)); int view_projection_matrix_loc = shader_prog->GetUniformLocationARB("view_projection_matrix"); Matrix4 mvp_matrix = GetOpenGLModelViewProjectionMatrix(); shader_prog->SetUniformLocMatrix4fv((GLint) view_projection_matrix_loc, 1, false, (GLfloat*)&mvp_matrix.m); if (in_vertex_loc != -1) { CHECKGL(glEnableVertexAttribArrayARB(in_vertex_loc)); CHECKGL(glVertexAttribPointerARB((GLuint)in_vertex_loc, 4, GL_FLOAT, GL_FALSE, 16, vtx_buffer)); } CHECKGL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); if (in_vertex_loc != -1) CHECKGL(glDisableVertexAttribArrayARB(in_vertex_loc)); shader_prog->End(); } ObjectPtr GraphicsEngine::GetTextureLayerOverTextureProgram(LayerBlendMode layer_blend_mode) { if (blend_tex_tex_prog_[layer_blend_mode].IsValid()) { return blend_tex_tex_prog_[layer_blend_mode]; } ObjectPtr VS = _graphics_display.m_DeviceFactory->CreateVertexShader(); ObjectPtr PS = _graphics_display.m_DeviceFactory->CreatePixelShader(); std::string vertex_code = NUX_VERTEX_SHADER_HEADER "uniform mat4 view_projection_matrix; \n\ attribute vec4 in_vertex; \n\ attribute vec4 in_bkg_tex_coord; \n\ attribute vec4 in_frg_tex_coord; \n\ varying vec4 bkg_tex_coord; \n\ varying vec4 frg_tex_coord; \n\ void main() \n\ { \n\ bkg_tex_coord = in_bkg_tex_coord; \n\ frg_tex_coord = in_frg_tex_coord; \n\ gl_Position = view_projection_matrix * (in_vertex); \n\ }"; std::string pixel_code = NUX_FRAGMENT_SHADER_HEADER "varying vec4 bkg_tex_coord; \n\ varying vec4 frg_tex_coord; \n\ uniform vec4 bkg_color; \n\ uniform vec4 frg_color; \n\ uniform sampler2D bkg_texture; \n\ uniform sampler2D frg_texture; \n\ %s \n\ void main() \n\ { \n\ vec3 bkg_tex = texture2D(bkg_texture, bkg_tex_coord.st).rgb * bkg_color.rgb; \n\ vec3 frg_tex = texture2D(frg_texture, frg_tex_coord.st).rgb * frg_color.rgb; \n\ gl_FragColor.rgb = %s(bkg_tex.rgb * bkg_color.aaa, frg_tex.rgb * frg_color.aaa); \n\ gl_FragColor.a = 1.0; \n\ }"; int safe_area = 10; int code_buffer_size = pixel_code.length(); code_buffer_size += GetBlendModeBlendFunc(layer_blend_mode).length(); code_buffer_size += GetBlendModeString(layer_blend_mode).length() + safe_area; char* shader_prog = new char[code_buffer_size]; std::memset(shader_prog, 0, code_buffer_size); sprintf(shader_prog, pixel_code.c_str(), GetBlendModeBlendFunc(layer_blend_mode).c_str(), GetBlendModeString(layer_blend_mode).c_str()); blend_tex_tex_prog_[layer_blend_mode] = _graphics_display.m_DeviceFactory->CreateShaderProgram(); VS->SetShaderCode(vertex_code.c_str()); PS->SetShaderCode(shader_prog); delete [] shader_prog; blend_tex_tex_prog_[layer_blend_mode]->ClearShaderObjects(); blend_tex_tex_prog_[layer_blend_mode]->AddShaderObject(VS); blend_tex_tex_prog_[layer_blend_mode]->AddShaderObject(PS); CHECKGL(glBindAttribLocation(blend_tex_tex_prog_[layer_blend_mode]->GetOpenGLID(), 0, "in_vertex")); blend_tex_tex_prog_[layer_blend_mode]->Link(); return blend_tex_tex_prog_[layer_blend_mode]; } void GraphicsEngine::QRP_GLSL_TextureLayerOverTexture(int x, int y, int width, int height, ObjectPtr bkg_device_texture, TexCoordXForm& bkg_texxform, const Color& bkg_color, ObjectPtr frg_device_texture, TexCoordXForm& frg_texxform, const Color& frg_color, LayerBlendMode layer_blend_mode) { if (!UsingGLSLCodePath()) return; ObjectPtr ShaderProg = GetTextureLayerOverTextureProgram(layer_blend_mode); QRP_Compute_Texture_Coord(width, height, bkg_device_texture, bkg_texxform); QRP_Compute_Texture_Coord(width, height, frg_device_texture, frg_texxform); float fx = x, fy = y; float vtx_buffer[] = { fx, fy, 0.0f, 1.0f, bkg_texxform.u0, bkg_texxform.v0, 0.0f, 1.0f, frg_texxform.u0, frg_texxform.v0, 0.0f, 1.0f, fx, fy + height, 0.0f, 1.0f, bkg_texxform.u0, bkg_texxform.v1, 0.0f, 1.0f, frg_texxform.u0, frg_texxform.v1, 0.0f, 1.0f, fx + width, fy + height, 0.0f, 1.0f, bkg_texxform.u1, bkg_texxform.v1, 0.0f, 1.0f, frg_texxform.u1, frg_texxform.v1, 0.0f, 1.0f, fx + width, fy, 0.0f, 1.0f, bkg_texxform.u1, bkg_texxform.v0, 0.0f, 1.0f, frg_texxform.u1, frg_texxform.v0, 0.0f, 1.0f, }; CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); ShaderProg->Begin(); int bkg_texture_loc = ShaderProg->GetUniformLocationARB("bkg_texture"); int frg_texture_loc = ShaderProg->GetUniformLocationARB("frg_texture"); int in_vertex_loc = ShaderProg->GetAttributeLocation("in_vertex"); int in_bkg_tex_coord_loc = ShaderProg->GetAttributeLocation("in_bkg_tex_coord"); int in_frg_tex_coord_loc = ShaderProg->GetAttributeLocation("in_frg_tex_coord"); int TextureCoef0Location = ShaderProg->GetUniformLocationARB("bkg_color"); int TextureCoef1Location = ShaderProg->GetUniformLocationARB("frg_color"); SetTexture(GL_TEXTURE0, bkg_device_texture); SetTexture(GL_TEXTURE1, frg_device_texture); CHECKGL(glUniform1iARB(bkg_texture_loc, 0)); CHECKGL(glUniform1iARB(frg_texture_loc, 1)); CHECKGL(glUniform4fARB(TextureCoef0Location, bkg_color.red, bkg_color.green, bkg_color.blue, bkg_color.alpha )); CHECKGL(glUniform4fARB(TextureCoef1Location, frg_color.red, frg_color.green, frg_color.blue, frg_color.alpha )); int view_projection_matrix_loc = ShaderProg->GetUniformLocationARB("view_projection_matrix"); Matrix4 mvp_matrix = GetOpenGLModelViewProjectionMatrix(); ShaderProg->SetUniformLocMatrix4fv((GLint) view_projection_matrix_loc, 1, false, (GLfloat*) & (mvp_matrix.m)); CHECKGL(glEnableVertexAttribArrayARB(in_vertex_loc)); CHECKGL(glVertexAttribPointerARB((GLuint) in_vertex_loc, 4, GL_FLOAT, GL_FALSE, 48, vtx_buffer)); if (in_bkg_tex_coord_loc != -1) { CHECKGL(glEnableVertexAttribArrayARB(in_bkg_tex_coord_loc)); CHECKGL(glVertexAttribPointerARB((GLuint) in_bkg_tex_coord_loc, 4, GL_FLOAT, GL_FALSE, 48, vtx_buffer + 4)); } if (in_frg_tex_coord_loc != -1) { CHECKGL(glEnableVertexAttribArrayARB(in_frg_tex_coord_loc)); CHECKGL(glVertexAttribPointerARB((GLuint) in_frg_tex_coord_loc, 4, GL_FLOAT, GL_FALSE, 48, vtx_buffer + 8)); } CHECKGL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); CHECKGL(glDisableVertexAttribArrayARB(in_vertex_loc)); if (in_bkg_tex_coord_loc != -1) CHECKGL(glDisableVertexAttribArrayARB(in_bkg_tex_coord_loc)); if (in_frg_tex_coord_loc != -1) CHECKGL(glDisableVertexAttribArrayARB(in_frg_tex_coord_loc)); ShaderProg->End(); } }./NuxGraphics/IOpenGLPixelBufferOject.cpp0000644000004100000410000000775013313171755020577 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "GLDeviceObjects.h" #include "IOpenGLPixelBufferOject.h" namespace nux { NUX_IMPLEMENT_OBJECT_TYPE(IOpenGLPixelBufferObject); IOpenGLPixelBufferObject::IOpenGLPixelBufferObject(unsigned int Size, VBO_USAGE Usage, NUX_FILE_LINE_DECL) : IOpenGLResource(RTVERTEXBUFFER, NUX_FILE_LINE_PARAM) , _Length(Size) , _Usage(Usage) , _MemMap(0) , _OffsetToLock(0) , _SizeToLock(0) { CHECKGL(glGenBuffersARB(1, &_OpenGLID)); CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, _OpenGLID)); CHECKGL(glBufferDataARB(GL_ARRAY_BUFFER_ARB, _Length, NULL, Usage)); CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); GRunTimeStats.Register(this); } IOpenGLPixelBufferObject::~IOpenGLPixelBufferObject() { CHECKGL(glDeleteBuffersARB(1, &_OpenGLID)); _OpenGLID = 0; GRunTimeStats.UnRegister(this); } int IOpenGLPixelBufferObject::Lock( unsigned int OffsetToLock, unsigned int SizeToLock, void **ppbData) { nuxAssert(SizeToLock <= _Length); nuxAssert(OffsetToLock + SizeToLock <= _Length); if (SizeToLock == 0) { if (OffsetToLock == 0) { // lock the entire buffer SizeToLock = _Length; } else return OGL_INVALID_CALL; } // If _MemMap, _OffsetToLock and _SizeToLock are not equal to zero, then we have already mapped the buffer // Unlock it before locking again. nuxAssert(_MemMap == 0); nuxAssert(_OffsetToLock == 0); nuxAssert(_SizeToLock == 0); #ifndef NUX_OPENGLES_20 //FIXME: GLES 2.0 doesn't support PBOs, we need to allocate client memory and copy data there // When locking it shouldn't matter if we use GL_PIXEL_UNPACK_BUFFER_ARB or GL_PIXEL_PACK_BUFFER_ARB. // We just want a pointer to the data. CHECKGL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, _OpenGLID)); // Map the Entire buffer into system memory _MemMap = (BYTE *) glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_READ_WRITE); // we maybe reading or writing to the PBO. CHECKGL_MSG(glMapBufferARB); *ppbData = (void *) (_MemMap + OffsetToLock); _OffsetToLock = OffsetToLock; _SizeToLock = SizeToLock; CHECKGL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0)); #endif return OGL_OK; } int IOpenGLPixelBufferObject::Unlock() { #ifndef NUX_OPENGLES_20 CHECKGL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, _OpenGLID)); //CHECKGL(glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, _OffsetToLock, _SizeToLock, _MemMap)); CHECKGL(glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB)); CHECKGL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0)); #endif _MemMap = 0; _OffsetToLock = 0; _SizeToLock = 0; return OGL_OK; } void IOpenGLPixelBufferObject::BindPackPixelBufferObject() { #ifndef NUX_OPENGLES_20 CHECKGL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, _OpenGLID)); #endif } void IOpenGLPixelBufferObject::BindUnpackPixelBufferObject() { #ifndef NUX_OPENGLES_20 CHECKGL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, _OpenGLID)); #endif } unsigned int IOpenGLPixelBufferObject::GetSize() { return _Length; } } ./NuxGraphics/IOpenGLRectangleTexture.cpp0000644000004100000410000001115413313171755020655 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "GLDeviceObjects.h" #include "IOpenGLRectangleTexture.h" namespace nux { NUX_IMPLEMENT_OBJECT_TYPE(IOpenGLRectangleTexture); IOpenGLRectangleTexture::IOpenGLRectangleTexture( unsigned int Width , unsigned int Height , unsigned int Levels , BitmapFormat PixelFormat, bool Dummy, NUX_FILE_LINE_DECL) : IOpenGLBaseTexture(RTTEXTURERECTANGLE, Width, Height, 1, Levels, PixelFormat, NUX_FILE_LINE_PARAM) { #ifndef NUX_OPENGLES_20 if (Dummy == false) { CHECKGL(glGenTextures(1, &_OpenGLID)); CHECKGL(glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _OpenGLID)); } //_SurfaceArray.Empty(Levels); for (unsigned int l = 0; l < Levels; l++) { IOpenGLSurface *surface = new IOpenGLSurface(this, _OpenGLID, GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_RECTANGLE_ARB, l, 0, NUX_FILE_LINE_PARAM); if (Dummy == false) surface->InitializeLevel(); _SurfaceArray.push_back(ObjectPtr (surface)); surface->UnReference(); } SetFiltering(GL_NEAREST, GL_NEAREST); SetWrap(GL_CLAMP, GL_CLAMP, GL_CLAMP); SetRenderStates(); GRunTimeStats.Register(this); #endif } IOpenGLRectangleTexture::~IOpenGLRectangleTexture() { for (int l = 0; l < _NumMipLevel; l++) { _SurfaceArray[l] = ObjectPtr (0);; } _SurfaceArray.clear(); CHECKGL(glDeleteTextures(1, &_OpenGLID)); _OpenGLID = 0; GRunTimeStats.UnRegister(this); } ObjectPtr IOpenGLRectangleTexture::GetSurfaceLevel(int Level) { if (Level < _NumMipLevel) { return _SurfaceArray[Level]; } else { nuxAssertMsg(0, "[IOpenGLRectangleTexture::GetSurfaceLevel] Invalid surface level"); } return ObjectPtr (0); } void IOpenGLRectangleTexture::GetSurfaceLevel(int Level, ObjectPtr& surface) { surface = GetSurfaceLevel(Level); } int IOpenGLRectangleTexture::LockRect( int Level, SURFACE_LOCKED_RECT *pLockedRect, const SURFACE_RECT *pRect) { nuxAssertMsg(pLockedRect, "[IOpenGLRectangleTexture::LockRect] Invalid parameter 'pLockedRect'."); nuxAssertMsg(Level >= 0, "[IOpenGLRectangleTexture::LockRect] Invalid mipmap level."); nuxAssertMsg(Level < _NumMipLevel, "[IOpenGLRectangleTexture::LockRect] Invalid mipmap level."); if (Level < _NumMipLevel) { ObjectPtr pSurfaceLevel = _SurfaceArray[Level]; return pSurfaceLevel->LockRect(pLockedRect, pRect); } else { pLockedRect->pBits = 0; pLockedRect->Pitch = 0; return OGL_INVALID_SURFACE_LEVEL; } return OGL_OK; } int IOpenGLRectangleTexture::UnlockRect( int Level ) { nuxAssertMsg(Level >= 0, "[IOpenGLRectangleTexture::LockRect] Invalid mipmap level."); nuxAssertMsg(Level < _NumMipLevel, "[IOpenGLRectangleTexture::LockRect] Invalid mipmap level."); if (Level < _NumMipLevel) { ObjectPtr pSurfaceLevel = _SurfaceArray[Level]; return pSurfaceLevel->UnlockRect(); } else { return OGL_INVALID_SURFACE_LEVEL; } return OGL_OK; } unsigned int IOpenGLRectangleTexture::EnableGammaCorrection(bool /* b */) { nuxAssert(_OpenGLID); return OGL_OK; } unsigned char* IOpenGLRectangleTexture::GetSurfaceData(int level, int &width, int &height, int &stride) { width = 0; height = 0; stride = 0; if (level < 0) { nuxAssertMsg(level >= 0, "[IOpenGLRectangleTexture::GetSurfaceData] Invalid mipmap level."); return NULL; } if (level >= _NumMipLevel) { nuxAssertMsg(level < _NumMipLevel, "[IOpenGLRectangleTexture::GetSurfaceData] Invalid mipmap level."); return NULL; } ObjectPtr pSurfaceLevel = _SurfaceArray[level]; return pSurfaceLevel->GetSurfaceData(width, height, stride); } } ./NuxGraphics/IOpenGLCubeTexture.h0000644000004100000410000000465713313171755017306 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef IOPENGLCUBETEXTURE_H #define IOPENGLCUBETEXTURE_H namespace nux { class IOpenGLBaseTexture; class IOpenGLCubeTexture: public IOpenGLBaseTexture { NUX_DECLARE_OBJECT_TYPE(IOpenGLCubeTexture, IOpenGLBaseTexture); public: virtual ~IOpenGLCubeTexture(); int GetCubeMapSurface( eCUBEMAP_FACES FaceType, int Level, IOpenGLSurface **ppCubeMapSurface ); int CubeLockRect( eCUBEMAP_FACES FaceType, int Level, SURFACE_LOCKED_RECT *pLockedRect, const SURFACE_RECT *pRect); int CubeUnlockRect( eCUBEMAP_FACES FaceType, int Level ); unsigned int EnableGammaCorrection(bool b); int GetLevelDesc( int Level, SURFACE_DESC *pDesc ) { nuxAssert(Level >= 0 ); nuxAssert(Level < _NumMipLevel); if ((Level < 0) || (Level > _NumMipLevel)) { pDesc->Width = 0; pDesc->Height = 0; pDesc->PixelFormat = BITFMT_UNKNOWN; pDesc->Type = _ResourceType; } else { pDesc->Width = Max (1, _Width >> Level); pDesc->Height = Max (1, _Height >> Level); pDesc->PixelFormat = _PixelFormat; pDesc->Type = _ResourceType; } return OGL_OK; } private: IOpenGLCubeTexture( unsigned int EdgeLength , int Levels , BitmapFormat PixelFormat); // unsigned int _Width; // unsigned int _Height; std::map* > _SurfaceArray; friend class GpuDevice; friend class IOpenGLSurface; }; } #endif // IOPENGLCUBETEXTURE_H ./NuxGraphics/IOpenGLVolume.cpp0000644000004100000410000004357613313171755016654 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "GLDeviceObjects.h" #include "IOpenGLVolume.h" #include "GraphicsDisplay.h" #include "GpuDevice.h" namespace nux { NUX_IMPLEMENT_OBJECT_TYPE(IOpenGLVolume); IOpenGLVolume::~IOpenGLVolume() { } int IOpenGLVolume::RefCount() const { if (_VolumeTexture) return _VolumeTexture->RefCount(); nuxAssert(0); // Surface with no underlying texture. That should not happen. return 0; } int IOpenGLVolume::LockBox( VOLUME_LOCKED_BOX *pLockedVolume, const VOLUME_BOX *pBox) { #ifndef NUX_OPENGLES_20 // If _LockedRect.pBits or _LockedRect.Pitch are not equal to zero, then we have already Locked the buffer // Unlock it before locking again. nuxAssert(_LockedBox.pBits == 0); nuxAssert(_LockedBox.RowPitch == 0); //nuxAssert(_LockedBox.SlicePitch == 0); nuxAssert(_CompressedDataSize == 0); if ((_LockedBox.pBits != 0) || (_LockedBox.RowPitch != 0) || (_CompressedDataSize != 0)) { // already locked; return OGL_INVALID_LOCK; } _Box.Front = _Box.Back = _Box.Bottom = _Box.Left = _Box.Right = _Box.Top = 0; //GLint unpack_alignment = GPixelFormats[_VolumeTexture->_PixelFormat].RowMemoryAlignment; CHECKGL(glBindTexture(_STextureTarget, _VolumeTexture->_OpenGLID)); unsigned int surface_size = 0; IOpenGLVolumeTexture *texture = _VolumeTexture; if (_VolumeTexture->_ResourceType != RTVOLUMETEXTURE) { nuxAssertMsg(0, "Unknown resource type"); } int texwidth, texheight; texwidth = ImageSurface::GetLevelWidth(texture->_PixelFormat, texture->_Width, _SMipLevel); texheight = ImageSurface::GetLevelHeight(texture->_PixelFormat, texture->_Height, _SMipLevel); if ( texture->_PixelFormat == BITFMT_DXT1 || texture->_PixelFormat == BITFMT_DXT2 || texture->_PixelFormat == BITFMT_DXT3 || texture->_PixelFormat == BITFMT_DXT4 || texture->_PixelFormat == BITFMT_DXT5) { if (texture->_PixelFormat == BITFMT_DXT1) { // We can conceive a 4x4 DXT1 block as if each texel uses 4 bits. // Actually, for DXT, we have 2 16-bits colors(5:6:5), and each texel uses 2 bits to interpolate // between the 2 colors. // --------------------- // | COLOR0 | 16 bits // --------------------- // | COLOR1 | 16 bits // --------------------- // | xx | xx | xx | xx | xx = 2 bits // --------------------- // | xx | xx | xx | xx | // --------------------- // | xx | xx | xx | xx | // --------------------- // | xx | xx | xx | xx | // --------------------- // A line of n texel DXT1 data uses n/2 bytes(4 bits/texel). So the number of bytes used for a // texwidth texel, is texwidth/2 bytes. // Note that texwidth is divisible by 4(to to the upper rounding to 4), therefore, it is also divisible // by 2. // glCompressedTexImage2DARB, glCompressedTexImage3DARB, // glCompressedTexSubImage2DARB, glCompressedTexSubImage3DARB are not affected by glPixelStorei. surface_size = ImageSurface::GetLevelSize(texture->_PixelFormat, texture->_Width, texture->_Height, _SMipLevel); _LockedBox.RowPitch = ImageSurface::GetLevelPitch(texture->_PixelFormat, texture->_Width, texture->_Height, _SMipLevel); if (_Initialized == false) { InitializeLevel(); } } else { // A line of n texel DXT3/5 data uses n bytes(1 byte/texel). So the number of bytes used for a // texwidth texels, is texwidth bytes. // glCompressedTexImage2DARB, glCompressedTexImage3DARB, // glCompressedTexSubImage2DARB, glCompressedTexSubImage3DARB are not affected by glPixelStorei. surface_size = ImageSurface::GetLevelSize(texture->_PixelFormat, texture->_Width, texture->_Height, _SMipLevel); _LockedBox.RowPitch = ImageSurface::GetLevelPitch(texture->_PixelFormat, texture->_Width, texture->_Height, _SMipLevel); if (_Initialized == false) { InitializeLevel(); } } } else { _LockedBox.RowPitch = ImageSurface::GetLevelPitch(texture->_PixelFormat, texture->_Width, texture->_Height, _SMipLevel); surface_size = ImageSurface::GetLevelSize(texture->_PixelFormat, texture->_Width, texture->_Height, _SMipLevel); if (_Initialized == false) { InitializeLevel(); } } _Box.Left = 0; _Box.Top = 0; _Box.Bottom = texheight; _Box.Right = texwidth; _Box.Front = 0; _Box.Back = ImageSurface::GetLevelDim(texture->_PixelFormat, texture->GetDepth(), _SMipLevel); if (GetGraphicsDisplay()->GetGpuDevice()->UsePixelBufferObjects()) { GetGraphicsDisplay()->GetGpuDevice()->AllocateUnpackPixelBufferIndex(&_AllocatedUnpackBuffer); } if (pBox == 0) { _CompressedDataSize = GetDepth() * surface_size; if (GetGraphicsDisplay()->GetGpuDevice()->UsePixelBufferObjects()) { // Mapping the entire area of the surface if (1) { _LockedBox.pBits = GetGraphicsDisplay()->GetGpuDevice()->LockUnpackPixelBufferIndex(_AllocatedUnpackBuffer, _CompressedDataSize); } else { GetGraphicsDisplay()->GetGpuDevice()->BindUnpackPixelBufferIndex(_AllocatedUnpackBuffer); CHECKGL(glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, _CompressedDataSize, NULL, GL_STREAM_DRAW_ARB)); _LockedBox.pBits = glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY_ARB); CHECKGL_MSG(glMapBufferARB ); CHECKGL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); } pLockedVolume->pBits = _LockedBox.pBits; pLockedVolume->RowPitch = _LockedBox.RowPitch; pLockedVolume->SlicePitch = surface_size; } else { //[DEBUGGING - NO PBO] // Mapping the entire area of the surface _LockedBox.pBits = new BYTE[_CompressedDataSize]; pLockedVolume->pBits = _LockedBox.pBits; pLockedVolume->RowPitch = _LockedBox.RowPitch; pLockedVolume->SlicePitch = surface_size; } } else { nuxAssert(pBox->Front >= 0); nuxAssert(pBox->Back <= GetDepth()); nuxAssert(pBox->Front < pBox->Back); int RectWidth = pBox->Right - pBox->Left; int RectHeight = pBox->Bottom - pBox->Top; int NumSlice = pBox->Back - pBox->Front; nuxAssert(RectWidth >= 0); nuxAssert(RectHeight >= 0); nuxAssert(NumSlice >= 0); unsigned int RectSize = ImageSurface::GetLevelSize(GetPixelFormat(), RectWidth, RectHeight, 0); //(((RectWidth * BytePerPixel + (unpack_alignment-1)) >> (halfUnpack)) << (halfUnpack)) * RectHeight; if (RectSize == 0) { pLockedVolume->pBits = 0; pLockedVolume->RowPitch = 0; return OGL_INVALID_LOCK; } _CompressedDataSize = NumSlice * RectSize; if (GetGraphicsDisplay()->GetGpuDevice()->UsePixelBufferObjects()) { _LockedBox.pBits = GetGraphicsDisplay()->GetGpuDevice()->LockUnpackPixelBufferIndex(_AllocatedUnpackBuffer, NumSlice * RectSize); // GetGraphicsDisplay()->GetGpuDevice()->BindUnpackPixelBufferIndex(_AllocatedUnpackBuffer); // CHECKGL(glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, NumSlice * RectSize, NULL, GL_STATIC_DRAW_ARB)); // _LockedBox.pBits = glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY); // CHECKGL_MSG(glMapBufferARB ); // CHECKGL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); pLockedVolume->pBits = ((BYTE *) _LockedBox.pBits); pLockedVolume->RowPitch = ImageSurface::GetLevelPitch(GetPixelFormat(), RectWidth, RectHeight, 0); //(((RectWidth * BytePerPixel + (unpack_alignment-1)) >> (halfUnpack)) << (halfUnpack)); pLockedVolume->SlicePitch = RectSize; } else { //[DEBUGGING - NO PBO] _LockedBox.pBits = new BYTE[_CompressedDataSize]; pLockedVolume->pBits = ((BYTE *) _LockedBox.pBits); pLockedVolume->RowPitch = ImageSurface::GetLevelPitch(GetPixelFormat(), RectWidth, RectHeight, 0); //(((RectWidth * BytePerPixel + (unpack_alignment-1)) >> (halfUnpack)) << (halfUnpack)); pLockedVolume->SlicePitch = RectSize; } _Box.Left = pBox->Left; _Box.Top = pBox->Top; _Box.Bottom = pBox->Bottom; _Box.Right = pBox->Right; _Box.Front = pBox->Front; _Box.Back = pBox->Back; } #endif return OGL_OK; } int IOpenGLVolume::UnlockBox() { #ifndef NUX_OPENGLES_20 if (_LockedBox.pBits == 0) { return OGL_INVALID_UNLOCK; } int MemAlignment = ImageSurface::GetMemAlignment(_VolumeTexture->_PixelFormat); CHECKGL(glPixelStorei(GL_UNPACK_ALIGNMENT, MemAlignment)); nuxAssert(MemAlignment == _VolumeTexture->GetFormatRowMemoryAlignment()); if (_STextureTarget == GL_TEXTURE_3D) { BYTE *DataPtr = 0; CHECKGL(glBindTexture(_STextureTarget, _VolumeTexture->_OpenGLID)); if (GetGraphicsDisplay()->GetGpuDevice()->UsePixelBufferObjects()) { // Unmap the texture image buffer GetGraphicsDisplay()->GetGpuDevice()->BindUnpackPixelBufferIndex(_AllocatedUnpackBuffer); CHECKGL(glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB)); DataPtr = NUX_BUFFER_OFFSET(0); } else { CHECKGL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); DataPtr = (BYTE *) _LockedBox.pBits; } IOpenGLTexture2D *texture = (IOpenGLTexture2D *) _VolumeTexture; int width = _Box.Right - _Box.Left; int height = _Box.Bottom - _Box.Top; int depth = _Box.Back - _Box.Front; int xoffset = _Box.Left; int yoffset = _Box.Top; int zoffset = _Box.Front; if ( texture->_PixelFormat == BITFMT_DXT1 || texture->_PixelFormat == BITFMT_DXT2 || texture->_PixelFormat == BITFMT_DXT3 || texture->_PixelFormat == BITFMT_DXT4 || texture->_PixelFormat == BITFMT_DXT5) { nuxAssert(_CompressedDataSize != 0); // This part does not work. The image is messed up. // Driver bug??? Tried glCompressedTexImage3DARB. Same result. // But I know the data that is loaded is correct. glCompressedTexSubImage3DARB(_SSurfaceTarget, _SMipLevel, // level xoffset, yoffset, zoffset, width, height, depth, GPixelFormats[texture->_PixelFormat].PlatformFormat, _CompressedDataSize, // image Size DataPtr // data ); CHECKGL_MSG(glCompressedTexSubImage3DARB); // glCompressedTexImage3DARB(_SSurfaceTarget, // _SMipLevel, // level // GPixelFormats[texture->_PixelFormat].PlatformFormat, // width, // height, // depth, // 0, // border // _CompressedDataSize, // image Size // DataPtr // data // ); // CHECKGL_MSG(glCompressedTexImage2DARB); } else { CHECKGL(glTexSubImage3D(_SSurfaceTarget, _SMipLevel, xoffset, yoffset, zoffset, // z offset width, height, depth, GPixelFormats[texture->_PixelFormat].Format, GPixelFormats[texture->_PixelFormat].type, DataPtr )); } } else { nuxAssertMsg(0, "Incorrect Texture Target."); } if (GetGraphicsDisplay()->GetGpuDevice()->UsePixelBufferObjects()) { CHECKGL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); GetGraphicsDisplay()->GetGpuDevice()->FreeUnpackPixelBufferIndex(_AllocatedUnpackBuffer); } else { //[DEBUGGING - NO PBO] if (_LockedBox.pBits) { delete [] ((BYTE *) _LockedBox.pBits); } } CHECKGL(glPixelStorei(GL_UNPACK_ALIGNMENT, GetGraphicsDisplay()->GetGpuDevice()->GetPixelStoreAlignment())); _LockedBox.pBits = 0; _LockedBox.RowPitch = 0; _CompressedDataSize = 0; #endif return OGL_OK; } int IOpenGLVolume::InitializeLevel() { #ifndef NUX_OPENGLES_20 // Because we use SubImage when unlocking surfaces, we must first get some dummy data in the surface before we can make a lock. int volwidth = ImageSurface::GetLevelDim(_VolumeTexture->_PixelFormat, _VolumeTexture->_Width, _SMipLevel); int volheight = ImageSurface::GetLevelDim(_VolumeTexture->_PixelFormat, _VolumeTexture->_Height, _SMipLevel); int voldepth = ImageSurface::GetLevelDim(_VolumeTexture->_PixelFormat, _VolumeTexture->_Depth, _SMipLevel); int size = ImageSurface::GetLevelSize( _VolumeTexture->_PixelFormat, _VolumeTexture->_Width, _VolumeTexture->_Height, _VolumeTexture->_Depth, _SMipLevel); int MemAlignment = ImageSurface::GetMemAlignment(_VolumeTexture->_PixelFormat); nuxAssert( volwidth > 0 ); // Should never happen nuxAssert( volheight > 0 ); // Should never happen nuxAssert( voldepth > 0 ); // Should never happen nuxAssert( size > 0 ); // Should never happen BYTE *DummyBuffer = new BYTE[size]; Memset(DummyBuffer, 0, size); CHECKGL(glPixelStorei(GL_UNPACK_ALIGNMENT, MemAlignment)); if ( _VolumeTexture->_PixelFormat == BITFMT_DXT1 || _VolumeTexture->_PixelFormat == BITFMT_DXT2 || _VolumeTexture->_PixelFormat == BITFMT_DXT3 || _VolumeTexture->_PixelFormat == BITFMT_DXT4 || _VolumeTexture->_PixelFormat == BITFMT_DXT5) { { glCompressedTexImage3DARB( _SSurfaceTarget, _SMipLevel, // level GPixelFormats[_VolumeTexture->_PixelFormat].PlatformFormat, volwidth, volheight, voldepth, 0, // border size, // image Size DummyBuffer // data ); CHECKGL_MSG(glCompressedTexImage3DARB); } } else { glTexImage3D( _SSurfaceTarget, _SMipLevel, // level GPixelFormats[_VolumeTexture->_PixelFormat].PlatformFormat, volwidth, volheight, voldepth, 0, // border GPixelFormats[_VolumeTexture->_PixelFormat].Format, GPixelFormats[_VolumeTexture->_PixelFormat].type, DummyBuffer); CHECKGL_MSG(glTexImage3D); } delete [] DummyBuffer; // { //[DEBUGGING - Red Texture] // // This is going to put some red in the texture. // // The texture is not compressed. // BYTE *color_array = new BYTE[texwidth*texheight*4]; // for (unsigned int i = 0; i < texwidth*texheight*4; i += 4) // { // color_array[i + 0] = 0xff; // color_array[i + 1] = _SMipLevel * 0x3F; // color_array[i + 2] = 0x0; // color_array[i + 3] = 0xFF; // } // glTexImage2D(GL_TEXTURE_2D, // _SMipLevel, // GL_RGBA8, texwidth, texheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, color_array); // CHECKGL_MSG(glTexImage2D); // delete [] color_array; // } CHECKGL(glPixelStorei(GL_UNPACK_ALIGNMENT, GetGraphicsDisplay()->GetGpuDevice()->GetPixelStoreAlignment())); _Initialized = true; #endif return OGL_OK; } BitmapFormat IOpenGLVolume::GetPixelFormat() const { if (_VolumeTexture == 0) return BITFMT_UNKNOWN; else return _VolumeTexture->GetPixelFormat(); } int IOpenGLVolume::GetWidth() const { if (_VolumeTexture->_ResourceType == RTVOLUMETEXTURE) return ImageSurface::GetLevelDim(_VolumeTexture->_PixelFormat, _VolumeTexture->_Width, _SMipLevel); nuxAssert(0); // Should not happen return 0; } int IOpenGLVolume::GetHeight() const { if (_VolumeTexture->_ResourceType == RTVOLUMETEXTURE) return ImageSurface::GetLevelDim(_VolumeTexture->_PixelFormat, _VolumeTexture->_Height, _SMipLevel); nuxAssert(0); // Should not happen return 0; } int IOpenGLVolume::GetDepth() const { if (_VolumeTexture->_ResourceType == RTVOLUMETEXTURE) return ImageSurface::GetLevelDim(_VolumeTexture->_PixelFormat, _VolumeTexture->_Depth, _SMipLevel); nuxAssert(0); // Should not happen return 0; } } ./NuxGraphics/IOpenGLPixelBufferOject.h0000644000004100000410000000332213313171755020233 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef IOPENGLPIXELBUFFEROBJECT_H #define IOPENGLPIXELBUFFEROBJECT_H namespace nux { class IOpenGLPixelBufferObject: public IOpenGLResource { NUX_DECLARE_OBJECT_TYPE(IOpenGLPixelBufferObject, IOpenGLResource); public: virtual ~IOpenGLPixelBufferObject(); int Lock( unsigned int OffsetToLock, unsigned int SizeToLock, void **ppbData); int Unlock(); int GetDescription(INDEXBUFFER_DESC *desc) const { desc->Usage = _Usage; desc->Size = _Length; return OGL_OK; } void BindPackPixelBufferObject(); void BindUnpackPixelBufferObject(); unsigned int GetSize(); private: IOpenGLPixelBufferObject(unsigned int Size, VBO_USAGE Usage, NUX_FILE_LINE_PROTO); unsigned int _Length; VBO_USAGE _Usage; BYTE *_MemMap; unsigned int _OffsetToLock; unsigned int _SizeToLock; friend class GpuDevice; }; } #endif // IOPENGLPIXELBUFFEROJECT_H ./NuxGraphics/FreetypeFont.cpp0000644000004100000410000007372613313171755016641 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "FreetypeFont.h" #include "agg_rendering_buffer.h" #include "GLTextureManager.h" //#include "OpenGL/GLsdk/GL/gl.h" //#include "OpenGL/GLsdk/GL/glprocs.h" //#include #include #include "GfxServer.h" #include "OpenGLEngine/GLCheck.h" #include "OpenGLEngine/OpenGLEngine.h" FontMgr *FontMgr::pinstance = 0; int Dot_GlyphIndex; void GLDrawRectangle (int xmin, int ymin, int xmax, int ymax) { glColor3f (1.0f, 1.0f, 1.0f); glDisable (GL_TEXTURE_2D); glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); glBegin (GL_QUADS); glVertex3i (xmin, ymin, 1); glVertex3i (xmax, ymin, 1); glVertex3i (xmax, ymax, 1); glVertex3i (xmin, ymax, 1); glEnd(); glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); glEnable (GL_TEXTURE_2D); } FontMgr::FontMgr() { m_font_list = new list ; current_font = NULL; current_style = NULL; } FontMgr *FontMgr::Instance() { if (pinstance == 0) pinstance = new FontMgr(); return pinstance; } bool FontMgr::load_font (const char *font_filename) { FT_Library library; // handle to library FT_Face face; // handle to face object FT_Error error; error = FT_Init_FreeType ( &library ); if (error ) { return false; } error = FT_New_Face ( library, font_filename, 0, &face ); if ( error == FT_Err_Unknown_File_Format ) { // the font file could be opened and read, but it appears // that its font format is unsupported } else if ( error ) { // another error code means that the font file could not; // be opened or read, or simply that it is broken...; return false; } int font_bitmap_width, font_bitmap_height; font_bitmap_width = 0; font_bitmap_height = 18; error = FT_Set_Pixel_Sizes ( face, // handle to face object font_bitmap_width, // pixel_width font_bitmap_height ); // pixel_height if (error) { return false; } FontStyle *fs = new FontStyle(); FontFamily *ff = new FontFamily(); ff->font_name = strdup (face->family_name); ff->m_face = face; ff->style_list = new list ; fs->style_name = strdup (face->style_name); set_current_font (face->family_name, face->style_name); // check if the font is already loaded if (find_font ((const char*)face->family_name, (const char*)face->style_name) ) return true; // the font is already loaded fs->charmap = new CharData[face->num_glyphs]; fs->ascent = face->ascender; fs->descent = face->descender; fs->texture_width = font_bitmap_width; fs->texture_height = font_bitmap_height; fs->line_spacing = face->ascender >> 6; fs->num_glyph = face->num_glyphs; int char_num; unsigned char *imgp, *imp; for (char_num = 0; char_num < face->num_glyphs; char_num++) { FT_UInt glyph_index = FT_Get_Char_Index (face, char_num); error = FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT); if (error) continue; error = FT_Render_Glyph (face->glyph, ft_render_mode_normal); if (error) continue; /*error = FT_Load_Char( face, char_num, FT_LOAD_RENDER );*/ unsigned int PO2w = NextPowerOfTwo (face->glyph->bitmap.width); unsigned int PO2h = NextPowerOfTwo (face->glyph->bitmap.rows); if ( ( (glyph_index == 0) && (char_num == 0) ) || (glyph_index != 0) ) { imgp = (unsigned char *) calloc (PO2h * PO2w * 4, sizeof (unsigned char) ); imp = imgp; //cout << "rows = " << face->glyph->bitmap.rows << endl; //cout << "width = " << face->glyph->bitmap.width << endl; //cout << "pitch = " << face->glyph->bitmap.pitch << endl; int i, j; int position = 0; for ( j = 0; j < face->glyph->bitmap.rows; j++) { for ( i = 0; i < face->glyph->bitmap.width; i++) { //if(imp < imgp + font_bitmap_height*font_bitmap_width*4) // sometimes a char has more rows than the texture { * (imp + 4 * i + 0) = * (face->glyph->bitmap.buffer + j * face->glyph->bitmap.pitch + i); // *(imp + 4*i+1) = *(face->glyph->bitmap.buffer + j*face->glyph->bitmap.pitch +i); // *(imp + 4*i+2) = *(face->glyph->bitmap.buffer + j*face->glyph->bitmap.pitch +i); /* if(*(imp + 4*i+0) == 0) *(imp + 4*i+3) = 0x0; if(*(imp + 4*i+0) == 255) *(imp + 4*i+3) = 0xff; else *(imp + 4*i+3) = *(imp + 4*i+0); */ //*(imp + 4*i+0) = 0; * (imp + 4 * i + 1) = * (imp + 4 * i + 0); * (imp + 4 * i + 2) = * (imp + 4 * i + 0); * (imp + 4 * i + 3) = * (imp + 4 * i + 0); } } //imp += 4*font_bitmap_width; imp += 4 * PO2w; // position += 4*font_bitmap_width; } //ImageFormat *image = new ImageFormat(); //image->allocate(BITFMT_GRAY8, font_bitmap_width, font_bitmap_height); /*image->width = font_bitmap_width; image->Height() = font_bitmap_height; image->bpp = 32; image->data = imgp;*/ //unsigned char* buffer = new unsigned char[font_bitmap_width * font_bitmap_height]; //agg::rendering_buffer rbuf(buffer, font_bitmap_width, font_bitmap_height, font_bitmap_height*4); //TextureMgr* texturemgr = TextureMgr::Instance(); GLuint texname; glPixelStorei (GL_UNPACK_ALIGNMENT, 1); CHECKGL(glGenTextures (1, &texname)); glBindTexture (GL_TEXTURE_2D, texname); /* float *border_color = new float[4]; *(border_color) = 0; *(border_color+1) = 1.0f; *(border_color+2) = 0; *(border_color+3) = 1.0f; glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border_color); glTexEnvfv(GL_TEXTURE_2D, GL_TEXTURE_ENV_COLOR, border_color); */ fs->charmap[char_num].gltexid = texname; fs->charmap[char_num].glTexWidth = PO2w; fs->charmap[char_num].glTexHeight = PO2h; glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, PO2w, PO2h, 0, GL_RGBA, GL_UNSIGNED_BYTE, imgp); // fs->charmap[char_num].gltexid = texturemgr->load_image(image); } else fs->charmap[char_num].gltexid = fs->charmap[0].gltexid; // the missing glyph fs->charmap[char_num].hadvance = face->glyph->metrics.horiAdvance >> 6; // 1/64th of a pixel fs->charmap[char_num].vadvance = face->glyph->metrics.vertAdvance >> 6; fs->charmap[char_num].hbearingX = face->glyph->metrics.horiBearingX >> 6; fs->charmap[char_num].hbearingY = face->glyph->metrics.horiBearingY >> 6; fs->charmap[char_num].vbearingX = face->glyph->metrics.vertBearingX >> 6; fs->charmap[char_num].vbearingY = face->glyph->metrics.vertBearingY >> 6; fs->charmap[char_num].gwidth = face->glyph->metrics.width >> 6; fs->charmap[char_num].gheight = face->glyph->metrics.height >> 6; fs->charmap[char_num].bitmap_left_bearing = face->glyph->bitmap_left; fs->charmap[char_num].bitmap_top_bearing = face->glyph->bitmap_top; fs->charmap[char_num].bitmap_width = face->glyph->bitmap.width; fs->charmap[char_num].bitmap_height = face->glyph->bitmap.rows; fs->charmap[char_num].glyph_index = glyph_index; } ff->style_list->push_back (fs); m_font_list->push_back (ff); return true; } int FontMgr::get_character_texture_id (const char *font_name, int encoding, CharData *cd) { list ::iterator iter; for (iter = m_font_list->begin(); iter != m_font_list->end(); ++iter) { if (strcmp ( (*iter)->font_name, font_name) == 0) { cd->bitmap_width = (* (*iter)->style_list->begin() )->charmap[encoding].bitmap_width; cd->bitmap_height = (* (*iter)->style_list->begin() )->charmap[encoding].bitmap_height; cd->bitmap_left_bearing = (* (*iter)->style_list->begin() )->charmap[encoding].bitmap_left_bearing; cd->bitmap_top_bearing = (* (*iter)->style_list->begin() )->charmap[encoding].bitmap_top_bearing; cd->hadvance = (* (*iter)->style_list->begin() )->charmap[encoding].hadvance; cd->glTexWidth = (* (*iter)->style_list->begin() )->charmap[encoding].glTexWidth; cd->glTexHeight = (* (*iter)->style_list->begin() )->charmap[encoding].glTexHeight; return ( (* (*iter)->style_list->begin() )->charmap[encoding].gltexid); } } return 0; } int FontMgr::get_character_texture_id (int encoding, CharData *cd) { FontStyle *fs; fs = get_font_style (current_font, current_style); if (fs != NULL) { cd->bitmap_width = fs->charmap[encoding].bitmap_width; cd->bitmap_height = fs->charmap[encoding].bitmap_height; cd->bitmap_left_bearing = fs->charmap[encoding].bitmap_left_bearing; cd->bitmap_top_bearing = fs->charmap[encoding].bitmap_top_bearing; cd->hadvance = fs->charmap[encoding].hadvance; cd->gwidth = fs->charmap[encoding].gwidth; cd->gheight = fs->charmap[encoding].gheight; cd->glTexWidth = fs->charmap[encoding].glTexWidth; cd->glTexHeight = fs->charmap[encoding].glTexHeight; return fs->charmap[encoding].gltexid; } return 0; } void FontMgr::get_style_texture_size (const char *font_name, int *width, int *height) { list ::iterator iter; for (iter = m_font_list->begin(); iter != m_font_list->end(); ++iter) { if (strcmp ( (*iter)->font_name, font_name) == 0) { *width = (* (*iter)->style_list->begin() )->texture_width; *height = (* (*iter)->style_list->begin() )->texture_height; return; } } } void FontMgr::get_style_texture_size (int *width, int *height) { FontStyle *fs; fs = get_font_style (current_font, current_style); if (fs != NULL) { *width = fs->texture_width; *height = fs->texture_height; return; } } void FontMgr::get_style_line_spacing (const char *font_name, int *line_spacing) { list ::iterator iter; for (iter = m_font_list->begin(); iter != m_font_list->end(); ++iter) { if (strcmp ( (*iter)->font_name, font_name) == 0) { *line_spacing = (* (*iter)->style_list->begin() )->line_spacing; } } } void FontMgr::get_style_line_spacing (int *line_spacing) { FontStyle *fs; fs = get_font_style (current_font, current_style); if (fs != NULL) { *line_spacing = fs->line_spacing; return; } } unsigned int FontMgr::get_null_character_texture_id (const char *font_name) { list ::iterator iter; for (iter = m_font_list->begin(); iter != m_font_list->end(); ++iter) { if (strcmp ( (*iter)->font_name, font_name) == 0) { return ( (* (*iter)->style_list->begin() )->charmap[0].gltexid); } } return 0; } unsigned int FontMgr::get_null_character_texture_id() { FontStyle *fs; fs = get_font_style (current_font, current_style); if (fs != NULL) { return fs->charmap[0].gltexid; } return 0; } bool FontMgr::find_font (const char *font_name, const char *style_name) { list ::iterator iter; for (iter = m_font_list->begin(); iter != m_font_list->end(); ++iter) { if (strcmp ( (*iter)->font_name, font_name) == 0) { return true; } } return false; } FontFamily *FontMgr::get_font_family (const char *font_name) { list ::iterator iter; for (iter = m_font_list->begin(); iter != m_font_list->end(); ++iter) { if (strcmp ( (*iter)->font_name, font_name) == 0) { return (*iter); } } return NULL; } FontStyle *FontMgr::get_font_style (char *font_name, char *style_name) { list ::iterator iter; list ::iterator iter1; for (iter = m_font_list->begin(); iter != m_font_list->end(); ++iter) { if (strcmp ( (*iter)->font_name, font_name) == 0) { for (iter1 = ( (*iter)->style_list)->begin(); iter1 != ( (*iter)->style_list)->end(); ++iter1) if (strcmp ( (*iter1)->style_name, style_name) == 0) { return (*iter1); } } } return NULL; } void FontMgr::set_current_font (char *font_name, char *style_name) { if (current_font != NULL) free ( current_font); if (current_style != NULL) free (current_style); current_font = strdup (font_name); current_style = strdup (style_name); } FontMgr::~FontMgr() { } void enable_drawing_in_restricted_area (int xmin, int ymin, int xmax, int ymax) { glScissor (xmin, ymax, xmax - xmin, ymax - ymin); glEnable (GL_SCISSOR_TEST); } void disable_drawing_in_restricted_area() { glDisable (GL_SCISSOR_TEST); } void FontMgr::draw_text (int rect_xmin, int rect_ymin, int rect_xmax, int rect_ymax, const char *text, const char *sh_name) { int num_cararcter; int width, height, bitmap_x, bitmap_y; unsigned int ascii_code; int line_spacing; int x_cursor_position; int y_cursor_position; if ( (rect_xmin == 0) && (rect_xmax == 0) && (rect_ymin == 0) && (rect_ymax == 0) ) // the drawing area is invalid return; // if(num_cararcter == 0) // return; // NULL string; return //enable_drawing_in_restricted_area(rect_xmin, rect_ymin, rect_xmax, rect_ymax); // enable scissoring // FIXME (correct with the size of the Window 480-ymin, 480-ymax) glColor3f (1.0f, 1.0f, 1.0f); glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); glBegin (GL_QUADS); glVertex3i (rect_xmin, rect_ymin, 1); glVertex3i (rect_xmax, rect_ymin, 1); glVertex3i (rect_xmax, rect_ymax, 1); glVertex3i (rect_xmin, rect_ymax, 1); glEnd(); glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); get_style_texture_size (&width, &height); get_style_line_spacing (&line_spacing); x_cursor_position = rect_xmin; y_cursor_position = rect_ymin + line_spacing; num_cararcter = strlen (text); glEnable (GL_TEXTURE_2D); for (int i = 0; i < num_cararcter; i++) { ascii_code = (unsigned int) text[i]; CharData cd; int texture_id = get_character_texture_id (ascii_code, &cd); glBindTexture (GL_TEXTURE_2D, texture_id /*TextureMgr::Instance()->glid(texture_id)*/); if (ascii_code == 13) // return caractere { x_cursor_position = rect_xmin; y_cursor_position += height + 2; // line_spacing; } if (texture_id != get_null_character_texture_id() ) { glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); if (x_cursor_position + cd.bitmap_left_bearing + cd.gwidth > rect_xmax - 5) // 5 pixel margin at the end of the line { x_cursor_position = rect_xmin; y_cursor_position += height + 2; // line_spacing; } bitmap_x = x_cursor_position + cd.bitmap_left_bearing; bitmap_y = y_cursor_position - cd.bitmap_top_bearing; glColor3f (1.0f, 0.0f, 1.0f); glBegin (GL_QUADS); glTexCoord2f (0.0f, 0.0f); glVertex3i (bitmap_x, bitmap_y, 1); glTexCoord2f (0.0f, 1.0f); glVertex3i (bitmap_x, bitmap_y + height, 1); glTexCoord2f (1.0f, 1.0f); glVertex3i (bitmap_x + width, bitmap_y + height, 1); glTexCoord2f (1.0f, 0.0f); glVertex3i (bitmap_x + width, bitmap_y, 1); glEnd(); x_cursor_position += cd.hadvance; if (x_cursor_position > rect_xmax) { x_cursor_position = rect_xmin; y_cursor_position += height + 2; // line_spacing; } } } glDisable (GL_TEXTURE_2D); //disable_drawing_in_restricted_area(); // disable scissoring } // We start by packing the information related to a single glyph image into a single structure instead of parallel arrays. // We thus define the following structure type: typedef struct TGlyph_ { FT_UInt index; // glyph index FT_Vector pos; // glyph origin on the baseline FT_Glyph glyph; // glyph image } TGlyphStruct, *PGlyphStruct; TGlyphStruct gGlyphs[1000]; // glyphs table int gNumGlyphs = 0; // We also translate each glyph image directly after it is loaded to its position on the baseline at load time. // As we will see, this as several advantages. Our glyph sequence loader thus becomes: void FontMgr::ComputeGlyphString (int x, int y, const char *text) { //FT_GlyphSlot slot = face->glyph; // a small shortcut FT_Bool use_kerning; FT_UInt previous; int pen_x, pen_y, n; PGlyphStruct ptrGlyph; // current glyph in table FT_Error error; int num_chars = strlen (text); //... create face object ... FT_Face face = get_font_family (current_font)->m_face; pen_x = x; // start at (0,0) pen_y = y; gNumGlyphs = 0; use_kerning = FT_HAS_KERNING ( face ); previous = 0; ptrGlyph = gGlyphs; for ( n = 0; n < num_chars; n++ ) { //ptrGlyph->index = FT_Get_Char_Index( face, text[n] ); ptrGlyph->index = get_font_style (current_font, current_style)->charmap[text[n]].glyph_index; if ( use_kerning && previous && ptrGlyph->index ) { FT_Vector delta; FT_Get_Kerning ( face, previous, ptrGlyph->index, FT_KERNING_DEFAULT, &delta ); pen_x += delta.x >> 6; } // store current pen position ptrGlyph->pos.x = pen_x; ptrGlyph->pos.y = pen_y; // error = FT_Load_Glyph(face, ptrGlyph->index, FT_LOAD_NO_BITMAP); // if ( error ) continue; // error = FT_Get_Glyph(face->glyph, &ptrGlyph->glyph); // if ( error ) continue; pen_x += get_font_style (current_font, current_style)->charmap[text[n]].hadvance; previous = ptrGlyph->index; // discard glyph image (bitmap or not) FT_Done_Glyph ( gGlyphs[n].glyph ); // increment number of glyphs ptrGlyph++; } // count number of glyphs loaded gNumGlyphs = ptrGlyph - gGlyphs; } unsigned int FontMgr::GetStringWidth (const std::string &text) { StringBBox stringBBox; ComputeStringBBox (stringBBox, text.c_str() ); return stringBBox.width; } unsigned int FontMgr::GetStringHeight (const std::string &text) { StringBBox stringBBox; ComputeStringBBox (stringBBox, text.c_str() ); return stringBBox.height; } void FontMgr::ComputeStringBBox (StringBBox &stringBBox, const char *text) { int numCharacter = strlen (text); FT_Face face = get_font_family (current_font)->m_face; FT_Bool use_kerning = FT_HAS_KERNING ( face ); int current_glyph_index = 0; int previous_glyph_index = 0; int width = 0; int max_ybearing = 0; int max_height = 0; int max_downline = 0; // for each glyph image, compute its bounding box, // translate it, and grow the string bbox for ( int n = 0; n < numCharacter; n++ ) { // set the character were interested in CharData cd = get_font_style (current_font, current_style)->charmap[text[n]]; current_glyph_index = cd.glyph_index; if (use_kerning && previous_glyph_index && cd.glyph_index) { FT_Vector delta; FT_Get_Kerning ( face, previous_glyph_index, current_glyph_index, FT_KERNING_DEFAULT, &delta ); width += delta.x >> 6; } width += cd.hadvance; if (cd.hbearingY > max_ybearing) max_ybearing = cd.hbearingY; if (cd.bitmap_height - cd.hbearingY > max_downline) max_downline = cd.bitmap_height - cd.hbearingY; if (cd.bitmap_height > max_height) max_height = cd.bitmap_height; previous_glyph_index = current_glyph_index; } stringBBox.x = 0; stringBBox.y = 0; stringBBox.width = width; stringBBox.height = max_ybearing + max_downline; stringBBox.ybearing = max_ybearing; stringBBox.downline = max_downline; } void FontMgr::PositionString (const PageBBox &pageBBox, StringBBox &strBBox, TextAlignment alignment) { int x, y; int xmin, ymin, xmax, ymax; xmin = pageBBox.xmin + pageBBox.x_margin; xmax = pageBBox.xmax - pageBBox.x_margin; ymin = pageBBox.ymin + pageBBox.y_margin; ymax = pageBBox.ymax - pageBBox.y_margin; switch (alignment) { case eAlignTextCenter: default: x = xmin + ( (float) (xmax - xmin) - (float) (strBBox.width) ) / 2.0f; y = ymin + ( (float) (ymax - ymin) - (float) (strBBox.height) ) / 2.0f + strBBox.ybearing; break; case eAlignTextLeft: x = xmin; y = ymin + ( (float) (ymax - ymin) - (float) (strBBox.height) ) / 2.0f + strBBox.ybearing; break; case eAlignTextRight: x = xmin + ( (float) (xmax - xmin) - (float) (strBBox.width) ); y = ymin + ( (float) (ymax - ymin) - (float) (strBBox.height) ) / 2.0f + strBBox.ybearing; break; } strBBox.x = x; strBBox.y = y; } void FontMgr::RenderGlyph (const PageBBox &pageSize, const char *text, TextAlignment alignment) { FT_Vector start; StringBBox stringBBox; // get bbox of original glyph sequence /*ComputeStringBBox(stringBBox, text); PositionString(pageSize, stringBBox, alignment); ComputeGlyphString(stringBBox.x, stringBBox.y, text);*/ // compute string dimensions in integer pixels //int string_width = stringBBox.width; //int string_height = stringBBox.height; // set up start position in 26.6 cartesian space //start.x = ( ( target_width - string_width ) / 2 ) * 64; //start.y = ( ( target_height - string_height ) / 2 ) * 64; float angle = 0; //FT_Matrix matrix; // set up transform (a rotation here) /*matrix.xx = (FT_Fixed)( cos( angle ) * 0x10000L ); matrix.xy = (FT_Fixed)(-sin( angle ) * 0x10000L ); matrix.yx = (FT_Fixed)( sin( angle ) * 0x10000L ); matrix.yy = (FT_Fixed)( cos( angle ) * 0x10000L );*/ glEnable (GL_TEXTURE_2D); int bmpX; int bmpY; int bmpWidth; int bmpHeight; float u; float v; // int window_height = GfxServer::get_server()->getWindowHeight(); // glScissor(pageSize.xmin, window_height - pageSize.ymax, // pageSize.xmax - pageSize.xmin, pageSize.ymax - pageSize.ymin); gOpenGLEngine.PushClippingRectangle (inl::Rect (pageSize.xmin, pageSize.ymin, pageSize.xmax - pageSize.xmin, pageSize.ymax - pageSize.ymin) ); glEnable (GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); for ( int n = 0; n < gNumGlyphs; n++ ) { unsigned int ascii_code = (unsigned int) text[n]; FT_Face face = get_font_family (current_font)->m_face; int gltexid = get_font_style ((char*)face->family_name, (char*)face->style_name)->charmap[ascii_code].gltexid; CharData cd = get_font_style ((char*)face->family_name, (char*)face->style_name)->charmap[ascii_code]; glBindTexture (GL_TEXTURE_2D, gltexid); glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); // Set text Color here glColor4f (0.0f, 0.0f, 0.0f, 1); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); if (gltexid != get_null_character_texture_id() ) { bmpX = gGlyphs[n].pos.x + cd.bitmap_left_bearing; bmpY = gGlyphs[n].pos.y - cd.bitmap_top_bearing; bmpWidth = cd.bitmap_width; bmpHeight = cd.bitmap_height; if (cd.glTexWidth != 0 && cd.glTexHeight != 0) { u = float (cd.bitmap_width) / cd.glTexWidth; v = float (cd.bitmap_height) / cd.glTexHeight; } else { u = 1; v = 1; } glBegin (GL_QUADS); glMultiTexCoord2fARB (GL_TEXTURE0_ARB, 0.0f, 0.0f); glVertex3i (bmpX , bmpY, 1); glMultiTexCoord2fARB (GL_TEXTURE0_ARB, 0.0f, v); glVertex3i (bmpX , bmpY + bmpHeight, 1); glMultiTexCoord2fARB (GL_TEXTURE0_ARB, u, v); glVertex3i (bmpX + bmpWidth, bmpY + bmpHeight, 1); glMultiTexCoord2fARB (GL_TEXTURE0_ARB, u, 0.0f); glVertex3i (bmpX + bmpWidth, bmpY, 1); glEnd(); } } // FT_Face face = get_font_family(current_font)->m_face; // unsigned int ascii_code = (unsigned int) text[strlen(text)-1]; // CharData last_cd = get_font_style(face->family_name, face->style_name)->charmap[ascii_code]; // CharData dot_cd = get_font_style(face->family_name, face->style_name)->charmap['%']; // int dot_gltexid = get_font_style(face->family_name, face->style_name)->charmap['%'].gltexid; // // if(dot_cd.glTexWidth != 0 && dot_cd.glTexHeight != 0) // { // // This first check made sure that the GL texture for '.' has been loaded. // // Position of first dot // int posX = gGlyphs[gNumGlyphs-1].pos.x + last_cd.hadvance; // int posY = gGlyphs[gNumGlyphs-1].pos.y;// - dot_cd.bitmap_top_bearing; // // bmpWidth = dot_cd.bitmap_width; // bmpHeight = dot_cd.bitmap_height; // u = float(dot_cd.bitmap_width) / dot_cd.glTexWidth; // v = float(dot_cd.bitmap_height) / dot_cd.glTexHeight; // // glBindTexture(GL_TEXTURE_2D, dot_gltexid); // // int page_right_border_posX = pageSize.xmin + pageSize.xmax - pageSize.xmin; // while(posX + dot_cd.hadvance < page_right_border_posX) // { // bmpX = posX + dot_cd.bitmap_left_bearing; // bmpY = posY - dot_cd.bitmap_top_bearing; // // glBegin(GL_QUADS); // glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.0f, 0.0f); glVertex3i(bmpX , bmpY, 1); // glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.0f, v); glVertex3i(bmpX , bmpY + bmpHeight, 1); // glMultiTexCoord2fARB(GL_TEXTURE0_ARB, u, v); glVertex3i(bmpX + bmpWidth, bmpY + bmpHeight, 1); // glMultiTexCoord2fARB(GL_TEXTURE0_ARB, u, 0.0f); glVertex3i(bmpX + bmpWidth, bmpY, 1); // glEnd(); // posX += dot_cd.hadvance; // } // } // GLDrawRectangle( // stringBBox.x, // stringBBox.y - stringBBox.ybearing, // stringBBox.x + stringBBox.width, // stringBBox.y - stringBBox.downline); glDisable (GL_BLEND); glDisable (GL_TEXTURE_2D); gOpenGLEngine.PopClippingRectangle(); } void FontMgr::RenderTextLineEdit (const PageBBox &pageSize, const std::string &Str, unsigned int CursorPosition, int offset) { FT_Vector start; StringBBox stringBBox; // get bbox of original glyph sequence ComputeStringBBox (stringBBox, Str.c_str() ); PositionString (pageSize, stringBBox, eAlignTextLeft); ComputeGlyphString (stringBBox.x + offset, stringBBox.y, Str.c_str() ); RenderGlyph (pageSize, Str.c_str(), eAlignTextLeft); // Render Cursor std::string temp = Str.substr (0, CursorPosition); int w = GetStringWidth (temp); int h = GetStringHeight (temp); glDisable (GL_TEXTURE_2D); glColor4f (1, 0, 0, 1); glBegin (GL_LINES); glVertex3i (pageSize.xmin + w + offset, pageSize.ymin, 1); glVertex3i (pageSize.xmin + w + offset, pageSize.ymax, 1); glEnd(); } void FontMgr::RenderTextLineStatic (const PageBBox &pageSize, const std::string &Str, TextAlignment alignment, char trailingchar) { return; FT_Vector start; StringBBox stringBBox; // get bbox of original glyph sequence ComputeStringBBox (stringBBox, Str.c_str() ); PositionString (pageSize, stringBBox, alignment); ComputeGlyphString (stringBBox.x, stringBBox.y, Str.c_str() ); RenderGlyph (pageSize, Str.c_str(), alignment); if (trailingchar == 0) return; const char *text = Str.c_str(); FT_Face face = get_font_family (current_font)->m_face; unsigned int ascii_code = (unsigned int) text[strlen (text)-1]; CharData last_cd = get_font_style ((char*)face->family_name, (char*)face->style_name)->charmap[ascii_code]; CharData dot_cd = get_font_style ((char*)face->family_name, (char*)face->style_name)->charmap[trailingchar]; int dot_gltexid = get_font_style ((char*)face->family_name, (char*)face->style_name)->charmap[trailingchar].gltexid; glEnable (GL_TEXTURE_2D); if (dot_cd.glTexWidth != 0 && dot_cd.glTexHeight != 0) { // This first check made sure that the GL texture for '.' has been loaded. // Position of first dot int posX = gGlyphs[gNumGlyphs-1].pos.x + last_cd.hadvance; int posY = gGlyphs[gNumGlyphs-1].pos.y; // - dot_cd.bitmap_top_bearing; int bmpWidth = dot_cd.bitmap_width; int bmpHeight = dot_cd.bitmap_height; float u = float (dot_cd.bitmap_width) / dot_cd.glTexWidth; float v = float (dot_cd.bitmap_height) / dot_cd.glTexHeight; // glBindTexture(GL_TEXTURE_2D, dot_gltexid); // glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); // // Set text Color here // glColor4f(0.0f, 0.0f, 0.0f, 1); // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // glEnable(GL_BLEND); // glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); int page_right_border_posX = pageSize.xmin + pageSize.xmax - pageSize.xmin; while (posX + dot_cd.hadvance < page_right_border_posX) { int bmpX = posX + dot_cd.bitmap_left_bearing; int bmpY = posY - dot_cd.bitmap_top_bearing; glBegin (GL_QUADS); glMultiTexCoord2fARB (GL_TEXTURE0_ARB, 0.0f, 0.0f); glVertex3i (bmpX , bmpY, 1); glMultiTexCoord2fARB (GL_TEXTURE0_ARB, 0.0f, v); glVertex3i (bmpX , bmpY + bmpHeight, 1); glMultiTexCoord2fARB (GL_TEXTURE0_ARB, u, v); glVertex3i (bmpX + bmpWidth, bmpY + bmpHeight, 1); glMultiTexCoord2fARB (GL_TEXTURE0_ARB, u, 0.0f); glVertex3i (bmpX + bmpWidth, bmpY, 1); glEnd(); posX += dot_cd.hadvance; } } glDisable (GL_BLEND); glDisable (GL_TEXTURE_2D); } ./NuxGraphics/IOpenGLQuery.cpp0000644000004100000410000000743413313171755016503 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "GLResource.h" #include "GpuDevice.h" #include "GLDeviceObjects.h" #include "IOpenGLQuery.h" namespace nux { NUX_IMPLEMENT_OBJECT_TYPE(IOpenGLQuery); unsigned int IOpenGLQuery::_CurrentlyActiveQuery = 0; IOpenGLQuery::IOpenGLQuery(QUERY_TYPE Type) : IOpenGLResource(RTQUERY) , _Type(Type) , _QueryStarted(false) { #ifndef NUX_OPENGLES_20 CHECKGL(glGenQueriesARB(1, &_OpenGLID)) ; #endif } // The return type identifies the query state(see Queries). // The method returns 1(S_OK) if the query data is available and 0(S_FALSE) if it is not. // These are considered successful return values. int IOpenGLQuery::GetData( int *pData, unsigned int /* Size */, unsigned int /* GetDataFlags */ ) { #ifndef NUX_OPENGLES_20 unsigned int ResultReady = 0; glGetQueryObjectuivARB(_OpenGLID, GL_QUERY_RESULT_AVAILABLE_ARB, &ResultReady); CHECKGL_MSG( glGetQueryObjectuivARB ); if (ResultReady) { glGetQueryObjectuivARB(_OpenGLID, GL_QUERY_RESULT_ARB, (GLuint *) pData); CHECKGL_MSG( glGetQueryObjectuivARB ); return 1; } #endif return 0; } unsigned int IOpenGLQuery::GetDataSize() { return 0; } void IOpenGLQuery::GetDevice(GpuDevice **ppDevice) { // Do not call this function. *ppDevice = NULL; } QUERY_TYPE IOpenGLQuery::GetType() { return _Type; } void IOpenGLQuery::Issue( unsigned int IssueFlags ) { #ifndef NUX_OPENGLES_20 if (IssueFlags == (unsigned int) ISSUE_BEGIN) { nuxAssert(_CurrentlyActiveQuery == 0); if (_QueryStarted == true) { nuxError("The Query as already been activated"); } else { _QueryStarted = true; CHECKGL(glBeginQueryARB(GL_SAMPLES_PASSED_ARB, _OpenGLID)); _CurrentlyActiveQuery = _OpenGLID; } } else if (IssueFlags == (unsigned int) ISSUE_END) { nuxAssert(_CurrentlyActiveQuery == _OpenGLID); if (_QueryStarted == false) { nuxError("The Query as already been stoped"); } else { _QueryStarted = false; CHECKGL(glEndQueryARB(GL_SAMPLES_PASSED_ARB)); _CurrentlyActiveQuery = 0; } } #endif } // Return True is the result is available. That is glGetQueryObjectuivARB won't block // if called with GL_QUERY_RESULT_ARB. bool IOpenGLQuery::IsResultAvailable() { unsigned int ResultReady = 0; #ifndef NUX_OPENGLES_20 glGetQueryObjectuivARB(_OpenGLID, GL_QUERY_RESULT_AVAILABLE_ARB, &ResultReady); CHECKGL_MSG( glGetQueryObjectuivARB ); #endif return ResultReady != 0; } // Return the result of the query. Make sure IsResultAvailable returned TRUE before calling this function. // If you fail to do that, GetResult will block before returning. unsigned int IOpenGLQuery::GetResult() { unsigned int SamplesPassed = 0; #ifndef NUX_OPENGLES_20 glGetQueryObjectuivARB(_OpenGLID, GL_QUERY_RESULT_ARB, &SamplesPassed); CHECKGL_MSG( glGetQueryObjectuivARB ); #endif return SamplesPassed; } } ./NuxGraphics/IOpenGLGLSLShader.h0000644000004100000410000002123113313171755016722 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef IOPENGLSHADER_H #define IOPENGLSHADER_H namespace nux { class IOpenGLResource; bool ExtractShaderString3(const std::string &ShaderToken, const std::string &ShaderSource, std::string &RetSource, std::string ShaderPreprocessorDefines = std::string("")); class IOpenGLShader: public IOpenGLResource { NUX_DECLARE_OBJECT_TYPE(IOpenGLShader, IOpenGLResource); IOpenGLShader(std::string ShaderName, OpenGLResourceType ResourceType); virtual ~IOpenGLShader(); public: virtual void SetShaderCode(const ANSICHAR *ShaderCode, const char *ShaderPreprocessorDefines = "") = 0; virtual bool Compile() = 0; virtual bool IsValid() = 0; std::string _ShaderName; std::string _ShaderCode; }; class IOpenGLVertexShader: public IOpenGLShader { NUX_DECLARE_OBJECT_TYPE(IOpenGLVertexShader, IOpenGLShader); public: virtual ~IOpenGLVertexShader(); virtual void SetShaderCode(const ANSICHAR *ShaderCode, const char *VtxShaderPreprocessorDefines = ""); virtual bool Compile(); virtual bool IsValid(); private: IOpenGLVertexShader(std::string ShaderName = std::string("Vertex Shader")); int m_CompiledAndReady; friend class GpuDevice; }; class IOpenGLPixelShader: public IOpenGLShader { NUX_DECLARE_OBJECT_TYPE(IOpenGLPixelShader, IOpenGLShader); public: virtual ~IOpenGLPixelShader(); virtual void SetShaderCode(const ANSICHAR *ShaderCode, const char *FrgShaderPreprocessorDefines = ""); virtual bool Compile(); virtual bool IsValid(); private: IOpenGLPixelShader(std::string ShaderName = std::string("Fragment Shader")); int m_CompiledAndReady; friend class GpuDevice; }; #if 0 class IOpenGLGeometryShader: public IOpenGLShader { NUX_DECLARE_OBJECT_TYPE(IOpenGLGeometryShader, IOpenGLShader); public: virtual ~IOpenGLGeometryShader(); virtual void SetShaderCode(const ANSICHAR *ShaderCode, const char *GeometryShaderPreprocessorDefines = ""); virtual bool Compile(); virtual bool IsValid(); void SetInputPrimitiveType(GLenum type); void SetOutputPrimitiveType(GLenum type); void SetMaxVertexOutput(int max_vertex_output); private: IOpenGLGeometryShader(std::string ShaderName = std::string("Geometry Shader")); int m_CompiledAndReady; friend class GpuDevice; }; #endif class IOpenGLShaderProgram: public IOpenGLResource { NUX_DECLARE_OBJECT_TYPE(IOpenGLShaderProgram, IOpenGLResource); public: virtual ~IOpenGLShaderProgram(); // Load an inalogic shader. void LoadVertexShader(const char *glslshader, const char *VtxShaderPreprocessorDefines = ""); void LoadPixelShader(const char *glslshader, const char *FrgShaderPreprocessorDefines = ""); void LoadIShaderFile(const char *ShaderFileName, const char *VtxShaderPreprocessorDefines = "", const char *FrgShaderPreprocessorDefines = ""); void LoadIShader(const char *ShaderCode, const char *VtxShaderPreprocessorDefines = "", const char *FrgShaderPreprocessorDefines = ""); void AddShaderParameter(GLShaderParameter *Parameter); void AddShaderObject(ObjectPtr ShaderObject); void RemoveShaderObject(ObjectPtr ShaderObject); void ClearShaderObjects(); bool Link(); void Begin(); void End(); static void SetShaderTracking(bool enabled); public: bool SetUniform1f(char *varname, GLfloat v0); bool SetUniform2f(char *varname, GLfloat v0, GLfloat v1); bool SetUniform3f(char *varname, GLfloat v0, GLfloat v1, GLfloat v2); bool SetUniform4f(char *varname, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); bool SetUniform1i(char *varname, GLint v0); bool SetUniform2i(char *varname, GLint v0, GLint v1); bool SetUniform3i(char *varname, GLint v0, GLint v1, GLint v2); bool SetUniform4i(char *varname, GLint v0, GLint v1, GLint v2, GLint v3); bool SetUniform1fv(char *varname, GLsizei count, GLfloat *value); bool SetUniform2fv(char *varname, GLsizei count, GLfloat *value); bool SetUniform3fv(char *varname, GLsizei count, GLfloat *value); bool SetUniform4fv(char *varname, GLsizei count, GLfloat *value); bool SetUniform1iv(char *varname, GLsizei count, GLint *value); bool SetUniform2iv(char *varname, GLsizei count, GLint *value); bool SetUniform3iv(char *varname, GLsizei count, GLint *value); bool SetUniform4iv(char *varname, GLsizei count, GLint *value); bool SetUniformMatrix2fv(char *varname, GLsizei count, GLboolean transpose, GLfloat *value); bool SetUniformMatrix3fv(char *varname, GLsizei count, GLboolean transpose, GLfloat *value); bool SetUniformMatrix4fv(char *varname, GLsizei count, GLboolean transpose, GLfloat *value); bool SetUniform1f(GLint loc, GLfloat v0); bool SetUniform2f(GLint loc, GLfloat v0, GLfloat v1); bool SetUniform3f(GLint loc, GLfloat v0, GLfloat v1, GLfloat v2); bool SetUniform4f(GLint loc, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); bool SetUniform1i(GLint loc, GLint v0); bool SetUniform2i(GLint loc, GLint v0, GLint v1); bool SetUniform3i(GLint loc, GLint v0, GLint v1, GLint v2); bool SetUniform4i(GLint loc, GLint v0, GLint v1, GLint v2, GLint v3); bool SetUniform1fv(GLint loc, GLsizei count, GLfloat *value); bool SetUniform2fv(GLint loc, GLsizei count, GLfloat *value); bool SetUniform3fv(GLint loc, GLsizei count, GLfloat *value); bool SetUniform4fv(GLint loc, GLsizei count, GLfloat *value); bool SetUniform1iv(GLint loc, GLsizei count, GLint *value); bool SetUniform2iv(GLint loc, GLsizei count, GLint *value); bool SetUniform3iv(GLint loc, GLsizei count, GLint *value); bool SetUniform4iv(GLint loc, GLsizei count, GLint *value); bool SetUniformLocMatrix2fv(GLint loc, GLsizei count, GLboolean transpose, GLfloat *value); bool SetUniformLocMatrix3fv(GLint loc, GLsizei count, GLboolean transpose, GLfloat *value); bool SetUniformLocMatrix4fv(GLint loc, GLsizei count, GLboolean transpose, GLfloat *value); void GetUniformfv(char *name, GLfloat *values); void GetUniformiv(char *name, GLint *values); int GetUniformLocationARB(const GLchar *name); void GetActiveUniformARB(GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLchar *name); // glGetObjectParameterARBfv Parameters // object // Specifies the handle of the object to be queried // // pname // Specifies the an object parameter. Accepted symbolic names are // GL_OBJECT_TYPE_ARB , // GL_OBJECT_SUBTYPE_ARB, // GL_OBJECT_DELETE_STATUS_ARB, // GL_OBJECT_LINK_STATUS_ARB, // GL_OBJECT_VALIDATE_STATUS_ARB, // GL_OBJECT_COMPILE_STATUS_ARB, // GL_OBJECT_INFO_LOG_LENGTH_ARB, // GL_OBJECT_ATTACHED_OBJECTS_ARB, // GL_OBJECT_ACTIVE_ATTRIBUTES_ARB, // GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB, // GL_OBJECT_ACTIVE_UNIFORMS_ARB, // GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB, // GL_OBJECT_SHADER_SOURCE_LENGTH_ARB // // params // Returns the requested object parameter // void GetObjectParameterfvARB(GLenum pname, GLfloat *params); bool SetSampler(char *name, int exture_unit); GLShaderParameter *_FirstParameter; void CheckAttributeLocation(); void CheckUniformLocation(); int GetAttributeLocation(const char *AttributeName); private: IOpenGLShaderProgram(std::string ShaderProgramName = std::string("ShaderProgram")); ShaderAttributeDefinition m_ProgramAttributeDefinition[16/*NUM_VERTEX_SHADER_INPUT_ATTRIBUTE*/]; std::vector > ShaderObjectList; bool m_CompiledAndReady; std::string _ShaderProgramName; friend class GpuDevice; }; } #endif // IOPENGLSHADER_H ./NuxGraphics/IOpenGLQuery.h0000644000004100000410000000357113313171755016146 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef IOPENGLQUERY_H #define IOPENGLQUERY_H namespace nux { class IOpenGLResource; class IOpenGLQuery: public IOpenGLResource { NUX_DECLARE_OBJECT_TYPE(IOpenGLQuery, IOpenGLResource); public: int GetData( int *pData, unsigned int Size, unsigned int GetDataFlags ); unsigned int GetDataSize(); void GetDevice( GpuDevice **ppDevice ); QUERY_TYPE GetType(); void Issue( unsigned int IssueFlags ); // Convenient functions // Return True is the result is available. That is glGetQueryObjectuivARB won't block // if called with GL_QUERY_RESULT_ARB. bool IsResultAvailable(); // Return the result of the query. Make sure IsResultAvailable returned TRUE before calling this function. // If you fail to do that, GetResult will block before returning. unsigned int GetResult(); IOpenGLQuery(QUERY_TYPE Type); virtual ~IOpenGLQuery() {}; private: QUERY_TYPE _Type; bool _QueryStarted; friend class GpuDevice; static unsigned int _CurrentlyActiveQuery; }; } #endif // IOPENGLQUERY_H ./NuxGraphics/FontTexture.h0000644000004100000410000001575213313171755016156 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef FONTTEXTURE_H #define FONTTEXTURE_H class IOpenGLPixelShader; namespace nux { typedef enum _TextAlignment { eAlignTextNone = 0, eAlignTextLeft = 1, eAlignTextRight = 2, eAlignTextCenter = 3, } TextAlignment; class StringBBox { public: StringBBox() { x = 0; y = 0; width = 0; height = 0; ybearing = 0; downline = 0; }; ~StringBBox() {}; int x; int y; int width; int height; int ybearing; // max ybearing of the string int downline; // max downline of the string(max space below the baseline) }; class PageBBox { public: PageBBox() { xmin = 0; ymin = 0; xmax = 0; ymax = 0; x_margin = 0; y_margin = 0; }; ~PageBBox() {}; INT xmin; INT ymin; INT xmax; INT ymax; INT x_margin; INT y_margin; }; /////////////////////////////////////////////////////////////////////////////////////////////////////// struct CharDescriptor { //clean 16 bytes unsigned short x; unsigned short y; unsigned short Width; unsigned short Height; short XOffset; short YOffset; unsigned short page; short XAdvance; short abcA; short abcB; short abcC; CharDescriptor() : x( 0 ) , y( 0 ) , Width( 0 ) , Height( 0 ) , XOffset( 0 ) , YOffset( 0 ) , page( 0 ) , XAdvance( 0 ) , abcA( 0 ) , abcB( 0 ) , abcC( 0 ) { } }; struct KerningPair { unsigned short first; unsigned short second; short amount; KerningPair() : first(0), second(0), amount(0) {} }; struct Charset { bool italic; bool bold; unsigned short LineHeight; unsigned short Base; unsigned short Width, Height; unsigned short Pages; unsigned short FontHeight; unsigned short Ascent; unsigned short Descent; int AvgCharWidth; int MaxCharWidth; int InternalLeading; int ExternalLeading; unsigned short NumChar; CharDescriptor Chars[256]; unsigned short NumKerningPairs; KerningPair *Kerning; Charset() : italic(false), bold(false), LineHeight(0), Base(0), Width(0), Height(0) , Pages(0), FontHeight(0), Ascent(0), Descent(0), AvgCharWidth(0) , MaxCharWidth(0), InternalLeading(0), ExternalLeading(0) , NumChar(0), NumKerningPairs(0), Kerning(NULL) {} ~Charset() { delete [] Kerning; } }; // Information about a glyph. Tex_y2 can be calculated from tex_y1 // and _tex_line_height(see below). Advance is the width of the // glyph in screen space. struct Glyph { float tex_x1, tex_y1, tex_x2; int advance; }; class FontRenderer; //////////////////////////////////////////////////////////////////////////////////////////////////// // This font system loads in a custom file containing a gray scale // texture(used as alpha texture) with all the letters on it, and // information about what glyph is where. class FontTexture: public Object { public: NUX_DECLARE_OBJECT_TYPE(FontTexture, Object); FontTexture(const char *FontFile, NUX_FILE_LINE_PROTO); FontTexture(INT width, INT height, BYTE *Texture); ~FontTexture(); // The line height is a constant; int GetLineHeight() const { return m_Charset.FontHeight; } // Knowing the width of a character or a string can be useful if you // want your UI to look good at all. int GetCharWidth(const char &c) const; int GetStringWidth(const std::string &str) const; int GetCharStringWidth(const char *str) const; int GetStringWidth(const std::string &str, int num_char_to_compute) const; int GetCharStringWidth(const char *str, int num_char_to_compute) const; int GetFontHeight(); // CursorPosToX(similar to ScriptStringCPtoX from microsoft UniScript) // The CursorPosToX function returns the x-coordinate for the leading or trailing edge of a character position. // Parameters // icp // [in] Character position in the string. // fTrailing // [in] Indicates the edge of the icp that corresponds to the x coordinate. If TRUE, it indicates the trailing edge. If FALSE, it indicates the leading edge. // pX // [out] Pointer to a variable that receives the corresponding x coordinate for the icp. // // Return Values // If the function succeeds, it returns S_OK. // If the function fails, it returns an HRESULT. // The return value can be tested with the SUCCEEDED and FAILED macros. bool CursorPosToX(const std::string &Str, int icp, bool fTrailing, int *pX); // XToCursorPosition(similar to ScriptStringXtoCP from microsoft UniScript) // The XToCursorPosition function converts an x-coordinate to a character position. // // Parameters // iX // [in] Specifies the x coordinate. // FirstVisibleCharIndex, // [in] Index of the first visible character in the text box // piCh // [out] Pointer to a variable that receives the character position corresponding to iX. // piTrailing // [out] Pointer to a variable that receives an indicator whether the position is the leading or trailing edge of the character. // // Return Values // If the function is successful, it returns S_OK. // If the function fails, it returns an HRESULT. // The return value can be tested with the SUCCEEDED and FAILED macros. bool XToCursorPosition(const std::string &Str, int iX, unsigned int FirstVisibleCharIndex, int *piCh, int *piTrailing); bool BMFontParseFNT( std::istream &Stream); const Charset &GetFontInfo() const; std::vector TextureArray; private: INT _RefCount; INT _textureBMF; std::vector m_gl_texture_id; Charset m_Charset; friend class FontRenderer; }; } #endif //FONTTEXTURE_H ./NuxGraphics/nux-graphics.pc.in0000644000004100000410000000057713313171755017056 0ustar www-datawww-dataprefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: NuxGraphics Description: Core OpenGL graphics functions for Nux Version: @VERSION@ Libs: -L${libdir} -lnux-graphics-@NUX_API_VERSION@ Cflags: -I${includedir}/Nux-@NUX_API_VERSION@ Requires: glib-2.0 cairo libpng gdk-pixbuf-2.0 nux-core-@NUX_API_VERSION@ @GL_PKGS@ xxf86vm xinerama @GEIS_PKGS@ ./NuxGraphics/GLPBuffer.h0000644000004100000410000001123313313171755015431 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef __PBUFFERS_H__ #define __PBUFFERS_H__ #ifndef NUX_OPENGLES_20 #if defined(WIN32) #include "GLResource.h" # pragma warning (disable : 4786) #elif defined(UNIX) # include # include #elif defined(__APPLE__) # include #endif #include #include // The pixel format for the pbuffer is controlled by the mode string passed // into the PBuffer constructor. This string can have the following attributes: // // r - r pixel format (for float buffer). // rg - rg pixel format (for float buffer). // rgb - rgb pixel format. 8 bit or 16/32 bit in float buffer mode // rgba - same as "rgb alpha" string // alpha - must have alpha channel // depth - must have a depth buffer // depth=n - must have n-bit depth buffer // stencil - must have a stencil buffer // double - must support double buffered rendering // samples=n - must support n-sample antialiasing (n can be 2 or 4) // float=n - must support n-bit per channel floating point // // texture2D // textureRECT // textureCUBE - must support binding pbuffer as texture to specified target // - binding the depth buffer is also supporting by specifying // '=depth' like so: texture2D=depth or textureRECT=depth // - the internal format of the texture will be rgba by default or // float if pbuffer is floating point // namespace nux { class PBuffer { public: // see above for documentation on strMode format // set managed to true if you want the class to cleanup OpenGL objects in destructor PBuffer (const char *strMode, bool managed = false); ~PBuffer(); bool Initialize (int iWidth, int iHeight, bool bShareContexts, bool bShareObjects); void Destroy(); void Activate (PBuffer *current = NULL); // to switch between pbuffers, pass active pbuffer as argument void Deactivate(); #if defined(WIN32) int Bind (int iBuffer); int Release (int iBuffer); void HandleModeSwitch(); #endif unsigned int GetSizeInBytes(); unsigned int CopyToBuffer (void *ptr, int w = -1, int h = -1); inline int GetNumComponents() { return m_iNComponents; } inline int GetBitsPerComponent() { return m_iBitsPerComponent; } inline int GetWidth() { return m_iWidth; } inline int GetHeight() { return m_iHeight; } inline bool IsSharedContext() { return m_bSharedContext; } #if defined(WIN32) inline bool IsTexture() { return m_bIsTexture; } #endif protected: #if defined(NUX_OS_WINDOWS) HDC m_hDC; ///< Handle to a device context. HGLRC m_hGLRC; ///< Handle to a GL context. HPBUFFERARB m_hPBuffer;///< Handle to a pbuffer. HGLRC m_hOldGLRC; HDC m_hOldDC; std::vector m_pfAttribList; std::vector m_pbAttribList; bool m_bIsTexture; #elif defined(NUX_OS_LINUX) Display *m_pDisplay; GLXPbuffer m_glxPbuffer; GLXContext m_glxContext; Display *m_pOldDisplay; GLXPbuffer m_glxOldDrawable; GLXContext m_glxOldContext; std::vector m_pfAttribList; std::vector m_pbAttribList; #elif defined(NUX_OS_MACOSX) AGLContext m_context; WindowPtr m_window; std::vector m_pfAttribList; #endif int m_iWidth; int m_iHeight; int m_iNComponents; int m_iBitsPerComponent; const char *m_strMode; bool m_bSharedContext; bool m_bShareObjects; private: std::string getStringValue (std::string token); int getIntegerValue (std::string token); #if defined(NUX_OS_WINDOWS) || defined(NUX_OS_LINUX) void parseModeString (const char *modeString, std::vector *pfAttribList, std::vector *pbAttribList); bool m_bIsActive; bool m_bManaged; #endif }; } #endif // NUX_OPENGLES_20 #endif // __PBUFFERS_H__ ./NuxGraphics/GdkGraphics.h0000644000004100000410000000242213313171755016043 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef NUXIMAGE_GDKGRAPHICS_H #define NUXIMAGE_GDKGRAPHICS_H #include namespace nux { class NBitmapData; class GdkGraphics { public: GdkGraphics(); explicit GdkGraphics(const char* filename); // Takes ownership of the GdkPixbuf. explicit GdkGraphics(GdkPixbuf* pixbuf); ~GdkGraphics(); bool LoadImage(const char* filename); NBitmapData* GetBitmap() const; private: GdkPixbuf* pixbuf_; }; } #endif // NUXIMAGE_GDKGRAPHICS_H ./NuxGraphics/GdiImageLoader.cpp0000644000004100000410000001062613313171755017012 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "NuxCore/NuxCore.h" #include "GdiImageLoader.h" namespace nux { NBitmapData* GdiLoadImageFile(const TCHAR* filename) { ULONG_PTR token; Gdiplus::GdiplusStartupInput input; Gdiplus::GdiplusStartup(&token, &input, NULL); Gdiplus::Bitmap* bitmap = new Gdiplus::Bitmap(TCHAR_TO_UNICHAR(filename)); if (bitmap == 0 || (bitmap->GetType() == Gdiplus::ImageTypeUnknown) || (bitmap->GetWidth() == 0) || (bitmap->GetHeight() == 0)) { Gdiplus::GdiplusShutdown(token); return 0; } Gdiplus::BitmapData* bitmap_data = new Gdiplus::BitmapData; if (bitmap_data == 0) { delete bitmap; Gdiplus::GdiplusShutdown(token); return 0; } Gdiplus::PixelFormat pixel_format = bitmap->GetPixelFormat(); int channels = 4; BitmapFormat bitmap_format = BITFMT_UNKNOWN; if (pixel_format == PixelFormat24bppRGB) { bitmap_format = BITFMT_B8G8R8; channels = 3; } else if ((pixel_format == PixelFormat32bppARGB) || (pixel_format == PixelFormat32bppPARGB) || (pixel_format == PixelFormat32bppRGB)) { if (pixel_format == PixelFormat32bppARGB) pixel_format = PixelFormat32bppPARGB; // request conversion to pre-multiplied RGBA bitmap_format = BITFMT_B8G8R8A8; channels = 4; } else if ((pixel_format == PixelFormat16bppARGB1555) || (pixel_format == PixelFormat16bppGrayScale) || (pixel_format == PixelFormat16bppRGB555) || (pixel_format == PixelFormat16bppRGB565)) { pixel_format = PixelFormat24bppRGB; // request conversion to RGB bitmap_format = BITFMT_B8G8R8; channels = 3; } else if ((pixel_format == PixelFormat1bppIndexed) || (pixel_format == PixelFormat4bppIndexed) || (pixel_format == PixelFormat8bppIndexed)) { pixel_format = PixelFormat32bppARGB; // request conversion to RGBA bitmap_format = BITFMT_B8G8R8A8; channels = 4; } else if (pixel_format == PixelFormat48bppRGB) { pixel_format = PixelFormat24bppRGB; // request conversion to RGBA bitmap_format = BITFMT_B8G8R8; channels = 3; } else if ((pixel_format == PixelFormat64bppARGB) || (pixel_format == PixelFormat64bppPARGB)) { pixel_format = PixelFormat32bppARGB; // request conversion to RGBA bitmap_format = BITFMT_B8G8R8A8; channels = 4; } Gdiplus::Rect rect(0, 0, bitmap->GetWidth(), bitmap->GetHeight()); Gdiplus::Status status = bitmap->LockBits(&rect, Gdiplus::ImageLockModeRead, pixel_format, bitmap_data); if (status != Gdiplus::Ok) { delete bitmap_data; delete bitmap; Gdiplus::GdiplusShutdown(token); return 0; } unsigned int width = bitmap->GetWidth(); unsigned int height = bitmap->GetHeight(); NTextureData *Texture = NULL; Texture = new NTextureData(bitmap_format, width, height, 1); if (Texture == 0) { bitmap->UnlockBits(bitmap_data); delete bitmap_data; delete bitmap; Gdiplus::GdiplusShutdown(token); return 0; } ImageSurface &image_surface = Texture->GetSurface(0); unsigned char* dest = image_surface.GetPtrRawData(); int dest_pitch = image_surface.GetPitch(); unsigned char* dst = dest; unsigned char *src = (unsigned char*) bitmap_data->Scan0; unsigned int src_pitch = bitmap_data->Stride; for (unsigned int i = 0; i < height; i++) { Memcpy(dst, src + i*src_pitch, width*channels); dst += dest_pitch; } bitmap->UnlockBits(bitmap_data); delete bitmap_data; delete bitmap; Gdiplus::GdiplusShutdown(token); return Texture; } } ./NuxGraphics/GraphicsEngine.h0000644000004100000410000013630213313171755016550 0ustar www-datawww-data/* * Copyright 2010-2012 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef OPENGLENGINE_H #define OPENGLENGINE_H #include "GLResource.h" #include "GpuDevice.h" #include "GLDeviceObjects.h" #include "GLResourceManager.h" #include "GLTextureResourceManager.h" #include "GLVertexResourceManager.h" #include "GLRenderStates.h" #include "FontTexture.h" #include "RenderingPipe.h" #include "GLShader.h" #if defined(NUX_OS_WINDOWS) #include "GraphicsDisplay.h" #include "GLWindowManager.h" #elif defined(NUX_OS_LINUX) #include "GraphicsDisplay.h" #include "GLWindowManager.h" #endif #define NUX_MAX_GAUSSIAN_SIGMA 11 #define NUX_MIN_GAUSSIAN_SIGMA 1 #ifndef NUX_OPENGLES_20 #define NUX_VERTEX_SHADER_HEADER "#version 110 \n" #else #define NUX_VERTEX_SHADER_HEADER #endif #ifndef NUX_OPENGLES_20 #define NUX_FRAGMENT_SHADER_HEADER "#version 110 \n" #else #define NUX_FRAGMENT_SHADER_HEADER "precision mediump float; \n" #endif namespace nux { class FontTexture; class FontRenderer; class FilePath; class BaseTexture; class TextureRectangle; class ROPConfig { public: ROPConfig(); ~ROPConfig(); bool Blend; unsigned int SrcBlend; unsigned int DstBlend; static ROPConfig Default; }; class BlendOperator { public: BlendOperator(); ~BlendOperator(); void EnableBlending(bool enable); void SetPorterDuffOperator(PorterDuffOperator op); void SetCustomBlendOperator(unsigned int src_blend, unsigned int dst_blend); bool _enable; unsigned int _src_blend; unsigned int _dst_blend; }; typedef struct { int x; int y; int width; int height; } OpenGLContext; class FxStructure { public: FxStructure(); ~FxStructure(); ObjectPtr dst_texture; ObjectPtr src_texture; ObjectPtr temp_texture; }; typedef enum { LAYER_BLEND_MODE_NORMAL, // Darken Modes LAYER_BLEND_MODE_DARKEN, LAYER_BLEND_MODE_MULTIPLY, LAYER_BLEND_MODE_COLOR_BURN, LAYER_BLEND_MODE_LINEAR_BURN, // Lighten Modes LAYER_BLEND_MODE_LIGHTEN, LAYER_BLEND_MODE_SCREEN, LAYER_BLEND_MODE_COLOR_DODGE, LAYER_BLEND_MODE_LINEAR_DODGE, // Constrast Modes LAYER_BLEND_MODE_OVERLAY, LAYER_BLEND_MODE_SOFT_LIGHT, LAYER_BLEND_MODE_HARD_LIGHT, LAYER_BLEND_MODE_VIVID_LIGHT, LAYER_BLEND_MODE_LINEAR_LIGHT, LAYER_BLEND_MODE_PIN_LIGHT, LAYER_BLEND_MODE_HARD_MIX, // Inversion Modes LAYER_BLEND_MODE_DIFFERENCE, LAYER_BLEND_MODE_EXCLUSION, // Cancellation Modes LAYER_BLEND_MODE_SUBTRACT, // Others LAYER_BLEND_MODE_AVERAGE, LAYER_BLEND_MODE_ADD, LAYER_BLEND_MODE_NEGATION, LAYER_BLEND_MODE_REFLECT, LAYER_BLEND_MODE_GLOW, LAYER_BLEND_MODE_PHOENIX, //LAYER_BLEND_MODE_OPACITY, LAYER_BLEND_MODE_LAST } LayerBlendMode; //! Rendering engine class /*! This is the object that renders the graphics primitives. */ class GraphicsEngine { public: /*! @param GlWindow The graphics window for this rendering engine. @param create_rendering_data If true, then in GraphicsEngine, the system creates the OpenGL shaders and the font textures for the rendering. */ GraphicsEngine(GraphicsDisplay& GlWindow, bool create_rendering_data = true); ~GraphicsEngine(); void SetContext(int x, int y, int width, int height); void GetContextSize(int& w, int& h) const; int GetContextWidth() const; int GetContextHeight() const; int GetContextX() const; int GetContextY() const; void GetWindowSize(int& w, int& h) const; int GetWindowWidth() const; int GetWindowHeight() const; OpenGLContext m_CurrrentContext; // Load Textures BaseTexture* Load2DTextureFile(const char* filename); BaseTexture* Load2DRectangleTextureFile(const char* filename); BaseTexture* Load2DTextureFileGenerateAlpha(const char* filename, int red, int green, int blue); void SetTexture(int TextureUnit, BaseTexture* Texture); void SetTexture(int TextureUnit, ObjectPtr< IOpenGLBaseTexture > Texture); void EnableTextureMode(int TextureUnit, int TextureMode); void DisableTextureMode(int TextureUnit, int TextureMode); void DisableAllTextureMode(int TextureUnit); /////////////////// // DRAW TEXTURE // /////////////////// // Neutral //! Render a textured quad. /*! Shader Output = ve4(tex.r, tex.g, tex.b, tex.a) */ void QRP_1Tex(int x, int y, int width, int height, ObjectPtr Tex0, TexCoordXForm& texxform, const Color& color0); //! Render a textured quad. /*! Multiply the shader rgb output with the texture alpha. Shader Output = ve4(tex.r*tex.a, tex.g*tex.a, tex.b*tex.a, tex.a) */ void QRP_1TexPremultiply(int x, int y, int width, int height, ObjectPtr Tex0, TexCoordXForm& texxform, const Color& color0); void QRP_TexDesaturate(int x, int y, int width, int height, ObjectPtr Tex0, TexCoordXForm& texxform, const Color& color0, float desaturation_factor); void QRP_Pixelate(int x, int y, int width, int height, ObjectPtr DeviceTexture, TexCoordXForm& texxform, const Color& c0, int pixel_size); void QRP_Color(int x, int y, int width, int height, const Color& c0); void QRP_Color(int x, int y, int width, int height, const Color& c0, const Color& c1, const Color& c2, const Color& c3); void QRP_ColorModTexAlpha(int x, int y, int width, int height, ObjectPtr DeviceTexture, TexCoordXForm& texxform0, const Color& color); void QRP_2Tex(int x, int y, int width, int height, ObjectPtr DeviceTexture0, TexCoordXForm& texxform0, const Color& color0, ObjectPtr DeviceTexture1, TexCoordXForm& texxform1, const Color& color1); void QRP_2TexMod(int x, int y, int width, int height, ObjectPtr DeviceTexture0, TexCoordXForm& texxform0, const Color& color0, ObjectPtr DeviceTexture1, TexCoordXForm& texxform1, const Color& color1); void QRP_4Tex(int x, int y, int width, int height, ObjectPtr DeviceTexture0, TexCoordXForm& texxform0, const Color& color0, ObjectPtr DeviceTexture1, TexCoordXForm& texxform1, const Color& color1, ObjectPtr DeviceTexture2, TexCoordXForm& texxform2, const Color& color2, ObjectPtr DeviceTexture3, TexCoordXForm& texxform3, const Color& color3); void QRP_Triangle(int x0, int y0, int x1, int y1, int x2, int y2, Color c0); void QRP_Triangle(int x0, int y0, int x1, int y1, int x2, int y2, Color c0, Color c1, Color c2); void QRP_Line(int x0, int y0, int x1, int y1, Color c0); void QRP_Line(int x0, int y0, int x1, int y1, Color c0, Color c1); void QRP_QuadWireframe(int x0, int y0, int width, int height, Color c0, Color c1, Color c2, Color c3); ObjectPtr QRP_GetBlurTexture( int x, int y, int buffer_width, int buffer_height, ObjectPtr device_texture, TexCoordXForm& texxform, const Color& c0, float sigma = 1.0f, int num_pass = 1); ObjectPtr QRP_GetAlphaTexture( ObjectPtr device_texture, TexCoordXForm& texxform, const Color& c0); ObjectPtr QRP_GetColorMatrixTexture( ObjectPtr device_texture, TexCoordXForm& texxform, const Color& c0, Matrix4 color_matrix, Vector4 offset); ObjectPtr QRP_GetPower( ObjectPtr device_texture, TexCoordXForm& texxform, const Color& c0, const Vector4& exponent); ObjectPtr QRP_GetLQBlur( int x, int y, int buffer_width, int buffer_height, ObjectPtr device_texture, TexCoordXForm& texxform, const Color& c0); ObjectPtr QRP_GetHQBlur( int x, int y, int buffer_width, int buffer_height, ObjectPtr device_texture, TexCoordXForm& texxform, const Color& c0, float sigma = 1.0f, int num_pass = 1); void QRP_DisturbedTexture( int x, int y, int width, int height, ObjectPtr distorsion_texture, TexCoordXForm& texxform0, const Color& c0, ObjectPtr src_device_texture, TexCoordXForm& texxform1, const Color& c1); ObjectPtr QRP_GetPixelBlocks( ObjectPtr device_texture, TexCoordXForm& texxform0, const Color& c0, int pixel_size); void QRP_GetCopyTexture( int width, int height, ObjectPtr& dst_device_texture, ObjectPtr& src_device_texture, TexCoordXForm& texxform0, const Color& c0); #ifndef NUX_OPENGLES_20 // ASM void QRP_ASM_1Tex(int x, int y, int width, int height, ObjectPtr Tex0, TexCoordXForm& texxform, const Color& color0); void QRP_ASM_1TexPremultiply(int x, int y, int width, int height, ObjectPtr Tex0, TexCoordXForm& texxform, const Color& color0); void QRP_ASM_Pixelate(int x, int y, int width, int height, ObjectPtr DeviceTexture, TexCoordXForm& texxform, const Color& c0, int pixel_size); void QRP_ASM_Color(int x, int y, int width, int height, const Color& c0); void QRP_ASM_Color(int x, int y, int width, int height, const Color& c0, const Color& c1, const Color& c2, const Color& c3); void QRP_ASM_ColorModTexAlpha(int x, int y, int width, int height, ObjectPtr DeviceTexture, TexCoordXForm& texxform0, const Color& color); void QRP_ASM_2Tex(int x, int y, int width, int height, ObjectPtr DeviceTexture0, TexCoordXForm& texxform0, const Color& color0, ObjectPtr DeviceTexture1, TexCoordXForm& texxform1, const Color& color1); void QRP_ASM_2TexMod(int x, int y, int width, int height, ObjectPtr DeviceTexture0, TexCoordXForm& texxform0, const Color& color0, ObjectPtr DeviceTexture1, TexCoordXForm& texxform1, const Color& color1); void QRP_ASM_4Tex(int x, int y, int width, int height, ObjectPtr DeviceTexture0, TexCoordXForm& texxform0, const Color& color0, ObjectPtr DeviceTexture1, TexCoordXForm& texxform1, const Color& color1, ObjectPtr DeviceTexture2, TexCoordXForm& texxform2, const Color& color2, ObjectPtr DeviceTexture3, TexCoordXForm& texxform3, const Color& color3); void QRP_ASM_Triangle(int x0, int y0, int x1, int y1, int x2, int y2, Color c0); void QRP_ASM_Triangle(int x0, int y0, int x1, int y1, int x2, int y2, Color c0, Color c1, Color c2); void QRP_ASM_Line(int x0, int y0, int x1, int y1, Color c0); void QRP_ASM_Line(int x0, int y0, int x1, int y1, Color c0, Color c1); void QRP_ASM_QuadWireframe(int x0, int y0, int width, int height, Color c0, Color c1, Color c2, Color c3); void QRP_ASM_Power (int x, int y, int width, int height, ObjectPtr device_texture, TexCoordXForm& texxform, const Color& c0, Vector4 exponent); void QRP_ASM_AlphaReplicate (int x, int y, int width, int height, ObjectPtr device_texture, TexCoordXForm& texxform, const Color& c0); void QRP_ASM_HorizontalGauss(int x, int y, int width, int height, ObjectPtr device_texture, TexCoordXForm& texxform, const Color& c0, float sigma = 1.0f); void QRP_ASM_VerticalGauss (int x, int y, int width, int height, ObjectPtr device_texture, TexCoordXForm& texxform, const Color& c0, float sigma = 1.0f); void QRP_ASM_ColorMatrix (int x, int y, int width, int height, ObjectPtr device_texture, TexCoordXForm& texxform, const Color& c0, Matrix4 color_matrix, Vector4 offset); //! Blur texture /*! @param device_texture The texture that is to be blurred. @param texxform Texture transformation of device_texture. @param x Position of the source texture in result buffer. @param y Position of the source texture in result buffer. @param buffer_width Width of result texture. @param buffer_height Height of result texture. @param sigma */ ObjectPtr QRP_ASM_GetBlurTexture( int x, int y, int buffer_width, int buffer_height, ObjectPtr device_texture, TexCoordXForm& texxform, const Color& color, float sigma = 1.0f, int num_pass = 1); void QRP_ASM_GetBlurTextureFx( int x, int y, int buffer_width, int buffer_height, FxStructure* fx_structure, TexCoordXForm& texxform, const Color& color, float sigma = 1.0f, int num_pass = 1); //! Replicate the alpha channel in all components of the texture. /*! @param device_texture Source texture. @param texxform Texture transformation parameter. @param color Modulation color. @return Texture with all components set to the alpha value of the source. */ ObjectPtr QRP_ASM_GetAlphaTexture( ObjectPtr device_texture, TexCoordXForm& texxform, const Color& color); //! Color matrix filter. /*! @param device_texture Source texture. @param texxform Texture transformation parameter. @param c Modulation color. @param color_matrix 4x4 section of the color matrix filter. @param offset Last column of the color matrix filter. @return Texture resulting from the processing of the source through a color matrix. */ ObjectPtr QRP_ASM_GetColorMatrixTexture( ObjectPtr device_texture, TexCoordXForm& texxform, const Color& c, Matrix4 color_matrix, Vector4 offset); //! Texture components raised to a power. /*! Each component of the texture is raised to a power provided in the exponent parameter. @param device_texture Source texture. @param texxform Texture transformation parameter. @param c Modulation color. @param exponent Power values for each component. @return A texture where the component of the source texture have been raised to a power. */ ObjectPtr QRP_ASM_GetPower( ObjectPtr device_texture, TexCoordXForm& texxform, const Color& c0, const Vector4& exponent); ObjectPtr QRP_ASM_GetLQBlur( int x, int y, int buffer_width, int buffer_height, ObjectPtr device_texture, TexCoordXForm& texxform, const Color& c0); ObjectPtr QRP_ASM_GetHQBlur( int x, int y, int buffer_width, int buffer_height, ObjectPtr device_texture, TexCoordXForm& texxform, const Color& c0, float sigma = 1.0f, int num_pass = 1); void QRP_ASM_DisturbedTexture( int x, int y, int width, int height, ObjectPtr distorsion_texture, TexCoordXForm& texxform0, const Color& c0, ObjectPtr src_device_texture, TexCoordXForm& texxform1, const Color& c1); //! Pixel blocks. /*! @param device_texture Source texture. @param texxform Texture transformation parameter. @param color Modulation color. @param pixel_size Size of pixel blocks. @return A texture pixelated version of the source texture. */ ObjectPtr QRP_ASM_GetPixelBlocks( ObjectPtr device_texture, TexCoordXForm& texxform0, const Color& color, int pixel_size); void QRP_ASM_GetCopyTexture( int width, int height, ObjectPtr& dst_device_texture, ObjectPtr& src_device_texture, TexCoordXForm& texxform0, const Color& c0); #endif // GLSL void QRP_GLSL_1Tex(int x, int y, int width, int height, ObjectPtr DeviceTexture, TexCoordXForm& texxform, const Color& c0); void QRP_GLSL_1TexPremultiply(int x, int y, int width, int height, ObjectPtr DeviceTexture, TexCoordXForm& texxform, const Color& c0); void QRP_GLSL_TexDesaturate(int x, int y, int width, int height, ObjectPtr Tex0, TexCoordXForm& texxform, const Color& color0, float desaturation_factor); void QRP_GLSL_Pixelate(int x, int y, int width, int height, ObjectPtr DeviceTexture, TexCoordXForm& texxform, const Color& c0, int pixel_size); void QRP_GLSL_Color(int x, int y, int width, int height, const Color& c0); void QRP_GLSL_Color(int x, int y, int width, int height, const Color& c0, const Color& c1, const Color& c2, const Color& c3); void QRP_GLSL_ColorModTexAlpha(int x, int y, int width, int height, ObjectPtr DeviceTexture, TexCoordXForm& texxform0, const Color& color); void QRP_GLSL_2Tex(int x, int y, int width, int height, ObjectPtr DeviceTexture0, TexCoordXForm& texxform0, const Color& color0, ObjectPtr DeviceTexture1, TexCoordXForm& texxform1, const Color& color1); void QRP_GLSL_2TexMod(int x, int y, int width, int height, ObjectPtr DeviceTexture0, TexCoordXForm& texxform0, const Color& color0, ObjectPtr DeviceTexture1, TexCoordXForm& texxform1, const Color& color1); void QRP_GLSL_4Tex(int x, int y, int width, int height, ObjectPtr DeviceTexture0, TexCoordXForm& texxform0, const Color& color0, ObjectPtr DeviceTexture1, TexCoordXForm& texxform1, const Color& color1, ObjectPtr DeviceTexture2, TexCoordXForm& texxform2, const Color& color2, ObjectPtr DeviceTexture3, TexCoordXForm& texxform3, const Color& color3); void QRP_GLSL_Triangle (int x0, int y0, int x1, int y1, int x2, int y2, Color c0); void QRP_GLSL_Triangle (int x0, int y0, int x1, int y1, int x2, int y2, Color c0, Color c1, Color c2); void QRP_GLSL_Line (int x0, int y0, int x1, int y1, Color c0); void QRP_GLSL_Line (int x0, int y0, int x1, int y1, Color c0, Color c1); void QRP_GLSL_QuadWireframe(int x0, int y0, int width, int height, Color c0, Color c1, Color c2, Color c3); void QRP_GLSL_Power (int x, int y, int width, int height, ObjectPtr device_texture, TexCoordXForm& texxform, const Color& c0, Vector4 exponent); void QRP_GLSL_AlphaReplicate (int x, int y, int width, int height, ObjectPtr device_texture, TexCoordXForm& texxform, const Color& c0); void QRP_GLSL_HorizontalGauss(int x, int y, int width, int height, ObjectPtr device_texture, TexCoordXForm& texxform, const Color& c0, float sigma = 1.0f); void QRP_GLSL_VerticalGauss (int x, int y, int width, int height, ObjectPtr device_texture, TexCoordXForm& texxform, const Color& c0, float sigma = 1.0f); void QRP_GLSL_HorizontalHQGauss(int x, int y, int width, int height, ObjectPtr device_texture, TexCoordXForm& texxform, const Color& c0, float sigma = 1.0f); void QRP_GLSL_VerticalHQGauss (int x, int y, int width, int height, ObjectPtr device_texture, TexCoordXForm& texxform, const Color& c0, float sigma = 1.0f); void QRP_GLSL_HorizontalLSGauss(int x, int y, int width, int height, ObjectPtr device_texture, TexCoordXForm& texxform, const Color& c0, float sigma = 1.0f); void QRP_GLSL_VerticalLSGauss (int x, int y, int width, int height, ObjectPtr device_texture, TexCoordXForm& texxform, const Color& c0, float sigma = 1.0f); void QRP_GLSL_ColorMatrix (int x, int y, int width, int height, ObjectPtr device_texture, TexCoordXForm& texxform, const Color& c0, Matrix4 color_matrix, Vector4 offset); /*! @param device_texture The texture that is to be blurred. @param texxform Texture transformation of device_texture. @param x Position of the source texture in result buffer. @param y Position of the source texture in result buffer. @param buffer_width Width of result texture. @param buffer_height Height of result texture. */ ObjectPtr QRP_GLSL_GetBlurTexture( int x, int y, int buffer_width, int buffer_height, ObjectPtr device_texture, TexCoordXForm& texxform, const Color& c0, float sigma = 1.0f, int num_pass = 1); ObjectPtr QRP_GLSL_GetLSBlurTexture( int x, int y, int buffer_width, int buffer_height, ObjectPtr device_texture, TexCoordXForm& texxform, const Color& c0, float sigma = 1.0f, int num_pass = 1); ObjectPtr QRP_GLSL_GetAlphaTexture( ObjectPtr device_texture, TexCoordXForm& texxform, const Color& c0); ObjectPtr QRP_GLSL_GetColorMatrixTexture( ObjectPtr device_texture, TexCoordXForm& texxform, const Color& c0, Matrix4 color_matrix, Vector4 offset); ObjectPtr QRP_GLSL_GetPower( ObjectPtr device_texture, TexCoordXForm& texxform, const Color& c0, const Vector4& exponent); ObjectPtr QRP_GLSL_GetLQBlur( int x, int y, int buffer_width, int buffer_height, ObjectPtr device_texture, TexCoordXForm& texxform, const Color& c0); ObjectPtr QRP_GLSL_GetHQBlur( int x, int y, int buffer_width, int buffer_height, ObjectPtr device_texture, TexCoordXForm& texxform, const Color& c0, float sigma = 1.0f, int num_pass = 1); void QRP_GLSL_GetHQBlurFx( int x, int y, int buffer_width, int buffer_height, FxStructure* fx_structure, TexCoordXForm& texxform, const Color& c0, float sigma = 1.0f, int num_pass = 1); void QRP_GLSL_GetLSBlurFx( int x, int y, int buffer_width, int buffer_height, FxStructure *fx_structure, TexCoordXForm &texxform, const Color& c0, float sigma = 1.0f, int num_pass = 1); void QRP_GLSL_DisturbedTexture( int x, int y, int width, int height, ObjectPtr distorsion_texture, TexCoordXForm& texxform0, const Color& c0, ObjectPtr src_device_texture, TexCoordXForm& texxform1, const Color& c1); ObjectPtr QRP_GLSL_GetDisturbedTexture( int x, int y, int width, int height, ObjectPtr distorsion_texture, TexCoordXForm& texxform0, const Color& c0, ObjectPtr src_device_texture, TexCoordXForm& texxform1, const Color& c1); void QRP_GLSL_GetDisturbedTextureFx( int x, int y, int width, int height, ObjectPtr distorsion_texture, TexCoordXForm& texxform0, const Color& c0, FxStructure* fx_structure, TexCoordXForm& texxform1, const Color& c1); //! Pixel blocks. /*! @param device_texture Source texture. @param texxform Texture transformation parameter. @param color Modulation color. @param pixel_size Size of pixel blocks. @return A texture pixelated version of the source texture. */ ObjectPtr QRP_GLSL_GetPixelBlocks( ObjectPtr device_texture, TexCoordXForm& texxform0, const Color& c0, int pixel_size); void QRP_GLSL_GetCopyTexture( int width, int height, ObjectPtr& dst_device_texture, ObjectPtr& src_device_texture, TexCoordXForm& texxform0, const Color& c0); ////////////////////// // DRAW CLIPPING // ////////////////////// mutable std::vector ClippingRect; void PushClippingRectangle(Rect const& rect); void PopClippingRectangle(); void EmptyClippingRegion(); //! Set the clipping according to the clipping rectangle stack. void ApplyClippingRectangle(); void SetGlobalClippingRectangle(Rect const& rect); void DisableGlobalClippingRectangle(); //! Bypass the clipping rectangle stack and set a different clipping rectangle region. /*! You may restore the clipping rectangle stack with ApplyClippingRectangle. */ void SetClippingRectangle(const Rect& rect); //! Bypass the clipping rectangle stack and set a different clipping rectangle region. void SetOpenGLClippingRectangle(int x, int y, unsigned int width, unsigned int height); Rect GetClippingRegion() const; int GetNumberOfClippingRegions() const; void AddClipOffset(int x, int y); //!< Deprecated. Use PushClipOffset. void PushClipOffset(int x, int y); void PopClipOffset(); void ClearAreaColorDepthStencil(int x, int y, int width, int height, Color clearcolor, float cleardepth, int clearstencil); void ClearAreaColor(int x, int y, int width, int height, Color clearcolor); void ClearAreaDepthStencil(int x, int y, int width, int height, float cleardepth, int clearstencil); void Set3DView(int w, int h); //! Push a screen aligned 2D matrix. void Push2DWindow(int w, int h); void Pop2DWindow(); void Push2DModelViewMatrix(Matrix4 mat); Matrix4 Pop2DModelViewMatrix(); void Clear2DModelViewMatrix(); std::list m_2DModelViewMatricesStack; void SetViewport(int x, int y, int w, int h); Rect GetViewportRect() const; int GetViewportWidth() const; int GetViewportHeight() const; int GetViewportX() const; int GetViewportY() const; void GetViewportSize(int& viewport_width, int& viewport_height) const; void SetScissor(int x, int y, int w, int h); /*! When setting a matrix to translate the widgets, the scissor region is not translated accordingly. This function provides a mean to offset the scissor region. It is useful when translating a widget during and overlay drawing. See an example in the code of NUX-01. @param x Clipping area offset. @param y Clipping area offset. */ void SetScissorOffset(int x, int y); Rect const& GetScissorRect() const; void EnableScissoring(bool b); // void LoadPainterImages(); // const PainterImage* GetImage(UXStyleImageRef style); // Rect GetImageGeometry(UXStyleImageRef style); // std::list m_PainterImageList; int RenderColorText(ObjectPtr Font, int x, int y, std::string const& Str, const Color& TextColor, bool WriteAlphaChannel, int NumCharacter); int RenderColorTextLineStatic(ObjectPtr Font, const PageBBox& pageSize, std::string const& Str, const Color& TextColor, bool WriteAlphaChannel, TextAlignment alignment); int RenderColorTextLineEdit(ObjectPtr Font, const PageBBox& pageSize, std::string const& Str, const Color& TextColor, bool WriteAlphaChannel, const Color& SelectedTextColor, const Color& SelectedTextBackgroundColor, const Color& TextBlinkColor, const Color& CursorColor, bool ShowCursor, unsigned int CursorPosition, int offset = 0, int selection_start = 0, int selection_end = 0); ObjectPtr CreateTextureFromBackBuffer(int x, int y, int width, int height); //Statistics void ResetStats(); /*! Cache a resource if it has previously been cached. If the resource does not contain valid data then the returned value is not valid. Check that the returned hardware resource is valid by calling ObjectPtr.IsValid(). @param Resource The resource to cache. @return A hardware resource. */ ObjectPtr CacheResource(ResourceData* Resource); /*! Update a resource if it has previously been cached. @param Resource The resource to cache. */ void UpdateResource(ResourceData* Resource); bool FlushCachedResourceData(ResourceData* Resource); bool IsResourceCached(ResourceData* Resource); NResourceCache ResourceCache; Matrix4 GetProjectionMatrix(); //! Return the transpose version of GetProjectionMatrix(); Matrix4 GetOpenGLProjectionMatrix(); void SetProjectionMatrix(const Matrix4& matrix); //! Set orthographic projection matrix. /*! The default projection matrix used by nux. @param viewport_width Viewport width. @param viewport_height Viewport height. */ void SetOrthographicProjectionMatrix(int viewport_width, int viewport_height); //! Set orthographic projection matrix. /*! The default projection matrix used by nux. @param left coordinate of viewport location. @param right coordinate of viewport location. @param top coordinate of viewport location. @param bottom coordinate of viewport location. */ void SetOrthographicProjectionMatrix(int left, int right, int bottom, int top); //! Reset the projection matrix to identity. void ResetProjectionMatrix(); Matrix4 GetModelViewMatrix(); //! Return the transpose version of GetModelViewMatrix(); Matrix4 GetOpenGLModelViewMatrix(); Matrix4 GetModelViewProjectionMatrix(); Matrix4 GetOpenGLModelViewProjectionMatrix(); GpuRenderStates& GetRenderStates() { return *_graphics_display.m_DeviceFactory->gpu_render_states_; } void ResetRenderStates() { _graphics_display.m_DeviceFactory->gpu_render_states_->ResetStateChangeToDefault(); } void VerifyRenderStates() { _graphics_display.m_DeviceFactory->gpu_render_states_->CheckStateChange(); } ObjectPtr GetFont(); ObjectPtr GetBoldFont(); //! Return True is GraphicsEngine is using the GLSL shader code path. /*! @return True is the system is using the GLSL shader code path. */ bool UsingGLSLCodePath(); //! Return True is GraphicsEngine is using the ARB program code path. /*! @return True is the system is using the ARB program code path. */ bool UsingARBProgramCodePath(); //! Push a model view matrix on the stack. void PushModelViewMatrix(const Matrix4& matrix); //! Push an Identity model view matrix on the stack. void PushIdentityModelViewMatrix(); //! Push a 2D Translation model view matrix. /*! This is used by Nux to harmonize quads and lines pixel rendering in OpenGL. */ void Push2DTranslationModelViewMatrix(float tx, float ty, float tz); //! Pop a model view matrix off the stack. /*! Return True is a matrix was successfully popped. False if there was no matrix to pop. */ bool PopModelViewMatrix(); //! Reset the model view matrix to identity. void ResetModelViewMatrixStack(); //! Bypass the model view matrix stack and set a custom matrix. /*! You may restore the view matrix stack by calling ApplyModelViewMatrix. */ void SetModelViewMatrix(const Matrix4& matrix); //! Set the model view matrix according to the model view matrix stack. void ApplyModelViewMatrix(); //! Transform a rectangle with the model view matrix. /*! This transformation is only good as long as the model view matrix only contains 2D translations. The output rectangle width and height are the same as the input rectangle. @param rect The rectangle to transform. */ Rect ModelViewXFormRect(const Rect& rect); //! Return the depth of the model view matrix stack. /*! @return The depth of the model view matrix stack. */ int ModelViewStackDepth(); //! Push a projection matrix on the stack. void PushProjectionMatrix(const Matrix4& matrix); //! Pop a projection matrix off the stack. /*! Return True is a matrix was successfully popped. False if there was no matrix to pop. */ bool PopProjectionMatrix(); //! Return the depth of the projection matrix stack. /*! @return The depth of the projection matrix stack. */ int ProjectionStackDepth(); //! Push a raster operation configuration setting on the stack. void PushPorterDuffBlend(const PorterDuffOperator& porter_duff_op); //! Push a state that disables the blending. void PushDisableBlend(); //! Push a custom blend state. /*! @param src_blend OpenGL source blending mode. @param dst_blend OpenGL destination blending mode. */ void PushBlend(unsigned int src_blend, unsigned int dst_blend); //! Pop a raster operation configuration setting off the stack. /*! Return True is a matrix was successfully popped. False if there was no matrix to pop. */ bool PopBlend(); //! Return the depth of the raster operation stack. /*! @return The depth of the raster operation stack. */ int BlendStackDepth(); //! Blends a color layer over a texture. /*! Blends a color over a texture layer. @param bkg_device_texture Background texture. @param frg_color Foreground color. */ void QRP_GLSL_ColorLayerOverTexture(int x, int y, int width, int height, ObjectPtr bkg_device_texture, TexCoordXForm& bkg_texxform, const Color& bkg_color, const Color& frg_color, LayerBlendMode layer_blend_mode); //! Blends a texture layer over a color. /*! Blends a texture over a color layer. @param bkg_color Background color. @param frg_device_texture Foreground texture. */ void QRP_GLSL_TextureLayerOverColor(int x, int y, int width, int height, const Color& bkg_color, ObjectPtr frg_device_texture, TexCoordXForm& frg_texxform, const Color& frg_color, LayerBlendMode layer_blend_mode); //! Blends a texture layer over a texture. /*! Uses a layer blending operation to render two textures. @param bkg_device_texture Background texture layer. @param frg_device_texture Foreground texture layer. */ void QRP_GLSL_TextureLayerOverTexture(int x, int y, int width, int height, ObjectPtr bkg_device_texture, TexCoordXForm& bkg_texxform, const Color& bkg_color, ObjectPtr frg_device_texture, TexCoordXForm& frg_texxform, const Color& frg_color, LayerBlendMode layer_blend_mode); //! Blends a color layer over a color. /*! Uses a layer blending operation to render two colors. @param bkg_color Background color layer. @param frg_color Foreground color layer. */ void QRP_GLSL_ColorLayerOverColor(int x, int y, int width, int height, const Color& bkg_color, const Color& frg_color, LayerBlendMode layer_blend_mode); private: ObjectPtr _normal_font; //!< The normal font renderer ObjectPtr _bold_font; //!< The bold font renderer void InitShaders(); //! Helper function to compute a Gaussian filter weights void GaussianWeights(float **weights, float sigma, unsigned int num_tap); int LinearSampleGaussianWeights(std::vector& weights, std::vector& offsets, float sigma); //! Helper function to set an fbo void SetFrameBufferHelper( ObjectPtr& fbo, ObjectPtr& colorbuffer, ObjectPtr& depthbuffer, int width, int height); #ifndef NUX_OPENGLES_20 void InitAsmColorShader(); //! Render polygons with a single color. ObjectPtr m_AsmColor; void InitAsmTextureShader(); //! Render polygons with a texture modulated by a color. ObjectPtr m_AsmTextureModColor; //! Same as m_AsmTextureModColor for rectangle textures. ObjectPtr m_AsmTextureRectModColor; void InitAsmTexturePremultiplyShader(); //! Render polygons with a texture modulated by a color. ObjectPtr m_AsmTexturePremultiplyModColor; //! Same as m_AsmTextureModColor for rectangle textures. ObjectPtr m_AsmTexturePremultiplyRectModColor; void InitAsmPixelateShader(); //! Render a pixelated texture over a polygon. ObjectPtr m_AsmPixelate; //! Render a pixelated texture rectangle over a polygon. ObjectPtr m_AsmPixelateRect; void InitAsmColorModTexMaskAlpha(); //! Render polygons with a color masked by the alpha provided sampling a texture. //! Requires: Enable GPU Alpha Blending ObjectPtr m_AsmColorModTexMaskAlpha; ObjectPtr m_AsmColorModTexRectMaskAlpha; void InitAsm2TextureAdd(); //! Render polygons with 2 textures, each modulated by a color, and added together. ObjectPtr m_Asm2TextureAdd; ObjectPtr m_Asm2TextureRectAdd; void InitAsm2TextureMod(); //! Render polygons with 2 textures, each modulated by a color, and then multiplied together. ObjectPtr m_Asm2TextureMod; ObjectPtr m_Asm2TextureRectMod; void InitAsm4TextureAdd(); //! Render polygons with 4 textures, each modulated by a color, and added together. ObjectPtr m_Asm4TextureAdd; ObjectPtr m_Asm4TextureRectAdd; void InitAsmPower(); //! Raise a texture component to a power. /*! result = color0 * (tex0)^(exponent) = (tex0.r^exponent.r, tex0.g^exponent.g, tex0.b^exponent.b, tex0.a^exponent.a); */ ObjectPtr _asm_tex_component_exponentiation_prog; ObjectPtr _asm_texrect_component_exponentiation_prog; void InitAsmAlphaReplicate(); //! Replicate the alpha component into r, g and b. /*! result = color0 * (tex0.a, tex0.a, tex0.a, tex0.a); */ ObjectPtr _asm_tex_alpha_replicate_prog; ObjectPtr _asm_texrect_alpha_replicate_prog; void InitAsmSeparableGaussFilter(); //! Gauss horizontal filter. ObjectPtr _asm_tex_separable_gauss_filter_prog; ObjectPtr _asm_texrect_separable_gauss_filter_prog; // void InitAsmSeparableGaussFilter2(); // //! Gauss horizontal filter. // ObjectPtr _asm_tex_separable_gauss_filter_prog2; // ObjectPtr _asm_texrect_separable_gauss_filter_prog2; void InitAsmColorMatrixFilter(); //! Color matrix filter. ObjectPtr _asm_tex_color_matrix_filter_prog; ObjectPtr _asm_texrect_color_matrix_filter_prog; void InitAsm2TextureDepRead(); ObjectPtr m_ASM2TextureDepRead; ObjectPtr m_ASM2TextureRectDepRead; void InitAsmBlendModes(); ObjectPtr m_AsmPSBNormal; ObjectPtr m_AsmPSBLighten; ObjectPtr m_AsmPSBDarken; ObjectPtr m_AsmPSBMultiply; #endif void InitSlColorShader(); //! Render polygons with a single color. ObjectPtr m_SlColor; void InitSlTextureShader(); //! Render polygons with a texture modulated by a color. ObjectPtr m_SlTextureModColor; void InitSlTexturePremultiplyShader(); //! Render polygons with a premultiplied texture modulated by a color. ObjectPtr m_SlTexturePremultiplyModColor; void InitSlPixelateShader(); //! Render a pixelated texture over a polygon. ObjectPtr m_SLPixelate; void InitSlColorModTexMaskAlpha(); //! Render polygons with a color masked by the alpha provided sampling a texture. //! Requires: Enable GPU Alpha Blending ObjectPtr m_SlColorModTexMaskAlpha; ObjectPtr m_SlColorModTexRectMaskAlpha; void InitSl2TextureAdd(); //! Render polygons with 2 textures, each modulated by a color, and added together. //! result = (tex0*color0)+(tex1*color1) ObjectPtr m_Sl2TextureAdd; void InitSl2TextureDepRead(); //! Render a quad with 2 textures. One texture sample is use to offset the coordinates of the second texture read. //! result = (tex1(coord1.xy + tex0.xy)*color1) ObjectPtr m_Sl2TextureDepRead; void InitSl2TextureMod(); //! Render polygons with 2 textures, each modulated by a color, and then multiplied together. //! result = (tex0*color0)*(tex1*color1) ObjectPtr m_Sl2TextureMod; void InitSl4TextureAdd(); //! Render polygons with 4 textures, each modulated by a color, and added together. ObjectPtr m_Sl4TextureAdd; void InitSLPower(); //! Raise a texture component to a power. /*! result = color0 * (tex0)^(exponent) = (tex0.r^exponent.r, tex0.g^exponent.g, tex0.b^exponent.b, tex0.a^exponent.a); */ ObjectPtr _component_exponentiation_prog; void InitSLAlphaReplicate(); //! Replicate the alpha component into r, g and b. /*! result = color0 * (tex0.a, tex0.a, tex0.a, tex0.a); */ ObjectPtr _alpha_replicate_prog; void InitSLHorizontalGaussFilter(); //! Gauss horizontal filter. ObjectPtr _horizontal_gauss_filter_prog; void InitSLVerticalGaussFilter(); //! Gauss vertical filter. ObjectPtr _vertical_gauss_filter_prog; void InitSLHorizontalHQGaussFilter(int sigma); //! Gauss horizontal filter. ObjectPtr _horizontal_hq_gauss_filter_prog[NUX_MAX_GAUSSIAN_SIGMA]; void InitSLVerticalHQGaussFilter(int sigma); //! Gauss vertical filter. ObjectPtr _vertical_hq_gauss_filter_prog[NUX_MAX_GAUSSIAN_SIGMA]; void InitSLHorizontalLSGaussFilter(int k); //! Gauss horizontal filter. ObjectPtr _horizontal_ls_gauss_filter_prog[NUX_MAX_GAUSSIAN_SIGMA]; void InitSLVerticalLSGaussFilter(int k); //! Gauss vertical filter. ObjectPtr _vertical_ls_gauss_filter_prog[NUX_MAX_GAUSSIAN_SIGMA]; void InitSLColorMatrixFilter(); //! Color matrix filter. ObjectPtr _color_matrix_filter_prog; void InitSLDesaturation(); ObjectPtr desaturation_prog_; void InitSlBlendModes(); void InitBlendModeNormal(); void InitBlendModeLighten(); void InitBlendModeDarken(); ObjectPtr shader_layer_blend_normal_; ObjectPtr shader_layer_blend_lighten_; ObjectPtr shader_layer_blend_darken_; ObjectPtr shader_layer_blend_multiply_; // Blend modes ObjectPtr blend_tex_color_prog_[LAYER_BLEND_MODE_LAST]; ObjectPtr blend_color_tex_prog_[LAYER_BLEND_MODE_LAST]; ObjectPtr blend_tex_tex_prog_[LAYER_BLEND_MODE_LAST]; ObjectPtr blend_color_color_prog_[LAYER_BLEND_MODE_LAST]; std::string GetBlendModeBlendFunc(LayerBlendMode layer_blend_mode); std::string GetBlendModeString(LayerBlendMode layer_blend_mode); ObjectPtr GetColorBlendOverTexProgram(LayerBlendMode layer_blend_mode); ObjectPtr GetTextureLayerOverColorProgram(LayerBlendMode layer_blend_mode); ObjectPtr GetTextureLayerOverTextureProgram(LayerBlendMode layer_blend_mode); ObjectPtr GetColorLayerOverColorProgram(LayerBlendMode layer_blend_mode); //! Test the gpu features and set variables such as \e _use_glsl_shaders. void EvaluateGpuCaps(); bool _use_glsl_shaders; //!< True if the system is using the glsl code path. ObjectPtr _offscreen_fbo; ObjectPtr _offscreen_color_rt0; ObjectPtr _offscreen_depth_rt0; ObjectPtr _offscreen_color_rt1; ObjectPtr _offscreen_depth_rt1; ObjectPtr _offscreen_color_rt2; ObjectPtr _offscreen_depth_rt2; ObjectPtr _offscreen_color_rt3; ObjectPtr _offscreen_depth_rt3; Matrix4 _projection_matrix; Matrix4 _model_view_matrix; std::list _model_view_stack; std::list _blend_stack; //! The system GraphicsDisplay object GraphicsDisplay& _graphics_display; Rect _viewport; Rect _scissor; int _clip_offset_x; int _clip_offset_y; Rect _clipping_rect; //! Set to \i true to enable the global clipping rectangle. /*! When rendering directly to the OpenGL back buffer, we may enable a global clipping rectangle. This is mostly useful in embedded mode. \sa _global_clipping_rect; */ bool _global_clipping_enabled; //! Define a global clipping rectangle. Rect _global_clipping_rect; std::list _clip_offset_stack; FontRenderer* _font_renderer; //Statistics mutable long m_quad_stats; mutable long m_quad_tex_stats; mutable long m_triangle_stats; mutable long m_triangle_tex_stats; mutable long m_line_stats; GraphicsEngine(const GraphicsEngine&); // Does not make sense for a singleton. This is a self assignment. GraphicsEngine& operator = (const GraphicsEngine&); // Declare operator address-of as private GraphicsEngine* operator & (); }; } #endif // OPENGLENGINE_H ./NuxGraphics/GLTimer.cpp0000644000004100000410000000417113313171755015516 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "NuxCore/NuxCore.h" #include "GLResource.h" #include "GLTimer.h" namespace nux { GLTimer::GLTimer() { #if defined(NUX_OS_WINDOWS) LARGE_INTEGER freq; QueryPerformanceFrequency(&freq); QueryPerformanceCounter(&now); res = (float) (1.0f / (double) freq.QuadPart); #elif defined(NUX_OS_LINUX) gettimeofday(&m_last_time, NULL); #endif } GLTimer::~GLTimer() { } void GLTimer::Reset(void) { #if defined(NUX_OS_WINDOWS) QueryPerformanceCounter(&now); #elif defined(NUX_OS_LINUX) gettimeofday(&m_last_time, NULL); #endif } float GLTimer::PassedMilliseconds(void) { #if defined(NUX_OS_WINDOWS) LARGE_INTEGER temp; QueryPerformanceCounter(&temp); double elapsedTime = (temp.QuadPart - now.QuadPart) * res * 1000.0f; //now.QuadPart = temp.QuadPart; return elapsedTime; #elif defined(NUX_OS_LINUX) timeval current_time; float elapsedTime; gettimeofday(¤t_time, NULL); elapsedTime = (current_time.tv_sec - m_last_time.tv_sec) * 1000.0f; // seconds to millisecond elapsedTime += (current_time.tv_usec - m_last_time.tv_usec) / 1000.0f; // micro seconds to millisecond return elapsedTime; #endif } // float GLTimer::PassedFrac(void) // { // LARGE_INTEGER temp; // QueryPerformanceCounter(&temp); // return(temp.QuadPart - now.QuadPart) * res; // } } ./NuxGraphics/GraphicsEngine.cpp0000644000004100000410000012446513313171755017112 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "NuxCore/NuxCore.h" #include "ImageSurface.h" #include "GpuDevice.h" #include "GLDeviceObjects.h" #include "GLResourceManager.h" #include "GLTextureResourceManager.h" #include "GLVertexResourceManager.h" #include "FontTexture.h" #include "FontRenderer.h" #include "GraphicsEngine.h" namespace nux { BlendOperator::BlendOperator() { _enable = true; _src_blend = GL_ONE; _dst_blend = GL_ONE_MINUS_SRC_ALPHA; } BlendOperator::~BlendOperator() { _enable = true; _src_blend = GL_ONE; _dst_blend = GL_ONE_MINUS_SRC_ALPHA; } void BlendOperator::EnableBlending(bool enable) { _enable = enable; } void BlendOperator::SetPorterDuffOperator(PorterDuffOperator op) { switch(op) { case CLEAR: _src_blend = GL_ZERO; _dst_blend = GL_ZERO; break; case SRC: _src_blend = GL_ONE; _dst_blend = GL_ZERO; break; case DST: _src_blend = GL_ZERO; _dst_blend = GL_ONE; break; case SRC_OVER: _src_blend = GL_ONE; _dst_blend = GL_ONE_MINUS_SRC_ALPHA; break; case DST_OVER: _src_blend = GL_ONE_MINUS_DST_ALPHA; _dst_blend = GL_ONE; break; case SRC_IN: _src_blend = GL_DST_ALPHA; _dst_blend = GL_ZERO; break; case DST_IN: _src_blend = GL_ZERO; _dst_blend = GL_SRC_ALPHA; break; case SRC_OUT: _src_blend = GL_ONE_MINUS_DST_ALPHA; _dst_blend = GL_ZERO; break; case DST_OUT: _src_blend = GL_ZERO; _dst_blend = GL_ONE_MINUS_SRC_ALPHA; break; case SRC_ATOP: _src_blend = GL_DST_ALPHA; _dst_blend = GL_ONE_MINUS_SRC_ALPHA; break; case DST_ATOP: _src_blend = GL_ONE_MINUS_DST_ALPHA; _dst_blend = GL_SRC_ALPHA; break; case XOR: _src_blend = GL_ONE_MINUS_DST_ALPHA; _dst_blend = GL_ONE_MINUS_SRC_ALPHA; break; case PLUS: _src_blend = GL_ONE; _dst_blend = GL_ONE; break; default: // Use SRC_OVER _src_blend = GL_ONE; _dst_blend = GL_ONE_MINUS_SRC_ALPHA; break; } } void BlendOperator::SetCustomBlendOperator(unsigned int /* src_blend */, unsigned int /* dst_blend */) { } ROPConfig ROPConfig::Default; ROPConfig::ROPConfig() { Blend = false; SrcBlend = GL_SRC_ALPHA; DstBlend = GL_ONE_MINUS_SRC_ALPHA; } ROPConfig::~ROPConfig() { } FxStructure::FxStructure() { src_texture = nux::GetGraphicsDisplay()->GetGpuDevice()->CreateTexture(1, 1, 1, nux::BITFMT_R8G8B8A8, NUX_TRACKER_LOCATION); dst_texture = nux::GetGraphicsDisplay()->GetGpuDevice()->CreateTexture(1, 1, 1, nux::BITFMT_R8G8B8A8, NUX_TRACKER_LOCATION); temp_texture = nux::GetGraphicsDisplay()->GetGpuDevice()->CreateTexture(1, 1, 1, nux::BITFMT_R8G8B8A8, NUX_TRACKER_LOCATION); } FxStructure::~FxStructure() { } GraphicsEngine::GraphicsEngine(GraphicsDisplay& GlWindow, bool create_rendering_data) : _graphics_display(GlWindow) { IOpenGLShaderProgram::SetShaderTracking(true); _scissor.x = 0; _scissor.y = 0; _clip_offset_x = 0; _clip_offset_y = 0; _font_renderer = 0; _use_glsl_shaders = false; _global_clipping_enabled = false; // Evaluate the features provided by the GPU. EvaluateGpuCaps(); if (UsingGLSLCodePath()) { nuxDebugMsg("The GraphicsEngine is using the GLSL shader code path."); } else { nuxDebugMsg("The GraphicsEngine is using the assenbly shader code path."); } GlWindow.m_GraphicsContext = this; ResetStats(); _projection_matrix.Identity(); _model_view_matrix.Identity(); ResourceCache.InitializeResourceFactories(); m_CurrrentContext.x = 0; m_CurrrentContext.y = 0; m_CurrrentContext.width = _graphics_display.GetWindowWidth(); m_CurrrentContext.height = _graphics_display.GetWindowHeight(); SetViewport(0, 0, _graphics_display.GetWindowWidth(), _graphics_display.GetWindowHeight()); SetScissor(0, 0, _graphics_display.GetWindowWidth(), _graphics_display.GetWindowHeight()); EnableScissoring(true); GpuDevice* gpu_device = _graphics_display.GetGpuDevice(); const GpuInfo& gpu_info = gpu_device->GetGpuInfo(); if (create_rendering_data) { #ifndef NUX_OPENGLES_20 bool opengl_14_support = true; if ((gpu_device->GetOpenGLMajorVersion() == 1) && (gpu_device->GetOpenGLMinorVersion() < 4)) { // OpenGL version is less than OpenGL 1.4 opengl_14_support = false; } if (gpu_info.Support_ARB_Fragment_Shader() && gpu_info.Support_ARB_Vertex_Program() && opengl_14_support) { InitAsmColorShader(); InitAsmTextureShader(); InitAsmPixelateShader(); InitAsmColorModTexMaskAlpha(); InitAsm2TextureAdd(); InitAsm2TextureMod(); InitAsm4TextureAdd(); InitAsmBlendModes(); InitAsmPower(); InitAsmAlphaReplicate(); InitAsmSeparableGaussFilter(); InitAsmColorMatrixFilter(); //InitAsm2TextureDepRead(); // NUXTODO: fix the shader } #endif if ((gpu_info.Support_ARB_Vertex_Program() && gpu_info.Support_ARB_Fragment_Program()) || (gpu_info.Support_ARB_Vertex_Shader() && gpu_info.Support_ARB_Fragment_Shader())) { _font_renderer = new FontRenderer(*this); } if (gpu_info.Support_EXT_Framebuffer_Object()) _offscreen_fbo = gpu_device->CreateFrameBufferObject(); _offscreen_color_rt0 = _graphics_display.GetGpuDevice()->CreateTexture(2, 2, 1, BITFMT_R8G8B8A8, NUX_TRACKER_LOCATION); _offscreen_color_rt1 = _graphics_display.GetGpuDevice()->CreateTexture(2, 2, 1, BITFMT_R8G8B8A8, NUX_TRACKER_LOCATION); _offscreen_color_rt2 = _graphics_display.GetGpuDevice()->CreateTexture(2, 2, 1, BITFMT_R8G8B8A8, NUX_TRACKER_LOCATION); _offscreen_color_rt3 = _graphics_display.GetGpuDevice()->CreateTexture(2, 2, 1, BITFMT_R8G8B8A8, NUX_TRACKER_LOCATION); _offscreen_depth_rt0 = _graphics_display.GetGpuDevice()->CreateTexture(2, 2, 1, BITFMT_D24S8, NUX_TRACKER_LOCATION); _offscreen_depth_rt1 = _graphics_display.GetGpuDevice()->CreateTexture(2, 2, 1, BITFMT_D24S8, NUX_TRACKER_LOCATION); } } GraphicsEngine::~GraphicsEngine() { _offscreen_color_rt0.Release(); _offscreen_color_rt1.Release(); _offscreen_depth_rt0.Release(); _offscreen_depth_rt1.Release(); _offscreen_fbo.Release(); ResourceCache.Flush(); NUX_SAFE_DELETE(_font_renderer); } void GraphicsEngine::EvaluateGpuCaps() { #ifdef NUX_OS_WINDOWS if (_graphics_display.GetGpuDevice()->GetGpuInfo().Support_ARB_Vertex_Shader() && _graphics_display.GetGpuDevice()->GetGpuInfo().Support_ARB_Fragment_Shader()) #else if (_graphics_display.GetGpuDevice()->GetGpuInfo().Support_ARB_Vertex_Shader() && _graphics_display.GetGpuDevice()->GetGpuInfo().Support_ARB_Fragment_Shader() && (_graphics_display.GetGpuDevice()->GetOpenGLMajorVersion() >= 2)) #endif { std::string renderer_string = ANSI_TO_TCHAR(NUX_REINTERPRET_CAST(const char* , glGetString(GL_RENDERER))); CHECKGL_MSG(glGetString(GL_RENDERER)); // Exclude Geforce FX from using GLSL if (renderer_string.find("GeForce FX", 0) != tstring::npos) { _use_glsl_shaders = false; return; } // Exclude Geforce FX Go from using GLSL: this case is not needed since it is detected by the one above. if (renderer_string.find("GeForce FX Go", 0) != tstring::npos) { _use_glsl_shaders = false; return; } _use_glsl_shaders = true; } else { _use_glsl_shaders = false; } } bool GraphicsEngine::UsingGLSLCodePath() { return _use_glsl_shaders; } bool GraphicsEngine::UsingARBProgramCodePath() { return !_use_glsl_shaders; } ObjectPtr GraphicsEngine::GetFont() { #if defined(NUX_OS_WINDOWS) if (_normal_font.IsNull()) { FontTexture* fnt = new FontTexture(GNuxGraphicsResources.FindResourceLocation("Fonts/Tahoma_size_8.txt", true).c_str(), NUX_TRACKER_LOCATION); _normal_font = ObjectPtr (fnt); fnt->UnReference(); } #else if (_normal_font.IsNull()) { FontTexture* fnt = new FontTexture(GNuxGraphicsResources.FindResourceLocation("Fonts/nuxfont_size_8.txt", true).c_str(), NUX_TRACKER_LOCATION); _normal_font = ObjectPtr (fnt); fnt->UnReference(); } #endif return _normal_font; } ObjectPtr GraphicsEngine::GetBoldFont() { #if defined(NUX_OS_WINDOWS) if (_bold_font.IsNull()) { FontTexture* fnt = new FontTexture(GNuxGraphicsResources.FindResourceLocation("Fonts/Tahoma_size_8_bold.txt", true).c_str(), NUX_TRACKER_LOCATION); _bold_font = ObjectPtr (fnt); fnt->UnReference(); } #else if (_bold_font.IsNull()) { FontTexture* fnt = new FontTexture(GNuxGraphicsResources.FindResourceLocation("Fonts/nuxfont_size_8_bold.txt", true).c_str(), NUX_TRACKER_LOCATION); _bold_font = ObjectPtr (fnt); fnt->UnReference(); } #endif return _bold_font; } void GraphicsEngine::SetContext(int x, int y, int width, int height) { m_CurrrentContext.x = x; m_CurrrentContext.y = y; if (width <= 0 || height <= 0) { //nuxAssertMsg(0, "[GraphicsEngine::SetContext] Incorrect context size."); if (_graphics_display.m_DeviceFactory->GetCurrentFrameBufferObject().IsValid()) { m_CurrrentContext.width = _graphics_display.m_DeviceFactory->GetCurrentFrameBufferObject()->GetWidth(); m_CurrrentContext.height = _graphics_display.m_DeviceFactory->GetCurrentFrameBufferObject()->GetHeight(); } else { m_CurrrentContext.width = GetWindowWidth(); m_CurrrentContext.height = GetWindowHeight(); } } else { m_CurrrentContext.width = width; m_CurrrentContext.height = height; } } void GraphicsEngine::GetContextSize(int& w, int& h) const { w = m_CurrrentContext.width; h = m_CurrrentContext.height; } int GraphicsEngine::GetContextWidth() const { return m_CurrrentContext.width; } int GraphicsEngine::GetContextHeight() const { return m_CurrrentContext.height; } int GraphicsEngine::GetContextX() const { return m_CurrrentContext.x; } int GraphicsEngine::GetContextY() const { return m_CurrrentContext.y; } void GraphicsEngine::GetWindowSize(int& w, int& h) const { _graphics_display.GetWindowSize(w, h); } int GraphicsEngine::GetWindowWidth() const { return _graphics_display.GetWindowWidth(); } int GraphicsEngine::GetWindowHeight() const { return _graphics_display.GetWindowHeight(); } int GraphicsEngine::RenderColorText(ObjectPtr Font, int x, int y, std::string const& Str, const Color& TextColor, bool WriteAlphaChannel, int NumCharacter) { if (_font_renderer) return _font_renderer->RenderColorText(Font, x, y, Str, TextColor, WriteAlphaChannel, NumCharacter); return 0; } int GraphicsEngine::RenderColorTextLineStatic(ObjectPtr Font, const PageBBox& pageSize, std::string const& Str, const Color& TextColor, bool WriteAlphaChannel, TextAlignment alignment) { if (_font_renderer) return _font_renderer->RenderColorTextLineStatic(Font, pageSize, Str, TextColor, WriteAlphaChannel, alignment); return 0; } int GraphicsEngine::RenderColorTextLineEdit(ObjectPtr Font, const PageBBox& pageSize, std::string const& Str, const Color& TextColor, bool WriteAlphaChannel, const Color& SelectedTextColor, const Color& SelectedTextBackgroundColor, const Color& TextBlinkColor, const Color& CursorColor, bool ShowCursor, unsigned int CursorPosition, int offset, int selection_start, int selection_end) { if (_font_renderer) return _font_renderer->RenderColorTextLineEdit(Font, pageSize, Str, TextColor, WriteAlphaChannel, SelectedTextColor, SelectedTextBackgroundColor, TextBlinkColor, CursorColor, ShowCursor, CursorPosition, offset, selection_start, selection_end); return 0; } void GraphicsEngine::SetTexture(int TextureUnit, BaseTexture* Texture) { nuxAssertMsg(Texture != 0, "[GraphicsEngine::SetTexture] Texture is NULL."); if ((TextureUnit < GL_TEXTURE0) || (TextureUnit > GL_TEXTURE31)) return; ObjectPtr CachedTexture = ResourceCache.GetCachedResource(Texture); SetTexture(TextureUnit, CachedTexture->m_Texture); } void GraphicsEngine::SetTexture(int TextureUnit, ObjectPtr< IOpenGLBaseTexture > DeviceTexture) { NUX_RETURN_IF_FALSE(DeviceTexture.IsValid()); CHECKGL(glActiveTextureARB(TextureUnit)); DeviceTexture->BindTextureToUnit(TextureUnit); } void GraphicsEngine::EnableTextureMode(int TextureUnit, int TextureMode) { if ((TextureUnit < GL_TEXTURE0) || (TextureUnit > GL_TEXTURE31)) return; CHECKGL(glActiveTextureARB(TextureUnit)); CHECKGL(glEnable(TextureMode)); } void GraphicsEngine::DisableTextureMode(int TextureUnit, int TextureMode) { if ((TextureUnit < GL_TEXTURE0) || (TextureUnit > GL_TEXTURE31)) return; CHECKGL(glActiveTextureARB(TextureUnit)); CHECKGL(glDisable(TextureMode)); CHECKGL(glBindTexture(TextureMode, 0)); } void GraphicsEngine::DisableAllTextureMode(int TextureUnit) { if ((TextureUnit < GL_TEXTURE0) || (TextureUnit > GL_TEXTURE31)) return; _graphics_display.GetGpuDevice()->InvalidateTextureUnit(TextureUnit); } ////////////////////// // DRAW CLIPPING // ////////////////////// void GraphicsEngine::PushClippingRectangle(Rect const& rect) { if (_graphics_display.m_DeviceFactory->GetCurrentFrameBufferObject().IsValid()) { // There is an active framebuffer set. Push the clipping rectangles to that fbo clipping stack. _graphics_display.m_DeviceFactory->GetCurrentFrameBufferObject()->PushClippingRegion(rect); return; } Rect r0 = ModelViewXFormRect(rect); Rect r1; unsigned int stacksize = (unsigned int) ClippingRect.size(); int x0, y0, x1, y1; int window_width, window_height; window_width = _viewport.width; window_height = _viewport.height; if (stacksize == 0) { r1.Set(0, 0, window_width, window_height); } else { r1 = ClippingRect[stacksize-1]; } // http://www.codecomments.com/archive263-2004-12-350347.html // If your rectangles are given in 2D as Top,Left,Bottom,Right coordinates, as typical for GUI programming, then it's simply: // intersect.Left = max(a.Left, b.Left); // intersect.Top = max(a.Top, b.Top); // intersect.Right = min(a.Right, b.Right ); // intersect.Bottom = min(a.Bottom, b.Bottom); // And the intersection is empty unless intersect.Right > intersect.Left && intersect.Bottom > intersect.Top x0 = Max(r0.x, r1.x); y0 = Max(r0.y, r1.y); x1 = Min(r0.x + r0.width, r1.x + r1.width); y1 = Min(r0.y + r0.height, r1.y + r1.height); if ((x1 > x0) && (y1 > y0)) { _clipping_rect.Set(x0, y0, x1 - x0, y1 - y0); ClippingRect.push_back(Rect(x0, y0, x1 - x0, y1 - y0)); EnableScissoring(true); SetOpenGLClippingRectangle(x0, window_height - y0 - (y1 - y0), x1 - x0, y1 - y0); } else { _clipping_rect.Set(0, 0, 0, 0); ClippingRect.push_back(_clipping_rect); EnableScissoring(true); SetOpenGLClippingRectangle(0, 0, 0, 0); } } void GraphicsEngine::PopClippingRectangle() { if (_graphics_display.m_DeviceFactory->GetCurrentFrameBufferObject().IsValid()) { _graphics_display.m_DeviceFactory->GetCurrentFrameBufferObject()->PopClippingRegion(); return; } ClippingRect.pop_back(); unsigned int stacksize = (unsigned int) ClippingRect.size(); if (stacksize == 0) { _clipping_rect.Set(0, 0, _viewport.width, _viewport.height); EnableScissoring(true); SetOpenGLClippingRectangle(0, 0, _viewport.width, _viewport.height); } else { _clipping_rect = ClippingRect [stacksize-1]; Rect B = _clipping_rect; EnableScissoring(true); SetOpenGLClippingRectangle(B.x, _viewport.height - B.y - B.GetHeight(), B.GetWidth(), B.GetHeight()); } } void GraphicsEngine::ApplyClippingRectangle() { if (_graphics_display.m_DeviceFactory->GetCurrentFrameBufferObject().IsValid()) { _graphics_display.m_DeviceFactory->GetCurrentFrameBufferObject()->ApplyClippingRegion(); return; } unsigned int stacksize = (unsigned int) ClippingRect.size(); if (stacksize == 0) { _clipping_rect.Set(0, 0, _viewport.width, _viewport.height); EnableScissoring(true); SetOpenGLClippingRectangle(0, 0, _viewport.width, _viewport.height); } else { _clipping_rect = ClippingRect[stacksize-1]; Rect B = _clipping_rect; EnableScissoring(true); SetOpenGLClippingRectangle(B.x, _viewport.height - B.y - B.GetHeight(), B.GetWidth(), B.GetHeight()); } } void GraphicsEngine::EmptyClippingRegion() { if (_graphics_display.m_DeviceFactory->GetCurrentFrameBufferObject().IsValid()) { _graphics_display.m_DeviceFactory->GetCurrentFrameBufferObject()->EmptyClippingRegion(); return; } ClippingRect.clear(); { _clipping_rect.Set(0, 0, _viewport.width, _viewport.height); EnableScissoring(true); SetOpenGLClippingRectangle(0, 0, _viewport.width, _viewport.height); } } void GraphicsEngine::SetGlobalClippingRectangle(Rect const& rect) { _global_clipping_enabled = true; _global_clipping_rect.Set(rect.x, _viewport.height - rect.y - rect.height, rect.width, rect.height); ApplyClippingRectangle(); } void GraphicsEngine::DisableGlobalClippingRectangle() { _global_clipping_enabled = false; _global_clipping_rect.Set(0, 0, _viewport.width, _viewport.height); ApplyClippingRectangle(); } Rect GraphicsEngine::GetClippingRegion() const { if (_graphics_display.m_DeviceFactory->GetCurrentFrameBufferObject().IsValid()) { Rect r = _graphics_display.m_DeviceFactory->GetCurrentFrameBufferObject()->GetClippingRegion(); return r; } return _clipping_rect; // unsigned int stacksize = (unsigned int) ClippingRect.size(); // // if (stacksize == 0) // { // return Rect(0, 0, _viewport.width, _viewport.height); // } // else // { // Rect r = ClippingRect[stacksize-1]; // return r; // } } void GraphicsEngine::SetClippingRectangle(const Rect& rect) { _clipping_rect = rect; SetOpenGLClippingRectangle(rect.x, _viewport.height - rect.y - rect.height, rect.width, rect.height); } void GraphicsEngine::SetOpenGLClippingRectangle(int x, int y, unsigned int width, unsigned int height) { if (!_graphics_display.m_DeviceFactory->GetCurrentFrameBufferObject().IsValid()) { if (_global_clipping_enabled) { Rect intersection = Rect(x, y, width, height).Intersect(_global_clipping_rect); SetScissor(intersection.x, intersection.y, intersection.width, intersection.height); } else { SetScissor(x, y, width, height); } } else { SetScissor(x, y, width, height); } } int GraphicsEngine::GetNumberOfClippingRegions() const { if (_graphics_display.m_DeviceFactory->GetCurrentFrameBufferObject().IsValid()) { int n = _graphics_display.m_DeviceFactory->GetCurrentFrameBufferObject()->GetNumberOfClippingRegions(); return n; } return(int) ClippingRect.size(); } void GraphicsEngine::AddClipOffset(int x, int y) { PushClipOffset(x, y); } void GraphicsEngine::PushClipOffset(int x, int y) { _clip_offset_stack.push_back(Point(x, y)); _clip_offset_x = 0; _clip_offset_y = 0; std::list::iterator it; for (it = _clip_offset_stack.begin(); it != _clip_offset_stack.end(); ++it) { _clip_offset_x += (*it).x; _clip_offset_y += (*it).y; } } void GraphicsEngine::PopClipOffset() { if (_clip_offset_stack.empty()) { _clip_offset_x = 0; _clip_offset_y = 0; } _clip_offset_stack.pop_back(); _clip_offset_x = 0; _clip_offset_y = 0; std::list::iterator it; for (it = _clip_offset_stack.begin(); it != _clip_offset_stack.end(); ++it) { _clip_offset_x += (*it).x; _clip_offset_y += (*it).y; } } /////////////////// // DRAW TEXTURE // /////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Rendering calls // // From "OpenGL Programming Guide.pdf" // // If exact two-dimensional rasterization is desired, you must carefully specify both the orthographic // projection and the vertices of primitives that are to be rasterized. The orthographic projection // should be specified with integer coordinates, as shown in the following example: // gluOrtho2D(0, width, 0, height); // where width and height are the dimensions of the viewport. Given this projection matrix, polygon // vertices and pixel image positions should be placed at integer coordinates to rasterize predictably. // For example, glRecti(0, 0, 1, 1) reliably fills the lower left pixel of the viewport, and glRasterPos2i(0, // 0) reliably positions an unzoomed image at the lower left of the viewport. Point vertices, line // vertices, and bitmap positions should be placed at half-integer locations, however. For example, a // line drawn from(x1, 0.5) to(x2, 0.5) will be reliably rendered along the bottom row of pixels int the // viewport, and a point drawn at(0.5, 0.5) will reliably fill the same pixel as glRecti(0, 0, 1, 1). // An optimum compromise that allows all primitives to be specified at integer positions, while still // ensuring predictable rasterization, is to translate x and y by 0.375, as shown in the following code // fragment. Such a translation keeps polygon and pixel image edges safely away from the centers of // pixels, while moving line vertices close enough to the pixel centers. // glViewport(0, 0, width, height); // glMatrixMode(GL_PROJECTION); // glLoadIdentity(); // gluOrtho2D(0, width, 0, height); // glMatrixMode(GL_MODELVIEW); // glLoadIdentity(); // glTranslatef(0.375, 0.375, 0.0); /* render all primitives at integer positions */ const float RASTERIZATION_OFFSET = 0.0f; void GraphicsEngine::Push2DWindow(int w, int h) { #ifndef NUX_OPENGLES_20 { _model_view_matrix.Translate(m_CurrrentContext.x + RASTERIZATION_OFFSET, m_CurrrentContext.y + RASTERIZATION_OFFSET, 0); Matrix4 temp; std::list::iterator it; for (it = m_2DModelViewMatricesStack.begin(); it != m_2DModelViewMatricesStack.end(); ++it) { temp = _model_view_matrix; _model_view_matrix = temp * (*it); } } { _projection_matrix.Orthographic(0, w, h, 0, -1.0f, 1.0f); } #else // ModelView { _model_view_matrix.Translate(m_CurrrentContext.x + RASTERIZATION_OFFSET, m_CurrrentContext.y + RASTERIZATION_OFFSET, 0); Matrix4 temp; std::list::iterator it; for (it = m_2DModelViewMatricesStack.begin(); it != m_2DModelViewMatricesStack.end(); it++) { temp = _model_view_matrix; _model_view_matrix = temp * (*it); } } // Projection { _projection_matrix.Orthographic(0, w, h, 0, -1.0f, 1.0f); } #endif } void GraphicsEngine::Pop2DWindow() { #ifndef NUX_OPENGLES_20 CHECKGL(glMatrixMode(GL_PROJECTION)); CHECKGL(glLoadIdentity()); CHECKGL(glFrustum( -1.0, // left 1.0, // right -1.0, // bottom 1.0, // top 0.1, // near, 2000.0 // far )); CHECKGL(glMatrixMode(GL_MODELVIEW)); CHECKGL(glLoadIdentity()); #endif } void GraphicsEngine::Push2DModelViewMatrix(Matrix4 mat) { m_2DModelViewMatricesStack.push_back(mat); { _model_view_matrix.Translate(m_CurrrentContext.x + RASTERIZATION_OFFSET, m_CurrrentContext.y + RASTERIZATION_OFFSET, 0); Matrix4 temp; std::list::iterator it; for (it = m_2DModelViewMatricesStack.begin(); it != m_2DModelViewMatricesStack.end(); ++it) { temp = _model_view_matrix; _model_view_matrix = (*it) * temp; } } } Matrix4 GraphicsEngine::Pop2DModelViewMatrix() { Matrix4 Mat; Mat.Zero(); if (m_2DModelViewMatricesStack.empty()) return Mat; std::list::iterator it; it = m_2DModelViewMatricesStack.end(); --it; Mat = (*it); m_2DModelViewMatricesStack.pop_back(); { _model_view_matrix.Translate(m_CurrrentContext.x + RASTERIZATION_OFFSET, m_CurrrentContext.y + RASTERIZATION_OFFSET, 0); Matrix4 temp; std::list::iterator it; for (it = m_2DModelViewMatricesStack.begin(); it != m_2DModelViewMatricesStack.end(); ++it) { temp = _model_view_matrix; _model_view_matrix = temp * (*it); } } return Mat; } void GraphicsEngine::Clear2DModelViewMatrix() { m_2DModelViewMatricesStack.clear(); { _model_view_matrix.Translate(m_CurrrentContext.x + RASTERIZATION_OFFSET, m_CurrrentContext.y + RASTERIZATION_OFFSET, 0); Matrix4 temp; std::list::iterator it; for (it = m_2DModelViewMatricesStack.begin(); it != m_2DModelViewMatricesStack.end(); ++it) { temp = _model_view_matrix; _model_view_matrix = temp * (*it); } } } void GraphicsEngine::PushIdentityModelViewMatrix() { PushModelViewMatrix(Matrix4::IDENTITY()); } void GraphicsEngine::PushModelViewMatrix(const Matrix4& matrix) { if (_model_view_stack.empty()) _model_view_matrix = matrix; else _model_view_matrix = matrix * _model_view_stack.back(); _model_view_stack.push_back(_model_view_matrix); } void GraphicsEngine::Push2DTranslationModelViewMatrix(float tx, float ty, float tz) { Matrix4 temp; temp.Translate(tx, ty, tz); PushModelViewMatrix(temp); } bool GraphicsEngine::PopModelViewMatrix() { if (!_model_view_stack.empty()) _model_view_stack.pop_back(); if (_model_view_stack.empty()) { _model_view_matrix = Matrix4::IDENTITY(); return false; } _model_view_matrix = _model_view_stack.back(); return true; } void GraphicsEngine::ResetModelViewMatrixStack() { _model_view_stack.clear(); _model_view_matrix = Matrix4::IDENTITY(); } void GraphicsEngine::SetModelViewMatrix(const Matrix4& matrix) { _model_view_matrix = matrix; } void GraphicsEngine::ApplyModelViewMatrix() { if (_model_view_stack.empty()) _model_view_matrix = Matrix4::IDENTITY(); else _model_view_matrix = _model_view_stack.back(); } Rect GraphicsEngine::ModelViewXFormRect(const Rect& rect) { Vector4 v0(rect.x, rect.y, 0.0f, 1.0f); Vector4 v1 = _model_view_matrix * v0; Rect r(v1.x, v1.y, rect.width, rect.height); return r; } int GraphicsEngine::ModelViewStackDepth() { return(int)_model_view_stack.size(); } void GraphicsEngine::PushPorterDuffBlend(const PorterDuffOperator& porter_duff_op) { BlendOperator blend_op; blend_op.SetPorterDuffOperator(porter_duff_op); _blend_stack.push_front(blend_op); GetRenderStates().SetBlend(blend_op._enable, blend_op._src_blend, blend_op._dst_blend); } void GraphicsEngine::PushDisableBlend() { BlendOperator blend_op; blend_op.EnableBlending(false); _blend_stack.push_front(blend_op); GetRenderStates().SetBlend(blend_op._enable); } bool GraphicsEngine::PopBlend() { if (_blend_stack.empty()) { GetRenderStates().SetBlend(false, GL_ONE, GL_ZERO); return false; } _blend_stack.pop_front(); BlendOperator blend_op = (*_blend_stack.begin()); GetRenderStates().SetBlend(blend_op._enable, blend_op._src_blend, blend_op._dst_blend); return true; } int GraphicsEngine::BlendStackDepth() { return(int) _blend_stack.size(); } Matrix4 GraphicsEngine::GetProjectionMatrix() { return _projection_matrix; } Matrix4 GraphicsEngine::GetOpenGLProjectionMatrix() { Matrix4 mat = GetProjectionMatrix(); mat.Transpose(); return mat; } void GraphicsEngine::SetProjectionMatrix(const Matrix4& matrix) { _projection_matrix = matrix; } void GraphicsEngine::SetOrthographicProjectionMatrix(int viewport_width, int viewport_height) { _projection_matrix.Orthographic(0, viewport_width, viewport_height, 0, -1.0f, 1.0f); } void GraphicsEngine::SetOrthographicProjectionMatrix(int left, int right, int bottom, int top) { _projection_matrix.Orthographic(left, right, bottom, top, -1.0f, 1.0f); } void GraphicsEngine::ResetProjectionMatrix() { _projection_matrix = Matrix4::IDENTITY(); } Matrix4 GraphicsEngine::GetModelViewMatrix() { return _model_view_matrix; } Matrix4 GraphicsEngine::GetOpenGLModelViewMatrix() { Matrix4 mat = _model_view_matrix; mat.Transpose(); return mat; } Matrix4 GraphicsEngine::GetModelViewProjectionMatrix() { return _projection_matrix * _model_view_matrix; } Matrix4 GraphicsEngine::GetOpenGLModelViewProjectionMatrix() { // This matrix is the transposed version of GetModelViewProjectionMatrix. Matrix4 mat = _projection_matrix * _model_view_matrix; mat.Transpose(); return mat; } void GraphicsEngine::SetViewport(int origin_x, int origin_y, int w, int h) { nuxAssert(w >= 0); nuxAssert(h >= 0); _viewport.x = origin_x; _viewport.y = origin_y; _viewport.width = w; _viewport.height = h; if (_viewport.width < 0) { nuxAssertMsg(0, "[GraphicsEngine::SetViewport] Incorrect context size."); _viewport.width = 1; } if (_viewport.height < 0) { nuxAssertMsg(0, "[GraphicsEngine::SetViewport] Incorrect context size."); _viewport.height = 1; } CHECKGL(glViewport(origin_x, origin_y, _viewport.width, _viewport.height)); } // Rect GraphicsEngine::GetViewportRect() // { // return Rect(_viewport.x, _viewport.y, _viewport.width, _viewport.height); // } Rect GraphicsEngine::GetViewportRect() const { return _viewport; } int GraphicsEngine::GetViewportWidth() const { return _viewport.width; } int GraphicsEngine::GetViewportHeight() const { return _viewport.height; } int GraphicsEngine::GetViewportX() const { return _viewport.x; } int GraphicsEngine::GetViewportY() const { return _viewport.y; } void GraphicsEngine::GetViewportSize(int& viewport_width, int& viewport_height) const { viewport_width = _viewport.width; viewport_height = _viewport.height; } void GraphicsEngine::SetScissorOffset(int /* x */, int /* y */) { nuxAssertMsg(0, "[GraphicsEngine::SetScissorOffset] SetScissorOffset is deprecated."); // m_ScissorXOffset = x; // m_ScissorYOffset = y; } void GraphicsEngine::SetScissor(int x, int y, int w, int h) { nuxAssert(w >= 0); nuxAssert(h >= 0); NUX_RETURN_IF_FALSE(w >= 0); NUX_RETURN_IF_FALSE(h >= 0); _scissor.x = x; _scissor.y = y; _scissor.width = w; _scissor.height = h; if (_scissor.x < 0) { _scissor.width += _scissor.x; _scissor.x = 0; } if (_scissor.y < 0) { _scissor.height += _scissor.y; _scissor.y = 0; } if (_scissor.width <= 0) { // jaytaoko: This is a hack for what looks like a bug(#726033) in the radeon opensource driver // on R300/400/500. Rather than passing a null region to glScissor, we give the clip area a 1 pixel width. //_scissor.width = 1; CHECKGL(glScissor(0, 0, 1, 1)); return; } if (_scissor.height <= 0) { // jaytaoko: This is a hack for what looks like a bug(#726033) in the radeon opensource driver // on R300/400/500. Rather than passing a null region to glScissor, we give the clip area a 1 pixel height. //_scissor.height = 1; CHECKGL(glScissor(0, 0, 1, 1)); return; } CHECKGL(glScissor(_scissor.x, _scissor.y, _scissor.width, _scissor.height)); } Rect const& GraphicsEngine::GetScissorRect() const { return _scissor; } void GraphicsEngine::EnableScissoring(bool b) { GetRenderStates().EnableScissor(b); } ///////////////////////////////////////// // 2D Area Clear Color Depth Stencil // ///////////////////////////////////////// void GraphicsEngine::ClearAreaColorDepthStencil(int x, int y, int width, int height, Color clear_color, float /* cleardepth */, int clearstencil) { // enable stencil buffer CHECKGL(glEnable(GL_STENCIL_TEST)); // write a one to the stencil buffer everywhere we are about to draw CHECKGL(glStencilFunc(GL_ALWAYS, clearstencil, 0xFFFFFFFF)); // this is to always pass a one to the stencil buffer where we draw CHECKGL(glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE)); //CHECKGL(glEnable(GL_DEPTH_TEST)); //CHECKGL(glDepthFunc(GL_ALWAYS)); QRP_Color(x, y, width, height, clear_color); //CHECKGL(glDepthFunc(GL_LESS)); //CHECKGL(glDisable(GL_DEPTH_TEST)); CHECKGL(glDisable(GL_STENCIL_TEST)); } void GraphicsEngine::ClearAreaColor(int x, int y, int width, int height, Color clear_color) { QRP_Color(x, y, width, height, clear_color); } void GraphicsEngine::ClearAreaDepthStencil(int x, int y, int width, int height, float /* cleardepth */, int clearstencil) { // enable stencil buffer CHECKGL(glEnable(GL_STENCIL_TEST)); // write a one to the stencil buffer everywhere we are about to draw CHECKGL(glStencilFunc(GL_ALWAYS, clearstencil, 0xFFFFFFFF)); // this is to always pass a one to the stencil buffer where we draw CHECKGL(glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE)); CHECKGL(glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE)); //CHECKGL(glEnable(GL_DEPTH_TEST)); //CHECKGL(glDepthFunc(GL_ALWAYS)); QRP_Color(x, y, width, height, color::Black); //CHECKGL(glDepthFunc(GL_LESS)); //CHECKGL(glDisable(GL_DEPTH_TEST)); CHECKGL(glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE)); CHECKGL(glDisable(GL_STENCIL_TEST)); } //Statistics void GraphicsEngine::ResetStats() { m_quad_stats = 0; m_quad_tex_stats = 0; m_triangle_stats = 0; m_triangle_tex_stats = 0; m_line_stats = 0; } ObjectPtr< CachedResourceData > GraphicsEngine::CacheResource(ResourceData* Resource) { return ResourceCache.GetCachedResource(Resource); } bool GraphicsEngine::FlushCachedResourceData(ResourceData* Resource) { if (!IsResourceCached(Resource)) return false; ResourceCache.FlushResourceId(Resource->GetResourceIndex()); return true; } void GraphicsEngine::UpdateResource(ResourceData* Resource) { ObjectPtr GLResource = ResourceCache.FindCachedResourceById(Resource->GetResourceIndex()); //(CachedResourceData*)(*(ResourceCache.ResourceMap.find(Resource->ResourceIndex))).second; if (GLResource.IsValid()) { // Iterate through all resource updater types(list is sorted by subclass depth). for (unsigned int i = 0; i < ResourceCache.GetResourceUpdaters().size(); ++i) { NResourceUpdater* ResourceUpdater = ResourceCache.GetResourceUpdaters() [i]; nuxAssert(ResourceUpdater); // Check if the updater is valid for updating the resource. if (ResourceUpdater->UpdatesThisResource(Resource)) { ResourceUpdater->UpdateResource(GLResource, Resource); break; } } } } bool GraphicsEngine::IsResourceCached(ResourceData* Resource) { return ResourceCache.IsCachedResource(Resource); } void GraphicsEngine::SetFrameBufferHelper( ObjectPtr& fbo, ObjectPtr& colorbuffer, ObjectPtr& depthbuffer, int width, int height) { if ((colorbuffer.IsValid() == false) || (colorbuffer->GetWidth() != width) || (colorbuffer->GetHeight() != height)) { colorbuffer = _graphics_display.GetGpuDevice()->CreateTexture(width, height, 1, BITFMT_R8G8B8A8, NUX_TRACKER_LOCATION); } bool use_depth_buffer = _graphics_display.GetGpuDevice()->GetGpuInfo().Support_Depth_Buffer(); if (use_depth_buffer && depthbuffer.IsValid() && ((depthbuffer->GetWidth() != width) || (depthbuffer->GetHeight() != height))) { // Generate a new depth texture only if a valid one was passed to this function. depthbuffer = _graphics_display.GetGpuDevice()->CreateTexture(width, height, 1, BITFMT_D24S8, NUX_TRACKER_LOCATION); } fbo->FormatFrameBufferObject(width, height, BITFMT_R8G8B8A8); fbo->SetRenderTarget(0, colorbuffer->GetSurfaceLevel(0)); if (use_depth_buffer && depthbuffer.IsValid()) fbo->SetDepthSurface(depthbuffer->GetSurfaceLevel(0)); else fbo->SetDepthSurface(ObjectPtr(NULL)); fbo->Activate(); fbo->EmptyClippingRegion(); SetContext(0, 0, width, height); SetViewport(0, 0, width, height); Push2DWindow(width, height); } /*! Description - This function calculates position offsets for our gaussian weight values to utilise the GPU bilinear sampling * which gets neighbouring pixel's data in just one sample. This serves to halve the loop for both vertical and * horizontal blur shaders. * Params - First two parameters are the weight and weight offsets which are passed as uniforms to our shader. * our sigma dictates how strong our blur will be. * Return - We return our loop count which is a #define in our vertical and horizontal shaders. */ int GraphicsEngine::LinearSampleGaussianWeights(std::vector& weights, std::vector& offsets, float sigma) { //Calculate our support which is used as our loop count. int support = int(sigma * 3.0f); weights.push_back(exp(-(0*0)/(2*sigma*sigma))/(sqrt(2*constants::pi)*sigma)); float total = weights.back(); //Our first weight has an offset of 0. offsets.push_back(0); for (int i = 1; i <= support; i++) { float w1 = exp(-(i*i)/(2*sigma*sigma))/(sqrt(2*constants::pi)*sigma); float w2 = exp(-((i+1)*(i+1))/(2*sigma*sigma))/(sqrt(2*constants::pi)*sigma); weights.push_back(w1 + w2); total += 2.0f * weights[i]; //Calculate our offset to utilise our GPU's bilinear sampling capability. By sampling in between texel we get the data of //neighbouring pixels with only one sample. offsets.push_back((i * w1 + (i + 1) * w2) / weights[i]); } //Normalise our weights. for (int i = 0; i < support; i++) { weights[i] /= total; } return support; } void GraphicsEngine::GaussianWeights(float **weights, float sigma, unsigned int num_tap) { *weights = new float[num_tap]; float sum = 0.0f; unsigned int i = 0; unsigned int half = (num_tap-1)/2; (*weights)[half] = (1.0f/(sqrt(2.0f*3.14159265358f)*sigma)) * exp(-0.0f/(2.0f*sigma*sigma)); sum += (*weights)[half]; for (i = 0; i < half; i++) { float X = (i + 1)*(i + 1); (*weights)[half - i - 1] = (*weights)[half + i + 1] = (1.0f/(sqrt(2.0f*3.14159265358f)*sigma)) * exp(-X/(2.0f*sigma*sigma)); sum += 2.0f * ((*weights)[half - i - 1]); } /* normalization */ for (i = 0; i < num_tap; i++) { (*weights)[i] = (*weights)[i] / sum; } } ObjectPtr GraphicsEngine::CreateTextureFromBackBuffer(int x, int y, int width, int height) { ObjectPtr fbo = _graphics_display.GetGpuDevice()->GetCurrentFrameBufferObject(); int X, Y, W, H; if (fbo.IsValid()) { int fbo_width = fbo->GetWidth(); int fbo_height = fbo->GetHeight(); X = Clamp (x, 0, fbo_width); Y = Clamp (y, 0, fbo_height); W = Min (fbo_width - x, width); H = Min (fbo_height - y, height); if ((W <= 0) || (H <= 0)) { nuxAssertMsg(0, "[GraphicsEngine::CreateTextureFromBackBuffer] Invalid request."); return ObjectPtr (0); } // Inverse Y because of OpenGL upside-down nature Y = fbo_height - Y - H; } else { // There is no fbo. Reading directly from the back-buffer. int bb_width = _graphics_display.GetWindowWidth(); int bb_height = _graphics_display.GetWindowHeight(); X = Clamp (x, 0, bb_width); Y = Clamp (y, 0, bb_height); W = Min (bb_width - x, width); H = Min (bb_height - y, height); if ((W <= 0) || (H <= 0)) { nuxAssertMsg(0, "[GraphicsEngine::CreateTextureFromBackBuffer] Invalid request."); return ObjectPtr (0); } // Inverse Y because of OpenGL upside-down nature Y = bb_height - Y - H; } ObjectPtr device_texture = _graphics_display.GetGpuDevice()->CreateSystemCapableDeviceTexture(W, H, 1, BITFMT_R8G8B8A8, NUX_TRACKER_LOCATION); ObjectPtr sfc = device_texture->GetSurfaceLevel(0); sfc->CopyRenderTarget(X, Y, W, H); return device_texture; } } ./NuxGraphics/IOpenGLTexture2D.cpp0000644000004100000410000001155613313171755017224 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "GLDeviceObjects.h" #include "IOpenGLTexture2D.h" namespace nux { NUX_IMPLEMENT_OBJECT_TYPE(IOpenGLTexture2D); IOpenGLTexture2D::IOpenGLTexture2D(unsigned int Width , unsigned int Height , unsigned int Levels , BitmapFormat PixelFormat, bool Dummy, NUX_FILE_LINE_DECL) : IOpenGLBaseTexture(RTTEXTURE, Width, Height, 1, Levels, PixelFormat, NUX_FILE_LINE_PARAM) { external_id_ = Dummy; if (external_id_ == false) { CHECKGL(glGenTextures(1, &_OpenGLID)); CHECKGL(glBindTexture(GL_TEXTURE_2D, _OpenGLID)); } //_SurfaceArray.Empty(Levels); for (unsigned int l = 0; l < Levels; l++) { IOpenGLSurface *surface = new IOpenGLSurface(this, _OpenGLID, GL_TEXTURE_2D, GL_TEXTURE_2D, l, 0, NUX_FILE_LINE_PARAM); if (Dummy == false) surface->InitializeLevel(); _SurfaceArray.push_back(ObjectPtr (surface)); surface->UnReference(); } SetFiltering(GL_NEAREST, GL_NEAREST); SetWrap(GL_REPEAT, GL_REPEAT, GL_REPEAT); #ifdef NUX_OPENGLES_20 // NPOT textures in GLES2 only support GL_CLAMP_TO_EDGE unless // GL_OES_texture_npot is supported. // TODO: Check for GL_OES_texture_npot if (!_IsPOT) { SetWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); } #endif SetRenderStates(); GRunTimeStats.Register(this); } IOpenGLTexture2D::~IOpenGLTexture2D() { for (int l = 0; l < _NumMipLevel; l++) { _SurfaceArray[l] = ObjectPtr (0);; } _SurfaceArray.clear(); if (external_id_ == false) { CHECKGL(glDeleteTextures(1, &_OpenGLID)); } GRunTimeStats.UnRegister(this); _OpenGLID = 0; } ObjectPtr IOpenGLTexture2D::GetSurfaceLevel(int Level) { if ((Level >= 0) && (Level < _NumMipLevel)) { return _SurfaceArray[Level]; } else { nuxAssertMsg(0, "[IOpenGLTexture2D::GetSurfaceLevel] Invalid surface level"); } return ObjectPtr (0); } void IOpenGLTexture2D::GetSurfaceLevel(int Level, ObjectPtr& surface) { surface = GetSurfaceLevel(Level); } int IOpenGLTexture2D::LockRect( int Level, SURFACE_LOCKED_RECT *pLockedRect, const SURFACE_RECT *pRect) { nuxAssertMsg(pLockedRect, "[IOpenGLTexture2D::LockRect] Invalid parameter 'pLockedRect'."); nuxAssertMsg(Level >= 0, "[IOpenGLTexture2D::LockRect] Invalid mipmap level."); nuxAssertMsg(Level < _NumMipLevel, "[IOpenGLTexture2D::LockRect] Invalid mipmap level."); if (Level < _NumMipLevel) { ObjectPtr pSurfaceLevel = _SurfaceArray[Level]; return pSurfaceLevel->LockRect(pLockedRect, pRect); } else { pLockedRect->pBits = 0; pLockedRect->Pitch = 0; return OGL_INVALID_SURFACE_LEVEL; } return OGL_OK; } int IOpenGLTexture2D::UnlockRect(int Level) { nuxAssertMsg(Level >= 0, "[IOpenGLTexture2D::LockRect] Invalid mipmap level."); nuxAssertMsg(Level < _NumMipLevel, "[IOpenGLTexture2D::LockRect] Invalid mipmap level."); if (Level < _NumMipLevel) { ObjectPtr pSurfaceLevel = _SurfaceArray[Level]; return pSurfaceLevel->UnlockRect(); } else { return OGL_INVALID_SURFACE_LEVEL; } return OGL_OK; } unsigned int IOpenGLTexture2D::EnableGammaCorrection(bool /* b */) { nuxAssert(_OpenGLID); return OGL_OK; } unsigned char* IOpenGLTexture2D::GetSurfaceData(int level, int &width, int &height, int &stride) { width = 0; height = 0; stride = 0; if (level < 0) { nuxAssertMsg(level >= 0, "[IOpenGLTexture2D::GetSurfaceData] Invalid mipmap level."); return NULL; } if (level >= _NumMipLevel) { nuxAssertMsg(level < _NumMipLevel, "[IOpenGLTexture2D::GetSurfaceData] Invalid mipmap level."); return NULL; } ObjectPtr pSurfaceLevel = _SurfaceArray[level]; return pSurfaceLevel->GetSurfaceData(width, height, stride); } } ./NuxGraphics/GLTimer.h0000644000004100000410000000221213313171755015155 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef GLTIMER_H #define GLTIMER_H namespace nux { class GLTimer { public: GLTimer(); ~GLTimer(); void Reset(); float PassedMilliseconds(); //float PassedFrac(); protected: #if defined(NUX_OS_WINDOWS) LARGE_INTEGER now; float res; #elif defined(NUX_OS_LINUX) timeval m_last_time; #endif }; } #endif // GLTIMER_H ./NuxGraphics/GLVertexResourceManager.cpp0000644000004100000410000003060513313171755020717 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "GLResource.h" #include "GLResourceManager.h" #include "GLDeviceObjects.h" #include "GpuDevice.h" #include "GLVertexResourceManager.h" #include "GraphicsEngine.h" namespace nux { NUX_IMPLEMENT_OBJECT_TYPE(VertexBuffer); NUX_IMPLEMENT_OBJECT_TYPE(IndexBuffer); NUX_IMPLEMENT_OBJECT_TYPE(VertexDeclaration); NUX_IMPLEMENT_OBJECT_TYPE(MeshBuffer); NUX_IMPLEMENT_OBJECT_TYPE(CachedVertexBuffer); NUX_IMPLEMENT_OBJECT_TYPE(CachedIndexBuffer); NUX_IMPLEMENT_OBJECT_TYPE(CachedVertexDeclaration); NUX_IMPLEMENT_OBJECT_TYPE(CachedMeshBuffer); VertexBuffer::VertexBuffer() { _Stride = 0; } VertexBuffer::~VertexBuffer() { _Data.clear(); } VertexBuffer::VertexBuffer(int num_element, int size) { Allocate(num_element, size); } void VertexBuffer::Allocate(int num_element, int size) { nuxAssert(num_element > 0); nuxAssert(size > 0); if ((size <= 0) || (num_element <= 0)) { _Data.clear(); _Stride = 0; return; } // Make sure Size is a multiple of Stride int sz = size * num_element; _Stride = size; _Data.clear(); _Data.resize(sz); } int VertexBuffer::GetSize() const { return _Data.size(); } int VertexBuffer::GetStride() const { return _Stride; } int VertexBuffer::GetNumElement() const { return _Data.size() / _Stride; } const void* VertexBuffer::GetPtrRawData() const { if (_Data.empty()) return 0; return NUX_STATIC_CAST(const void*, &_Data[0]); } void* VertexBuffer::GetPtrRawData() { if (_Data.empty()) return 0; return NUX_CONST_CAST(void*, ((NUX_CONST_CAST(const VertexBuffer*, this))->GetPtrRawData())); } IndexBuffer::IndexBuffer() { _Stride = 0; } IndexBuffer::~IndexBuffer() { _Data.clear(); } IndexBuffer::IndexBuffer(int num_element, int size) { Allocate(num_element, size); } void IndexBuffer::Allocate(int num_index, int size) { nuxAssert(num_index > 0); nuxAssert(size > 0); nuxAssert((size == 2) || (size == 4)); if ((size <= 0) || (num_index <= 0)) { _Data.clear(); _Stride = 0; return; } _num_index = num_index; // Make sure Size is a multiple of Stride int sz = _num_index * size; _Stride = size; _Data.clear(); _Data.resize(sz); } int IndexBuffer::GetSize() const { return _Data.size(); } int IndexBuffer::GetStride() const { return _Stride; } int IndexBuffer::GetNumIndex() const { return _num_index; } const void* IndexBuffer::GetPtrRawData() const { return NUX_STATIC_CAST(const void*, &_Data[0]); } void* IndexBuffer::GetPtrRawData() { return NUX_CONST_CAST(void*, ((NUX_CONST_CAST(const IndexBuffer*, this))->GetPtrRawData())); } VertexDeclaration::VertexDeclaration() { _declaration.clear(); } VertexDeclaration::~VertexDeclaration() { _declaration.clear(); } void VertexDeclaration::AddVertexComponent(VERTEXELEMENT Component) { _declaration.push_back(Component); } CachedVertexBuffer::CachedVertexBuffer(NResourceSet* ResourceManager, VertexBuffer* SourceVtxBuffer) : CachedResourceData(ResourceManager) , _Size(0) , _Stride(0) { UpdateResource(SourceVtxBuffer); } CachedVertexBuffer::~CachedVertexBuffer() { // Not necessary for a smart pointer but do it anyway to be clear; _vertex_buffer = ObjectPtr (0); } bool CachedVertexBuffer::UpdateResource(ResourceData* Source) { if (Source == 0) { _Stride = 0; _vertex_buffer.Release(); return true; } VertexBuffer* SourceVtxBuffer = 0; nuxAssert(Source->Type().IsDerivedFromType(VertexBuffer::StaticObjectType)); if (Source->Type().IsDerivedFromType(VertexBuffer::StaticObjectType)) { SourceVtxBuffer = NUX_STATIC_CAST(VertexBuffer* , Source); } else { return false; } if ((SourceVtxBuffer->GetSize() == 0) || (SourceVtxBuffer->GetStride() == 0)) { _Stride = 0; _vertex_buffer.Release(); return true; } if (_Size != SourceVtxBuffer->GetSize()) { // The current size of the cached buffer is not the same as the requested one. // Delete the previously allocated buffer and create a new one. _Size = SourceVtxBuffer->GetSize(); _Stride = SourceVtxBuffer->GetStride(); //Release the previous vertex buffer if any. _vertex_buffer.Release(); _vertex_buffer = GetGraphicsDisplay()->GetGpuDevice()->CreateVertexBuffer(_Size, VBO_USAGE_STATIC); LoadVertexData(SourceVtxBuffer); } else { // The buffer size has changed. Delete the previously allocated buffer and create a new one. _Stride = SourceVtxBuffer->GetStride(); LoadVertexData(SourceVtxBuffer); } return true; } void CachedVertexBuffer::LoadVertexData(VertexBuffer* SourceVtxBuffer) { if ((SourceVtxBuffer == 0) || (SourceVtxBuffer->GetSize() == 0) || (SourceVtxBuffer->GetStride() == 0)) { return; } unsigned char* pData; _vertex_buffer->Lock(0, 0, (void**) &pData); Memcpy(pData, SourceVtxBuffer->GetPtrRawData(), SourceVtxBuffer->GetSize()); _vertex_buffer->Unlock(); } int CachedVertexBuffer::GetElementSize() const { return _Size; } int CachedVertexBuffer::GetBufferStride() const { return _Stride; } CachedIndexBuffer::CachedIndexBuffer(NResourceSet* ResourceManager, IndexBuffer* SourceIdxBuffer) : CachedResourceData(ResourceManager) , _Size(0) , _Stride(0) { UpdateResource(SourceIdxBuffer); } CachedIndexBuffer::~CachedIndexBuffer() { // Not necessary for a smart pointer but do it anyway to be clear; _index_buffer = ObjectPtr (0); } bool CachedIndexBuffer::UpdateResource(ResourceData* Source) { if (Source == 0) { _Size = 0; _Stride = 0; _index_buffer.Release(); return true; } IndexBuffer* SourceIdxBuffer = 0; nuxAssert(Source->Type().IsDerivedFromType(IndexBuffer::StaticObjectType)); if (Source->Type().IsDerivedFromType(IndexBuffer::StaticObjectType)) { SourceIdxBuffer = NUX_STATIC_CAST(IndexBuffer*, Source); } else { return false; } if ((SourceIdxBuffer->GetSize() == 0) || (SourceIdxBuffer->GetStride() == 0)) { _Size = 0; _Stride = 0; _index_buffer.Release(); return true; } if (_Size != SourceIdxBuffer->GetSize()) { _Size = SourceIdxBuffer->GetSize(); _Stride = SourceIdxBuffer->GetStride(); //Release the previous vertex buffer if any. _index_buffer.Release(); _index_buffer = GetGraphicsDisplay()->GetGpuDevice()->CreateIndexBuffer(_Size, VBO_USAGE_STATIC, (SourceIdxBuffer->GetStride() == 2) ? INDEX_FORMAT_USHORT : INDEX_FORMAT_UINT); LoadIndexData(SourceIdxBuffer); } else { _Stride = SourceIdxBuffer->GetStride(); LoadIndexData(SourceIdxBuffer); } _num_index = SourceIdxBuffer->GetNumIndex(); return true; } void CachedIndexBuffer::LoadIndexData(IndexBuffer* SourceIdxBuffer) { if ((SourceIdxBuffer == 0) || (SourceIdxBuffer->GetSize() == 0) || (SourceIdxBuffer->GetStride() == 0)) { return; } unsigned char* pData; _index_buffer->Lock(0, 0, (void**) &pData); Memcpy(pData, SourceIdxBuffer->GetPtrRawData(), SourceIdxBuffer->GetSize()); _index_buffer->Unlock(); } int CachedIndexBuffer::GetElementSize() const { return _Size; } int CachedIndexBuffer::GetBufferStride() const { return _Stride; } int CachedIndexBuffer::GetNumIndex() const { return _num_index; } CachedVertexDeclaration::CachedVertexDeclaration(NResourceSet* ResourceManager, VertexDeclaration* SourceVertexDeclaration) : CachedResourceData(ResourceManager) { UpdateResource(SourceVertexDeclaration); } CachedVertexDeclaration::~CachedVertexDeclaration() { _declaration = ObjectPtr (0); } bool CachedVertexDeclaration::UpdateResource(ResourceData* Source) { if (Source == 0) { _declaration = ObjectPtr (0); return true; } VertexDeclaration* SourceVertexDeclaration = 0; nuxAssert(Source->Type().IsDerivedFromType(VertexDeclaration::StaticObjectType)); if (Source->Type().IsDerivedFromType(VertexDeclaration::StaticObjectType)) { SourceVertexDeclaration = NUX_STATIC_CAST(VertexDeclaration*, Source); } else { return false; } if (SourceVertexDeclaration == 0) { _declaration = ObjectPtr (0); return true; } _declaration = GetGraphicsDisplay()->GetGpuDevice()->CreateVertexDeclaration(&SourceVertexDeclaration->_declaration[0]); return true; } MeshBuffer::MeshBuffer(NUX_FILE_LINE_DECL) : ResourceData(NUX_FILE_LINE_PARAM) { _vertex_buffer = 0; _index_buffer = 0; _vertex_declaration = 0; } MeshBuffer::~MeshBuffer() { if (_vertex_buffer) _vertex_buffer->UnReference(); if (_index_buffer) _index_buffer->UnReference(); if (_vertex_declaration) _vertex_declaration->UnReference(); } bool MeshBuffer::Update(const MeshData* mesh_data) { int num_element = mesh_data->_num_element; int element_size = mesh_data->_element_size; _mesh_primitive_type = mesh_data->_mesh_primitive_type; _vertex_buffer = new VertexBuffer(); _vertex_buffer->Allocate(num_element, element_size); memcpy(_vertex_buffer->GetPtrRawData(), mesh_data->_vertex_data, num_element * element_size); int num_index = mesh_data->_num_index; int index_size = mesh_data->_index_size; _index_buffer = new IndexBuffer(); _index_buffer->Allocate(num_index, index_size); memcpy(_index_buffer->GetPtrRawData(), mesh_data->_index_data, num_index * index_size); _vertex_declaration = new VertexDeclaration(); VERTEXELEMENT ve_position(0, 0, ATTRIB_CT_FLOAT, 4, 36); VERTEXELEMENT ve_normal(0, 16, ATTRIB_CT_FLOAT, 3, 36); VERTEXELEMENT ve_texcoord(0, 28, ATTRIB_CT_FLOAT, 2, 36); _vertex_declaration->AddVertexComponent(ve_position); _vertex_declaration->AddVertexComponent(ve_normal); _vertex_declaration->AddVertexComponent(ve_texcoord); _vertex_declaration->AddVertexComponent(DECL_END); return true; } ObjectPtr MeshBuffer::GetCachedMeshBuffer() { return GetGraphicsDisplay()->GetGraphicsEngine()->CacheResource(this); } CachedMeshBuffer::CachedMeshBuffer(NResourceSet* ResourceManager, MeshBuffer* resource) : CachedResourceData(ResourceManager) { UpdateResource(resource); } CachedMeshBuffer::~CachedMeshBuffer() { } bool CachedMeshBuffer::UpdateResource(ResourceData* source) { nuxAssert(source->Type().IsDerivedFromType(MeshBuffer::StaticObjectType)); MeshBuffer* mesh_buffer = NUX_STATIC_CAST(MeshBuffer*, source); _cached_vertex_buffer = GetGraphicsDisplay()->GetGraphicsEngine()->CacheResource(mesh_buffer->_vertex_buffer); _cached_index_buffer = GetGraphicsDisplay()->GetGraphicsEngine()->CacheResource(mesh_buffer->_index_buffer); _cached_vertex_declaration = GetGraphicsDisplay()->GetGraphicsEngine()->CacheResource(mesh_buffer->_vertex_declaration); _cached_vertex_declaration->_declaration->SetVertexBuffer(0, _cached_vertex_buffer->_vertex_buffer); _cached_vertex_declaration->_declaration->SetVertexBuffer(1, _cached_vertex_buffer->_vertex_buffer); _cached_vertex_declaration->_declaration->SetVertexBuffer(2, _cached_vertex_buffer->_vertex_buffer); _mesh_primitive_type = mesh_buffer->_mesh_primitive_type; return true; } } ./NuxGraphics/XInputWindow.h0000644000004100000410000000504113313171755016274 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef XINPUTWINDOW_H #define XINPUTWINDOW_H /* Xlib.h is the default header that is included and has the core functionallity */ #include /* Xatom.h includes functionallity for creating new protocol messages */ #include /* keysym.h contains keysymbols which we use to resolv what keys that are being pressed */ #include #include #include #include "NuxCore/NuxCore.h" #include "NuxCore/Rect.h" namespace nux { class XInputWindow { public: XInputWindow(const char* title, bool take_focus = False, int override_redirect = 0); ~XInputWindow(); static std::vector const& NativeHandleList(); void EnableStruts(bool enable); bool StrutsEnabled(); void EnableOverlayStruts(bool enable); bool OverlayStrutsEnabled(); void EnsureInputs(); void EnableTakeFocus (); //! Set the position and size of the window void SetGeometry(const Rect& geo); //! Set the position and size of the window void SetGeometry(int x, int y, int width, int height); //! Get the window geometry. Rect const& GetGeometry() const; //! Get X11 the Window. Window GetWindow (); void SetInputFocus (); void Hide (); void Show (); private: std::vector GetStrutsData(); void SetStruts (); void UnsetStruts (); void SetOverlayStruts (); void UnsetOverlayStruts (); void EnableDnd (); void DisableDnd (); static std::vector native_windows_; bool strutsEnabled_; bool overlayStrutsEnabled_; Window window_; Display *display_; Rect geometry_; bool shown_; bool mapped_; }; } #endif // XINPUTWINDOW_H ./NuxGraphics/GLRenderStates.h0000644000004100000410000013266013313171755016513 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef GLRENDERSTATES_H #define GLRENDERSTATES_H #include "NuxCore/NuxCore.h" #include "GpuDevice.h" namespace nux { enum { GFXRS_FRONT_POLYGONMODE, // GL_FILL GFXRS_BACK_POLYGONMODE, // GL_FILL GFXRS_CULLFACEENABLE, // GL_FALSE GFXRS_CULLFACE, // GL_BACK GFXRS_FRONTFACE, // GL_CCW GFXRS_SCISSORTESTENABLE, // GL_FALSE GFXRS_ZTESTENABLE, // GL_TRUE GFXRS_ZWRITEENABLE, // GL_TRUE GFXRS_ZFUNC, // GL_LESS GFXRS_ZNEAR, // 0.0f GFXRS_ZFAR, // 1.0f GFXRS_ALPHABLENDENABLE, // GL_FALSE GFXRS_BLENDOP, // GL_FUNC_ADD GFXRS_BLENDOPALPHA, // GL_FUNC_ADD GFXRS_SRCBLEND, // GL_ONE GFXRS_DESTBLEND, // GL_ZERO GFXRS_SRCBLENDALPHA, // GL_ONE GFXRS_DESTBLENDALPHA, // GL_ZERO GFXRS_ALPHATESTENABLE, // GL_FALSE GFXRS_ALPHATESTREF, // 0x0 GFXRS_ALPHATESTFUNC, // GL_ALWAYS GFXRS_STENCILENABLE, // GL_FALSE GFXRS_TWOSIDEDSTENCILENABLE, // GL_FALSE GFXRS_FRONT_STENCILWRITEMASK, // 0xFFFFFFFF GFXRS_BACK_STENCILWRITEMASK, // 0xFFFFFFFF GFXRS_FRONT_STENCILFUNC, // GL_ALWAYS GFXRS_FRONT_STENCILREF, // 0x0 GFXRS_FRONT_STENCILMASK, // 0xFF GFXRS_FRONT_STENCILFAIL, // GL_KEEP GFXRS_FRONT_STENCILZFAIL, // GL_KEEP GFXRS_FRONT_STENCILZPASS, // GL_KEEP GFXRS_BACK_STENCILFUNC, // GL_ALWAYS GFXRS_BACK_STENCILREF, // 0x0 GFXRS_BACK_STENCILMASK, // 0xFF GFXRS_BACK_STENCILFAIL, // GL_KEEP GFXRS_BACK_STENCILZFAIL, // GL_KEEP GFXRS_BACK_STENCILZPASS, // GL_KEEP GFXRS_LINESMOOTHENABLE, // GL_FALSE GFXRS_LINEWIDTH, // 1.0f GFXRS_LINEHINT, // GL_FASTEST GFXRS_COLORWRITEENABLE_R, // TRUE or FALSE GFXRS_COLORWRITEENABLE_G, // TRUE or FALSE GFXRS_COLORWRITEENABLE_B, // TRUE or FALSE GFXRS_COLORWRITEENABLE_A, // TRUE or FALSE GFXRS_MAX_RENDERSTATES, }; enum { GFXSS_ADDRESSU, GFXSS_ADDRESSV, GFXSS_ADDRESSW, GFXSS_MINFILTER, GFXSS_MAGFILTER, GFXSS_MIPMAPFILTER, GFXSS_MIPMAPLODBIAS, GFXSS_MAXANISOTROPY, GFXSS_SRGBWRITEENABLE, GFXSS_MAX_SAMPLERSTATES, }; typedef enum { CLEAR = 0, SRC, DST, SRC_OVER, DST_OVER, SRC_IN, DST_IN, SRC_OUT, DST_OUT, SRC_ATOP, DST_ATOP, XOR, PLUS } PorterDuffOperator; struct RenderStateMap { unsigned int Checked; unsigned int State; unsigned int iValue; float fValue; }; class GpuRenderStates { public: GpuRenderStates(GpuBrand board, GpuInfo* info); ~GpuRenderStates(); void ResetDefault(); void ResetStateChangeToDefault(); void CommitStateChangeToDefault(); void CheckStateChange(); void SubmitChangeStates(); //! Check that all render states ar conform to the default void CheckRenderStatesConformity(); // Render states #ifndef NUX_OPENGLES_20 inline void SetAlphaTest( bool EnableAlphaTest_, unsigned int AlphaTestFunc_ = GL_ALWAYS, BYTE AlphaTestRef_ = 0); #endif inline void SetBlend(bool AlphaBlendEnable_); inline void SetBlend(bool AlphaBlendEnable_, unsigned int SrcBlendFactor_ /*= GL_ONE*/, unsigned int DestBlendFactor_ /*= GL_ZERO*/); inline void GetBlend(unsigned int& AlphaBlendEnable_, unsigned int& SrcBlendFactor_, unsigned int& DestBlendFactor_); inline void SetSeparateBlend(bool _bEnable, unsigned int SrcBlendFactor_ /*= GL_ONE*/, unsigned int DestBlendFactor_ /*= GL_ZERO*/, unsigned int SrcFactorAlpha_ /*= GL_ONE*/, unsigned int DestFactorAlpha_ /*= GL_ZERO*/); inline void SetPremultipliedBlend(PorterDuffOperator op); inline void SetBlendOp( unsigned int BlendOp = GL_FUNC_ADD); inline void SetSeparateBlendOp( unsigned int BlendOpRGB_ = GL_FUNC_ADD, unsigned int BlendOpAlpha_ = GL_FUNC_ADD); inline void SetCullMode(bool EnableCullFace, unsigned int FrontFace_ = GL_CCW, unsigned int Cullface_ = GL_BACK); inline void SetDepthTest(bool EnableDepthTest, unsigned int WriteEnable_ = GL_TRUE, unsigned int DepthFunc_ = GL_LEQUAL); inline void SetDepthRange( float zNear = 0.0f, float zFar = 1.0f); inline void SetStencil(bool enable_stencil); inline void SetStencilFunc(unsigned int func, int ref, unsigned int mask); inline void SetStencilOp(unsigned int stencil_fail, unsigned int stencil_pass_depth_fail, unsigned int stencil_pass_depth_pass); #if 0 // If two sided stencil is not activated, the setting is also used for the back face. inline void SetStencilFrontFace( bool EnableStencil_, // GL_TRUE enable stencil test unsigned int Func_ = GL_ALWAYS, unsigned int FailOp_ = GL_KEEP, unsigned int ZFailOp_ = GL_KEEP, unsigned int ZPassOp_ = GL_KEEP, unsigned int Ref_ = 0, unsigned int Mask_ = 0xffffffff); // Set stencil test for the back face. inline void SetStencilBackFace( bool EnableTwoSideStencil_, // GL_TRUE enable Two Sided Stencil test unsigned int Func_ = GL_ALWAYS, unsigned int FailOp_ = GL_KEEP, unsigned int ZFailOp_ = GL_KEEP, unsigned int ZPassOp_ = GL_KEEP, unsigned int Ref_ = 0, unsigned int Mask_ = 0xffffffff); inline void SetFrontFaceStencilWriteMask( unsigned int WriteMask_ = 0xffffffff); inline void SetBackFaceStencilWriteMask( unsigned int WriteMask_ = 0xffffffff); #endif inline void EnableLineSmooth( bool EnableLineSmooth = TRUE, unsigned int LineWidth = 1, unsigned int HINT = GL_FASTEST); inline void SetColorMask( unsigned int bRed = TRUE, unsigned int bGreen = TRUE, unsigned int bBlue = TRUE, unsigned int bAlpha = TRUE); inline void GetColorMask( unsigned int& bRed, unsigned int& bGreen, unsigned int& bBlue, unsigned int& bAlpha); inline void SetDepthMask(unsigned int bDepth = TRUE); inline void EnableScissor(unsigned int bScissor = FALSE); #ifndef NUX_OPENGLES_20 inline void SetPolygonMode(unsigned int FrontMode = GL_FILL, unsigned int BackMode = GL_FILL); #else inline void SetPolygonMode(unsigned int FrontMode, unsigned int BackMode); #endif inline void SetPolygonOffset(unsigned int bEnable, float Factor = 0.0f, float Units = 0.0f); private: GpuBrand gpu_brand_; GpuInfo* gpu_info_; #ifndef NUX_OPENGLES_20 inline void HW__EnableAlphaTest(unsigned int b); inline void HW__SetAlphaTestFunc( unsigned int AlphaTestFunc_, BYTE AlphaTestRef_); #endif inline void HW__EnableAlphaBlend(unsigned int b); inline void HW__SetSeparateAlphaBlend_Enable(unsigned int b); inline void HW__SetSeparateAlphaBlendFactors( unsigned int SrcBlendFactor_, unsigned int DestBlendFactor_, unsigned int SrcFactorAlpha_, unsigned int DestFactorAlpha_); inline void HW__SetAlphaBlendOp(unsigned int BlendOpRGB_, unsigned int BlendOpAlpha_); inline void HW__EnableCulling(unsigned int b); inline void HW__SetFrontFace(unsigned int FrontFace_); inline void HW__SetCullFace(unsigned int CullFace_); inline void HW__SetEnableDepthTest(unsigned int b); inline void HW__SetDepthFunc(unsigned int Func); inline void HW__SetDepthRange(float zNear, float zFar); inline void HW__EnableStencil(unsigned int b); inline void HW__SetStencilOp(unsigned int FailOp_, unsigned int ZFailOp_, unsigned int ZPassOp_); inline void HW__SetStencilFunc(unsigned int func, int ref, unsigned int mask); #if 0 inline void HW__EnableTwoSidedStencil(unsigned int b); inline void HW__SetStencilFrontFaceWriteMask(unsigned int WriteMask_); inline void HW__SetStencilBackFaceWriteMask(unsigned int WriteMask_); inline void HW__SetFrontFaceStencilFunc(unsigned int Func_, unsigned int Ref_, unsigned int Mask_); inline void HW__SetBackFaceStencilFunc( unsigned int Func_, unsigned int Ref_, unsigned int Mask_); inline void HW__SetFrontFaceStencilOp( unsigned int FailOp_, unsigned int ZFailOp_, unsigned int ZPassOp_); inline void HW__SetBackFaceStencilOp( unsigned int FailOp_, unsigned int ZFailOp_, unsigned int ZPassOp_); #endif #ifndef NUX_OPENGLES_20 inline void HW__EnableLineSmooth(unsigned int EnableLineSmooth); #endif inline void HW__SetLineWidth(unsigned int width, unsigned int HINT); inline void HW__SetColorMask(unsigned int bRed, unsigned int bGreen, unsigned int bBlue, unsigned int bAlpha); inline void HW__SetDepthMask(unsigned int bDepth); inline void HW__EnableScissor(unsigned int bScissor); #ifndef NUX_OPENGLES_20 inline void HW__SetPolygonMode(unsigned int FrontMode, unsigned int BackMode); #endif private: RenderStateMap render_state_changes_[GFXRS_MAX_RENDERSTATES]; RenderStateMap sampler_state_changes_[4][GFXSS_MAX_SAMPLERSTATES]; }; #define SET_RS_VALUE(a, b) (a).iValue = (b) #define RS_VALUE(a) (a).iValue //#define SET_RS_VALUE_FLOAT(a, b) (a).fValue = (b) //#define RS_VALUE_FLOAT(a, b) (a).fValue #ifndef NUX_OPENGLES_20 inline void GpuRenderStates::SetAlphaTest( bool EnableAlphaTest_, unsigned int AlphaTestFunc_, BYTE AlphaTestRef_) { if (EnableAlphaTest_) { if (!RS_VALUE(render_state_changes_[GFXRS_ALPHATESTENABLE])) { HW__EnableAlphaTest(TRUE); } if ((RS_VALUE(render_state_changes_[GFXRS_ALPHATESTFUNC]) != AlphaTestFunc_) || (RS_VALUE(render_state_changes_[GFXRS_ALPHATESTREF]) != AlphaTestRef_)) { HW__SetAlphaTestFunc(AlphaTestFunc_, AlphaTestRef_); } } else { HW__EnableAlphaTest(GL_FALSE); HW__SetAlphaTestFunc(AlphaTestFunc_, AlphaTestRef_); } } #endif inline void GpuRenderStates::SetBlend(bool AlphaBlendEnable_) { if (AlphaBlendEnable_) { if (!RS_VALUE(render_state_changes_[GFXRS_ALPHABLENDENABLE])) { HW__EnableAlphaBlend(TRUE); } } else { if (RS_VALUE(render_state_changes_[GFXRS_ALPHABLENDENABLE])) { HW__EnableAlphaBlend(GL_FALSE); } } } inline void GpuRenderStates::SetBlend(bool AlphaBlendEnable_, unsigned int SrcBlendFactor_, unsigned int DestBlendFactor_) { SetBlend(AlphaBlendEnable_); if ((RS_VALUE(render_state_changes_[GFXRS_SRCBLEND]) != SrcBlendFactor_) || (RS_VALUE(render_state_changes_[GFXRS_DESTBLEND]) != DestBlendFactor_)) { HW__SetSeparateAlphaBlendFactors( SrcBlendFactor_, DestBlendFactor_, SrcBlendFactor_, DestBlendFactor_); } } inline void GpuRenderStates::GetBlend(unsigned int& AlphaBlendEnable_, unsigned int& SrcBlendFactor_, unsigned int& DestBlendFactor_) { AlphaBlendEnable_ = RS_VALUE(render_state_changes_[GFXRS_ALPHABLENDENABLE]); SrcBlendFactor_ = RS_VALUE(render_state_changes_[GFXRS_SRCBLEND]); DestBlendFactor_ = RS_VALUE(render_state_changes_[GFXRS_DESTBLEND]); } inline void GpuRenderStates::SetSeparateBlend(bool EnableSeparateAlphaBlend, unsigned int SrcBlendFactor_, unsigned int DestBlendFactor_, unsigned int SrcBlendFactorAlpha_, unsigned int DestBlendFactorAlpha_) { SetBlend(EnableSeparateAlphaBlend); // if (EnableSeparateAlphaBlend) // { // if (!RS_VALUE(render_state_changes_[GFXRS_ALPHABLENDENABLE])) // { // HW__EnableAlphaBlend(TRUE); // } if ((RS_VALUE(render_state_changes_[GFXRS_SRCBLEND]) != SrcBlendFactor_) || (RS_VALUE(render_state_changes_[GFXRS_DESTBLEND]) != DestBlendFactor_) || (RS_VALUE(render_state_changes_[GFXRS_SRCBLENDALPHA]) != SrcBlendFactorAlpha_) || (RS_VALUE(render_state_changes_[GFXRS_DESTBLENDALPHA]) != DestBlendFactorAlpha_)) { HW__SetSeparateAlphaBlendFactors( SrcBlendFactor_, DestBlendFactor_, SrcBlendFactorAlpha_, DestBlendFactorAlpha_); } // } // else // { // HW__EnableAlphaBlend(GL_FALSE); // HW__SetSeparateAlphaBlendFactors( // SrcBlendFactor_, // DestBlendFactor_, // SrcBlendFactorAlpha_, // DestBlendFactorAlpha_); // } } inline void GpuRenderStates::SetPremultipliedBlend(PorterDuffOperator op) { static const struct { const unsigned int src_blend; const unsigned int dst_blend; } factor[13] = { { GL_ZERO, GL_ZERO }, // CLEAR { GL_ONE, GL_ZERO }, // SRC { GL_ZERO, GL_ONE }, // DST { GL_ONE, GL_ONE_MINUS_SRC_ALPHA }, // SRC_OVER { GL_ONE_MINUS_DST_ALPHA, GL_ONE }, // DST_OVER { GL_DST_ALPHA, GL_ZERO }, // SRC_IN { GL_ZERO, GL_SRC_ALPHA }, // DST_IN { GL_ONE_MINUS_DST_ALPHA, GL_ZERO }, // SRC_OUT { GL_ZERO, GL_ONE_MINUS_SRC_ALPHA }, // DST_OUT { GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA }, // SRC_ATOP { GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA }, // DST_ATOP { GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA }, // XOR { GL_ONE, GL_ONE } // PLUS }; if ((RS_VALUE(render_state_changes_[GFXRS_SRCBLEND]) != factor[op].src_blend) || (RS_VALUE(render_state_changes_[GFXRS_DESTBLEND]) != factor[op].dst_blend)) { HW__SetSeparateAlphaBlendFactors (factor[op].src_blend, factor[op].dst_blend, factor[op].src_blend, factor[op].dst_blend); } } inline void GpuRenderStates::SetBlendOp(unsigned int BlendOp) { if ((RS_VALUE(render_state_changes_[GFXRS_BLENDOP]) != BlendOp)) { HW__SetAlphaBlendOp(BlendOp, BlendOp); } } inline void GpuRenderStates::SetSeparateBlendOp( unsigned int BlendOpRGB_, unsigned int BlendOpAlpha_) { if ((RS_VALUE(render_state_changes_[GFXRS_BLENDOP]) != BlendOpRGB_) || (RS_VALUE(render_state_changes_[GFXRS_BLENDOPALPHA]) != BlendOpAlpha_)) { HW__SetAlphaBlendOp(BlendOpRGB_, BlendOpAlpha_); } } inline void GpuRenderStates::SetCullMode(bool EnableCullFace, unsigned int FrontFace_, unsigned int Cullface_) { if (EnableCullFace) { if (!RS_VALUE(render_state_changes_[GFXRS_CULLFACEENABLE])) { HW__EnableCulling(TRUE); } if (RS_VALUE(render_state_changes_[GFXRS_FRONTFACE]) != FrontFace_) { HW__SetFrontFace(FrontFace_); } if (RS_VALUE(render_state_changes_[GFXRS_CULLFACE]) != Cullface_) { HW__SetCullFace(Cullface_); } } else { HW__EnableCulling(FALSE); HW__SetFrontFace(FrontFace_); HW__SetCullFace(Cullface_); } } inline void GpuRenderStates::SetDepthTest(bool EnableDepthTest, unsigned int WriteEnable_, unsigned int DepthFunc_) { if (EnableDepthTest) { if (!RS_VALUE(render_state_changes_[GFXRS_ZTESTENABLE])) { HW__SetEnableDepthTest(TRUE); } if (RS_VALUE(render_state_changes_[GFXRS_ZWRITEENABLE]) != WriteEnable_) { HW__SetDepthMask(WriteEnable_); } if (RS_VALUE(render_state_changes_[GFXRS_ZFUNC]) != DepthFunc_) { HW__SetDepthFunc(DepthFunc_); } } else { HW__SetEnableDepthTest(FALSE); HW__SetDepthMask(WriteEnable_); HW__SetDepthFunc(DepthFunc_); } } inline void GpuRenderStates::SetDepthRange(float zNear, float zFar) { if ((RS_VALUE(render_state_changes_[GFXRS_ZNEAR]) != static_cast (zNear)) || (RS_VALUE(render_state_changes_[GFXRS_ZFAR]) != static_cast (zFar))) { HW__SetDepthRange(zNear, zFar); } } void GpuRenderStates::SetStencil(bool enable_stencil) { if (enable_stencil) { if (!RS_VALUE(render_state_changes_[GFXRS_STENCILENABLE])) { HW__EnableStencil(TRUE); } } else { HW__EnableStencil(FALSE); } } void GpuRenderStates::SetStencilFunc(unsigned int func, int ref, unsigned int mask) { if ( (RS_VALUE(render_state_changes_[GFXRS_FRONT_STENCILFUNC]) != func) || (RS_VALUE(render_state_changes_[GFXRS_FRONT_STENCILREF]) != (unsigned int)ref) || (RS_VALUE(render_state_changes_[GFXRS_FRONT_STENCILMASK]) != mask) ) { HW__SetStencilFunc(func, ref, mask); } } void GpuRenderStates::SetStencilOp(unsigned int stencil_fail, unsigned int stencil_pass_depth_fail, unsigned int stencil_pass_depth_pass) { if ( (RS_VALUE(render_state_changes_[GFXRS_FRONT_STENCILFAIL]) != stencil_fail) || (RS_VALUE(render_state_changes_[GFXRS_FRONT_STENCILZFAIL]) != stencil_pass_depth_fail) || (RS_VALUE(render_state_changes_[GFXRS_FRONT_STENCILZPASS]) != stencil_pass_depth_pass) ) { HW__SetStencilOp(stencil_fail, stencil_pass_depth_fail, stencil_pass_depth_pass); } } #if 0 inline void GpuRenderStates::SetStencilFrontFace( bool EnableStencil_, // GL_TRUE enable stencil test unsigned int Func_, unsigned int FailOp_, unsigned int ZFailOp_, unsigned int ZPassOp_, unsigned int Ref_, unsigned int Mask_) { if (EnableStencil_) { if (!RS_VALUE(render_state_changes_[GFXRS_STENCILENABLE])) { HW__EnableStencil(TRUE); } if ( (RS_VALUE(render_state_changes_[GFXRS_FRONT_STENCILFUNC]) != Func_) || (RS_VALUE(render_state_changes_[GFXRS_FRONT_STENCILREF]) != Ref_) || (RS_VALUE(render_state_changes_[GFXRS_FRONT_STENCILMASK]) != Mask_) || (RS_VALUE(render_state_changes_[GFXRS_FRONT_STENCILFAIL]) != FailOp_) || (RS_VALUE(render_state_changes_[GFXRS_FRONT_STENCILZFAIL]) != ZFailOp_) || (RS_VALUE(render_state_changes_[GFXRS_FRONT_STENCILZPASS]) != ZPassOp_) ) { HW__SetFrontFaceStencilFunc(Func_, Ref_, Mask_); HW__SetFrontFaceStencilOp(FailOp_, ZFailOp_, ZPassOp_); } } else { HW__EnableStencil(FALSE); HW__SetFrontFaceStencilFunc(Func_, Ref_, Mask_); HW__SetFrontFaceStencilOp(FailOp_, ZFailOp_, ZPassOp_); } } inline void GpuRenderStates::SetStencilBackFace( bool EnableTwoSideStencil_, // GL_TRUE enable Two Sided Stencil test unsigned int Func_, unsigned int FailOp_, unsigned int ZFailOp_, unsigned int ZPassOp_, unsigned int Ref_, unsigned int Mask_) { if (EnableTwoSideStencil_) { if (!RS_VALUE(render_state_changes_[GFXRS_STENCILENABLE])) { HW__EnableStencil(TRUE); } if (!RS_VALUE(render_state_changes_[GFXRS_TWOSIDEDSTENCILENABLE])) { HW__EnableTwoSidedStencil(TRUE); } if ( (RS_VALUE(render_state_changes_[GFXRS_BACK_STENCILFUNC]) != Func_) || (RS_VALUE(render_state_changes_[GFXRS_BACK_STENCILREF]) != Ref_) || (RS_VALUE(render_state_changes_[GFXRS_BACK_STENCILMASK]) != Mask_) || (RS_VALUE(render_state_changes_[GFXRS_BACK_STENCILFAIL]) != FailOp_) || (RS_VALUE(render_state_changes_[GFXRS_BACK_STENCILZFAIL]) != ZFailOp_) || (RS_VALUE(render_state_changes_[GFXRS_BACK_STENCILZPASS]) != ZPassOp_) ) { HW__SetBackFaceStencilFunc(Func_, Ref_, Mask_); HW__SetBackFaceStencilOp(FailOp_, ZFailOp_, ZPassOp_); } } else { HW__EnableTwoSidedStencil(FALSE); HW__SetBackFaceStencilFunc(Func_, Ref_, Mask_); HW__SetBackFaceStencilOp(FailOp_, ZFailOp_, ZPassOp_); } } inline void GpuRenderStates::SetFrontFaceStencilWriteMask( unsigned int WriteMask_) { HW__SetStencilFrontFaceWriteMask(WriteMask_); } inline void GpuRenderStates::SetBackFaceStencilWriteMask( unsigned int WriteMask_) { HW__SetStencilBackFaceWriteMask(WriteMask_); } #endif inline void GpuRenderStates::EnableLineSmooth( bool EnableLineSmooth, unsigned int LineWidth, unsigned int Hint) { if (EnableLineSmooth) { if (!RS_VALUE(render_state_changes_[GFXRS_LINESMOOTHENABLE])) { #ifndef NUX_OPENGLES_20 HW__EnableLineSmooth(GL_TRUE); #endif } if ((RS_VALUE(render_state_changes_[GFXRS_LINEWIDTH]) != LineWidth) || (RS_VALUE(render_state_changes_[GFXRS_LINEHINT]) != Hint)) { HW__SetLineWidth(LineWidth, Hint); } } else { #ifndef NUX_OPENGLES_20 HW__EnableLineSmooth(GL_FALSE); #endif HW__SetLineWidth(LineWidth, Hint); } } inline void GpuRenderStates::SetColorMask( unsigned int bRed, unsigned int bGreen, unsigned int bBlue, unsigned int bAlpha) { if ((RS_VALUE(render_state_changes_[GFXRS_COLORWRITEENABLE_R]) != bRed) || (RS_VALUE(render_state_changes_[GFXRS_COLORWRITEENABLE_G]) != bGreen) || (RS_VALUE(render_state_changes_[GFXRS_COLORWRITEENABLE_B]) != bBlue) || (RS_VALUE(render_state_changes_[GFXRS_COLORWRITEENABLE_A]) != bAlpha)) { HW__SetColorMask(bRed, bGreen, bBlue, bAlpha); } } inline void GpuRenderStates::GetColorMask( unsigned int& bRed, unsigned int& bGreen, unsigned int& bBlue, unsigned int& bAlpha) { bRed = RS_VALUE(render_state_changes_[GFXRS_COLORWRITEENABLE_R]); bGreen = RS_VALUE(render_state_changes_[GFXRS_COLORWRITEENABLE_G]); bBlue = RS_VALUE(render_state_changes_[GFXRS_COLORWRITEENABLE_B]); bAlpha = RS_VALUE(render_state_changes_[GFXRS_COLORWRITEENABLE_A]); } inline void GpuRenderStates::SetDepthMask(unsigned int bDepth) { if ((RS_VALUE(render_state_changes_[GFXRS_ZWRITEENABLE]) != bDepth)) { HW__SetDepthMask(bDepth); } } inline void GpuRenderStates::EnableScissor(unsigned int bScissor) { if ((RS_VALUE(render_state_changes_[GFXRS_SCISSORTESTENABLE]) != bScissor)) { HW__EnableScissor(bScissor); } } #ifndef NUX_OPENGLES_20 inline void GpuRenderStates::SetPolygonMode(unsigned int FrontMode, unsigned int BackMode) { if ((RS_VALUE(render_state_changes_[GFXRS_FRONT_POLYGONMODE]) != FrontMode) || (RS_VALUE(render_state_changes_[GFXRS_BACK_POLYGONMODE]) != BackMode)) { HW__SetPolygonMode(FrontMode, BackMode); } } #else inline void GpuRenderStates::SetPolygonMode(unsigned int /*FrontMode*/, unsigned int /*BackMode*/) { } #endif #ifndef NUX_OPENGLES_20 inline void GpuRenderStates::HW__EnableAlphaTest(unsigned int b) { if (b) { CHECKGL(glEnable(GL_ALPHA_TEST)); } else { CHECKGL(glDisable(GL_ALPHA_TEST)); } SET_RS_VALUE(render_state_changes_[GFXRS_ALPHATESTENABLE], b ? GL_TRUE : GL_FALSE); } inline void GpuRenderStates::HW__SetAlphaTestFunc(unsigned int AlphaTestFunc_, BYTE AlphaTestRef_) { nuxAssertMsg( (AlphaTestFunc_ == GL_NEVER) || (AlphaTestFunc_ == GL_LESS) || (AlphaTestFunc_ == GL_EQUAL) || (AlphaTestFunc_ == GL_LEQUAL) || (AlphaTestFunc_ == GL_GREATER) || (AlphaTestFunc_ == GL_NOTEQUAL) || (AlphaTestFunc_ == GL_GEQUAL) || (AlphaTestFunc_ == GL_ALWAYS), "Error(HW__SetAlphaTestFunc): Invalid Alpha Test Function RenderState"); CHECKGL(glAlphaFunc(AlphaTestFunc_, (float) AlphaTestRef_ * (1.0f / 255.0f))); SET_RS_VALUE(render_state_changes_[GFXRS_ALPHATESTFUNC], AlphaTestFunc_); SET_RS_VALUE(render_state_changes_[GFXRS_ALPHATESTREF], AlphaTestRef_); } #endif inline void GpuRenderStates::HW__EnableAlphaBlend(unsigned int b) { if (b) { CHECKGL(glEnable(GL_BLEND)); } else { CHECKGL(glDisable(GL_BLEND)); } SET_RS_VALUE(render_state_changes_[GFXRS_ALPHABLENDENABLE], b ? GL_TRUE : GL_FALSE); } inline void GpuRenderStates::HW__SetSeparateAlphaBlendFactors( unsigned int SrcBlendFactor_, unsigned int DestBlendFactor_, unsigned int SrcFactorAlpha_, unsigned int DestFactorAlpha_) { nuxAssertMsg((SrcBlendFactor_ == GL_ZERO) || (SrcBlendFactor_ == GL_ONE) || (SrcBlendFactor_ == GL_SRC_COLOR) || (SrcBlendFactor_ == GL_ONE_MINUS_SRC_COLOR) || (SrcBlendFactor_ == GL_DST_COLOR) || (SrcBlendFactor_ == GL_ONE_MINUS_DST_COLOR) || (SrcBlendFactor_ == GL_SRC_ALPHA) || (SrcBlendFactor_ == GL_ONE_MINUS_SRC_ALPHA) || (SrcBlendFactor_ == GL_DST_ALPHA) || (SrcBlendFactor_ == GL_ONE_MINUS_DST_ALPHA) || (SrcBlendFactor_ == GL_CONSTANT_COLOR) || (SrcBlendFactor_ == GL_ONE_MINUS_CONSTANT_COLOR) || (SrcBlendFactor_ == GL_CONSTANT_ALPHA) || (SrcBlendFactor_ == GL_ONE_MINUS_CONSTANT_ALPHA) || (SrcBlendFactor_ == GL_SRC_ALPHA_SATURATE), "Error(HW__SetSeparateAlphaBlendFactors): Invalid Blend RenderState"); nuxAssertMsg((DestBlendFactor_ == GL_ZERO) || (DestBlendFactor_ == GL_ONE) || (DestBlendFactor_ == GL_SRC_COLOR) || (DestBlendFactor_ == GL_ONE_MINUS_SRC_COLOR) || (DestBlendFactor_ == GL_DST_COLOR) || (DestBlendFactor_ == GL_ONE_MINUS_DST_COLOR) || (DestBlendFactor_ == GL_SRC_ALPHA) || (DestBlendFactor_ == GL_ONE_MINUS_SRC_ALPHA) || (DestBlendFactor_ == GL_DST_ALPHA) || (DestBlendFactor_ == GL_ONE_MINUS_DST_ALPHA) || (DestBlendFactor_ == GL_CONSTANT_COLOR) || (DestBlendFactor_ == GL_ONE_MINUS_CONSTANT_COLOR) || (DestBlendFactor_ == GL_CONSTANT_ALPHA) || (DestBlendFactor_ == GL_ONE_MINUS_CONSTANT_ALPHA), "Error(HW__SetSeparateAlphaBlendFactors): Invalid Blend RenderState"); nuxAssertMsg((SrcFactorAlpha_ == GL_ZERO) || (SrcFactorAlpha_ == GL_ONE) || (SrcFactorAlpha_ == GL_SRC_COLOR) || (SrcFactorAlpha_ == GL_ONE_MINUS_SRC_COLOR) || (SrcFactorAlpha_ == GL_DST_COLOR) || (SrcFactorAlpha_ == GL_ONE_MINUS_DST_COLOR) || (SrcFactorAlpha_ == GL_SRC_ALPHA) || (SrcFactorAlpha_ == GL_ONE_MINUS_SRC_ALPHA) || (SrcFactorAlpha_ == GL_DST_ALPHA) || (SrcFactorAlpha_ == GL_ONE_MINUS_DST_ALPHA) || (SrcFactorAlpha_ == GL_CONSTANT_COLOR) || (SrcFactorAlpha_ == GL_ONE_MINUS_CONSTANT_COLOR) || (SrcFactorAlpha_ == GL_CONSTANT_ALPHA) || (SrcFactorAlpha_ == GL_ONE_MINUS_CONSTANT_ALPHA) || (SrcFactorAlpha_ == GL_SRC_ALPHA_SATURATE), "Error(HW__SetSeparateAlphaBlendFactors): Invalid Blend RenderState"); nuxAssertMsg((DestFactorAlpha_ == GL_ZERO) || (DestFactorAlpha_ == GL_ONE) || (DestFactorAlpha_ == GL_SRC_COLOR) || (DestFactorAlpha_ == GL_ONE_MINUS_SRC_COLOR) || (DestFactorAlpha_ == GL_DST_COLOR) || (DestFactorAlpha_ == GL_ONE_MINUS_DST_COLOR) || (DestFactorAlpha_ == GL_SRC_ALPHA) || (DestFactorAlpha_ == GL_ONE_MINUS_SRC_ALPHA) || (DestFactorAlpha_ == GL_DST_ALPHA) || (DestFactorAlpha_ == GL_ONE_MINUS_DST_ALPHA) || (DestFactorAlpha_ == GL_CONSTANT_COLOR) || (DestFactorAlpha_ == GL_ONE_MINUS_CONSTANT_COLOR) || (DestFactorAlpha_ == GL_CONSTANT_ALPHA) || (DestFactorAlpha_ == GL_ONE_MINUS_CONSTANT_ALPHA), "Error(HW__SetSeparateAlphaBlendFactors): Invalid Blend RenderState"); CHECKGL(glBlendFuncSeparate( SrcBlendFactor_, DestBlendFactor_, SrcFactorAlpha_, DestFactorAlpha_)); SET_RS_VALUE(render_state_changes_[GFXRS_SRCBLEND], SrcBlendFactor_); SET_RS_VALUE(render_state_changes_[GFXRS_DESTBLEND], DestBlendFactor_); SET_RS_VALUE(render_state_changes_[GFXRS_SRCBLENDALPHA], SrcFactorAlpha_); SET_RS_VALUE(render_state_changes_[GFXRS_DESTBLENDALPHA], DestFactorAlpha_); } inline void GpuRenderStates::HW__SetAlphaBlendOp( unsigned int BlendOpRGB_, unsigned int BlendOpAlpha_) { #ifdef NUX_OPENGLES_20 nuxAssertMsg( (BlendOpRGB_ == GL_FUNC_ADD) || (BlendOpRGB_ == GL_FUNC_SUBTRACT) || (BlendOpRGB_ == GL_FUNC_REVERSE_SUBTRACT), "Error(HW__SetAlphaBlendOp): Invalid Blend Equation RenderState"); nuxAssertMsg( (BlendOpAlpha_ == GL_FUNC_ADD) || (BlendOpAlpha_ == GL_FUNC_SUBTRACT) || (BlendOpAlpha_ == GL_FUNC_REVERSE_SUBTRACT), "Error(HW__SetAlphaBlendOp): Invalid Blend Equation RenderState"); CHECKGL(glBlendEquationSeparate(BlendOpRGB_, BlendOpAlpha_)); #else nuxAssertMsg( (BlendOpRGB_ == GL_FUNC_ADD) || (BlendOpRGB_ == GL_FUNC_SUBTRACT) || (BlendOpRGB_ == GL_FUNC_REVERSE_SUBTRACT) || (BlendOpRGB_ == GL_MIN) || (BlendOpRGB_ == GL_MAX), "Error(HW__SetAlphaBlendOp): Invalid Blend Equation RenderState"); nuxAssertMsg( (BlendOpAlpha_ == GL_FUNC_ADD) || (BlendOpAlpha_ == GL_FUNC_SUBTRACT) || (BlendOpAlpha_ == GL_FUNC_REVERSE_SUBTRACT) || (BlendOpAlpha_ == GL_MIN) || (BlendOpAlpha_ == GL_MAX), "Error(HW__SetAlphaBlendOp): Invalid Blend Equation RenderState"); if (gpu_info_->SupportOpenGL20()) { CHECKGL(glBlendEquationSeparate(BlendOpRGB_, BlendOpAlpha_)); } else if (gpu_info_->Support_EXT_Blend_Equation_Separate()) { CHECKGL(glBlendEquationSeparateEXT(BlendOpRGB_, BlendOpAlpha_)); } else { CHECKGL(glBlendEquation(BlendOpRGB_)); } #endif SET_RS_VALUE(render_state_changes_[GFXRS_BLENDOP], BlendOpRGB_); SET_RS_VALUE(render_state_changes_[GFXRS_BLENDOPALPHA], BlendOpAlpha_); } inline void GpuRenderStates::HW__EnableCulling(unsigned int b) { if (b) { CHECKGL(glEnable(GL_CULL_FACE)); } else { CHECKGL(glDisable(GL_CULL_FACE)); } SET_RS_VALUE(render_state_changes_[GFXRS_CULLFACEENABLE], b ? GL_TRUE : GL_FALSE); } inline void GpuRenderStates::HW__SetFrontFace(unsigned int FrontFace_) { nuxAssertMsg( (FrontFace_ == GL_CW) || (FrontFace_ == GL_CCW), "Error(HW__SetFrontFace): Invalid Front Face RenderState"); CHECKGL(glFrontFace(FrontFace_)); SET_RS_VALUE(render_state_changes_[GFXRS_FRONTFACE], FrontFace_); } inline void GpuRenderStates::HW__SetCullFace(unsigned int CullFace_) { nuxAssertMsg( (CullFace_ == GL_FRONT) || (CullFace_ == GL_BACK) || (CullFace_ == GL_FRONT_AND_BACK), "Error(HW__SetCullFace): Invalid Cull Face RenderState"); CHECKGL(glCullFace(CullFace_)); SET_RS_VALUE(render_state_changes_[GFXRS_CULLFACE], CullFace_); } inline void GpuRenderStates::HW__SetEnableDepthTest(unsigned int b) { if (b) { CHECKGL(glEnable(GL_DEPTH_TEST)); } else { CHECKGL(glDisable(GL_DEPTH_TEST)); } SET_RS_VALUE(render_state_changes_[GFXRS_ZTESTENABLE], b ? GL_TRUE : GL_FALSE); } inline void GpuRenderStates::HW__SetDepthRange(float zNear, float zFar) { CHECKGL(glDepthRange(zNear, zFar)); SET_RS_VALUE(render_state_changes_[GFXRS_ZNEAR], static_cast (Clamp(zNear, 0.0f, 1.0f))); SET_RS_VALUE(render_state_changes_[GFXRS_ZFAR], static_cast (Clamp(zFar, 0.0f, 1.0f))); } inline void GpuRenderStates::HW__SetDepthFunc(unsigned int Func) { nuxAssertMsg( (Func == GL_NEVER) || (Func == GL_LESS) || (Func == GL_EQUAL) || (Func == GL_LEQUAL) || (Func == GL_GREATER) || (Func == GL_NOTEQUAL) || (Func == GL_GEQUAL) || (Func == GL_ALWAYS), "Error(HW__SetDepthFunc): Invalid Depth Func RenderState"); CHECKGL(glDepthFunc(Func)); SET_RS_VALUE(render_state_changes_[GFXRS_ZFUNC], Func); } inline void GpuRenderStates::HW__EnableStencil(unsigned int b) { if (b) { CHECKGL(glEnable(GL_STENCIL_TEST)); } else { CHECKGL(glDisable(GL_STENCIL_TEST)); } SET_RS_VALUE(render_state_changes_[GFXRS_STENCILENABLE], b ? GL_TRUE : GL_FALSE); } inline void GpuRenderStates::HW__SetStencilFunc(unsigned int func, int ref, unsigned int mask) { nuxAssertMsg( (func == GL_NEVER) || (func == GL_LESS) || (func == GL_EQUAL) || (func == GL_LEQUAL) || (func == GL_GREATER) || (func == GL_NOTEQUAL) || (func == GL_GEQUAL) || (func == GL_ALWAYS), "Error(HW__SetFrontFaceStencilFunc): Invalid Stencil Function RenderState"); CHECKGL(glStencilFunc(func, ref, mask)); SET_RS_VALUE(render_state_changes_[GFXRS_FRONT_STENCILFUNC], func); SET_RS_VALUE(render_state_changes_[GFXRS_FRONT_STENCILREF], ref); SET_RS_VALUE(render_state_changes_[GFXRS_FRONT_STENCILMASK], mask); } inline void GpuRenderStates::HW__SetStencilOp(unsigned int stencil_fail, unsigned int stencil_pass_depth_fail, unsigned int stencil_pass_depth_pass) { nuxAssertMsg( (stencil_fail == GL_KEEP) || (stencil_fail == GL_ZERO) || (stencil_fail == GL_REPLACE) || (stencil_fail == GL_INCR) || (stencil_fail == GL_INCR_WRAP) || (stencil_fail == GL_DECR) || (stencil_fail == GL_DECR_WRAP) || (stencil_fail == GL_INVERT), "Error(HW__SetFrontFaceStencilOp): Invalid FailOp RenderState"); nuxAssertMsg( (stencil_pass_depth_fail == GL_KEEP) || (stencil_pass_depth_fail == GL_ZERO) || (stencil_pass_depth_fail == GL_REPLACE) || (stencil_pass_depth_fail == GL_INCR) || (stencil_pass_depth_fail == GL_INCR_WRAP) || (stencil_pass_depth_fail == GL_DECR) || (stencil_pass_depth_fail == GL_DECR_WRAP) || (stencil_pass_depth_fail == GL_INVERT), "Error(HW__SetFrontFaceStencilOp): Invalid ZFailOp RenderState"); nuxAssertMsg( (stencil_pass_depth_pass == GL_KEEP) || (stencil_pass_depth_pass == GL_ZERO) || (stencil_pass_depth_pass == GL_REPLACE) || (stencil_pass_depth_pass == GL_INCR) || (stencil_pass_depth_pass == GL_INCR_WRAP) || (stencil_pass_depth_pass == GL_DECR) || (stencil_pass_depth_pass == GL_DECR_WRAP) || (stencil_pass_depth_pass == GL_INVERT), "Error(HW__SetFrontFaceStencilOp): Invalid ZPassOp RenderState"); CHECKGL(glStencilOp(stencil_fail, stencil_pass_depth_fail, stencil_pass_depth_pass)); SET_RS_VALUE(render_state_changes_[GFXRS_FRONT_STENCILFAIL], stencil_fail); SET_RS_VALUE(render_state_changes_[GFXRS_FRONT_STENCILZFAIL], stencil_pass_depth_fail); SET_RS_VALUE(render_state_changes_[GFXRS_FRONT_STENCILZPASS], stencil_pass_depth_pass); } #if 0 inline void GpuRenderStates::HW__EnableTwoSidedStencil(unsigned int b) { if (b) { if (gpu_brand_ == GPU_BRAND_AMD) { CHECKGL(glEnable(GL_STENCIL_TEST)); } else { CHECKGL(glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)); } } else { if (gpu_brand_ == GPU_BRAND_AMD) { CHECKGL(glDisable(GL_STENCIL_TEST)); } else { CHECKGL(glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT)); } } SET_RS_VALUE(render_state_changes_[GFXRS_TWOSIDEDSTENCILENABLE], b ? GL_TRUE : GL_FALSE); } inline void GpuRenderStates::HW__SetStencilFrontFaceWriteMask(unsigned int WriteMask_) { CHECKGL(glActiveStencilFaceEXT(GL_FRONT)); CHECKGL(glStencilMask(WriteMask_)); SET_RS_VALUE(render_state_changes_[GFXRS_FRONT_STENCILWRITEMASK], WriteMask_); } inline void GpuRenderStates::HW__SetStencilBackFaceWriteMask(unsigned int WriteMask_) { CHECKGL(glActiveStencilFaceEXT(GL_BACK)); CHECKGL(glStencilMask(WriteMask_)); SET_RS_VALUE(render_state_changes_[GFXRS_BACK_STENCILWRITEMASK], WriteMask_); } inline void GpuRenderStates::HW__SetFrontFaceStencilFunc(unsigned int Func_, unsigned int Ref_, unsigned int Mask_) { nuxAssertMsg( (Func_ == GL_NEVER) || (Func_ == GL_LESS) || (Func_ == GL_EQUAL) || (Func_ == GL_LEQUAL) || (Func_ == GL_GREATER) || (Func_ == GL_NOTEQUAL) || (Func_ == GL_GEQUAL) || (Func_ == GL_ALWAYS), "Error(HW__SetFrontFaceStencilFunc): Invalid Stencil Function RenderState"); CHECKGL(glActiveStencilFaceEXT(GL_FRONT)); CHECKGL(glStencilFunc(Func_, Ref_, Mask_)); SET_RS_VALUE(render_state_changes_[GFXRS_FRONT_STENCILFUNC], Func_); SET_RS_VALUE(render_state_changes_[GFXRS_FRONT_STENCILREF], Ref_); SET_RS_VALUE(render_state_changes_[GFXRS_FRONT_STENCILMASK], Mask_); } inline void GpuRenderStates::HW__SetBackFaceStencilFunc( unsigned int Func_, unsigned int Ref_, unsigned int Mask_) { nuxAssertMsg( (Func_ == GL_NEVER) || (Func_ == GL_LESS) || (Func_ == GL_EQUAL) || (Func_ == GL_LEQUAL) || (Func_ == GL_GREATER) || (Func_ == GL_NOTEQUAL) || (Func_ == GL_GEQUAL) || (Func_ == GL_ALWAYS), "Error(HW__SetBackFaceStencilFunc): Invalid Stencil Function RenderState"); if (gpu_brand_ == GPU_BRAND_AMD) { CHECKGL(glStencilFuncSeparateATI(Func_/*Front function*/, Func_/*Back function*/, Ref_, Mask_)); // incorrect } else { CHECKGL(glActiveStencilFaceEXT(GL_BACK)); CHECKGL(glStencilFunc(Func_, Ref_, Mask_)); } SET_RS_VALUE(render_state_changes_[GFXRS_BACK_STENCILFUNC], Func_); SET_RS_VALUE(render_state_changes_[GFXRS_BACK_STENCILREF], Ref_); SET_RS_VALUE(render_state_changes_[GFXRS_BACK_STENCILMASK], Mask_); } inline void GpuRenderStates::HW__SetFrontFaceStencilOp( unsigned int FailOp_, unsigned int ZFailOp_, unsigned int ZPassOp_) { nuxAssertMsg( (FailOp_ == GL_KEEP) || (FailOp_ == GL_ZERO) || (FailOp_ == GL_REPLACE) || (FailOp_ == GL_INCR) || (FailOp_ == GL_INCR_WRAP) || (FailOp_ == GL_DECR) || (FailOp_ == GL_DECR_WRAP) || (FailOp_ == GL_INVERT), "Error(HW__SetFrontFaceStencilOp): Invalid FailOp RenderState"); nuxAssertMsg( (ZFailOp_ == GL_KEEP) || (ZFailOp_ == GL_ZERO) || (ZFailOp_ == GL_REPLACE) || (ZFailOp_ == GL_INCR) || (ZFailOp_ == GL_INCR_WRAP) || (ZFailOp_ == GL_DECR) || (ZFailOp_ == GL_DECR_WRAP) || (ZFailOp_ == GL_INVERT), "Error(HW__SetFrontFaceStencilOp): Invalid ZFailOp RenderState"); nuxAssertMsg( (ZPassOp_ == GL_KEEP) || (ZPassOp_ == GL_ZERO) || (ZPassOp_ == GL_REPLACE) || (ZPassOp_ == GL_INCR) || (ZPassOp_ == GL_INCR_WRAP) || (ZPassOp_ == GL_DECR) || (ZPassOp_ == GL_DECR_WRAP) || (ZPassOp_ == GL_INVERT), "Error(HW__SetFrontFaceStencilOp): Invalid ZPassOp RenderState"); if (gpu_brand_ == GPU_BRAND_AMD) { CHECKGL(glStencilOpSeparateATI(GL_FRONT, FailOp_, ZFailOp_, ZPassOp_)); } else { CHECKGL(glActiveStencilFaceEXT(GL_FRONT)); CHECKGL(glStencilOp(FailOp_, ZFailOp_, ZPassOp_)); } SET_RS_VALUE(render_state_changes_[GFXRS_FRONT_STENCILFAIL], FailOp_); SET_RS_VALUE(render_state_changes_[GFXRS_FRONT_STENCILZFAIL], ZFailOp_); SET_RS_VALUE(render_state_changes_[GFXRS_FRONT_STENCILZPASS], ZPassOp_); } inline void GpuRenderStates::HW__SetBackFaceStencilOp( unsigned int FailOp_, unsigned int ZFailOp_, unsigned int ZPassOp_) { nuxAssertMsg( (FailOp_ == GL_KEEP) || (FailOp_ == GL_ZERO) || (FailOp_ == GL_REPLACE) || (FailOp_ == GL_INCR) || (FailOp_ == GL_INCR_WRAP) || (FailOp_ == GL_DECR) || (FailOp_ == GL_DECR_WRAP) || (FailOp_ == GL_INVERT), "Error(HW__SetBackFaceStencilOp): Invalid FailOp RenderState"); nuxAssertMsg( (ZFailOp_ == GL_KEEP) || (ZFailOp_ == GL_ZERO) || (ZFailOp_ == GL_REPLACE) || (ZFailOp_ == GL_INCR) || (ZFailOp_ == GL_INCR_WRAP) || (ZFailOp_ == GL_DECR) || (ZFailOp_ == GL_DECR_WRAP) || (ZFailOp_ == GL_INVERT), "Error(HW__SetBackFaceStencilOp): Invalid ZFailOp RenderState"); nuxAssertMsg( (ZPassOp_ == GL_KEEP) || (ZPassOp_ == GL_ZERO) || (ZPassOp_ == GL_REPLACE) || (ZPassOp_ == GL_INCR) || (ZPassOp_ == GL_INCR_WRAP) || (ZPassOp_ == GL_DECR) || (ZPassOp_ == GL_DECR_WRAP) || (ZPassOp_ == GL_INVERT), "Error(HW__SetBackFaceStencilOp): Invalid ZPassOp RenderState"); if (gpu_brand_ == GPU_BRAND_AMD) { CHECKGL(glStencilOpSeparateATI(GL_BACK, FailOp_, ZFailOp_, ZPassOp_)); } else { CHECKGL(glActiveStencilFaceEXT(GL_BACK)); CHECKGL(glStencilOp(FailOp_, ZFailOp_, ZPassOp_)); } SET_RS_VALUE(render_state_changes_[GFXRS_BACK_STENCILFAIL], FailOp_); SET_RS_VALUE(render_state_changes_[GFXRS_BACK_STENCILZFAIL], ZFailOp_); SET_RS_VALUE(render_state_changes_[GFXRS_BACK_STENCILZPASS], ZPassOp_); } #endif #ifndef NUX_OPENGLES_20 inline void GpuRenderStates::HW__EnableLineSmooth(unsigned int EnableLineSmooth) { if (EnableLineSmooth) { CHECKGL(glEnable(GL_LINE_SMOOTH)); } else { CHECKGL(glDisable(GL_LINE_SMOOTH)); } SET_RS_VALUE(render_state_changes_[GFXRS_LINESMOOTHENABLE], EnableLineSmooth ? GL_TRUE : GL_FALSE); } #endif inline void GpuRenderStates::HW__SetLineWidth(unsigned int width, unsigned int Hint) { nuxAssertMsg( (Hint == GL_NICEST) || (Hint == GL_FASTEST) || (Hint == GL_DONT_CARE), "Error(HW__SetLineWidth): Invalid Line Hint RenderState"); CHECKGL(glLineWidth(width)); SET_RS_VALUE(render_state_changes_[GFXRS_LINEWIDTH], width); #ifndef NUX_OPENGLES_20 CHECKGL(glHint(GL_LINE_SMOOTH_HINT, Hint)); SET_RS_VALUE(render_state_changes_[GFXRS_LINEHINT], Hint); #endif } inline void GpuRenderStates::HW__SetColorMask( unsigned int bRed, unsigned int bGreen, unsigned int bBlue, unsigned int bAlpha) { CHECKGL(glColorMask(bRed, bGreen, bBlue, bAlpha)); SET_RS_VALUE(render_state_changes_[GFXRS_COLORWRITEENABLE_R], bRed); SET_RS_VALUE(render_state_changes_[GFXRS_COLORWRITEENABLE_G], bGreen); SET_RS_VALUE(render_state_changes_[GFXRS_COLORWRITEENABLE_B], bBlue); SET_RS_VALUE(render_state_changes_[GFXRS_COLORWRITEENABLE_A], bAlpha); } inline void GpuRenderStates::HW__SetDepthMask(unsigned int bDepth) { CHECKGL(glDepthMask(bDepth)); SET_RS_VALUE(render_state_changes_[GFXRS_ZWRITEENABLE], bDepth); } inline void GpuRenderStates::HW__EnableScissor(unsigned int bScissor) { if (bScissor) { CHECKGL(glEnable(GL_SCISSOR_TEST)); } else { CHECKGL(glDisable(GL_SCISSOR_TEST)); } SET_RS_VALUE(render_state_changes_[GFXRS_SCISSORTESTENABLE], bScissor ? GL_TRUE : GL_FALSE); } #ifndef NUX_OPENGLES_20 inline void GpuRenderStates::HW__SetPolygonMode(unsigned int FrontMode, unsigned int BackMode) { nuxAssertMsg( (FrontMode == GL_FILL) || (FrontMode == GL_LINE) || (FrontMode == GL_POINT), "Error(HW__SetPolygonMode): Invalid Point Hint RenderState"); nuxAssertMsg( (BackMode == GL_FILL) || (BackMode == GL_LINE) || (BackMode == GL_POINT), "Error(HW__SetPolygonMode): Invalid Point Hint RenderState"); CHECKGL(glPolygonMode(GL_FRONT, FrontMode)); CHECKGL(glPolygonMode(GL_BACK, BackMode)); SET_RS_VALUE(render_state_changes_[GFXRS_FRONT_POLYGONMODE], FrontMode); SET_RS_VALUE(render_state_changes_[GFXRS_BACK_POLYGONMODE], BackMode); } #endif #undef SET_RS_VALUE #undef RS_VALUE //#undef SET_RS_VALUE_FLOAT //#undef RS_VALUE_FLOAT } #endif // GLRENDERSTATES_H ./NuxGraphics/GLShader.cpp0000644000004100000410000000163313313171755015644 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "NuxCore/NuxCore.h" #include "GLResource.h" #include "GLShader.h" #include "GLShaderParameter.h" namespace nux { } ./NuxGraphics/GLSh_ColorPicker.h0000644000004100000410000000303613313171755016750 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef GLSH_COLORPICKER_H #define GLSH_COLORPICKER_H #include "IOpenGLGLSLShader.h" #include "GLShaderParameter.h" #include "GLDeviceObjects.h" namespace nux { class GLSh_ColorPicker { public: GLSh_ColorPicker(color::Channel cc); ~GLSh_ColorPicker(); void SetColor(float R, float G, float B, float A); void SetScreenPositionOffset(float x, float y); void Render(int x, int y, int z, int width, int height, int WindowWidth, int WindowHeight); private: float _R, _G, _B, _A; float _ScreenOffsetX, _ScreenOffsetY; ObjectPtr GlobalPixelShader; ObjectPtr sprog; #ifndef NUX_OPENGLES_20 ObjectPtr m_AsmProg; #endif }; } #endif // GLSH_COLORPICKER_H ./NuxGraphics/GLShaderParameter.h0000644000004100000410000001073613313171755017156 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef GLSHADERPARAMETER_H #define GLSHADERPARAMETER_H #include "GLError.h" #include "GLResource.h" namespace nux { //! Type of shader in a shader enum eShaderParameterType { eVERTEXUNIFORMTYPE, eFRAGMENTUNIFORMTYPE, eSAMPLERUNIFORMTYPE, }; //! Type of shader enum eShaderType { eVERTEXSHADERTYPE, eFRAGMENTSHADERTYPE }; class GLProgramObject; class IOpenGLShaderProgram; class GLShaderParameter { public: int m_Index; // Register m_Index / Attribute m_Index eShaderParameterType m_ShaderParameterType; std::string m_Name; bool m_bIsOptional; bool m_bIsStatic; bool bStaticSet; GLProgramObject *m_ShaderProgram; IOpenGLShaderProgram *m_ShaderProgram2; GLShaderParameter *m_NextParameter; UINT m_Size; UINT m_Type; GLShaderParameter(GLProgramObject *Shader, const char *ParamName, eShaderParameterType InType, bool InbIsOptional = FALSE, bool InbIsStatic = FALSE); inline void SetUniform1f( FLOAT FloatA ) { NUX_RETURN_IF_TRUE(m_Index == -1); CHECKGL(glUniform1fARB( m_Index, FloatA )); } inline void SetUniform1i( INT i ) { NUX_RETURN_IF_TRUE(m_Index == -1); CHECKGL(glUniform1iARB( m_Index, i )); } inline void SetUniform2f( FLOAT FloatA, FLOAT FloatB ) { NUX_RETURN_IF_TRUE(m_Index == -1); CHECKGL(glUniform2fARB( m_Index, FloatA, FloatB )); } inline void SetUniform3f( FLOAT FloatA, FLOAT FloatB, FLOAT FloatC ) { NUX_RETURN_IF_TRUE(m_Index == -1); CHECKGL(glUniform3fARB( m_Index, FloatA, FloatB, FloatC )); } inline void SetUniform4f( FLOAT FloatA, FLOAT FloatB, FLOAT FloatC, FLOAT FloatD ) { NUX_RETURN_IF_TRUE(m_Index == -1); CHECKGL(glUniform4fARB( m_Index, FloatA, FloatB, FloatC, FloatD )); } inline void SetUniform1fv( GLsizei count, GLfloat *value ) { NUX_RETURN_IF_TRUE(m_Index == -1); CHECKGL(glUniform1fvARB( m_Index, count, value )); } inline void SetUniform2fv( GLsizei count, GLfloat *value ) { NUX_RETURN_IF_TRUE(m_Index == -1); CHECKGL(glUniform2fvARB( m_Index, count, value )); } inline void SetUniform3fv( GLsizei count, GLfloat *value ) { NUX_RETURN_IF_TRUE(m_Index == -1); CHECKGL(glUniform3fvARB( m_Index, count, value )); } inline void SetUniform4fv( GLsizei count, GLfloat *value ) { NUX_RETURN_IF_TRUE(m_Index == -1); CHECKGL(glUniform4fvARB( m_Index, count, value )); } inline void SetUniformMatrix2fv( GLsizei count, GLfloat *value, GLboolean transpose = GL_FALSE ) { NUX_RETURN_IF_TRUE(m_Index == -1); CHECKGL(glUniformMatrix2fvARB( m_Index, count, transpose, value )); } inline void SetUniformMatrix3fv( GLsizei count, GLfloat *value, GLboolean transpose = GL_FALSE ) { NUX_RETURN_IF_TRUE(m_Index == -1); CHECKGL(glUniformMatrix3fvARB( m_Index, count, transpose, value )); } inline void SetUniformMatrix4fv( GLsizei count, GLfloat *value, GLboolean transpose = GL_FALSE ) { NUX_RETURN_IF_TRUE(m_Index == -1); CHECKGL(glUniformMatrix4fvARB( m_Index, count, transpose, value )); } inline void SetTexture( const GLuint /* textureId */) { //CHECKGL(glUniform1iARB( m_Index, textureId )); //CHECKGL(cgGLEnableTextureParameter( CgParameter )); } void MapTo( GLProgramObject *Shader ); private: }; } #endif // GLSHADERPARAMETER_H ./NuxGraphics/GlobalGraphicsInitializer.h0000644000004100000410000000475513313171755020755 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef NUXGRAPHICSGLOBALINITIALIZER_H #define NUXGRAPHICSGLOBALINITIALIZER_H #define NUX_GLOBAL_GRAPHICS_OBJECT_INIT_SEQUENCE() \ NUX_GLOBAL_OBJECT_VARIABLE(RenderingStats); \ NUX_GLOBAL_OBJECT_VARIABLE(NuxGraphicsResources); namespace nux { class NuxGraphicsGlobalSingletonInitializer { NUX_DISABLE_OBJECT_COPY(NuxGraphicsGlobalSingletonInitializer); NuxGraphicsGlobalSingletonInitializer *operator & (); const NuxGraphicsGlobalSingletonInitializer *operator & () const; public: NuxGraphicsGlobalSingletonInitializer(); ~NuxGraphicsGlobalSingletonInitializer(); static bool Ready(); private: static bool m_NuxGraphicsGlobalObjectsReady; NUX_GLOBAL_GRAPHICS_OBJECT_INIT_SEQUENCE(); }; // Nifty Counter idiom. See http://www-d0.fnal.gov/KAI/doc/tutorials/static_initialization.html class NuxGraphicsGlobalInitializer { public: NuxGraphicsGlobalInitializer(); ~NuxGraphicsGlobalInitializer(); private: static int m_Count; }; // Every compilation unit that includes this file will have its own instance of sGlobalInitializer. sGlobalInitializer is initialized // before the main function of the program is called. The first time sGlobalInitializer is initialized, it calls SystemStart() to create // our global object singleton. In SystemStart() we have a change to create our singletons in any order we like. // When the program exits, every instance of sGlobalInitializer will be destroyed. The last instance destroyed will call SystemShutdown(). // In SystemShutdown() we can destroy our global objects in any order we like. static NuxGraphicsGlobalInitializer sNuxGraphicsGlobalInitializer; } #endif // NUXGRAPHICSGLOBALINITIALIZER_H ./NuxGraphics/GraphicsDisplay.h0000644000004100000410000000206713313171755016750 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef GRAPHICSDISPLAY_H #define GRAPHICSDISPLAY_H #if defined(NUX_OS_WINDOWS) #include "GraphicsDisplayWin.h" #elif defined(USE_X11) #include "GraphicsDisplayX11.h" #else #error "GraphicsDisplay.h" is not implemented for this platform. #endif #endif //GRAPHICSDISPLAY_H ./NuxGraphics/GlobalGraphicsInitializer.cpp0000644000004100000410000000470213313171755021300 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "GLResource.h" #include "RunTimeStats.h" #include "NuxGraphicsResources.h" #include "FontTexture.h" #include "GlobalGraphicsInitializer.h" namespace nux { static NuxGraphicsGlobalSingletonInitializer *GNuxGraphicsGlobalInitializer = 0; static void SystemStart() { static unsigned char StaticBuffer[sizeof(NuxGraphicsGlobalSingletonInitializer) ]; // Placement new in our reserved buffer. GNuxGraphicsGlobalInitializer = new(StaticBuffer) NuxGraphicsGlobalSingletonInitializer(); //GLogDevice.AddOutputDevice( &NUX_GLOBAL_OBJECT_INSTANCE(NOutputLogFile)); //GLogDevice.AddOutputDevice( &NUX_GLOBAL_OBJECT_INSTANCE(NOutputVisualDebugConsole)); } static void SystemShutdown() { // Manually destroy initializer if (GNuxGraphicsGlobalInitializer) GNuxGraphicsGlobalInitializer->~NuxGraphicsGlobalSingletonInitializer(); GNuxGraphicsGlobalInitializer = 0; } bool NuxGraphicsGlobalSingletonInitializer::m_NuxGraphicsGlobalObjectsReady = false; NuxGraphicsGlobalSingletonInitializer::NuxGraphicsGlobalSingletonInitializer() { m_NuxGraphicsGlobalObjectsReady = true; } NuxGraphicsGlobalSingletonInitializer::~NuxGraphicsGlobalSingletonInitializer() { m_NuxGraphicsGlobalObjectsReady = false; } bool NuxGraphicsGlobalSingletonInitializer::Ready() { return m_NuxGraphicsGlobalObjectsReady; } int NuxGraphicsGlobalInitializer::m_Count = 0; NuxGraphicsGlobalInitializer::NuxGraphicsGlobalInitializer() { if (m_Count++ == 0) { SystemStart(); } } NuxGraphicsGlobalInitializer::~NuxGraphicsGlobalInitializer() { if (--m_Count == 0) { SystemShutdown(); } } } ./NuxGraphics/GLPBuffer.cpp0000644000004100000410000007101713313171755015772 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef NUX_OPENGLES_20 #include "NuxCore/NuxCore.h" #include "GLResource.h" #include "GLPBuffer.h" namespace nux { #if defined(NUX_OS_WINDOWS) PBuffer::PBuffer (const char *strMode, bool managed) : m_hDC (0), m_hGLRC (0), m_hPBuffer (0), m_hOldGLRC (0), m_hOldDC (0), m_bIsTexture (false), m_iWidth (0), m_iHeight (0), m_strMode (strMode), m_bSharedContext (false), m_bShareObjects (false), m_bIsBound (false), m_bIsActive (false), m_bManaged (managed) { m_pfAttribList.push_back (WGL_DRAW_TO_PBUFFER_ARB); m_pfAttribList.push_back (true); m_pfAttribList.push_back (WGL_SUPPORT_OPENGL_ARB); m_pfAttribList.push_back (true); m_pbAttribList.push_back (WGL_PBUFFER_LARGEST_ARB); m_pbAttribList.push_back (true); nuxDebugMsg (TEXT ("Declare a Pbuffer with \"%s\" parameters\n"), strMode); m_strMode = strMode; parseModeString (m_strMode, &m_pfAttribList, &m_pbAttribList); m_pfAttribList.push_back (0); m_pbAttribList.push_back (0); } PBuffer::~PBuffer() { if (m_bManaged) Destroy(); } // This function actually does the creation of the p-buffer. // It can only be called once a window has already been created. bool PBuffer::Initialize (int iWidth, int iHeight, bool bShareContexts, bool bShareObjects) { HDC hdc = wglGetCurrentDC(); HGLRC hglrc = wglGetCurrentContext(); int format = 0; int nfattribs = 0; int niattribs = 0; m_iWidth = iWidth; m_iHeight = iHeight; m_bSharedContext = bShareContexts; m_bShareObjects = bShareObjects; if (m_bSharedContext) { // Get the pixel format for the on-screen window. format = GetPixelFormat (hdc); if (format == 0) { nuxDebugMsg (TEXT ("pbuffer creation error: GetPixelFormat() failed") ); return false; } } else { unsigned int nformats; wglChoosePixelFormatARB (hdc, &m_pfAttribList[0], NULL, 1, &format, &nformats); if (nformats == 0) { nuxDebugMsg (TEXT ("pbuffer creation error: Couldn't find a suitable pixel format.") ); return false; } } m_hPBuffer = wglCreatePbufferARB (hdc, format, m_iWidth, m_iHeight, &m_pbAttribList[0]); if (!m_hPBuffer) { DWORD err = GetLastError(); nuxDebugMsg (TEXT ("pbuffer creation error: wglCreatePbufferARB() failed") ); if (err == ERROR_INVALID_PIXEL_FORMAT) { nuxDebugMsg (TEXT ("error: ERROR_INVALID_PIXEL_FORMAT") ); } else if (err == ERROR_NO_SYSTEM_RESOURCES) { nuxDebugMsg (TEXT ("error: ERROR_NO_SYSTEM_RESOURCES") ); } else if (err == ERROR_INVALID_DATA) { nuxDebugMsg (TEXT ("error: ERROR_INVALID_DATA") ); } return false; } // Get the device context. m_hDC = wglGetPbufferDCARB (m_hPBuffer); if (!m_hDC) { nuxDebugMsg (TEXT ("pbuffer creation error: wglGetPbufferDCARB() failed") ); return false; } if (m_bSharedContext) { // Let's use the same gl context.. // Since the device contexts are compatible (i.e. same pixelformat), // we should be able to use the same gl rendering context. m_hGLRC = hglrc; } else { // Create a new gl context for the p-buffer. m_hGLRC = wglCreateContext (m_hDC); if (!m_hGLRC) { nuxDebugMsg (TEXT ("pbuffer creation error: wglCreateContext() failed") ); return false; } if (m_bShareObjects) { if (!wglShareLists (hglrc, m_hGLRC) ) { nuxDebugMsg (TEXT ("pbuffer: wglShareLists() failed") ); return false; } } } GLint texFormat = WGL_NO_TEXTURE_ARB; wglQueryPbufferARB (m_hPBuffer, WGL_TEXTURE_FORMAT_ARB, &texFormat); if (texFormat != WGL_NO_TEXTURE_ARB) m_bIsTexture = true; // Determine the actual width and height we were able to create. wglQueryPbufferARB (m_hPBuffer, WGL_PBUFFER_WIDTH_ARB, &m_iWidth); wglQueryPbufferARB (m_hPBuffer, WGL_PBUFFER_HEIGHT_ARB, &m_iHeight); nuxDebugMsg ("Created a %d x %d pbuffer\n", m_iWidth, m_iHeight); #ifdef _DEBUG // query pixel format int iattributes[] = { WGL_RED_BITS_ARB, WGL_GREEN_BITS_ARB, WGL_BLUE_BITS_ARB, WGL_ALPHA_BITS_ARB, WGL_FLOAT_COMPONENTS_NV, WGL_DEPTH_BITS_ARB, WGL_SAMPLES_EXT, WGL_AUX_BUFFERS_ARB }; int ivalues[sizeof (iattributes) / sizeof (int) ]; if (wglGetPixelFormatAttribivARB (m_hDC, format, 0, sizeof (iattributes) / sizeof (int), iattributes, ivalues) ) { nuxDebugMsg ("r:%d g:%d b:%d a:%d float:%d depth:%d samples:%d aux:%d\n", ivalues[0], ivalues[1], ivalues[2], ivalues[3], ivalues[4], ivalues[5], ivalues[6], ivalues[7]); } #endif return true; } void PBuffer::Destroy() { if (m_hPBuffer) { if (!m_bSharedContext) wglDeleteContext (m_hGLRC); wglReleasePbufferDCARB (m_hPBuffer, m_hDC); wglDestroyPbufferARB (m_hPBuffer); } } void PBuffer::parseModeString (const char *modeString, std::vector *pfAttribList, std::vector *pbAttribList) { if (!modeString || strcmp (modeString, "") == 0) return; m_iBitsPerComponent = 8; m_iNComponents = 0; bool bIsFloatBuffer = false; bool bIsATIFloatBuffer = false; bool bIsTexture = false; bool bNeedAlpha = false; char *mode = _strdup (modeString); std::vector tokens; char *next_token = NULL; #ifdef WIN32_SECURE char *buf = strtok_s (mode, " ", &next_token); #else char *buf = strtok (mode, " "); #endif while (buf != NULL) { if (strstr (buf, "ati_float") != NULL) bIsATIFloatBuffer = true; else if (strstr (buf, "float") != NULL) bIsFloatBuffer = true; if (strstr (buf, "texture") != NULL) bIsTexture = true; if (strstr (buf, "alpha") != NULL) bNeedAlpha = true; tokens.push_back (buf); #ifdef WIN32_SECURE buf = strtok_s (NULL, " ", &next_token); #else buf = strtok (NULL, " "); #endif } pfAttribList->push_back (WGL_PIXEL_TYPE_ARB); #ifdef WGL_ATI_pixel_format_float if (bIsATIFloatBuffer) { pfAttribList->push_back (WGL_TYPE_RGBA_FLOAT_ATI); } else #endif { pfAttribList->push_back (WGL_TYPE_RGBA_ARB); } for (unsigned int i = 0; i < tokens.size(); i++) { std::string token = tokens[i]; if (token == "rgb" && (m_iNComponents <= 1) ) { /* pfAttribList->push_back(WGL_RED_BITS_ARB); pfAttribList->push_back(m_iBitsPerComponent); pfAttribList->push_back(WGL_GREEN_BITS_ARB); pfAttribList->push_back(m_iBitsPerComponent); pfAttribList->push_back(WGL_BLUE_BITS_ARB); pfAttribList->push_back(m_iBitsPerComponent);*/ m_iNComponents += 3; continue; } else if (token == "rgb") nuxDebugMsg ("warning : mistake in components definition (rgb + %d)\n", m_iNComponents); if (token == "rgba" && (m_iNComponents == 0) ) { /*pfAttribList->push_back(WGL_RED_BITS_ARB); pfAttribList->push_back(m_iBitsPerComponent); pfAttribList->push_back(WGL_GREEN_BITS_ARB); pfAttribList->push_back(m_iBitsPerComponent); pfAttribList->push_back(WGL_BLUE_BITS_ARB); pfAttribList->push_back(m_iBitsPerComponent); pfAttribList->push_back(WGL_ALPHA_BITS_ARB); pfAttribList->push_back(m_iBitsPerComponent);*/ m_iNComponents = 4; continue; } else if (token == "rgba") nuxDebugMsg ("warning : mistake in components definition (rgba + %d)\n", m_iNComponents); if (token == "alpha" && (m_iNComponents <= 3) ) { /*pfAttribList->push_back(WGL_ALPHA_BITS_ARB); pfAttribList->push_back(m_iBitsPerComponent);*/ m_iNComponents++; continue; } else if (token == "alpha") nuxDebugMsg ("warning : mistake in components definition (alpha + %d)\n", m_iNComponents); if (token == "r" && (m_iNComponents <= 1) ) // && bIsFloatBuffer) { /*pfAttribList->push_back(WGL_RED_BITS_ARB); pfAttribList->push_back(m_iBitsPerComponent);*/ m_iNComponents++; continue; } else if (token == "r") nuxDebugMsg ("warning : mistake in components definition (r + %d)\n", m_iNComponents); if (token == "rg" && (m_iNComponents <= 1) ) // && bIsFloatBuffer) { /*pfAttribList->push_back(WGL_RED_BITS_ARB); pfAttribList->push_back(m_iBitsPerComponent); pfAttribList->push_back(WGL_GREEN_BITS_ARB); pfAttribList->push_back(m_iBitsPerComponent);*/ m_iNComponents += 2; continue; } else if (token == "r") nuxDebugMsg ("warning : mistake in components definition (rg + %d)\n", m_iNComponents); if (token.find ("depth") == 0) { pfAttribList->push_back (WGL_DEPTH_BITS_ARB); pfAttribList->push_back (getIntegerValue (token) ); continue; } if (token.find ("stencil") == 0) { pfAttribList->push_back (WGL_STENCIL_BITS_ARB); pfAttribList->push_back (8); continue; } if (token.find ("samples") == 0) { pfAttribList->push_back (WGL_SAMPLE_BUFFERS_ARB); pfAttribList->push_back (1); pfAttribList->push_back (WGL_SAMPLES_ARB); pfAttribList->push_back (getIntegerValue (token) ); continue; } if (token.find ("aux") == 0) { pfAttribList->push_back (WGL_AUX_BUFFERS_ARB); pfAttribList->push_back (getIntegerValue (token) ); continue; } if (token == "double") { pfAttribList->push_back (WGL_DOUBLE_BUFFER_ARB); pfAttribList->push_back (true); continue; } if (token.find ("ati_float") == 0) { m_iBitsPerComponent = getIntegerValue (token); // type already set above continue; } else if (token.find ("float") == 0) { m_iBitsPerComponent = getIntegerValue (token); //bIsFloatBuffer = true; done previously pfAttribList->push_back (WGL_FLOAT_COMPONENTS_NV); pfAttribList->push_back (true); continue; } if (token.find ("texture") == 0) { if (token.find ("textureRECT") == 0 || bIsFloatBuffer) { pbAttribList->push_back (WGL_TEXTURE_TARGET_ARB); pbAttribList->push_back (WGL_TEXTURE_RECTANGLE_NV); } else if (token.find ("textureCUBE") == 0) { pbAttribList->push_back (WGL_TEXTURE_TARGET_ARB); pbAttribList->push_back (WGL_TEXTURE_CUBE_MAP_ARB); } else { pbAttribList->push_back (WGL_TEXTURE_TARGET_ARB); pbAttribList->push_back (WGL_TEXTURE_2D_ARB); } if (bIsFloatBuffer || bIsATIFloatBuffer) { if (m_iNComponents == 0) { nuxDebugMsg ("components not specified. assuming rgba...\n"); pfAttribList->push_back (WGL_RED_BITS_ARB); pfAttribList->push_back (m_iBitsPerComponent); pfAttribList->push_back (WGL_GREEN_BITS_ARB); pfAttribList->push_back (m_iBitsPerComponent); pfAttribList->push_back (WGL_BLUE_BITS_ARB); pfAttribList->push_back (m_iBitsPerComponent); pfAttribList->push_back (WGL_ALPHA_BITS_ARB); pfAttribList->push_back (m_iBitsPerComponent); m_iNComponents = 4; } } if (bIsFloatBuffer) { switch (m_iNComponents) { case 1: pfAttribList->push_back (WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV); pfAttribList->push_back (true); pbAttribList->push_back (WGL_TEXTURE_FORMAT_ARB); pbAttribList->push_back (WGL_TEXTURE_FLOAT_R_NV); break; case 2: pfAttribList->push_back (WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV); pfAttribList->push_back (true); pbAttribList->push_back (WGL_TEXTURE_FORMAT_ARB); pbAttribList->push_back (WGL_TEXTURE_FLOAT_RG_NV); break; case 3: pfAttribList->push_back (WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV); pfAttribList->push_back (true); pbAttribList->push_back (WGL_TEXTURE_FORMAT_ARB); pbAttribList->push_back (WGL_TEXTURE_FLOAT_RGB_NV); break; case 4: pfAttribList->push_back (WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV); pfAttribList->push_back (true); pbAttribList->push_back (WGL_TEXTURE_FORMAT_ARB); pbAttribList->push_back (WGL_TEXTURE_FLOAT_RGBA_NV); break; default: nuxDebugMsg ("Bad number of components (r=1,rg=2,rgb=3,rgba=4): %d\n", m_iNComponents); break; } } else { switch (m_iNComponents) { case 3: pfAttribList->push_back (WGL_BIND_TO_TEXTURE_RGB_ARB); pfAttribList->push_back (true); pbAttribList->push_back (WGL_TEXTURE_FORMAT_ARB); pbAttribList->push_back (WGL_TEXTURE_RGB_ARB); break; case 4: pfAttribList->push_back (WGL_BIND_TO_TEXTURE_RGBA_ARB); pfAttribList->push_back (true); pbAttribList->push_back (WGL_TEXTURE_FORMAT_ARB); pbAttribList->push_back (WGL_TEXTURE_RGBA_ARB); break; default: nuxDebugMsg ("Bad number of components (r=1,rg=2,rgb=3,rgba=4): %d\n", m_iNComponents); break; } } std::string option = getStringValue (token); if (option == "depth") { pfAttribList->push_back (WGL_BIND_TO_TEXTURE_DEPTH_NV); pfAttribList->push_back (true); pbAttribList->push_back (WGL_DEPTH_TEXTURE_FORMAT_NV); pbAttribList->push_back (WGL_TEXTURE_DEPTH_COMPONENT_NV); } continue; } if (token.find ("mipmap") == 0 && bIsTexture) { pbAttribList->push_back (WGL_MIPMAP_TEXTURE_ARB); pbAttribList->push_back (true); continue; } nuxDebugMsg ("unknown pbuffer attribute: %s\n", token.c_str() ); } if (m_iNComponents > 0) { pfAttribList->push_back (WGL_RED_BITS_ARB); pfAttribList->push_back (m_iBitsPerComponent); } if (m_iNComponents > 1) { pfAttribList->push_back (WGL_GREEN_BITS_ARB); pfAttribList->push_back (m_iBitsPerComponent); } if (m_iNComponents > 2) { pfAttribList->push_back (WGL_BLUE_BITS_ARB); pfAttribList->push_back (m_iBitsPerComponent); } if (m_iNComponents > 3) { pfAttribList->push_back (WGL_ALPHA_BITS_ARB); pfAttribList->push_back (m_iBitsPerComponent); } } // Check to see if the pbuffer was lost. // If it was lost, destroy it and then recreate it. void PBuffer::HandleModeSwitch() { int lost = 0; wglQueryPbufferARB (m_hPBuffer, WGL_PBUFFER_LOST_ARB, &lost); if (lost) { this->~PBuffer(); Initialize (m_iWidth, m_iHeight, m_bSharedContext, m_bShareObjects); } } int PBuffer::Bind (int iBuffer) { if (!m_bIsTexture) { nuxDebugMsg ("PBuffer::Bind() failed - pbuffer format does not support render to texture!\n"); return 0; } #if 0 // SGG - with MRT it is legal to bind different buffers of a pbuffer simultaneously if (m_bIsBound) { nuxDebugMsg ("PBuffer::Bind() failed - pbuffer is already bound.\n"); return 0; } #endif int ret = wglBindTexImageARB (m_hPBuffer, iBuffer); if (!ret) nuxDebugMsg ("PBuffer::Bind() failed.\n"); m_bIsBound = true; return ret; } int PBuffer::Release (int iBuffer) { if (!m_bIsTexture) { nuxDebugMsg ("PBuffer::Release() failed - pbuffer format does not support render to texture!\n"); return 0; } #if 0 // SGG - with MRT it is legal to bind different buffers of a pbuffer simultaneously if (!m_bIsBound) { nuxDebugMsg ("PBuffer::Release() failed - pbuffer is not bound.\n"); return 0; } #endif int ret = wglReleaseTexImageARB (m_hPBuffer, iBuffer); if (!ret) nuxDebugMsg ("PBuffer::Release() failed.\n"); m_bIsBound = false; return ret; } void PBuffer::Activate (PBuffer *current /* = NULL */) { if (current == this) { return; // no switch necessary } if (NULL == current || !current->m_bIsActive) { if (m_bIsActive) return; m_hOldGLRC = wglGetCurrentContext(); m_hOldDC = wglGetCurrentDC(); } else { m_hOldGLRC = current->m_hOldGLRC; m_hOldDC = current->m_hOldDC; current->m_hOldGLRC = 0; current->m_hOldDC = 0; current->m_bIsActive = false; } if (!wglMakeCurrent (m_hDC, m_hGLRC) ) nuxDebugMsg ("PBuffer::Activate() failed.\n"); m_bIsActive = true; } void PBuffer::Deactivate() { if (!m_bIsActive) return; if (!wglMakeCurrent (m_hOldDC, m_hOldGLRC) ) nuxDebugMsg ("PBuffer::Deactivate() failed.\n"); m_hOldGLRC = 0; m_hOldDC = 0; m_bIsActive = false; } #elif defined(NUX_OS_LINUX) PBuffer::PBuffer (const char *strMode, bool managed) : m_pDisplay (0), m_glxPbuffer (0), m_glxContext (0), m_pOldDisplay (0), m_glxOldDrawable (0), m_glxOldContext (0), m_iWidth (0), m_iHeight (0), m_strMode (strMode), m_bSharedContext (false), m_bShareObjects (false), m_bManaged (managed) { m_pfAttribList.push_back (GLX_DRAWABLE_TYPE); m_pfAttribList.push_back (GLX_PBUFFER_BIT); m_pfAttribList.push_back (GLX_RENDER_TYPE); m_pfAttribList.push_back (GLX_RGBA_BIT); m_pbAttribList.push_back (GLX_LARGEST_PBUFFER); m_pbAttribList.push_back (true); m_pbAttribList.push_back (GLX_PRESERVED_CONTENTS); m_pbAttribList.push_back (true); m_strMode = strMode; parseModeString (m_strMode, &m_pfAttribList, &m_pbAttribList); m_pfAttribList.push_back (0); m_pbAttribList.push_back (0); } PBuffer::~PBuffer() { if (m_bManaged) Destroy(); } bool PBuffer::Initialize (int iWidth, int iHeight, bool bShareContexts, bool bShareObjects) { Display *pDisplay = glXGetCurrentDisplay(); int iScreen = DefaultScreen (pDisplay); GLXContext glxContext = glXGetCurrentContext(); GLXFBConfig *glxConfig; int iConfigCount; m_bSharedContext = bShareContexts; m_bShareObjects = bShareObjects; m_iWidth = iWidth; m_iHeight = iHeight; if (m_bSharedContext) { glxConfig = glXGetFBConfigs (pDisplay, iScreen, &iConfigCount); if (!glxConfig) { nuxDebugMsg ("pbuffer creation error: glXGetFBConfigs() failed\n"); return false; } } else { glxConfig = glXChooseFBConfigSGIX (pDisplay, iScreen, &m_pfAttribList[0], &iConfigCount); if (!glxConfig) { nuxDebugMsg ("pbuffer creation error: glXChooseFBConfig() failed\n"); return false; } } m_glxPbuffer = glXCreateGLXPbufferSGIX (pDisplay, glxConfig[0], m_iWidth, m_iHeight, &m_pbAttribList[0]); if (!m_glxPbuffer) { nuxDebugMsg ("pbuffer creation error: glXCreatePbuffer() failed\n"); return false; } if (m_bSharedContext) { m_glxContext = glxContext; } else { if (m_bShareObjects) m_glxContext = glXCreateContextWithConfigSGIX (pDisplay, glxConfig[0], GLX_RGBA_TYPE, glxContext, true); else m_glxContext = glXCreateContextWithConfigSGIX (pDisplay, glxConfig[0], GLX_RGBA_TYPE, NULL, true); if (!glxConfig) { nuxDebugMsg ("pbuffer creation error: glXCreateNewContext() failed\n"); return false; } } m_pDisplay = pDisplay; unsigned int w, h; w = h = 0; glXQueryGLXPbufferSGIX (m_pDisplay, m_glxPbuffer, GLX_WIDTH, &w); glXQueryGLXPbufferSGIX (m_pDisplay, m_glxPbuffer, GLX_HEIGHT, &h); m_iWidth = w; m_iHeight = h; nuxDebugMsg ("Created a %d x %d pbuffer\n", m_iWidth, m_iHeight); return true; } void PBuffer::Destroy() { if (m_glxContext && !m_bSharedContext) glXDestroyContext (m_pDisplay, m_glxContext); if (m_glxPbuffer) glXDestroyGLXPbufferSGIX (m_pDisplay, m_glxPbuffer); m_glxContext = 0; m_glxPbuffer = 0; m_pDisplay = 0; } void PBuffer::parseModeString (const char *modeString, std::vector *pfAttribList, std::vector * /* pbAttribList */) { if (!modeString || strcmp (modeString, "") == 0) return; m_iBitsPerComponent = 8; m_iNComponents = 0; bool bIsFloatBuffer = false; char *mode = strdup (modeString); std::vector tokens; char *buf = strtok (mode, " "); while (buf != NULL) { if (strstr (buf, "float") != NULL) bIsFloatBuffer = true; tokens.push_back (buf); buf = strtok (NULL, " "); } for (unsigned int i = 0; i < tokens.size(); i++) { std::string token = tokens[i]; if (token == "rgb" && !bIsFloatBuffer) { pfAttribList->push_back (GLX_RED_SIZE); pfAttribList->push_back (m_iBitsPerComponent); pfAttribList->push_back (GLX_GREEN_SIZE); pfAttribList->push_back (m_iBitsPerComponent); pfAttribList->push_back (GLX_BLUE_SIZE); pfAttribList->push_back (m_iBitsPerComponent); m_iNComponents += 3; continue; } else if (token == "rgb") { nuxDebugMsg ("warning : mistake in components definition (rgb + %d)\n", m_iNComponents); } if (token == "rgba" && (m_iNComponents == 0) ) { pfAttribList->push_back (GLX_RED_SIZE); pfAttribList->push_back (m_iBitsPerComponent); pfAttribList->push_back (GLX_GREEN_SIZE); pfAttribList->push_back (m_iBitsPerComponent); pfAttribList->push_back (GLX_BLUE_SIZE); pfAttribList->push_back (m_iBitsPerComponent); pfAttribList->push_back (GLX_ALPHA_SIZE); pfAttribList->push_back (m_iBitsPerComponent); m_iNComponents = 4; continue; } else if (token == "rgba") { nuxDebugMsg ("warning : mistake in components definition (rgba + %d)\n", m_iNComponents); } if (token.find ("alpha") != token.npos) { pfAttribList->push_back (GLX_ALPHA_SIZE); pfAttribList->push_back (m_iBitsPerComponent); m_iNComponents++; continue; } else if (token == "alpha") { nuxDebugMsg ("warning : mistake in components definition (alpha + %d)\n", m_iNComponents); } if (token.find ("depth") != token.npos) { pfAttribList->push_back (GLX_DEPTH_SIZE); pfAttribList->push_back (getIntegerValue (token) ); continue; } if (token.find ("stencil") != token.npos) { pfAttribList->push_back (GLX_STENCIL_SIZE); pfAttribList->push_back (getIntegerValue (token) ); continue; } if (token.find ("samples") != token.npos) { pfAttribList->push_back (GLX_SAMPLE_BUFFERS_ARB); pfAttribList->push_back (1); pfAttribList->push_back (GLX_SAMPLES_ARB); pfAttribList->push_back (getIntegerValue (token) ); continue; } if (token == "double") { pfAttribList->push_back (GLX_DOUBLEBUFFER); pfAttribList->push_back (true); continue; } if (token.find ("float") == 0) { m_iBitsPerComponent = getIntegerValue (token); pfAttribList->push_back (GLX_FLOAT_COMPONENTS_NV); pfAttribList->push_back (true); continue; } nuxDebugMsg ("unknown pbuffer attribute: %s\n", token.c_str() ); } } void PBuffer::Activate (PBuffer *current /* = NULL */) { if (current == this) { return; // no switch necessary } if (NULL == current || !current->m_bIsActive) { m_pOldDisplay = glXGetCurrentDisplay(); m_glxOldDrawable = glXGetCurrentDrawable(); m_glxOldContext = glXGetCurrentContext(); } else { m_pOldDisplay = current->m_pOldDisplay; m_glxOldDrawable = current->m_glxOldDrawable; m_glxOldContext = current->m_glxOldContext; current->m_pOldDisplay = 0; current->m_glxOldDrawable = 0; current->m_glxOldContext = 0; } if (!glXMakeCurrent (m_pDisplay, m_glxPbuffer, m_glxContext) ) { nuxDebugMsg ("PBuffer::Activate() failed.\n"); } } void PBuffer::Deactivate() { if (!glXMakeCurrent (m_pOldDisplay, m_glxOldDrawable, m_glxOldContext) ) { nuxDebugMsg ("PBuffer::Deactivate() failed.\n"); } m_pOldDisplay = 0; m_glxOldDrawable = 0; m_glxOldContext = 0; } #elif defined(NUX_OS_MACOSX) PBuffer::PBuffer (const char *strMode) : m_iWidth (0), m_iHeight (0), m_strMode (strMode), m_bSharedContext (false), m_bShareObjects (false) { nuxDebugMsg ("pbuffer not implemented under Mac OS X yet\n"); } PBuffer::~PBuffer() { nuxDebugMsg ("pbuffer not implemented under Mac OS X yet\n"); } bool PBuffer::Initialize (int iWidth, int iHeight, bool bShareContexts, bool bShareObjects) { nuxDebugMsg ("pbuffer not implemented under Mac OS X yet\n"); return false; } void PBuffer::Activate() { nuxDebugMsg ("pbuffer not implemented under Mac OS X yet\n"); } void PBuffer::Deactivate() { nuxDebugMsg ("pbuffer not implemented under Mac OS X yet\n"); } #endif std::string PBuffer::getStringValue (std::string token) { size_t pos; if ( (pos = token.find ("=") ) != token.npos) { std::string value = token.substr (pos + 1, token.length() - pos + 1); return value; } else return ""; } int PBuffer::getIntegerValue (std::string token) { size_t pos; if ( (pos = token.find ("=") ) != token.npos) { std::string value = token.substr (pos + 1, token.length() - pos + 1); if (value.empty() ) return 1; return atoi (value.c_str() ); } else return 1; } //---------------------------------------------------------------------------------- // /// return the total size in bytes of the PBuffer // //---------------------------------------------------------------------------------- unsigned int PBuffer::GetSizeInBytes() { return m_iWidth * m_iHeight * (m_iNComponents / 8); } /*************************************************************************/ /** make a copy the entire PBuffer in the memory. You have to allocate this area (ptr). if ever you want to read a smaller size : specify it through w,h. otherwise w=h=-1 */ /*********************************************************************/ unsigned int PBuffer::CopyToBuffer (void *ptr, int w, int h) { GLenum format = 0; GLenum type = 0; switch (m_iNComponents) { case 1: // format = GL_LUMINANCE; // is it right to ask for Red only component ? break; case 2: format = GL_LUMINANCE_ALPHA; //How to ask for GL_RG ?? break; case 3: format = GL_RGB; break; case 4: format = GL_RGBA; break; } switch (m_iBitsPerComponent) { case 8: type = GL_UNSIGNED_BYTE; break; case 32: type = GL_FLOAT; break; #ifdef GL_NV_half_float case 16: type = GL_HALF_FLOAT_NV; break; #endif default: nuxDebugMsg ("unknown m_iBitsPerComponent\n"); # if defined(WIN32) __debugbreak(); # endif } Activate(); if ( (w < 0) || (w > m_iWidth) ) w = m_iWidth; if ( (h < 0) || (h > m_iHeight) ) h = m_iHeight; glReadPixels (0, 0, w, h, format, type, ptr); Deactivate(); return w * h * (m_iNComponents / 8); } } #endif // NUX_OPENGLES_20 ./NuxGraphics/GLShader.h0000644000004100000410000000174013313171755015310 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef GLSHADER_H #define GLSHADER_H #include "NuxCore/NuxCore.h" #include "NuxCore/Error.h" #include "NuxCore/OutputDevice.h" #include "GLResource.h" namespace nux { } #endif //GLSHADER_H ./NuxGraphics/OpenGLDefinitions.h0000644000004100000410000000143713313171755017202 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ ./NuxGraphics/GLSh_Fill.cpp0000644000004100000410000001025213313171755015753 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "NuxCore/NuxCore.h" #include "GLResource.h" #include "GpuDevice.h" #include "GLDeviceObjects.h" #include "GLSh_Fill.h" #include "GLShaderParameter.h" #include "GpuDevice.h" #include "GLTemplatePrimitiveBuffer.h" #include "NuxCore/Math/Matrix4.h" namespace nux { GLSh_Fill::GLSh_Fill() { // Color = new GLShaderParameter(0, "ColorFill", eFRAGMENTUNIFORMTYPE, TRUE); // ViewProjectionMatrix = new GLShaderParameter(0, "ViewProjectionMatrix", eVERTEXUNIFORMTYPE, TRUE); // Scale = new GLShaderParameter(0, "Scale", eVERTEXUNIFORMTYPE, TRUE); // Offset = new GLShaderParameter(0, "Offset", eVERTEXUNIFORMTYPE, TRUE); // // vs = GetGpuDevice()->CreateVertexShader(); // ps = GetGpuDevice()->CreatePixelShader(); // sprog = GetGpuDevice()->CreateShaderProgram(); // // sprog->AddShaderParameter(Color); // sprog->AddShaderParameter(ViewProjectionMatrix); // sprog->AddShaderParameter(Scale); // sprog->AddShaderParameter(Offset); // // NString SourceCode; // LoadFileToString(SourceCode, "..//Shaders//Fill.glsl"); // NString VertexShaderSource; // ExtractShaderString3("[Vertex Shader]", SourceCode, VertexShaderSource); // NString PixelShaderSource; // ExtractShaderString3("[Fragment Shader]", SourceCode, PixelShaderSource); // // vs->SetShaderCode(VertexShaderSource.GetTCharPtr()); // ps->SetShaderCode(PixelShaderSource.GetTCharPtr()); // vs->Compile(); // ps->Compile(); // // sprog->AddShaderObject(vs); // sprog->AddShaderObject(ps); // sprog->Link(); // // m_QuadBuffer = new TemplateQuadBuffer(GetGpuDevice()); // // Vector4 v[] = // // { // // Vector4(1, 0, 0, 0), // // Vector4(1, 0, 0, 0), // // Vector4(0, 0, 1, 0), // // Vector4(0, 0, 1, 0), // // }; // // m_QuadBuffer->SetPerVertexAttribute(1, 4, v); } GLSh_Fill::~GLSh_Fill() { NUX_SAFE_DELETE(m_QuadBuffer); NUX_SAFE_DELETE(Color); NUX_SAFE_DELETE(ViewProjectionMatrix); NUX_SAFE_DELETE(Scale); NUX_SAFE_DELETE(Offset); } void GLSh_Fill::SetColor(FLOAT R, FLOAT G, FLOAT B, FLOAT A) { _R = R; _G = G; _B = B; _A = A; } void GLSh_Fill::SetTransformMatrix(const Matrix4 &TransformMatrix) { m_TransformMatrix = TransformMatrix; } void GLSh_Fill::Render(INT x, INT y, INT /* z */, INT width, INT height) { return; CHECKGL(glDisable(GL_CULL_FACE)); sprog->Begin(); //Matrix4 ProjectionMatrix; //ProjectionMatrix.Orthographic(0, 640, 480, 0, 0.0, 10000.0); //ProjectionMatrix.Transpose(); ViewProjectionMatrix->SetUniformMatrix4fv(1, (GLfloat *) m_TransformMatrix.m, GL_FALSE); Scale->SetUniform4f(width, height, 1, 1); Offset->SetUniform4f(x, y, 0, 0); Color->SetUniform4f(_R, _G, _B, _A); INT VertexLocation = sprog->GetAttributeLocation("Vertex"); m_QuadBuffer->BindAttribute(VertexLocation, 0); // INT VertexColorLocation = sprog->GetAttributeLocation("VertexColor"); // m_QuadBuffer->BindAttribute(VertexColorLocation, 1); m_QuadBuffer->Render(1); m_QuadBuffer->UnBindAttribute(VertexLocation); // m_QuadBuffer->UnBindAttribute(VertexColorLocation); m_QuadBuffer->UnBind(); // Unbind the vertex and index buffer. sprog->End(); } void GLSh_Fill::CacheShader() { } } ./NuxGraphics/GLResourceManager.h0000644000004100000410000002426513313171755017173 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef GLRESOURCEMANAGER_H #define GLRESOURCEMANAGER_H namespace nux { // class BaseTexture; // class Texture2D; // class TextureRectangle; // class TextureCube; // class TextureVolume; // class TextureFrameAnimation; // // class NVertexBuffer; // class NIndexBuffer; // // class CachedTexture2D; // class CachedTextureRectangle; // class CachedTextureCube; // class CachedTextureVolume; // class CachedTextureFrameAnimation; // ResourceData CachedResourceData // | | // BaseTexture CachedBaseTexture // | | // Texture2D CachedTexture2D // // // NResourceFactory // | // NGLResourceFactory // | // TGLResourceFactory // // // NResourceSet // | // TResourceCache // | // NResourceCache: TResourceCache // // //! Base class for all types of resources. class ResourceData: public Object { NUX_DECLARE_OBJECT_TYPE(ResourceData, Object); public: ResourceData(NUX_FILE_LINE_PROTO); virtual ~ResourceData(); int GetResourceIndex() const; private: int m_ResourceIndex; }; class CachedResourceData; class NResourceSet { public: NResourceSet(); virtual ~NResourceSet() {}; protected: CachedResourceData *FirstResource; // Flush virtual void Flush() {} // FreeResource - Called when a potentially cached resource has been freed. virtual void FreeResource(ResourceData * /* Resource */) {} // FlushResource - Removes a resource from the set. virtual void FlushResource(CachedResourceData * /* Resource */) {} friend class CachedResourceData; }; enum EResourceUpdateHint { RUH_Static, // The resource is updated once, at creation time. RUH_CacheableDynamic, // The resource is updated occasionally, but not every frame. RUH_Dynamic // The resource changes every frame. }; class CachedResourceData: public Object { NUX_DECLARE_OBJECT_TYPE(CachedResourceData, Object); public: CachedResourceData(NResourceSet *InSet); virtual ~CachedResourceData(); //! Returns the size in bytes of the resource. /*! Returns the size in bytes of the resource. @return Size of the resource in bytes. */ virtual unsigned int GetSize() const { return Size; } //! Returns the size of the max LOD of the resource. /*! Returns the size of the max LOD of the resource. For a texture, this is the size of mipmap 0. Texture resource overwrite this function. @return Size of the resource in bytes. */ virtual unsigned int GetMaxLodSize() const { return Size; } /*! Updates the resource. */ virtual bool UpdateResource(ResourceData *Resource) = 0; protected: NResourceSet *Set; bool _cached; unsigned int NumRefs; NObjectType *ResourceType; unsigned int Size; EResourceUpdateHint UpdateHint; CachedResourceData *PrevResource; CachedResourceData *NextResource; template friend class TResourceCache; friend class NResourceCache; }; //! Device independent resource factory. class NResourceFactory { public: NResourceFactory(NObjectType *Type) : m_ResourceType(Type) {} virtual ~NResourceFactory() {} // Returns the resource type for this factory const NObjectType &Type() const { return *m_ResourceType; } /*! Returns true if the given ResourceData is created by this factory. @param Resource - the resource in question. */ bool BuildsThisResource(ResourceData *Resource) { return Resource->Type().IsObjectType(Type()); } virtual CachedResourceData *BuildResource(NResourceSet * /* ResourceManager */, ResourceData * /* Resource */) { return NULL; } private: //! Type associated with this factory class. NObjectType *m_ResourceType; }; template class TGLResourceFactory : public NResourceFactory { public: /*! Constructor. @param type - resource class type to associate w/ this factory. */ TGLResourceFactory(NObjectType *Type) : NResourceFactory(Type) {} virtual ~TGLResourceFactory(void) {} //! Create a new resource. /*! Create a new resource for the given ResourceData. @param ResourceManager The resource manager. @param Resource Resource to build and cache. @return The built resource. */ virtual CachedResourceData *BuildResource(NResourceSet *ResourceManager, ResourceData *Resource) { return new U(ResourceManager, (T *)Resource); } }; //! Device independent resource updater. class NResourceUpdater { public: NResourceUpdater(NObjectType *Type) : m_ResourceType(Type) {} //! Returns the resource type for this factory. const NObjectType &Type() const { return *m_ResourceType; } /*! Returns true if the given ResourceData can be updated by this factory. @param Resource The resource in question. */ bool UpdatesThisResource(ResourceData *Resource) { return Resource->Type().IsObjectType(Type()); } virtual bool UpdateResource(ObjectPtr< CachedResourceData > DeviceResource, ResourceData *Resource) const { return DeviceResource->UpdateResource(Resource); } private: //! Type associated with this factory class. NObjectType *m_ResourceType; }; template class TResourceCache: public NResourceSet { public: std::map< IdType, ObjectPtr< ResourceType > > ResourceMap; // Resource factory instances for each ResourceData/CachedResourceData pair. std::vector ResourceFactories; // Resource updater instances for each ResourceData type. std::vector ResourceUpdaters; TResourceCache() : NResourceSet() {} void Flush() { // See the language FAQ 35.18 at http://www.parashift.com/c++-faq-lite/templates.html for why the "typename". typename std::map< IdType, ObjectPtr< ResourceType > >::iterator It; for (It = ResourceMap.begin(); It != ResourceMap.end(); It++) { // ObjectPtr< ResourceType > CachedResource = (*It).second; // CachedResource->_cached = 0; // CachedResource.Release(); (*It).second->_cached = 0; (*It).second.Release(); } // Erases all elements from the map. ResourceMap.clear(); } void AddCachedResource(const IdType &Id, ObjectPtr< ResourceType > Resource) { typedef std::map< IdType, ObjectPtr< ResourceType > > MapType; ResourceMap.insert(typename MapType::value_type(Id, Resource)); Resource->_cached = 1; } ObjectPtr FindCachedResourceById(const IdType &Id) { typedef std::map< IdType, ObjectPtr< ResourceType > > MapType; typename MapType::iterator it = ResourceMap.find(Id); if (it != ResourceMap.end()) return(*it).second; return ObjectPtr (0); } /*! Remove a cached resource from the cache. The cached resource may still have references to it. The resource internal flag "_cached" is set to false. */ void FlushResourceId(const IdType &Id) { ObjectPtr CachedResource(0); typedef std::map > MapType; typename MapType::iterator it = ResourceMap.find(Id); if (it != ResourceMap.end()) CachedResource = (*it).second; if (CachedResource.IsValid()) { ResourceMap.erase(it); CachedResource->_cached = false; } } virtual void FlushResource(CachedResourceData *Resource) { typedef std::map< IdType, ObjectPtr< ResourceType > > MapType; typename MapType::iterator it; for (it = ResourceMap.begin(); it != ResourceMap.end(); it++) { ObjectPtr< ResourceType > CachedResource = (*it).second; if (CachedResource == Resource) { ResourceMap.erase(it); CachedResource->_cached = 0; // Make sure that if the following line deletes the resource, it doesn't try to remove itself from the TDynamicMap we're iterating over. return; } } } // Register CachedResourceData with the corresponding ResourceData virtual void InitializeResourceFactories() = 0; std::vector& GetResourceFactories(void) { return(ResourceFactories); } std::vector& GetResourceUpdaters(void) { return(ResourceUpdaters); } }; class NResourceCache: public TResourceCache { public: NResourceCache() : TResourceCache() {} ObjectPtr< CachedResourceData > GetCachedResource(ResourceData *Source); bool IsCachedResource(ResourceData *Source); virtual void InitializeResourceFactories(); // virtual void FreeResource(ResourceData *Resource) // { // FlushResourceId(Resource->GetResourceIndex()); // } }; //////////////////////////////////////////////////////////////////////////////////////////////////// } #endif // GLRESOURCEMANAGER_H ./NuxGraphics/VirtualKeyCodesX11.h0000644000004100000410000003434513313171755017235 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef VIRTUALKEYCODESX11_H #define VIRTUALKEYCODESX11_H namespace nux { // Virtual key codes // The following table shows the symbolic constant names, hexadecimal values, and mouse or keyboard equivalents for the virtual-key codes used by the system. The codes are listed in numeric order. // Symbolic constant name Value (hex) Mouse or keyboard equivalents #define NUX_VK_BACKSPACE XK_BackSpace // BACKSPACE key #define NUX_VK_TAB XK_Tab // TAB key #define NUX_VK_LEFT_TAB XK_ISO_Left_Tab // SHIFT TAB key #define NUX_VK_CLEAR XK_Clear // CLEAR key #define NUX_VK_ENTER XK_Return // ENTER key #define NUX_VK_SHIFT XK_Shift_L // SHIFT key #define NUX_VK_CONTROL XK_Control_L // CTRL key #define NUX_VK_MENU XK_Alt_L // ALT key #define NUX_VK_PAUSE XK_Pause // PAUSE key #define NUX_VK_CAPITAL XK_Caps_Lock // CAPS LOCK key #define NUX_VK_ESCAPE XK_Escape // ESC key #define NUX_VK_SPACE XK_space // SPACEBAR #define NUX_VK_PAGE_UP XK_Page_Up // PAGE UP key #define NUX_VK_PAGE_DOWN XK_Page_Down // PAGE DOWN key #define NUX_VK_END XK_End // END key #define NUX_VK_HOME XK_Home // HOME key #define NUX_VK_LEFT XK_Left // LEFT ARROW key #define NUX_VK_UP XK_Up // UP ARROW key #define NUX_VK_RIGHT XK_Right // RIGHT ARROW key #define NUX_VK_DOWN XK_Down // DOWN ARROW key #define NUX_VK_PRINT XK_Print // PRINT key #define NUX_VK_EXECUTE XK_Execute // EXECUTE key #define NUX_VK_INSERT XK_Insert // INS key #define NUX_VK_DELETE XK_Delete // DEL key /*#define NUX_VK_Multiply XK_Multiply #define NUX_VK_Add XK_Aadd #define NUX_VK_Subtract XK_Substract #define NUX_VK_Decimal XK_Decimal #define NUX_VK_Divide XK_Divide*/ #define NUX_VK_0 XK_0 // 0 key #define NUX_VK_1 XK_1 // 1 key #define NUX_VK_2 XK_2 // 2 key #define NUX_VK_3 XK_3 // 3 key #define NUX_VK_4 XK_4 // 4 key #define NUX_VK_5 XK_5 // 5 key #define NUX_VK_6 XK_6 // 6 key #define NUX_VK_7 XK_7 // 7 key #define NUX_VK_8 XK_8 // 8 key #define NUX_VK_9 XK_9 // 9 key #define NUX_VK_A XK_A // A key #define NUX_VK_B XK_B // B key #define NUX_VK_C XK_C // C key #define NUX_VK_D XK_D // D key #define NUX_VK_E XK_E // E key #define NUX_VK_F XK_F // F key #define NUX_VK_G XK_G // G key #define NUX_VK_H XK_H // H key #define NUX_VK_I XK_I // I key #define NUX_VK_J XK_J // J key #define NUX_VK_K XK_K // K key #define NUX_VK_L XK_L // L key #define NUX_VK_M XK_M // M key #define NUX_VK_N XK_N // N key #define NUX_VK_O XK_O // O key #define NUX_VK_P XK_P // P key #define NUX_VK_Q XK_Q // Q key #define NUX_VK_R XK_R // R key #define NUX_VK_S XK_S // S key #define NUX_VK_T XK_T // T key #define NUX_VK_U XK_U // U key #define NUX_VK_V XK_V // V key #define NUX_VK_W XK_W // W key #define NUX_VK_X XK_X // X key #define NUX_VK_Y XK_Y // Y key #define NUX_VK_Z XK_Z // Z key #define NUX_VK_a XK_a #define NUX_VK_b XK_b #define NUX_VK_c XK_c #define NUX_VK_d XK_d #define NUX_VK_e XK_e #define NUX_VK_f XK_f #define NUX_VK_g XK_g #define NUX_VK_h XK_h #define NUX_VK_i XK_i #define NUX_VK_j XK_j #define NUX_VK_k XK_k #define NUX_VK_l XK_l #define NUX_VK_m XK_m #define NUX_VK_n XK_n #define NUX_VK_o XK_o #define NUX_VK_p XK_p #define NUX_VK_q XK_q #define NUX_VK_r XK_r #define NUX_VK_s XK_s #define NUX_VK_t XK_t #define NUX_VK_u XK_u #define NUX_VK_v XK_v #define NUX_VK_w XK_w #define NUX_VK_x XK_x #define NUX_VK_y XK_y #define NUX_VK_z XK_z #define NUX_VK_LWIN XK_Super_L // Left Windows key (Microsoft Natural Keyboard) #define NUX_VK_RWIN XK_Super_R // Right Windows key (Microsoft Natural Keyboard) #define NUX_VK_NUMPAD0 XK_KP_0 // Numeric keypad 0 key #define NUX_VK_NUMPAD1 XK_KP_1 // Numeric keypad 1 key #define NUX_VK_NUMPAD2 XK_KP_2 // Numeric keypad 2 key #define NUX_VK_NUMPAD3 XK_KP_3 // Numeric keypad 3 key #define NUX_VK_NUMPAD4 XK_KP_4 // Numeric keypad 4 key #define NUX_VK_NUMPAD5 XK_KP_5 // Numeric keypad 5 key #define NUX_VK_NUMPAD6 XK_KP_6 // Numeric keypad 6 key #define NUX_VK_NUMPAD7 XK_KP_7 // Numeric keypad 7 key #define NUX_VK_NUMPAD8 XK_KP_8 // Numeric keypad 8 key #define NUX_VK_NUMPAD9 XK_KP_9 // Numeric keypad 9 key #define NUX_KP_MULTIPLY XK_KP_Multiply // Multiply key #define NUX_KP_ADD XK_KP_Add // Add key #define NUX_KP_SEPARATOR XK_KP_Separator // Separator key #define NUX_KP_SUBTRACT XK_KP_Subtract // Subtract key #define NUX_KP_DECIMAL XK_KP_Decimal // Decimal key #define NUX_KP_DIVIDE XK_KP_Divide // Divide key #define NUX_KP_ENTER XK_KP_Enter #define NUX_VK_F1 XK_F1 // F1 key #define NUX_VK_F2 XK_F2 // F2 key #define NUX_VK_F3 XK_F3 // F3 key #define NUX_VK_F4 XK_F4 // F4 key #define NUX_VK_F5 XK_F5 // F5 key #define NUX_VK_F6 XK_F6 // F6 key #define NUX_VK_F7 XK_F7 // F7 key #define NUX_VK_F8 XK_F8 // F8 key #define NUX_VK_F9 XK_F9 // F9 key #define NUX_VK_F10 XK_F10 // F10 key #define NUX_VK_F11 XK_F11 // F11 key #define NUX_VK_F12 XK_F12 // F12 key #define NUX_VK_F13 XK_F13 // F13 key #define NUX_VK_F14 XK_F14 // F14 key #define NUX_VK_F15 XK_F15 // F15 key #define NUX_VK_F16 XK_F16 // F16 key #define NUX_VK_F17 XK_F17 // F17 key #define NUX_VK_F18 XK_F18 // F18 key #define NUX_VK_F19 XK_F19 // F19 key #define NUX_VK_F20 XK_F20 // F20 key #define NUX_VK_F21 XK_F21 // F21 key #define NUX_VK_F22 XK_F22 // F22 key #define NUX_VK_F23 XK_F23 // F23 key #define NUX_VK_F24 XK_F24 // F24 key #define NUX_VK_NUMLOCK XK_Num_Lock // NUM LOCK key #define NUX_VK_SCROLL XK_Scroll_Lock // SCROLL LOCK key #define NUX_VK_LSHIFT XK_Shift_L // Left SHIFT key #define NUX_VK_RSHIFT XK_Shift_R // Right SHIFT key #define NUX_VK_LCONTROL XK_Control_L // Left CONTROL key #define NUX_VK_RCONTROL XK_Control_R // Right CONTROL key #define NUX_VK_LMENU XK_Alt_L // Left MENU key #define NUX_VK_RMENU XK_Alt_R // Right MENU key #define NUX_VK_FF /*0xFF*/ // Multimedia keys. See ScanCode keys. #define NUX_MAX_VK 256 } #endif // VIRTUALKEYCODESX11_H ./NuxGraphics/RenderingPipe.cpp0000644000004100000410000006033613313171755016753 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "GLResource.h" #include "IOpenGLBaseTexture.h" #include "IOpenGLTexture2D.h" #include "IOpenGLRectangleTexture.h" #include "RenderingPipe.h" #include "GraphicsEngine.h" namespace nux { struct TexWrapMapping { TexWrap tex_wrap_mode; unsigned int opengl_wrap_mode; }; struct TexWrapMapping TexWrapMappingArray [] = { {TEXWRAP_REPEAT, GL_REPEAT}, {TEXWRAP_CLAMP, GL_CLAMP}, {TEXWRAP_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE}, {TEXWRAP_CLAMP_TO_BORDER, GL_CLAMP_TO_BORDER}, {TEXWRAP_MIRRORED_REPEAT, GL_MIRRORED_REPEAT}, #ifndef NUX_OPENGLES_20 {TEXWRAP_MIRROR_CLAMP_EXT, GL_MIRROR_CLAMP_EXT}, {TEXWRAP_MIRROR_CLAMP_TO_EDGE_EXT, GL_MIRROR_CLAMP_TO_EDGE_EXT}, {TEXWRAP_MIRROR_CLAMP_TO_BORDER_EXT, GL_MIRROR_CLAMP_TO_BORDER_EXT}, #endif {TEXWRAP_UNKNOWN, 0} }; GLenum TexWrapGLMapping(TexWrap tex_wrap_mode) { int i = 0; while (TexWrapMappingArray[i].tex_wrap_mode != TEXWRAP_UNKNOWN) { if (TexWrapMappingArray[i].tex_wrap_mode == tex_wrap_mode) { return TexWrapMappingArray[i].opengl_wrap_mode; } ++i; } nuxAssertMsg(0, "[TexWrapGLMapping] Invalid texture wrap mode."); return GL_CLAMP; } struct TexFilterMapping { TexFilter tex_filter_mode; unsigned int opengl_filter_mode; }; struct TexFilterMapping TexFilterMappingArray [] = { {TEXFILTER_LINEAR, GL_LINEAR}, {TEXFILTER_NEAREST, GL_NEAREST}, {TEXFILTER_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_NEAREST}, {TEXFILTER_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_NEAREST}, {TEXFILTER_NEAREST_MIPMAP_LINEAR, GL_NEAREST_MIPMAP_LINEAR}, {TEXFILTER_LINEAR_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_LINEAR}, {TEXFILTER_UNKNOWN, 0}, }; GLenum TexFilterGLMapping(TexFilter tex_filter_mode) { int i = 0; while (TexFilterMappingArray[i].tex_filter_mode != TEXFILTER_UNKNOWN) { if (TexFilterMappingArray[i].tex_filter_mode == tex_filter_mode) { return TexFilterMappingArray[i].opengl_filter_mode; } ++i; } nuxAssertMsg(0, "[TexFilterGLMapping] Invalid texture filter mode."); return GL_REPEAT; } struct RopBlendMapping { RopBlend rop_blend_mode; unsigned int opengl_blend_op; }; struct RopBlendMapping RopBlendMappingArray [] = { {ROPBLEND_ZERO, GL_ZERO}, {ROPBLEND_ONE, GL_ONE}, {ROPBLEND_SRC_COLOR, GL_SRC_COLOR}, {ROPBLEND_ONE_MINUS_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR}, {ROPBLEND_DST_COLOR, GL_DST_COLOR}, {ROPBLEND_ONE_MINUS_DST_COLOR, GL_ONE_MINUS_DST_COLOR}, {ROPBLEND_SRC_ALPHA, GL_SRC_ALPHA}, {ROPBLEND_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA}, {ROPBLEND_DST_ALPHA, GL_DST_ALPHA}, {ROPBLEND_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA}, {ROPBLEND_CONSTANT_COLOR, GL_CONSTANT_COLOR}, {ROPBLEND_ONE_MINUS_CONSTANT_COLOR, GL_ONE_MINUS_CONSTANT_COLOR}, {ROPBLEND_CONSTANT_ALPHA, GL_CONSTANT_ALPHA}, {ROPBLEND_ONE_MINUS_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA}, {ROPBLEND_SRC_ALPHA_SATURATE, GL_SRC_ALPHA_SATURATE}, {ROPBLEND_UNKNOWN, 0}, }; GLenum RopBlendGLMapping(RopBlend rop_blend_mode) { int i = 0; while (RopBlendMappingArray[i].rop_blend_mode != ROPBLEND_UNKNOWN) { if (RopBlendMappingArray[i].rop_blend_mode == rop_blend_mode) { return RopBlendMappingArray[i].opengl_blend_op; } ++i; } nuxAssertMsg(0, "[RopBlendGLMapping] Invalid texture ROP operation."); return ROPBLEND_ONE; } TexCoordXForm::TexCoordXForm() { u0 = v0 = u1 = v1 = 0.0f; uscale = 1.0f; vscale = 1.0f; uoffset = 0.0f; voffset = 0.0f; flip_u_coord = false; flip_v_coord = false; uwrap = TEXWRAP_CLAMP; vwrap = TEXWRAP_CLAMP; min_filter = TEXFILTER_NEAREST; mag_filter = TEXFILTER_NEAREST; m_tex_coord_type = TexCoordXForm::OFFSET_SCALE_COORD; } void TexCoordXForm::FlipUCoord(bool b) { flip_u_coord = b; } void TexCoordXForm::FlipVCoord(bool b) { flip_v_coord = b; } void TexCoordXForm::FlipUVCoord(bool flip_u, bool flip_v) { flip_u_coord = flip_u; flip_v_coord = flip_v; } void TexCoordXForm::SetFilter(TexFilter minfitter, TexFilter magfilter) { min_filter = minfitter; mag_filter = magfilter; } void TexCoordXForm::SetWrap(TexWrap u_wrap, TexWrap v_wrap) { uwrap = u_wrap; vwrap = v_wrap; } void TexCoordXForm::SetTexCoordType(TexCoordType tex_coord_type) { m_tex_coord_type = tex_coord_type; } void QRP_Compute_Texture_Coord(int quad_width, int quad_height, ObjectPtr tex, TexCoordXForm &texxform) { float tex_width = tex->GetWidth(); float tex_height = tex->GetHeight(); if (tex->Type().IsDerivedFromType(IOpenGLTexture2D::StaticObjectType)) { if (texxform.m_tex_coord_type == TexCoordXForm::OFFSET_SCALE_COORD) { // Scale and offset the texture coordinates. // With a scale of 1.0 for both uscale and vscale, the texture is scaled over the entire surface of the quad. // If the texture and the quad have the same size, then the texture is mapped 1 to 1 with the pixels of the quad. texxform.u0 = texxform.uoffset; texxform.v0 = texxform.voffset; texxform.u1 = texxform.uoffset + texxform.uscale * (tex_width / (float)quad_width) * quad_width / tex_width; texxform.v1 = texxform.voffset + texxform.vscale * (tex_height / (float)quad_height) * quad_height / tex_height; } else if (texxform.m_tex_coord_type == TexCoordXForm::OFFSET_COORD) { // Offset the texture coordinates but preserve the proportion of the of the texture over the quad. // If the texture size is smaller than the quad, it will be tiled over it. texxform.u0 = texxform.uoffset; texxform.v0 = texxform.voffset; texxform.u1 = texxform.uoffset + quad_width / tex_width; texxform.v1 = texxform.voffset + quad_height / tex_height; } else if (texxform.m_tex_coord_type == TexCoordXForm::UNNORMALIZED_COORD) { texxform.u0 /= (float) tex_width; texxform.v0 /= (float) tex_height; texxform.u1 /= (float) tex_width; texxform.v1 /= (float) tex_height; } else if (texxform.m_tex_coord_type == TexCoordXForm::NORMALIZED_COORD || texxform.m_tex_coord_type == TexCoordXForm::FIXED_COORD) { // Use provided texture coordinates as is. } } else if (tex->Type().IsDerivedFromType(IOpenGLRectangleTexture::StaticObjectType)) { if (texxform.m_tex_coord_type == TexCoordXForm::OFFSET_SCALE_COORD) { texxform.u0 = int(texxform.uoffset * tex_width); texxform.v0 = int(texxform.voffset * tex_height); texxform.u1 = texxform.u0 + tex_width * texxform.uscale; texxform.v1 = texxform.v0 + tex_height * texxform.vscale; } else if (texxform.m_tex_coord_type == TexCoordXForm::OFFSET_COORD) { texxform.u0 = texxform.uoffset; texxform.v0 = texxform.voffset; texxform.u1 = texxform.u0 + quad_width; texxform.v1 = texxform.v0 + quad_height; } else if (texxform.m_tex_coord_type == TexCoordXForm::NORMALIZED_COORD) { texxform.u0 *= (float) tex_width; texxform.v0 *= (float) tex_height; texxform.u1 *= (float) tex_width; texxform.v1 *= (float) tex_height; } else if (texxform.m_tex_coord_type == TexCoordXForm::UNNORMALIZED_COORD || texxform.m_tex_coord_type == TexCoordXForm::FIXED_COORD) { // Use provided texture coordinates as is. } } if (texxform.flip_u_coord) { texxform.u0 = 1.0f - texxform.u0; texxform.u1 = 1.0f - texxform.u1; } if (texxform.flip_v_coord) { texxform.v0 = 1.0f - texxform.v0; texxform.v1 = 1.0f - texxform.v1; } if (tex->Type().IsDerivedFromType(IOpenGLRectangleTexture::StaticObjectType)) { // A chance to avoid some potential errors! Rectangle textures support only GL_CLAMP, GL_CLAMP_TO_EDGE, and GL_CLAMP_TO_BORDER. // See http://www.opengl.org/registry/specs/ARB/texture_rectangle.txt if (texxform.uwrap != TEXWRAP_CLAMP || texxform.uwrap != TEXWRAP_CLAMP_TO_EDGE || texxform.uwrap != TEXWRAP_CLAMP_TO_BORDER || texxform.vwrap != TEXWRAP_CLAMP || texxform.vwrap != TEXWRAP_CLAMP_TO_EDGE || texxform.vwrap != TEXWRAP_CLAMP_TO_BORDER) { texxform.uwrap = TEXWRAP_CLAMP; texxform.vwrap = TEXWRAP_CLAMP; } } #ifdef NUX_OPENGLES_20 // Enforce OpenGL ES 2.0 texture restrictions // 1. There is neither CLAMP nor CLAMP_TO_BORDER // 2. For NPOT textures, only CLAMP_TO_EDGE is supported // 3. For NPOT textures, only NEAREST and LINEAR are supported // // The last two constraints are relaxed by the GL_OES_texture_npot // extension which unfortunately is not supported by all implementations. // // Notes: we have mapped GL_CLAMP to GL_CLAMP_TO_EDGE in OpenGLMapping.h // so we also "support" TEXWRAP_CLAMP. if (texxform.uwrap == TEXWRAP_CLAMP_TO_BORDER || texxform.vwrap == TEXWRAP_CLAMP_TO_BORDER || (!tex->IsPowerOfTwo() && ((texxform.uwrap != TEXWRAP_CLAMP && texxform.uwrap != TEXWRAP_CLAMP_TO_EDGE) || (texxform.vwrap != TEXWRAP_CLAMP && texxform.vwrap != TEXWRAP_CLAMP_TO_EDGE)))) { texxform.uwrap = TEXWRAP_CLAMP_TO_EDGE; texxform.vwrap = TEXWRAP_CLAMP_TO_EDGE; } if (!tex->IsPowerOfTwo() && ((texxform.min_filter != TEXFILTER_NEAREST && texxform.min_filter != TEXFILTER_LINEAR) || (texxform.mag_filter != TEXFILTER_NEAREST && texxform.mag_filter != TEXFILTER_LINEAR))) { texxform.min_filter = TEXFILTER_LINEAR; texxform.mag_filter = TEXFILTER_LINEAR; } #endif tex->SetWrap(TexWrapGLMapping(texxform.uwrap), TexWrapGLMapping(texxform.vwrap), GL_CLAMP); tex->SetFiltering(TexFilterGLMapping(texxform.min_filter), TexFilterGLMapping(texxform.mag_filter)); } void GraphicsEngine::QRP_Color(int x, int y, int width, int height, const Color &color) { #ifndef NUX_OPENGLES_20 if (UsingGLSLCodePath()) QRP_GLSL_Color(x, y, width, height, color, color, color, color); else QRP_ASM_Color(x, y, width, height, color, color, color, color); #else QRP_GLSL_Color(x, y, width, height, color, color, color, color); #endif } void GraphicsEngine::QRP_Color(int x, int y, int width, int height, const Color &c0, const Color &c1, const Color &c2, const Color &c3) { #ifndef NUX_OPENGLES_20 if (UsingGLSLCodePath()) QRP_GLSL_Color(x, y, width, height, c0, c1, c2, c3); else QRP_ASM_Color(x, y, width, height, c0, c1, c2, c3); #else QRP_GLSL_Color(x, y, width, height, c0, c1, c2, c3); #endif } void GraphicsEngine::QRP_1Tex(int x, int y, int width, int height, ObjectPtr DeviceTexture, TexCoordXForm &texxform0, const Color &color0) { #ifndef NUX_OPENGLES_20 if (UsingGLSLCodePath()) QRP_GLSL_1Tex(x, y, width, height, DeviceTexture, texxform0, color0); else QRP_ASM_1Tex(x, y, width, height, DeviceTexture, texxform0, color0); #else QRP_GLSL_1Tex(x, y, width, height, DeviceTexture, texxform0, color0); #endif } void GraphicsEngine::QRP_1TexPremultiply(int x, int y, int width, int height, ObjectPtr DeviceTexture, TexCoordXForm &texxform0, const Color &color0) { #ifndef NUX_OPENGLES_20 if (UsingGLSLCodePath()) QRP_GLSL_1TexPremultiply(x, y, width, height, DeviceTexture, texxform0, color0); else QRP_ASM_1TexPremultiply(x, y, width, height, DeviceTexture, texxform0, color0); #else QRP_GLSL_1TexPremultiply(x, y, width, height, DeviceTexture, texxform0, color0); #endif } void GraphicsEngine::QRP_TexDesaturate(int x, int y, int width, int height, ObjectPtr DeviceTexture, TexCoordXForm& texxform0, const Color& color0, float desaturation_factor) { #ifndef NUX_OPENGLES_20 if (UsingGLSLCodePath()) QRP_GLSL_TexDesaturate(x, y, width, height, DeviceTexture, texxform0, color0, desaturation_factor); else { // Todo! //QRP_ASM_TexDesaturate(x, y, width, height, DeviceTexture, texxform0, color0, desaturation_factor); } #else QRP_GLSL_TexDesaturate(x, y, width, height, DeviceTexture, texxform0, color0, desaturation_factor); #endif } void GraphicsEngine::QRP_Pixelate(int x, int y, int width, int height, ObjectPtr DeviceTexture, TexCoordXForm &texxform, const Color &c0, int pixel_size) { #ifndef NUX_OPENGLES_20 if (UsingGLSLCodePath()) QRP_GLSL_Pixelate(x, y, width, height, DeviceTexture, texxform, c0, pixel_size); else QRP_ASM_Pixelate(x, y, width, height, DeviceTexture, texxform, c0, pixel_size); #else QRP_GLSL_Pixelate(x, y, width, height, DeviceTexture, texxform, c0, pixel_size); #endif } // Render the texture alpha into RGB and modulated by a color. void GraphicsEngine::QRP_ColorModTexAlpha(int x, int y, int width, int height, ObjectPtr< IOpenGLBaseTexture> DeviceTexture, TexCoordXForm &texxform, const Color &color) { #ifndef NUX_OPENGLES_20 if (UsingGLSLCodePath()) QRP_GLSL_ColorModTexAlpha(x, y, width, height, DeviceTexture, texxform, color); else QRP_ASM_ColorModTexAlpha(x, y, width, height, DeviceTexture, texxform, color); #else QRP_GLSL_ColorModTexAlpha(x, y, width, height, DeviceTexture, texxform, color); #endif } // Blend 2 textures together void GraphicsEngine::QRP_2Tex(int x, int y, int width, int height, ObjectPtr DeviceTexture0, TexCoordXForm &texxform0, const Color &color0, ObjectPtr DeviceTexture1, TexCoordXForm &texxform1, const Color &color1) { #ifndef NUX_OPENGLES_20 if (UsingGLSLCodePath()) QRP_GLSL_2Tex(x, y, width, height, DeviceTexture0, texxform0, color0, DeviceTexture1, texxform1, color1); else QRP_ASM_2Tex(x, y, width, height, DeviceTexture0, texxform0, color0, DeviceTexture1, texxform1, color1); #else QRP_GLSL_2Tex(x, y, width, height, DeviceTexture0, texxform0, color0, DeviceTexture1, texxform1, color1); #endif } void GraphicsEngine::QRP_2TexMod(int x, int y, int width, int height, ObjectPtr DeviceTexture0, TexCoordXForm &texxform0, const Color &color0, ObjectPtr DeviceTexture1, TexCoordXForm &texxform1, const Color &color1) { #ifndef NUX_OPENGLES_20 if (UsingGLSLCodePath()) QRP_GLSL_2TexMod(x, y, width, height, DeviceTexture0, texxform0, color0, DeviceTexture1, texxform1, color1); else QRP_ASM_2TexMod(x, y, width, height, DeviceTexture0, texxform0, color0, DeviceTexture1, texxform1, color1); #else QRP_GLSL_2TexMod(x, y, width, height, DeviceTexture0, texxform0, color0, DeviceTexture1, texxform1, color1); #endif } void GraphicsEngine::QRP_4Tex(int x, int y, int width, int height, ObjectPtr DeviceTexture0, TexCoordXForm &texxform0, const Color &color0, ObjectPtr DeviceTexture1, TexCoordXForm &texxform1, const Color &color1, ObjectPtr DeviceTexture2, TexCoordXForm &texxform2, const Color &color2, ObjectPtr DeviceTexture3, TexCoordXForm &texxform3, const Color &color3) { #ifndef NUX_OPENGLES_20 if (UsingGLSLCodePath()) QRP_GLSL_4Tex(x, y, width, height, DeviceTexture0, texxform0, color0, DeviceTexture1, texxform1, color1, DeviceTexture2, texxform2, color2, DeviceTexture3, texxform3, color3); else QRP_ASM_4Tex(x, y, width, height, DeviceTexture0, texxform0, color0, DeviceTexture1, texxform1, color1, DeviceTexture2, texxform2, color2, DeviceTexture3, texxform3, color3); #else QRP_GLSL_4Tex(x, y, width, height, DeviceTexture0, texxform0, color0, DeviceTexture1, texxform1, color1, DeviceTexture2, texxform2, color2, DeviceTexture3, texxform3, color3); #endif } void GraphicsEngine::QRP_Triangle(int x0, int y0, int x1, int y1, int x2, int y2, Color c0) { #ifndef NUX_OPENGLES_20 if (UsingGLSLCodePath()) QRP_GLSL_Triangle(x0, y0, x1, y1, x2, y2, c0, c0, c0); else QRP_ASM_Triangle(x0, y0, x1, y1, x2, y2, c0, c0, c0); #else QRP_GLSL_Triangle(x0, y0, x1, y1, x2, y2, c0, c0, c0); #endif } void GraphicsEngine::QRP_Triangle(int x0, int y0, int x1, int y1, int x2, int y2, Color c0, Color c1, Color c2) { #ifndef NUX_OPENGLES_20 if (UsingGLSLCodePath()) QRP_GLSL_Triangle(x0, y0, x1, y1, x2, y2, c0, c1, c2); else QRP_ASM_Triangle(x0, y0, x1, y1, x2, y2, c0, c1, c2); #else QRP_GLSL_Triangle(x0, y0, x1, y1, x2, y2, c0, c1, c2); #endif } void GraphicsEngine::QRP_Line(int x0, int y0, int x1, int y1, Color c0) { #ifndef NUX_OPENGLES_20 if (UsingGLSLCodePath()) QRP_GLSL_Line(x0, y0, x1, y1, c0, c0); else QRP_ASM_Line(x0, y0, x1, y1, c0, c0); #else QRP_GLSL_Line(x0, y0, x1, y1, c0, c0); #endif } void GraphicsEngine::QRP_Line(int x0, int y0, int x1, int y1, Color c0, Color c1) { #ifndef NUX_OPENGLES_20 if (UsingGLSLCodePath()) QRP_GLSL_Line(x0, y0, x1, y1, c0, c1); else QRP_ASM_Line(x0, y0, x1, y1, c0, c1); #else QRP_GLSL_Line(x0, y0, x1, y1, c0, c1); #endif } void GraphicsEngine::QRP_QuadWireframe(int x0, int y0, int width, int height, Color c0, Color c1, Color c2, Color c3) { #ifndef NUX_OPENGLES_20 if (UsingGLSLCodePath()) QRP_GLSL_QuadWireframe(x0, y0, width, height, c0, c1, c2, c3); else QRP_ASM_QuadWireframe(x0, y0, width, height, c0, c1, c2, c3); #else QRP_GLSL_QuadWireframe(x0, y0, width, height, c0, c1, c2, c3); #endif } ObjectPtr GraphicsEngine::QRP_GetBlurTexture( int x, int y, int buffer_width, int buffer_height, ObjectPtr device_texture, TexCoordXForm &texxform, const Color& c0, float sigma, int num_pass) { #ifndef NUX_OPENGLES_20 if (UsingGLSLCodePath()) return QRP_GLSL_GetBlurTexture(x, y, buffer_width, buffer_height, device_texture, texxform, c0, sigma, num_pass); else return QRP_ASM_GetBlurTexture(x, y, buffer_width, buffer_height, device_texture, texxform, c0, sigma, num_pass); #else return QRP_GLSL_GetBlurTexture(x, y, buffer_width, buffer_height, device_texture, texxform, c0, sigma, num_pass); #endif } ObjectPtr GraphicsEngine::QRP_GetAlphaTexture( ObjectPtr device_texture, TexCoordXForm &texxform, const Color& c0) { #ifndef NUX_OPENGLES_20 if (UsingGLSLCodePath()) return QRP_GLSL_GetAlphaTexture(device_texture, texxform, c0); else return QRP_ASM_GetAlphaTexture(device_texture, texxform, c0); #else return QRP_GLSL_GetAlphaTexture(device_texture, texxform, c0); #endif } ObjectPtr GraphicsEngine::QRP_GetColorMatrixTexture( ObjectPtr device_texture, TexCoordXForm &texxform, const Color& c0, Matrix4 color_matrix, Vector4 offset) { #ifndef NUX_OPENGLES_20 if (UsingGLSLCodePath()) return QRP_GLSL_GetColorMatrixTexture(device_texture, texxform, c0, color_matrix, offset); else return QRP_ASM_GetColorMatrixTexture(device_texture, texxform, c0, color_matrix, offset); #else return QRP_GLSL_GetColorMatrixTexture(device_texture, texxform, c0, color_matrix, offset); #endif } ObjectPtr GraphicsEngine::QRP_GetPower( ObjectPtr device_texture, TexCoordXForm &texxform, const Color& c0, const Vector4 &exponent) { #ifndef NUX_OPENGLES_20 if (UsingGLSLCodePath()) return QRP_GLSL_GetPower(device_texture, texxform, c0, exponent); else return QRP_ASM_GetPower(device_texture, texxform, c0, exponent); #else return QRP_GLSL_GetPower(device_texture, texxform, c0, exponent); #endif } ObjectPtr GraphicsEngine::QRP_GetLQBlur( int x, int y, int buffer_width, int buffer_height, ObjectPtr device_texture, TexCoordXForm &texxform, const Color& c0) { #ifndef NUX_OPENGLES_20 if (UsingGLSLCodePath()) return QRP_GLSL_GetLQBlur(x, y, buffer_width, buffer_height, device_texture, texxform, c0); else return QRP_ASM_GetLQBlur(x, y, buffer_width, buffer_height, device_texture, texxform, c0); #else return QRP_GLSL_GetLQBlur(x, y, buffer_width, buffer_height, device_texture, texxform, c0); #endif } ObjectPtr GraphicsEngine::QRP_GetHQBlur( int x, int y, int buffer_width, int buffer_height, ObjectPtr device_texture, TexCoordXForm &texxform, const Color& c0, float sigma, int num_pass) { #ifndef NUX_OPENGLES_20 if (UsingGLSLCodePath() && (_graphics_display.GetGpuDevice()->GetOpenGLMajorVersion() >= 2)) return QRP_GLSL_GetHQBlur(x, y, buffer_width, buffer_height, device_texture, texxform, c0, sigma, num_pass); else return QRP_ASM_GetBlurTexture(x, y, buffer_width, buffer_height, device_texture, texxform, c0, sigma, num_pass); #else return QRP_GLSL_GetBlurTexture(x, y, buffer_width, buffer_height, device_texture, texxform, c0, sigma, num_pass); #endif } void GraphicsEngine::QRP_DisturbedTexture( int x, int y, int width, int height, ObjectPtr distorsion_texture, TexCoordXForm &texxform0, const Color& c0, ObjectPtr src_device_texture, TexCoordXForm &texxform1, const Color& c1) { #ifndef NUX_OPENGLES_20 if (UsingGLSLCodePath()) QRP_GLSL_DisturbedTexture(x, y, width, height, distorsion_texture, texxform0, c0, src_device_texture, texxform1, c1); else { // NUXTODO //QRP_ASM_DisturbedTexture(x, y, width, height, distorsion_texture, texxform0, c0, src_device_texture, texxform1, c1); } #else QRP_GLSL_DisturbedTexture(x, y, width, height, distorsion_texture, texxform0, c0, src_device_texture, texxform1, c1); #endif } ObjectPtr GraphicsEngine::QRP_GetPixelBlocks( ObjectPtr device_texture, TexCoordXForm &texxform, const Color& color, int pixel_size) { #ifndef NUX_OPENGLES_20 if (UsingGLSLCodePath() && (_graphics_display.GetGpuDevice()->GetOpenGLMajorVersion() >= 2)) return QRP_GLSL_GetPixelBlocks(device_texture, texxform, color, pixel_size); else return QRP_ASM_GetPixelBlocks(device_texture, texxform, color, pixel_size); #else return QRP_GLSL_GetPixelBlocks(device_texture, texxform, color, pixel_size); #endif } void GraphicsEngine::QRP_GetCopyTexture( int width, int height, ObjectPtr& dst_device_texture, ObjectPtr& src_device_texture, TexCoordXForm &texxform0, const Color& c0) { #ifndef NUX_OPENGLES_20 if (UsingGLSLCodePath() && (_graphics_display.GetGpuDevice()->GetOpenGLMajorVersion() >= 2)) return QRP_GLSL_GetCopyTexture(width, height, dst_device_texture, src_device_texture, texxform0, c0); else return QRP_ASM_GetCopyTexture(width, height, dst_device_texture, src_device_texture, texxform0, c0); #else return QRP_GLSL_GetCopyTexture(width, height, dst_device_texture, src_device_texture, texxform0, c0); #endif } } ./NuxGraphics/IOpenGLBaseTexture.cpp0000644000004100000410000003533013313171755017625 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "NuxCore/NuxCore.h" #include "GLResource.h" #include "IOpenGLResource.h" #include "GLShaderParameter.h" #include "GLTextureStates.h" #include "IOpenGLBaseTexture.h" #include "IOpenGLSurface.h" namespace nux { NUX_IMPLEMENT_OBJECT_TYPE(IOpenGLBaseTexture); IOpenGLBaseTexture::IOpenGLBaseTexture(OpenGLResourceType ResourceType, unsigned int Width, unsigned int Height, unsigned int Depth, unsigned int NumMipLevel, BitmapFormat PixelFormat, NUX_FILE_LINE_DECL) : IOpenGLResource(ResourceType, NUX_FILE_LINE_PARAM) , _IsPOT(false) , _NumMipLevel(NumMipLevel) , _PixelFormat(PixelFormat) , _Width(Width) , _Height(Height) , _Depth(Depth) , _RowMemoryAlignment(1) { // if ((GPixelFormats[PixelFormat].BlockBytes == 1) || // (GPixelFormats[PixelFormat].BlockBytes == 2) || // (GPixelFormats[PixelFormat].BlockBytes == 3)) // _RowMemoryAlignment = 1; // else // _RowMemoryAlignment = 4; if (_ResourceType == RTTEXTURE) _TextureStates.SetType(GL_TEXTURE_2D); #ifndef NUX_OPENGLES_20 if (_ResourceType == RTTEXTURERECTANGLE) _TextureStates.SetType(GL_TEXTURE_RECTANGLE_ARB); if (_ResourceType == RTCUBETEXTURE) _TextureStates.SetType(GL_TEXTURE_CUBE_MAP_ARB); if (_ResourceType == RTVOLUMETEXTURE) _TextureStates.SetType(GL_TEXTURE_3D); if (_ResourceType == RTANIMATEDTEXTURE) _TextureStates.SetType(GL_TEXTURE_RECTANGLE_ARB); #endif _RowMemoryAlignment = ImageSurface::GetMemAlignment(PixelFormat); if (IsPowerOf2(Width) && IsPowerOf2(Height)) { _IsPOT = true; } } IOpenGLBaseTexture::~IOpenGLBaseTexture() { } void IOpenGLBaseTexture::SetRenderStates() { if (_ResourceType == RTTEXTURE) { CHECKGL(glBindTexture(GL_TEXTURE_2D, _OpenGLID)); } #ifndef NUX_OPENGLES_20 else if (_ResourceType == RTTEXTURERECTANGLE) { CHECKGL(glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _OpenGLID)); } else if (_ResourceType == RTCUBETEXTURE) { CHECKGL(glBindTexture(GL_TEXTURE_CUBE_MAP, _OpenGLID)); } else if (_ResourceType == RTVOLUMETEXTURE) { CHECKGL(glBindTexture(GL_TEXTURE_3D, _OpenGLID)); } else if (_ResourceType == RTANIMATEDTEXTURE) { CHECKGL(glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _OpenGLID)); } #endif else { nuxError("[IOpenGLBaseTexture::SetRenderStates] Incorrect texture resource type."); } _TextureStates.SetRenderStates(); } void IOpenGLBaseTexture::SetFiltering(unsigned int MinFilter, unsigned int MagFilter/*, unsigned int MIP = GL_NEAREST*/) { _TextureStates.SetFiltering(MinFilter, MagFilter); } void IOpenGLBaseTexture::SetWrap(unsigned int U, unsigned int V, unsigned int W) { _TextureStates.SetWrap(U, V, W); } void IOpenGLBaseTexture::SetLOD(float MinLod, float MaxLod) { _TextureStates.SetLOD(MinLod, MaxLod); } void IOpenGLBaseTexture::SetMipLevel(unsigned int MinMip, unsigned int MaxMip) { _TextureStates.SetMipLevel(MinMip, MaxMip); } void IOpenGLBaseTexture::SetBorderColor(float R, float G, float B, float A) { _TextureStates.SetBorderColor(R, G, B, A); } int IOpenGLBaseTexture::BindTexture() { if (_OpenGLID == 0) { CHECKGL(glBindTexture(GL_TEXTURE_2D, 0)); } else if (_ResourceType == RTTEXTURE) { CHECKGL(glBindTexture(GL_TEXTURE_2D, _OpenGLID)); } #ifndef NUX_OPENGLES_20 else if (_ResourceType == RTTEXTURERECTANGLE) { CHECKGL(glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _OpenGLID)); } else if (_ResourceType == RTCUBETEXTURE) { CHECKGL(glBindTexture(GL_TEXTURE_CUBE_MAP, _OpenGLID)); } else if (_ResourceType == RTVOLUMETEXTURE) { CHECKGL(glBindTexture(GL_TEXTURE_3D, _OpenGLID)); } else if (_ResourceType == RTANIMATEDTEXTURE) { CHECKGL(glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _OpenGLID)); } #endif else { nuxError("[GpuDevice::BindTexture] Unknown texture type."); return OGL_INVALID_TEXTURE; } _TextureStates.SetRenderStates(); return OGL_OK; } int IOpenGLBaseTexture::BindTextureToUnit(int TextureUnitIndex) { CHECKGL(glActiveTextureARB(TextureUnitIndex)); CHECKGL(glBindTexture(GL_TEXTURE_2D, 0)); #ifndef NUX_OPENGLES_20 CHECKGL(glBindTexture(GL_TEXTURE_3D, 0)); CHECKGL(glBindTexture(GL_TEXTURE_CUBE_MAP, 0)); CHECKGL(glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0)); CHECKGL(glDisable(GL_TEXTURE_2D)); CHECKGL(glDisable(GL_TEXTURE_3D)); CHECKGL(glDisable(GL_TEXTURE_RECTANGLE_ARB)); CHECKGL(glDisable(GL_TEXTURE_CUBE_MAP)); #endif if (_ResourceType == RTTEXTURE) { CHECKGL(glBindTexture(GL_TEXTURE_2D, _OpenGLID)); #ifndef NUX_OPENGLES_20 CHECKGL(glEnable(GL_TEXTURE_2D)); #endif } #ifndef NUX_OPENGLES_20 else if (_ResourceType == RTTEXTURERECTANGLE) { CHECKGL(glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _OpenGLID)); CHECKGL(glEnable(GL_TEXTURE_RECTANGLE_ARB)); } else if (_ResourceType == RTCUBETEXTURE) { CHECKGL(glBindTexture(GL_TEXTURE_CUBE_MAP, _OpenGLID)); CHECKGL(glEnable(GL_TEXTURE_CUBE_MAP)); } else if (_ResourceType == RTVOLUMETEXTURE) { CHECKGL(glBindTexture(GL_TEXTURE_3D, _OpenGLID)); CHECKGL(glEnable(GL_TEXTURE_3D)); } else if (_ResourceType == RTANIMATEDTEXTURE) { CHECKGL(glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _OpenGLID)); CHECKGL(glEnable(GL_TEXTURE_RECTANGLE_ARB)); } #endif else { nuxError("[IOpenGLBaseTexture::BindTexture] unknown texture type."); return OGL_ERROR; } _TextureStates.SetRenderStates(); return OGL_OK; } void IOpenGLBaseTexture::GetSurfaceLevel(int /* Level */, ObjectPtr& /* surface */) { } ObjectPtr IOpenGLBaseTexture::GetSurfaceLevel(int /* Level */) { return ObjectPtr (0); } int IOpenGLBaseTexture::LockRect(int /* Level */, SURFACE_LOCKED_RECT * /* pLockedRect */, const SURFACE_RECT * /* pRect */) { return 0; } int IOpenGLBaseTexture::UnlockRect(int /* Level */) { return 0; } unsigned char* IOpenGLBaseTexture::GetSurfaceData(int /* level */, int &width, int &height, int &stride) { // Make this call a pure virtual once it has been implemented for IOpenGLCubeTexture, // IOpenGLVolumeTexture and IOpenGLAnimatedTexture. width = 0; height = 0; stride = 0; return 0; } void IOpenGLBaseTexture::Save(const char* filename) { GLuint tex_id = GetOpenGLID(); glBindTexture(GL_TEXTURE_2D, tex_id); int width, height; #ifndef NUX_OPENGLES_20 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width); glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height); #else width = GetWidth(); height = GetHeight(); #endif if(!width || !height) return; uint32_t* pixels = new uint32_t[width * height]; uint32_t* tmp = pixels; #ifndef NUX_OPENGLES_20 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); #else GLuint fbo; glGenFramebuffers(1, &fbo); glBindFramebuffer(GL_FRAMEBUFFER, fbo); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex_id, 0); glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); glBindFramebuffer(GL_FRAMEBUFFER, 0); glDeleteFramebuffers(1, &fbo); #endif FILE* fp; if(!(fp = fopen(filename, "wb"))) { fprintf(stderr, "Cannot open file: %s\n", filename); return; } fprintf(fp, "P6\n%d %d\n255\n", width, height); int sz = width * height; for(int i=0; i> 16) & 0xff; int g = (pix >> 8) & 0xff; int b = pix & 0xff; fputc(r, fp); fputc(g, fp); fputc(b, fp); } fclose(fp); delete [] pixels; } int GetTextureSize(IOpenGLBaseTexture *pTexture) { GLint unpack_alignment = GPixelFormats[pTexture->_PixelFormat].RowMemoryAlignment; unsigned int halfUnpack = Log2(unpack_alignment); unsigned int TextureSize = 0; if ( pTexture->_PixelFormat == BITFMT_DXT1 || pTexture->_PixelFormat == BITFMT_DXT2 || pTexture->_PixelFormat == BITFMT_DXT3 || pTexture->_PixelFormat == BITFMT_DXT4 || pTexture->_PixelFormat == BITFMT_DXT5) { for (int Level = 0; Level < pTexture->GetNumMipLevel(); Level++) { unsigned int Width = Max (1, pTexture->_Width >> Level); unsigned int Height = Max (1, pTexture->_Height >> Level); unsigned int WidthInBlocks = Max ((Width + 3) / 4, 1); // round the width to the upper multiple of 4. DXT blocks are 4x4 texels. unsigned int HeightInBlocks = Max ((Height + 3) / 4, 1); // round the height to the upper multiple of 4. DXT blocks are 4x4 texels. if (pTexture->_PixelFormat == BITFMT_DXT1) { TextureSize += WidthInBlocks * HeightInBlocks * 8;; } else { TextureSize += WidthInBlocks * HeightInBlocks * 16; } } } else { for (int Level = 0; Level < pTexture->GetNumMipLevel(); Level++) { unsigned int Width = Max (1, pTexture->_Width >> Level); unsigned int Height = Max (1, pTexture->_Height >> Level); unsigned int BytePerPixel = GPixelFormats[pTexture->_PixelFormat].BlockBytes; unsigned int SlicePitch = (((Width * BytePerPixel + (unpack_alignment - 1)) >> (halfUnpack)) << (halfUnpack)) * Height; TextureSize += SlicePitch; } } if (pTexture->GetResourceType() == RTANIMATEDTEXTURE) { return TextureSize * pTexture->GetDepth(); } return TextureSize; } void GetTextureDesc(IOpenGLBaseTexture *pTexture, unsigned int Level, TEXTURE_DESC *pDesc) { GLint unpack_alignment = GPixelFormats[pTexture->_PixelFormat].RowMemoryAlignment; unsigned int halfUnpack = Log2(unpack_alignment); pDesc->PixelFormat = pTexture->_PixelFormat; if ( /*pTexture->_Format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||*/ pTexture->_PixelFormat == BITFMT_DXT1 || pTexture->_PixelFormat == BITFMT_DXT2 || pTexture->_PixelFormat == BITFMT_DXT3 || pTexture->_PixelFormat == BITFMT_DXT4 || pTexture->_PixelFormat == BITFMT_DXT5) { pDesc->Width = Max (1, pTexture->_Width >> Level); pDesc->Height = Max (1, pTexture->_Height >> Level); pDesc->WidthInBlocks = Max ((pDesc->Width + 3) / 4, 1); // round the width to the upper multiple of 4. DXT blocks are 4x4 texels. pDesc->HeightInBlocks = Max ((pDesc->Height + 3) / 4, 1); // round the height to the upper multiple of 4. DXT blocks are 4x4 texels. if ( /*pTexture->_Format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||*/ pTexture->_PixelFormat == BITFMT_DXT1) { // We can conceive a 4x4 DXT1 block as if each texel uses 4 bits. // Actually, for DXT, we have 2 16-bits colors(5:6:5), and each texel uses 2 bits to interpolate // between the 2 colors. // --------------------- // | COLOR0 | 16 bits // --------------------- // | COLOR1 | 16 bits // --------------------- // | xx | xx | xx | xx | xx = 2 bits // --------------------- // | xx | xx | xx | xx | // --------------------- // | xx | xx | xx | xx | // --------------------- // | xx | xx | xx | xx | // --------------------- // A line of n texel DXT1 data uses n/2 bytes(4 bits/texel). So the number of bytes used for a // texwidth texel, is texwidth/2 bytes. // Note that texwidth is divisible by 4(to to the upper rounding to 4), therefore, it is also divisible // by 2. // glCompressedTexImage2DARB, glCompressedTexImage3DARB, // glCompressedTexSubImage2DARB, glCompressedTexSubImage3DARB are not affected by glPixelStorei. pDesc->RowPitch = pDesc->WidthInBlocks * 8; pDesc->SlicePitch = pDesc->WidthInBlocks * pDesc->HeightInBlocks * 8; pDesc->BitsPerPixel = 0; // compressed pDesc->BytesPerBlock = 8; } else { // A line of n texel DXT3/5 data uses n bytes(1 byte/texel). So the number of bytes used for a // texwidth texels, is texwidth bytes. // glCompressedTexImage2DARB, glCompressedTexImage3DARB, // glCompressedTexSubImage2DARB, glCompressedTexSubImage3DARB are not affected by glPixelStorei. pDesc->RowPitch = pDesc->WidthInBlocks * 16; pDesc->SlicePitch = pDesc->WidthInBlocks * pDesc->HeightInBlocks * 16; pDesc->BitsPerPixel = 0; // compressed pDesc->BytesPerBlock = 16; } } else { pDesc->Width = Max (1, pTexture->_Width >> Level); pDesc->Height = Max (1, pTexture->_Height >> Level); pDesc->WidthInBlocks = pDesc->Width; pDesc->HeightInBlocks = pDesc->Height; unsigned int BytePerPixel = GPixelFormats[pTexture->_PixelFormat].BlockBytes; pDesc->BitsPerPixel = BytePerPixel * 8; pDesc->BytesPerBlock = BytePerPixel; // a block is a 1x1 pixel ie. 1 pixel. pDesc->RowPitch = (((pDesc->Width * BytePerPixel + (unpack_alignment - 1)) >> (halfUnpack)) << (halfUnpack)); pDesc->SlicePitch = (((pDesc->Width * BytePerPixel + (unpack_alignment - 1)) >> (halfUnpack)) << (halfUnpack)) * pDesc->Height; } } } ./NuxGraphics/BitmapFormats.cpp0000644000004100000410000002111313313171755016756 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "NuxCore/NuxCore.h" #include "BitmapFormats.h" namespace nux { PixelFormatInfo GPixelFormats[] = { // Name BlockSizeX BlockSizeY BlockSizeZ BlockBytes NumComponents Platform Internal Memory Flags Supported // Format Format Alignment { "BITFMT_UNKNOWN", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false }, // BITFMT_Unknown { "BITFMT_R8G8B8A8", 1, 1, 1, 4, 4, 0, 0, 0, 4, 0, true }, // BITFMT_R8G8B8A8 { "BITFMT_B8G8R8A8", 1, 1, 1, 4, 4, 0, 0, 0, 4, 0, true }, // BITFMT_B8G8R8A8 { "BITFMT_R8G8B8", 1, 1, 1, 3, 3, 0, 0, 0, 1, 0, true }, // BITFMT_R8G8B8 { "BITFMT_R5G6B5", 1, 1, 1, 2, 3, 0, 0, 0, 1, 0, true }, // BITFMT_R5G6B5 { "BITFMT_D24S8", 1, 1, 1, 4, 2, 0, 0, 0, 1, 0, true }, // BITFMT_D24S8 { "BITFMT_A8", 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, true }, // BITFMT_A8 { "BITFMT_DXT1", 4, 4, 1, 8, 3, 0, 0, 0, 1, 0, true }, // BITFMT_DXT1 { "BITFMT_DXT2", 4, 4, 1, 16, 4, 0, 0, 0, 1, 0, true }, // BITFMT_DXT2 { "BITFMT_DXT3", 4, 4, 1, 16, 4, 0, 0, 0, 1, 0, true }, // BITFMT_DXT3 { "BITFMT_DXT4", 4, 4, 1, 16, 4, 0, 0, 0, 1, 0, true }, // BITFMT_DXT4 { "BITFMT_DXT5", 4, 4, 1, 16, 4, 0, 0, 0, 1, 0, true }, // BITFMT_DXT5 #ifndef NUX_OPENGLES_20 { "BITFMT_A8R8G8B8", 1, 1, 1, 4, 4, 0, 0, 0, 4, 0, true }, // BITFMT_A8R8G8B8 { "BITFMT_A8B8G8R8", 1, 1, 1, 4, 4, 0, 0, 0, 4, 0, true }, // BITFMT_A8B8G8R8 { "BITFMT_B8G8R8", 1, 1, 1, 3, 3, 0, 0, 0, 1, 0, true }, // BITFMT_B8G8R8 { "BITFMT_RGBA16F", 1, 1, 1, 8, 4, 0, 0, 0, 1, 0, true }, // BITFMT_RGBA16F { "BITFMT_RGB32F", 1, 1, 1, 12, 3, 0, 0, 0, 1, 0, true }, // BITFMT_RGB32F { "BITFMT_RGBA32F", 1, 1, 1, 16, 4, 0, 0, 0, 1, 0, true }, // BITFMT_RGBA32F { "BITFMT_R10G10B10A2", 1, 1, 1, 4, 4, 0, 0, 0, 4, 0, true }, // BITFMT_R10G10B10A2 { "BITFMT_B10G10R10A2", 1, 1, 1, 4, 4, 0, 0, 0, 4, 0, true }, // BITFMT_B10G10R10A2 { "BITFMT_A2R10G10B10", 1, 1, 1, 4, 4, 0, 0, 0, 4, 0, true }, // BITFMT_A2R10G10B10 { "BITFMT_A2B10G10R10", 1, 1, 1, 4, 4, 0, 0, 0, 4, 0, true }, // BITFMT_A2B10G10R10 #endif { "BITFMT_END_GFX_FORMATS", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false }, // BITFMT_END_GFX_FORMATS }; ReadBackPixelFormatInfo GReadBackPixelFormats[] = { // Name BlockBytes NumComponents Format Type Flags Supported { "BITFMT_UNKNOWN", 0, 0, 0, 0, 0, false }, // BITFMT_Unknown { "BITFMT_R8G8B8A8", 4, 4, 0, 0, 0, true }, // BITFMT_R8G8B8A8 { "BITFMT_B8G8R8A8", 4, 4, 0, 0, 0, true }, // BITFMT_B8G8R8A8 { "BITFMT_R8G8B8", 3, 3, 0, 0, 0, true }, // BITFMT_R8G8B8 { "BITFMT_R5G6B5", 2, 3, 0, 0, 0, true }, // BITFMT_R5G6B5 { "BITFMT_D24S8", 4, 2, 0, 0, 0, true }, // BITFMT_D24S8 { "BITFMT_A8", 1, 1, 0, 0, 0, true }, // BITFMT_A8 { "BITFMT_DXT1", 8, 3, 0, 0, 0, true }, // BITFMT_DXT1 { "BITFMT_DXT2", 16, 4, 0, 0, 0, true }, // BITFMT_DXT2 { "BITFMT_DXT3", 16, 4, 0, 0, 0, true }, // BITFMT_DXT3 { "BITFMT_DXT4", 16, 4, 0, 0, 0, true }, // BITFMT_DXT4 { "BITFMT_DXT5", 16, 4, 0, 0, 0, true }, // BITFMT_DXT5 #ifndef NUX_OPENGLES_20 { "BITFMT_A8R8G8B8", 4, 4, 0, 0, 0, true }, // BITFMT_A8R8G8B8 { "BITFMT_A8B8G8R8", 4, 4, 0, 0, 0, true }, // BITFMT_A8B8G8R8 { "BITFMT_B8G8R8", 3, 3, 0, 0, 0, true }, // BITFMT_B8G8R8 { "BITFMT_RGBA16F", 8, 4, 0, 0, 0, true }, // BITFMT_RGBA16F { "BITFMT_RGB32F", 12, 3, 0, 0, 0, true }, // BITFMT_RGBA32F { "BITFMT_RGBA32F", 16, 4, 0, 0, 0, true }, // BITFMT_RGBA32F { "BITFMT_R10G10B10A2", 4, 4, 0, 0, 0, true }, // BITFMT_R10G10B10A2 { "BITFMT_B10G10R10A2", 4, 4, 0, 0, 0, true }, // BITFMT_B10G10R10A2 { "BITFMT_A2B10G10R10", 4, 4, 0, 0, 0, true }, // BITFMT_A2B10G10R10 { "BITFMT_A2R10G10B10", 4, 4, 0, 0, 0, true }, // BITFMT_A2R10G10B10 #endif { "BITFMT_END_GFX_FORMATS", 0, 0, 0, 0, 0, false }, // BITFMT_END_GFX_FORMATS }; } ./NuxGraphics/GLSh_Fill.h0000644000004100000410000000315113313171755015420 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef GLSH_FILL_H #define GLSH_FILL_H #include "IOpenGLGLSLShader.h" #include "GLShaderParameter.h" #include "GLDeviceObjects.h" namespace nux { class TemplateQuadBuffer; class GLSh_Fill { public: GLShaderParameter *Color; GLShaderParameter *ViewProjectionMatrix; GLShaderParameter *Scale; GLShaderParameter *Offset; GLSh_Fill(); ~GLSh_Fill(); void CacheShader(); void SetColor(FLOAT R, FLOAT G, FLOAT B, FLOAT A); void Render(INT x, INT y, INT z, INT width, INT height); void SetTransformMatrix(const Matrix4 &TransformMatrix); private: FLOAT _R, _G, _B, _A; ObjectPtr vs; ObjectPtr ps; ObjectPtr sprog; Matrix4 m_TransformMatrix; TemplateQuadBuffer *m_QuadBuffer; }; } #endif // GLSH_FILL_H ./NuxGraphics/IOpenGLIndexBuffer.h0000644000004100000410000000342413313171755017237 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef IOPENGLINDEXBUFFER_H #define IOPENGLINDEXBUFFER_H namespace nux { class IOpenGLResource; class IOpenGLIndexBuffer: public IOpenGLResource { NUX_DECLARE_OBJECT_TYPE(IOpenGLIndexBuffer, IOpenGLResource); public: virtual ~IOpenGLIndexBuffer(); int Lock( unsigned int OffsetToLock, unsigned int SizeToLock, void **ppbData); int Unlock(); int GetStride(); int GetDescription(INDEXBUFFER_DESC *desc) const { desc->Format = _Format; desc->Usage = _Usage; desc->Size = _Length; return OGL_OK; } void BindIndexBuffer(); unsigned int GetSize(); private: IOpenGLIndexBuffer(unsigned int Length, VBO_USAGE Usage, INDEX_FORMAT Format, NUX_FILE_LINE_PROTO); unsigned int _Length; INDEX_FORMAT _Format; VBO_USAGE _Usage; BYTE *_MemMap; unsigned int _OffsetToLock; unsigned int _SizeToLock; friend class GpuDevice; }; } #endif // IOPENGLINDEXBUFFER_H ./NuxGraphics/ImageSurface.cpp0000644000004100000410000012040413313171755016544 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "NuxCore/NuxCore.h" #include "NuxCore/Logger.h" #include "NuxCore/Math/MathFunctions.h" #include "BitmapFormats.h" #include "GdkGraphics.h" #if defined(NUX_OS_WINDOWS) #include "GdiImageLoader.h" #endif #include "ImageSurface.h" namespace nux { DECLARE_LOGGER(logger, "nux.image"); extern PixelFormatInfo GPixelFormats[]; NBitmapData *LoadGdkPixbuf(GdkPixbuf *pixbuf) { NUX_RETURN_VALUE_IF_NULL(pixbuf, nullptr); unsigned int width = gdk_pixbuf_get_width(pixbuf); unsigned int height = gdk_pixbuf_get_height(pixbuf); unsigned int row_bytes = gdk_pixbuf_get_rowstride(pixbuf); NTextureData *Texture = new NTextureData(BITFMT_R8G8B8A8, width, height, 1); guchar *img = gdk_pixbuf_get_pixels(pixbuf); auto& surface = Texture->GetSurface(0); for (unsigned int i = 0; i < width; ++i) { for (unsigned int j = 0; j < height; ++j) { guchar *pixels = img + ( j * row_bytes + i * 4); UINT value = (* (pixels + 3) << 24) | // a (* (pixels + 2) << 16) | // b (* (pixels + 1) << 8) | // g * (pixels + 0); // r surface.Write32b(i, j, value); } } return Texture; } NBitmapData *LoadImageFile(const TCHAR *filename) { if (!GFileManager.FileExist(filename)) { nuxAssertMsg(0, "[LoadImageFile] Can't find file: %s", filename); return 0; } NBitmapData *BitmapData = 0; #if defined(NUX_OS_WINDOWS) BitmapData = GdiLoadImageFile(filename); if (BitmapData) return BitmapData; #elif defined(NUX_OS_LINUX) GdkGraphics gdkgraphics; gdkgraphics.LoadImage(filename); BitmapData = gdkgraphics.GetBitmap(); if (BitmapData) return BitmapData; #endif // Unsupported format LOG_DEBUG(logger) << "Unknown file format: " << filename; return 0; } bool HasOpenEXRSupport() { #ifdef NUX_OPENEXR_SUPPORT return true; #else return false; #endif } void MakeCheckBoardImage(ImageSurface &Image, int width, int height, Color const& dark, Color const& light, int TileWidth, int TileHeight) { Image.Allocate(BITFMT_R8G8B8A8, width, height); if (TileWidth <= 0) TileWidth = 4; if (TileHeight <= 0) TileHeight = 4; for (int j = 0; j < height; ++j) { for (int i = 0; i < width; ++i) { /*every 8 bits, change color from black to white or vice versa */ bool even_column = ((i / TileWidth) % 2) == 0; bool even_row = ((j / TileHeight ) % 2) == 0; bool is_dark = even_column ^ even_row; Color const& c = is_dark ? dark : light; Image.Write(i, j, c.red * 255, c.green * 255, c.blue * 255, c.alpha * 255); } } Image.FlipVertical(); } NBitmapData::NBitmapData() : m_TotalMemorySize(0) { } NBitmapData::~NBitmapData() { } ImageSurface::ImageSurface() : width_(0) , height_(0) , format_(BITFMT_UNKNOWN) , m_Pitch(0) , bpe_(0) , Alignment_(4) { Allocate(format_, width_, height_); } ImageSurface::ImageSurface(BitmapFormat format, unsigned int width, unsigned int height) : width_(0) , height_(0) , format_(BITFMT_UNKNOWN) , m_Pitch(0) , bpe_(0) , Alignment_(4) { Allocate(format, width, height); } ImageSurface::ImageSurface(ImageSurface const& surface) { width_ = surface.width_; height_ = surface.height_; bpe_ = surface.bpe_; format_ = surface.format_; m_Pitch = surface.m_Pitch; Alignment_ = surface.Alignment_; RawData_ = surface.RawData_; } ImageSurface::ImageSurface(ImageSurface&& surface) : ImageSurface() { swap(*this, surface); } ImageSurface &ImageSurface::operator = (ImageSurface copy) { swap(*this, copy); return *this; } void swap(ImageSurface& lhs, ImageSurface& rhs) { using std::swap; swap(lhs.width_, rhs.width_); swap(lhs.height_, rhs.height_); swap(lhs.bpe_, rhs.bpe_); swap(lhs.format_, rhs.format_); swap(lhs.m_Pitch, rhs.m_Pitch); swap(lhs.Alignment_, rhs.Alignment_); swap(lhs.RawData_, rhs.RawData_); } int ImageSurface::GetPitch() const { return m_Pitch; } int ImageSurface::GetBlockHeight() const { unsigned int block = GPixelFormats[format_].BlockSizeY; unsigned int HeightInBlocks = Align(GetHeight(), block) / block; return HeightInBlocks; } BitmapFormat ImageSurface::GetFormat() const { return format_; } int ImageSurface::GetAlignment() const { return Alignment_; } void ImageSurface::Allocate(BitmapFormat format, int width, int height) { nuxAssert(format < BITFMT_END_GFX_FORMATS); nuxAssert(width >= 0); nuxAssert(height >= 0); if (width < 0) width = 0; if (height < 0) height = 0; if ((format_ == format) && (width_ == width) && (height_ == height)) { // no need to recreate Clear(); return; } if ((width == 0) || (height == 0)) { width_ = 0; height_ = 0; Alignment_ = 1; bpe_ = 0; format_ = BITFMT_UNKNOWN; m_Pitch = 0; RawData_.clear(); RawData_.shrink_to_fit(); return; } width_ = width; height_ = height; Alignment_ = GPixelFormats[format].RowMemoryAlignment; bpe_ = GPixelFormats[format].BlockBytes; format_ = format; // For DXT, width and height are rounded up to a multiple of 4 in order // to create 4x4 blocks of pixels; And in this context, byte alignment // is 1 ie. data is densely packed. unsigned int block = GPixelFormats[format].BlockSizeX; unsigned int shift = Log2(GPixelFormats[format].BlockSizeX); m_Pitch = Align((bpe_ * ((width_ + (block - 1)) >> shift)), Alignment_); block = GPixelFormats[format].BlockSizeY; shift = Log2(GPixelFormats[format].BlockSizeY); RawData_.resize(m_Pitch * Align((height + (block-1)) >> shift, block)); RawData_.shrink_to_fit(); Clear(); } // This computes the correct pitch of a line. For instance if the unpack // alignment is 4, the pitch must have a number of pixel multiple of 4. See // Avoiding 16 Common OpenGL Pitfalls // http://www.opengl.org/resources/features/KilgardTechniques/oglpitfall/ // 7. Watch Your Pixel Store Alignment int ImageSurface::GetLevelPitch(BitmapFormat format, int width, int /* height */, int miplevel) { int levelwidth = ImageSurface::GetLevelDim(format, width, miplevel); int bpe = GPixelFormats[format].BlockBytes; int memalignment = GPixelFormats[format].RowMemoryAlignment; int block = GPixelFormats[format].BlockSizeX; int shift = Log2(GPixelFormats[format].BlockSizeX); int pitch = Align((bpe * ((levelwidth + (block - 1)) >> shift)), memalignment); return pitch; } int ImageSurface::GetLevelPitchNoMemAlignment(BitmapFormat format, int width, int /* height */, int miplevel) { int levelwidth = ImageSurface::GetLevelDim(format, width, miplevel); int bpe = GPixelFormats[format].BlockBytes; int block = GPixelFormats[format].BlockSizeX; int shift = Log2(GPixelFormats[format].BlockSizeX); int pitch = Align((bpe * ((levelwidth + (block - 1)) >> shift)), 1); return pitch; } int ImageSurface::GetLevelSize(BitmapFormat format, int width, int height, int miplevel) { int pitch = ImageSurface::GetLevelPitch(format, width, height, miplevel); int levelheight = ImageSurface::GetLevelDim(format, height, miplevel); int block = GPixelFormats[format].BlockSizeY; int HeightInBlocks = Align(levelheight, block) / block; int size = pitch * HeightInBlocks; return size; } int ImageSurface::GetLevelSize(BitmapFormat format, int width, int height, int depth, int miplevel) { int pitch = ImageSurface::GetLevelPitch(format, width, height, miplevel); int levelheight = ImageSurface::GetLevelDim(format, height, miplevel); int leveldepth = ImageSurface::GetLevelDim(format, depth, miplevel); int block = GPixelFormats[format].BlockSizeY; int HeightInBlocks = Align(levelheight, block) / block; int size = pitch * HeightInBlocks; return leveldepth * size; } int ImageSurface::GetLevelWidth(BitmapFormat /* format */, int width, int miplevel) { // return 1 if the mip level does not exist. return Max (1, width >> miplevel); } int ImageSurface::GetLevelHeight(BitmapFormat /* format */, int height, int miplevel) { // return 1 if the mip level does not exist. return Max (1, height >> miplevel); } int ImageSurface::GetLevelDim(BitmapFormat /* format */, int length, int miplevel) { // return 1 if the mip level does not exist. return Max (1, length >> miplevel); } int ImageSurface::GetNumMipLevel(BitmapFormat /* format */, int width, int height) { int NumTotalMipLevel = 1 + floorf(Log2(Max(width, height))); return NumTotalMipLevel; } int ImageSurface::GetMemAlignment(BitmapFormat format) { return GPixelFormats[format].RowMemoryAlignment; } int ImageSurface::GetLevelBlockWidth(BitmapFormat format, int width, int miplevel) { int block = GPixelFormats[format].BlockSizeX; int WidthInBlocks = Align(GetLevelDim(format, width, miplevel), block) / block; return WidthInBlocks; } int ImageSurface::GetLevelBlockHeight(BitmapFormat format, int height, int miplevel) { int block = GPixelFormats[format].BlockSizeY; int HeightInBlocks = Align(GetLevelDim(format, height, miplevel), block) / block; return HeightInBlocks; } bool ImageSurface::IsNull() const { if ((width_ == 0) || (height_ == 0) || (format_ == BITFMT_UNKNOWN)) return true; return false; } void ImageSurface::Write32b(int i, int j, unsigned int value) { nuxAssert(i < width_); nuxAssert(j < height_); nuxAssert(bpe_ >= 4); if ((format_ == BITFMT_DXT1) || (format_ == BITFMT_DXT2) || (format_ == BITFMT_DXT3) || (format_ == BITFMT_DXT4) || (format_ == BITFMT_DXT5)) return; RawData_[j *m_Pitch + i *bpe_ + 0] = (unsigned char) (value & 0xff); RawData_[j *m_Pitch + i *bpe_ + 1] = (unsigned char) ((value & 0xff00) >> 8); RawData_[j *m_Pitch + i *bpe_ + 2] = (unsigned char) ((value & 0xff0000) >> 16); RawData_[j *m_Pitch + i *bpe_ + 3] = (unsigned char) ((value & 0xff000000) >> 24); } void ImageSurface::Write24b(int i, int j, unsigned int value) { nuxAssert(i < width_); nuxAssert(j < height_); nuxAssert(bpe_ >= 3); if ((format_ == BITFMT_DXT1) || (format_ == BITFMT_DXT2) || (format_ == BITFMT_DXT3) || (format_ == BITFMT_DXT4) || (format_ == BITFMT_DXT5)) return; RawData_[j *m_Pitch + i *bpe_ + 0] = (unsigned char) (value & 0xff); RawData_[j *m_Pitch + i *bpe_ + 1] = (unsigned char) ((value & 0xff00) >> 8); RawData_[j *m_Pitch + i *bpe_ + 2] = (unsigned char) ((value & 0xff0000) >> 16); } void ImageSurface::Write16b(int i, int j, unsigned short value) { nuxAssert(i < width_); nuxAssert(j < height_); nuxAssert(bpe_ >= 2); if ((format_ == BITFMT_DXT1) || (format_ == BITFMT_DXT2) || (format_ == BITFMT_DXT3) || (format_ == BITFMT_DXT4) || (format_ == BITFMT_DXT5)) return; RawData_[j *m_Pitch + i *bpe_ + 0] = (unsigned char) (value & 0xff); RawData_[j *m_Pitch + i *bpe_ + 1] = (unsigned char) ((value & 0xff00) >> 8); } void ImageSurface::Write8b(int i, int j, unsigned char value) { nuxAssert(i < width_); nuxAssert(j < height_); nuxAssert(bpe_ >= 1); if ((format_ == BITFMT_DXT1) || (format_ == BITFMT_DXT2) || (format_ == BITFMT_DXT3) || (format_ == BITFMT_DXT4) || (format_ == BITFMT_DXT5)) return; RawData_[j *m_Pitch + i *bpe_ + 0] = (unsigned char) (value & 0xff); } void ImageSurface::Write(int i, int j, unsigned char r, unsigned char g, unsigned char b, unsigned char a) { nuxAssert(i < width_); nuxAssert(j < height_); nuxAssert(bpe_ == 4); if ((format_ == BITFMT_DXT1) || (format_ == BITFMT_DXT2) || (format_ == BITFMT_DXT3) || (format_ == BITFMT_DXT4) || (format_ == BITFMT_DXT5)) return; if ((i < 0) || (i > width_)) return; if ((j < 0) || (j > height_)) return; if (bpe_ != 4) return; RawData_[j *m_Pitch + i *bpe_ + 0] = r; RawData_[j *m_Pitch + i *bpe_ + 1] = g; RawData_[j *m_Pitch + i *bpe_ + 2] = b; RawData_[j *m_Pitch + i *bpe_ + 3] = a; } unsigned int ImageSurface::Read(int i, int j) { nuxAssert(i < width_); nuxAssert(j < height_); nuxAssert(bpe_); if ((format_ == BITFMT_DXT1) || (format_ == BITFMT_DXT2) || (format_ == BITFMT_DXT3) || (format_ == BITFMT_DXT4) || (format_ == BITFMT_DXT5)) return 0x00000000; if (bpe_ == 4) { return ((unsigned int) RawData_[j * m_Pitch + i * bpe_ + 3] << 24) | ((unsigned int) RawData_[j * m_Pitch + i * bpe_ + 2] << 16) | ((unsigned int) RawData_[j * m_Pitch + i * bpe_ + 1] << 8) | ((unsigned int) RawData_[j * m_Pitch + i * bpe_ + 0] << 0); } if (bpe_ == 3) { return ((unsigned int) RawData_[j * m_Pitch + i * bpe_ + 2] << 16) | ((unsigned int) RawData_[j * m_Pitch + i * bpe_ + 1] << 8) | ((unsigned int) RawData_[j * m_Pitch + i * bpe_ + 0] << 0); } if (bpe_ == 2) { return ((unsigned int) RawData_[j * m_Pitch + i * bpe_ + 1] << 8) | ((unsigned int) RawData_[j * m_Pitch + i * bpe_ + 0] << 0); } if (bpe_ == 1) { return (unsigned int) RawData_[j * m_Pitch + i * bpe_ + 0]; } return 0x0000000; } void ImageSurface::Clear() { if (RawData_.empty()) return; if ((width_ == 0) || (height_ == 0)) return; auto size = GetSize(); memset(RawData_.data(), 0, size); } void ImageSurface::FlipHorizontal() { if ((format_ == BITFMT_DXT1) || (format_ == BITFMT_DXT2) || (format_ == BITFMT_DXT3) || (format_ == BITFMT_DXT4) || (format_ == BITFMT_DXT5)) return; int i, j, k; if (RawData_.empty()) return; if (width_ == 0 || height_ == 0) return; std::vector flip_data(m_Pitch*height_); for (j = 0; j < height_; j++) { for (i = 0; i < width_; i++) { for (k = 0; k < bpe_; k++) { flip_data[ (j*m_Pitch) + i *bpe_ + k] = RawData_[ (j*m_Pitch) + (width_-i-1) * bpe_ + k]; } } } RawData_.swap(flip_data); } void ImageSurface::FlipVertical() { if (RawData_.empty()) return; if (width_ == 0 || height_ == 0) return; if ((format_ == BITFMT_DXT1) || (format_ == BITFMT_DXT2) || (format_ == BITFMT_DXT3) || (format_ == BITFMT_DXT4) || (format_ == BITFMT_DXT5)) { FlipDXTVertical(); } else { std::vector flip_data(m_Pitch*height_); for (int j = 0; j < height_; j++) { for (int i = 0; i < width_; i++) { for (int k = 0; k < bpe_; k++) { flip_data[ (j*m_Pitch) + i *bpe_ + k] = RawData_[ (height_-j-1) *m_Pitch + i * bpe_ + k]; } } } RawData_.swap(flip_data); } } void ImageSurface::FlipDXTVertical() { //void(CDDSImage::*flipblocks)(DXTColBlock*, unsigned int); int xblocks = (width_ + 3) / 4; int yblocks = (height_ + 3) / 4; int blocksize; int linesize; switch(format_) { case BITFMT_DXT1: blocksize = 8; //flipblocks = &CDDSImage::flip_blocks_dxtc1; break; case BITFMT_DXT2: blocksize = 16; //flipblocks = &CDDSImage::flip_blocks_dxtc2; break; case BITFMT_DXT3: blocksize = 16; //flipblocks = &CDDSImage::flip_blocks_dxtc3; break; case BITFMT_DXT4: blocksize = 16; //flipblocks = &CDDSImage::flip_blocks_dxtc4; break; case BITFMT_DXT5: blocksize = 16; //flipblocks = &CDDSImage::flip_blocks_dxtc5; break; default: return; } linesize = xblocks * blocksize; DXTColBlock *top; DXTColBlock *bottom; for (int j = 0; j < (yblocks >> 1); j++) { top = reinterpret_cast(&(RawData_[j * linesize])); bottom = reinterpret_cast(&(RawData_[((yblocks - j) - 1) * linesize])); switch(format_) { case BITFMT_DXT1: FlipBlocksDXT1(top, xblocks); FlipBlocksDXT1(bottom, xblocks); break; case BITFMT_DXT2: FlipBlocksDXT3(top, xblocks); FlipBlocksDXT3(bottom, xblocks); break; case BITFMT_DXT3: FlipBlocksDXT3(top, xblocks); FlipBlocksDXT3(bottom, xblocks); break; case BITFMT_DXT4: FlipBlocksDXT5(top, xblocks); FlipBlocksDXT5(bottom, xblocks); break; case BITFMT_DXT5: FlipBlocksDXT5(top, xblocks); FlipBlocksDXT5(bottom, xblocks); break; default: nuxAssert("[ImageSurface::FlipDXTVertical] Invalid Switch option."); break; } SwapBlocks(bottom, top, linesize); } } void ImageSurface::SwapBlocks(void *byte1, void *byte2, int size) { std::vector tmp(size); memcpy(tmp.data(), byte1, size); memcpy(byte1, byte2, size); memcpy(byte2, tmp.data(), size); } void ImageSurface::FlipBlocksDXT1(DXTColBlock *line, int numBlocks) { DXTColBlock *curblock = line; for (int i = 0; i < numBlocks; i++) { SwapBlocks(&curblock->row[0], &curblock->row[3], sizeof(unsigned char)); SwapBlocks(&curblock->row[1], &curblock->row[2], sizeof(unsigned char)); curblock++; } } void ImageSurface::FlipBlocksDXT3(DXTColBlock *line, int numBlocks) { DXTColBlock *curblock = line; DXT3AlphaBlock *alphablock; for (int i = 0; i < numBlocks; i++) { alphablock = (DXT3AlphaBlock *) curblock; SwapBlocks(&alphablock->row[0], &alphablock->row[3], sizeof(unsigned short)); SwapBlocks(&alphablock->row[1], &alphablock->row[2], sizeof(unsigned short)); curblock++; SwapBlocks(&curblock->row[0], &curblock->row[3], sizeof(unsigned char)); SwapBlocks(&curblock->row[1], &curblock->row[2], sizeof(unsigned char)); curblock++; } } void ImageSurface::FlipBlocksDXT5(DXTColBlock *line, int numBlocks) { DXTColBlock *curblock = line; DXT5AlphaBlock *alphablock; for (int i = 0; i < numBlocks; i++) { alphablock = (DXT5AlphaBlock *) curblock; FlipDXT5Alpha(alphablock); curblock++; SwapBlocks(&curblock->row[0], &curblock->row[3], sizeof(unsigned char)); SwapBlocks(&curblock->row[1], &curblock->row[2], sizeof(unsigned char)); curblock++; } } void ImageSurface::FlipDXT5Alpha(DXT5AlphaBlock *block) { unsigned char gBits[4][4]; const unsigned long mask = 0x00000007; // bits = 00 00 01 11 unsigned long bits = 0; memcpy(&bits, &block->row[0], sizeof(unsigned char) * 3); gBits[0][0] = (unsigned char) (bits & mask); bits >>= 3; gBits[0][1] = (unsigned char) (bits & mask); bits >>= 3; gBits[0][2] = (unsigned char) (bits & mask); bits >>= 3; gBits[0][3] = (unsigned char) (bits & mask); bits >>= 3; gBits[1][0] = (unsigned char) (bits & mask); bits >>= 3; gBits[1][1] = (unsigned char) (bits & mask); bits >>= 3; gBits[1][2] = (unsigned char) (bits & mask); bits >>= 3; gBits[1][3] = (unsigned char) (bits & mask); bits = 0; memcpy(&bits, &block->row[3], sizeof(unsigned char) * 3); gBits[2][0] = (unsigned char) (bits & mask); bits >>= 3; gBits[2][1] = (unsigned char) (bits & mask); bits >>= 3; gBits[2][2] = (unsigned char) (bits & mask); bits >>= 3; gBits[2][3] = (unsigned char) (bits & mask); bits >>= 3; gBits[3][0] = (unsigned char) (bits & mask); bits >>= 3; gBits[3][1] = (unsigned char) (bits & mask); bits >>= 3; gBits[3][2] = (unsigned char) (bits & mask); bits >>= 3; gBits[3][3] = (unsigned char) (bits & mask); unsigned long *pBits = ((unsigned long *) & (block->row[0])); *pBits = *pBits | (gBits[3][0] << 0); *pBits = *pBits | (gBits[3][1] << 3); *pBits = *pBits | (gBits[3][2] << 6); *pBits = *pBits | (gBits[3][3] << 9); *pBits = *pBits | (gBits[2][0] << 12); *pBits = *pBits | (gBits[2][1] << 15); *pBits = *pBits | (gBits[2][2] << 18); *pBits = *pBits | (gBits[2][3] << 21); pBits = ((unsigned long *) & (block->row[3])); #ifdef __APPLE__ *pBits &= 0x000000ff; #else *pBits &= 0xff000000; #endif *pBits = *pBits | (gBits[1][0] << 0); *pBits = *pBits | (gBits[1][1] << 3); *pBits = *pBits | (gBits[1][2] << 6); *pBits = *pBits | (gBits[1][3] << 9); *pBits = *pBits | (gBits[0][0] << 12); *pBits = *pBits | (gBits[0][1] << 15); *pBits = *pBits | (gBits[0][2] << 18); *pBits = *pBits | (gBits[0][3] << 21); } const unsigned char *ImageSurface::GetPtrRawData() const { return RawData_.data(); } unsigned char *ImageSurface::GetPtrRawData() { return RawData_.data(); } int ImageSurface::GetSize() const { if ((format_ == BITFMT_DXT1) || (format_ == BITFMT_DXT2) || (format_ == BITFMT_DXT3) || (format_ == BITFMT_DXT4) || (format_ == BITFMT_DXT5)) { return m_Pitch * ((height_ + 3) >> 2); } else { return m_Pitch * height_; } } Color ImageSurface::AverageColor() { if (width_ == 0 || height_ == 0) return Color(0.f, 0.f, 0.f, 0.f); float r, g, b, a; r = g = b = a = 0; if (bpe_ == 8) { for (int j = 0; j < height_; j++) { for (int i = 0; i < width_; i++) { unsigned int v = Read(i, j); r += (v & 0x000000FF); g += (v & 0x0000FF00) >> 1; b += (v & 0x00FF0000) >> 2; a += (v & 0xFF000000) >> 3; } } } unsigned int num_pixels = width_ * height_; return Color(r / num_pixels, g / num_pixels, b / num_pixels, a / num_pixels); } /////////////////////////////////////////////////////////////////// NTextureData::NTextureData(BitmapFormat f, int width, int height, int NumMipmap) : m_NumMipmap(0) , m_MipSurfaceArray(1) { Allocate(f, width, height, NumMipmap); } void NTextureData::swap(NTextureData& other) { using std::swap; swap(this->m_NumMipmap, other.m_NumMipmap); swap(this->m_TotalMemorySize, other.m_TotalMemorySize); swap(this->m_MipSurfaceArray, other.m_MipSurfaceArray); } //! Copy constructor NTextureData::NTextureData(const NTextureData &object) { m_NumMipmap = object.m_NumMipmap; m_TotalMemorySize = object.m_TotalMemorySize; m_MipSurfaceArray = object.m_MipSurfaceArray; } //! Move constructor NTextureData::NTextureData(NTextureData&& other) : NTextureData() { swap(other); } //! Assignment constructor NTextureData &NTextureData::operator = (NTextureData copy) { swap(copy); return *this; } void NTextureData::Allocate(BitmapFormat format, int width, int height, int NumMipmapRequested) { nuxAssertMsg(width >= 0, "[NTextureData::Allocate] Error: Negative texture width."); nuxAssertMsg(height >= 0, "[NTextureData::Allocate] Error: Negative texture height."); nuxAssert(NumMipmapRequested >= 0); int NumTotalMipLevel = 1 + (int) Floor(Log2(Max(width, height))); m_NumMipmap = NumMipmapRequested; if (NumMipmapRequested == 0) m_NumMipmap = NumTotalMipLevel ? NumTotalMipLevel : 1; if (NumMipmapRequested > NumTotalMipLevel) m_NumMipmap = NumTotalMipLevel ? NumTotalMipLevel : 1; m_TotalMemorySize = 0; m_MipSurfaceArray.resize(m_NumMipmap); m_MipSurfaceArray.shrink_to_fit(); for (int i = 0; i < m_NumMipmap; ++i) { int w = width >> i; int h = height >> i; m_MipSurfaceArray[i] = ImageSurface(format, w, h); m_TotalMemorySize += m_MipSurfaceArray[i].GetSize(); } } void NTextureData::AllocateCheckBoardTexture(int width, int height, int NumMipmap, Color color0, Color color1, int TileWidth, int TileHeight) { Allocate(BITFMT_R8G8B8A8, width, height, NumMipmap); for (int i = 0; i < m_NumMipmap; ++i) { int w = ImageSurface::GetLevelDim(BITFMT_R8G8B8A8, GetWidth(), i); int h = ImageSurface::GetLevelDim(BITFMT_R8G8B8A8, GetHeight(), i); MakeCheckBoardImage(m_MipSurfaceArray[i], w, h, color0, color1, TileWidth, TileHeight); } } void NTextureData::AllocateColorTexture(int width, int height, int NumMipmap, Color color0) { Allocate(BITFMT_R8G8B8A8, width, height, NumMipmap); for (int i = 0; i < m_NumMipmap; ++i) { int w = ImageSurface::GetLevelDim(BITFMT_R8G8B8A8, GetWidth(), i); int h = ImageSurface::GetLevelDim(BITFMT_R8G8B8A8, GetHeight(), i); MakeCheckBoardImage(m_MipSurfaceArray[i], w, h, color0, color0); } } int NTextureData::GetNumMipmap() const { return m_NumMipmap; } bool NTextureData::SetSurface(int MipLevel, const ImageSurface &targetsurface) { nuxAssert(MipLevel >= 0); nuxAssert(MipLevel < m_NumMipmap); ImageSurface &surface = GetSurface(MipLevel); if (surface.GetFormat() != targetsurface.GetFormat()) return false; if (surface.GetWidth() != targetsurface.GetWidth()) return false; if (surface.GetHeight() != targetsurface.GetHeight()) return false; surface = targetsurface; return true; } /////////////////////////////////////////////////////////////////// NCubemapData::NCubemapData(BitmapFormat format, int width, int height, int NumMipmap) : m_NumMipmap(0) { Allocate(format, width, height, NumMipmap); } NCubemapData::~NCubemapData() { ClearData(); } void NCubemapData::ClearData() { int n = (int) m_MipSurfaceArray[0].size(); for (int i = 0; i < n; i++) { delete m_MipSurfaceArray[0][i]; delete m_MipSurfaceArray[1][i]; delete m_MipSurfaceArray[2][i]; delete m_MipSurfaceArray[3][i]; delete m_MipSurfaceArray[4][i]; delete m_MipSurfaceArray[5][i]; } m_MipSurfaceArray[0].clear(); m_MipSurfaceArray[1].clear(); m_MipSurfaceArray[2].clear(); m_MipSurfaceArray[3].clear(); m_MipSurfaceArray[4].clear(); m_MipSurfaceArray[5].clear(); } //! Copy constructor NCubemapData::NCubemapData(const NCubemapData &object) { for (int face = 0; face < 6; face++) for (int i = 0; i < object.GetNumMipmap(); i++) m_MipSurfaceArray[face].push_back(new ImageSurface(object.GetSurface(face, i))); } //! Assignment constructor NCubemapData &NCubemapData::operator = (const NCubemapData ©) { ClearData(); m_NumMipmap = copy.m_NumMipmap; m_TotalMemorySize = copy.m_TotalMemorySize; for (int face = 0; face < 6; face++) for (int i = 0; i < copy.GetNumMipmap(); i++) m_MipSurfaceArray[face].push_back(new ImageSurface(copy.GetSurface(face, i))); return *this; } void NCubemapData::Allocate(BitmapFormat format, int width, int height, int NumMipmapRequested) { nuxAssertMsg(width >= 0, "[NCubemapData::Allocate] Error: Negative texture width."); nuxAssertMsg(height >= 0, "[NCubemapData::Allocate] Error: Negative texture height."); nuxAssert(NumMipmapRequested >= 0); ClearData(); int NumTotalMipLevel = 1 + (int) Floor(Log2(Max(width, height))); m_NumMipmap = NumMipmapRequested; if (NumMipmapRequested == 0) m_NumMipmap = NumTotalMipLevel ? NumTotalMipLevel : 1; if (NumMipmapRequested > NumTotalMipLevel) m_NumMipmap = NumTotalMipLevel ? NumTotalMipLevel : 1; m_TotalMemorySize = 0; for (int face = 0; face < 6; face++) { for (int i = 0; i < m_NumMipmap; i++) { int w = width >> i; int h = height >> i; m_MipSurfaceArray[face].push_back(new ImageSurface(format, w, h)); m_TotalMemorySize += m_MipSurfaceArray[face][i]->GetSize(); } } } void NCubemapData::AllocateCheckBoardTexture(int width, int height, int NumMipmap, Color color0, Color color1, int TileWidth, int TileHeight) { Allocate(BITFMT_R8G8B8A8, width, height, NumMipmap); for (int face = 0; face < 6; face++) { for (int i = 0; i < m_NumMipmap; i++) { int w = ImageSurface::GetLevelDim(BITFMT_R8G8B8A8, GetWidth(), i); int h = ImageSurface::GetLevelDim(BITFMT_R8G8B8A8, GetHeight(), i); MakeCheckBoardImage(*m_MipSurfaceArray[face][i], w, h, color0, color1, TileWidth, TileHeight); } } } void NCubemapData::AllocateColorTexture(int width, int height, int NumMipmap, Color color0) { Allocate(BITFMT_R8G8B8A8, width, height, NumMipmap); for (int face = 0; face < 6; face++) { for (int i = 0; i < m_NumMipmap; i++) { int w = ImageSurface::GetLevelDim(BITFMT_R8G8B8A8, GetWidth(), i); int h = ImageSurface::GetLevelDim(BITFMT_R8G8B8A8, GetHeight(), i); MakeCheckBoardImage(*m_MipSurfaceArray[face][i], w, h, color0, color0); } } } int NCubemapData::GetNumMipmap() const { return m_MipSurfaceArray[0].size(); } bool NCubemapData::SetSurface(int face, int MipLevel, const ImageSurface &targetsurface) { nuxAssert(face >= 0); nuxAssert(face < 6); nuxAssert(MipLevel >= 0); nuxAssert(MipLevel < m_NumMipmap); ImageSurface &surface = GetSurface(face, MipLevel); if (surface.GetFormat() != targetsurface.GetFormat()) return false; if (surface.GetWidth() != targetsurface.GetWidth()) return false; if (surface.GetHeight() != targetsurface.GetHeight()) return false; surface = targetsurface; return true; } /////////////////////////////////////////////////////////////////// NVolumeData::NVolumeData(BitmapFormat format, int width, int height, int depth, int NumMipmap) : m_NumMipmap(0) , m_Depth(0) , m_MipSurfaceArray(0) { Allocate(format, width, height, depth, NumMipmap); } NVolumeData::~NVolumeData() { ClearData(); } void NVolumeData::ClearData() { for (int mip = 0; mip < GetNumMipmap(); mip++) { for (int s = 0; s < ImageSurface::GetLevelDim(GetFormat(), GetDepth(), mip); s++) { delete m_MipSurfaceArray[mip][s]; } m_MipSurfaceArray[mip].clear(); } delete [] m_MipSurfaceArray; } //! Copy constructor NVolumeData::NVolumeData(const NVolumeData &object) { for (int mip = 0; mip < object.GetNumMipmap(); mip++) { for (int s = 0; s < ImageSurface::GetLevelDim(object.GetFormat(), object.GetDepth(), mip); s++) { m_MipSurfaceArray[mip].push_back(new ImageSurface(object.GetSurface(s, mip))); } } } //! Assignment constructor NVolumeData &NVolumeData::operator = (const NVolumeData ©) { ClearData(); m_Depth = copy.m_Depth; m_NumMipmap = copy.m_NumMipmap; m_TotalMemorySize = copy.m_TotalMemorySize; m_MipSurfaceArray = new std::vector[m_NumMipmap]; for (int mip = 0; mip < copy.GetNumMipmap(); mip++) { for (int s = 0; s < ImageSurface::GetLevelDim(copy.GetFormat(), copy.GetDepth(), mip); s++) { m_MipSurfaceArray[mip].push_back(new ImageSurface(copy.GetSurface(s, mip))); } } return *this; } void NVolumeData::Allocate(BitmapFormat format, int width, int height, int depth, int NumMipmapRequested) { nuxAssertMsg(depth >= 0, "[NVolumeData::Allocate] Error: Negative number of slice."); nuxAssertMsg(width >= 0, "[NVolumeData::Allocate] Error: Negative texture width."); nuxAssertMsg(height >= 0, "[NVolumeData::Allocate] Error: Negative texture height."); nuxAssert(NumMipmapRequested >= 0); ClearData(); int NumTotalMipLevel = 1 + (int) Floor(Log2(Max(width, height))); m_NumMipmap = NumMipmapRequested; if (NumMipmapRequested == 0) m_NumMipmap = NumTotalMipLevel ? NumTotalMipLevel : 1; if (NumMipmapRequested > NumTotalMipLevel) m_NumMipmap = NumTotalMipLevel ? NumTotalMipLevel : 1; m_Depth = depth; m_MipSurfaceArray = new std::vector[m_NumMipmap]; m_TotalMemorySize = 0; for (int mip = 0; mip < m_NumMipmap; mip++) { for (int s = 0; s < ImageSurface::GetLevelDim(format, depth, mip); s++) { int w = ImageSurface::GetLevelDim(format, width, mip); int h = ImageSurface::GetLevelDim(format, height, mip); m_MipSurfaceArray[mip].push_back(new ImageSurface(format, w, h)); m_TotalMemorySize += m_MipSurfaceArray[mip][s]->GetSize(); } } } void NVolumeData::AllocateCheckBoardTexture(int width, int height, int slice, int NumMipmap, Color color0, Color color1, int TileWidth, int TileHeight) { Allocate(BITFMT_R8G8B8A8, width, height, slice, NumMipmap); for (int mip = 0; mip < m_NumMipmap; mip++) { for (int s = 0; s < ImageSurface::GetLevelDim(BITFMT_R8G8B8A8, GetDepth(), mip); s++) { int w = ImageSurface::GetLevelDim(BITFMT_R8G8B8A8, GetWidth(), mip); int h = ImageSurface::GetLevelDim(BITFMT_R8G8B8A8, GetHeight(), mip); MakeCheckBoardImage(* (m_MipSurfaceArray[mip][s]), w, h, color0, color1, TileWidth, TileHeight); } } } void NVolumeData::AllocateColorTexture(int width, int height, int slice, int NumMipmap, Color color0) { Allocate(BITFMT_R8G8B8A8, width, height, slice, NumMipmap); for (int mip = 0; mip < m_NumMipmap; mip++) { for (int s = 0; s < ImageSurface::GetLevelDim(BITFMT_R8G8B8A8, GetDepth(), mip); s++) { int w = ImageSurface::GetLevelDim(BITFMT_R8G8B8A8, GetWidth(), mip); int h = ImageSurface::GetLevelDim(BITFMT_R8G8B8A8, GetHeight(), mip); MakeCheckBoardImage(* (m_MipSurfaceArray[mip][s]), w, h, color0, color0); } } } int NVolumeData::GetNumMipmap() const { return m_NumMipmap; } bool NVolumeData::SetSurface(int Slice, int MipLevel, const ImageSurface &targetsurface) { nuxAssert(Slice >= 0); nuxAssert(Slice < m_Depth); nuxAssert(MipLevel >= 0); nuxAssert(MipLevel < m_NumMipmap); ImageSurface &surface = GetSurface(Slice, MipLevel); if (surface.GetFormat() != targetsurface.GetFormat()) return false; if (surface.GetWidth() != targetsurface.GetWidth()) return false; if (surface.GetHeight() != targetsurface.GetHeight()) return false; surface = targetsurface; return true; } /////////////////////////////////////////////////////////////////// NAnimatedTextureData::NAnimatedTextureData(BitmapFormat format, int width, int height, int depth) : m_NumMipmap(0) , m_Depth(0) , m_MipSurfaceArray(0) { Allocate(format, width, height, depth, 1); } NAnimatedTextureData::~NAnimatedTextureData() { ClearData(); } void NAnimatedTextureData::ClearData() { for (int mip = 0; mip < GetNumMipmap(); mip++) { for (int s = 0; s < ImageSurface::GetLevelDim(GetFormat(), GetDepth(), mip); s++) { delete m_MipSurfaceArray[mip][s]; } m_MipSurfaceArray[mip].clear(); } m_FrameTimeArray.clear(); delete [] m_MipSurfaceArray; } //! Copy constructor NAnimatedTextureData::NAnimatedTextureData(const NAnimatedTextureData &object) { for (int mip = 0; mip < object.GetNumMipmap(); mip++) { for (int s = 0; s < ImageSurface::GetLevelDim(object.GetFormat(), object.GetDepth(), mip); s++) { m_MipSurfaceArray[mip].push_back(new ImageSurface(object.GetSurface(mip, s))); } } for (int frame = 0; frame < object.GetDepth(); frame++) { m_FrameTimeArray.push_back(object.GetFrameTime(frame)); } } //! Assignment constructor NAnimatedTextureData &NAnimatedTextureData::operator = (const NAnimatedTextureData ©) { ClearData(); m_Depth = copy.GetDepth(); m_NumMipmap = copy.m_NumMipmap; m_TotalMemorySize = copy.m_TotalMemorySize; m_MipSurfaceArray = new std::vector[m_NumMipmap]; for (int mip = 0; mip < copy.GetNumMipmap(); mip++) { for (int s = 0; s < ImageSurface::GetLevelDim(copy.GetFormat(), copy.GetDepth(), mip); s++) { m_MipSurfaceArray[mip].push_back(new ImageSurface(copy.GetSurface(s))); } } for (int frame = 0; frame < copy.GetDepth(); frame++) { m_FrameTimeArray.push_back(copy.GetFrameTime(frame)); } return *this; } void NAnimatedTextureData::Allocate(BitmapFormat format, int width, int height, int depth, int NumMipmapRequested) { nuxAssertMsg(depth >= 0, "[NAnimatedTextureData::Allocate] Error: Negative number of slice."); nuxAssertMsg(width >= 0, "[NAnimatedTextureData::Allocate] Error: Negative texture width."); nuxAssertMsg(height >= 0, "[NAnimatedTextureData::Allocate] Error: Negative texture height."); nuxAssert(NumMipmapRequested >= 0); ClearData(); int NumTotalMipLevel = 1 + (int) Floor(Log2(Max(width, height))); m_NumMipmap = NumMipmapRequested; if (NumMipmapRequested == 0) m_NumMipmap = NumTotalMipLevel ? NumTotalMipLevel : 1; if (NumMipmapRequested > NumTotalMipLevel) m_NumMipmap = NumTotalMipLevel ? NumTotalMipLevel : 1; m_Depth = depth; m_MipSurfaceArray = new std::vector[m_NumMipmap]; m_TotalMemorySize = 0; for (int mip = 0; mip < m_NumMipmap; mip++) { for (int s = 0; s < ImageSurface::GetLevelDim(format, depth, mip); s++) { int w = ImageSurface::GetLevelDim(format, width, mip); int h = ImageSurface::GetLevelDim(format, height, mip); m_MipSurfaceArray[mip].push_back(new ImageSurface(format, w, h)); m_TotalMemorySize += m_MipSurfaceArray[mip][s]->GetSize(); } } } void NAnimatedTextureData::AllocateCheckBoardTexture(int width, int height, int slice, int NumMipmap, Color color0, Color color1, int TileWidth, int TileHeight) { Allocate(BITFMT_R8G8B8A8, width, height, slice, NumMipmap); for (int mip = 0; mip < m_NumMipmap; mip++) { for (int s = 0; s < ImageSurface::GetLevelDim(BITFMT_R8G8B8A8, GetDepth(), mip); s++) { int w = ImageSurface::GetLevelDim(BITFMT_R8G8B8A8, GetWidth(), mip); int h = ImageSurface::GetLevelDim(BITFMT_R8G8B8A8, GetHeight(), mip); MakeCheckBoardImage(* (m_MipSurfaceArray[mip][s]), w, h, color0, color1, TileWidth, TileHeight); } } } void NAnimatedTextureData::AllocateColorTexture(int width, int height, int slice, int NumMipmap, Color color0) { Allocate(BITFMT_R8G8B8A8, width, height, slice, NumMipmap); for (int mip = 0; mip < m_NumMipmap; mip++) { for (int s = 0; s < ImageSurface::GetLevelDim(BITFMT_R8G8B8A8, GetDepth(), mip); s++) { int w = ImageSurface::GetLevelDim(BITFMT_R8G8B8A8, GetWidth(), mip); int h = ImageSurface::GetLevelDim(BITFMT_R8G8B8A8, GetHeight(), mip); MakeCheckBoardImage(* (m_MipSurfaceArray[mip][s]), w, h, color0, color0); } } } int NAnimatedTextureData::GetNumMipmap() const { return m_NumMipmap; } bool NAnimatedTextureData::SetSurface(int Slice, int MipLevel, const ImageSurface &targetsurface) { nuxAssert(Slice >= 0); nuxAssert(Slice < m_Depth); nuxAssert(MipLevel >= 0); nuxAssert(MipLevel < m_NumMipmap); ImageSurface &surface = GetSurface(Slice, MipLevel); if (surface.GetFormat() != targetsurface.GetFormat()) return false; if (surface.GetWidth() != targetsurface.GetWidth()) return false; if (surface.GetHeight() != targetsurface.GetHeight()) return false; surface = targetsurface; return true; } } ./NuxGraphics/GLTextureResourceManager.cpp0000644000004100000410000010640213313171755021101 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "GLResource.h" #include "GLResourceManager.h" #include "GpuDevice.h" #include "GraphicsEngine.h" #include "GLTextureResourceManager.h" #include "NuxCore/Logger.h" namespace nux { DECLARE_LOGGER(logger, "nux.gltexture.resource.manager"); NUX_IMPLEMENT_OBJECT_TYPE(BaseTexture); NUX_IMPLEMENT_OBJECT_TYPE(Texture2D); NUX_IMPLEMENT_OBJECT_TYPE(TextureRectangle); NUX_IMPLEMENT_OBJECT_TYPE(TextureCube); NUX_IMPLEMENT_OBJECT_TYPE(TextureVolume); NUX_IMPLEMENT_OBJECT_TYPE(TextureFrameAnimation); NUX_IMPLEMENT_OBJECT_TYPE(CachedBaseTexture); NUX_IMPLEMENT_OBJECT_TYPE(CachedTexture2D); NUX_IMPLEMENT_OBJECT_TYPE(CachedTextureRectangle); NUX_IMPLEMENT_OBJECT_TYPE(CachedTextureCube); NUX_IMPLEMENT_OBJECT_TYPE(CachedTextureVolume); NUX_IMPLEMENT_OBJECT_TYPE(CachedTextureFrameAnimation); namespace { nux::BaseTexture* get_null_texture(std::string const& extra_msg = "") { if (!g_getenv("NUX_FALLBACK_TEXTURE")) { LOG_ERROR(logger) << "Invalid target, impossible to generate a new texture." << " " << extra_msg; return nullptr; } LOG_WARN(logger) << "Invalid target, impossible to generate a new valid texture." << " " << extra_msg << ". Using fallback mode..."; return GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableTexture(); } } /*! Up cast a Resource. The source must be derived from the destination type @param T Destination type. @param U Source type. @return The casted to the destination type */ template < class T, class U > static T* UpCastResource(U* Src) { if (!Src || !Src->Type().IsDerivedFromType(T::StaticObjectType)) nuxError("[UpCastResource] Cast of %s to %s failed", U::StaticObjectType.name, T::StaticObjectType.name); return(T*) Src; } BaseTexture* CreateTexture2DFromPixbuf(GdkPixbuf* pixbuf, bool premultiply) { NUX_RETURN_VALUE_IF_NULL(pixbuf, get_null_texture("Null Pixbuf")); const unsigned int rowstride = gdk_pixbuf_get_rowstride(pixbuf); const unsigned int width = gdk_pixbuf_get_width(pixbuf); const unsigned int height = gdk_pixbuf_get_height(pixbuf); // Put the RGB or RGBA pixels in a RGBA texture data object taking care // of alpha premultiplication if requested. // FIXME(loicm) Implies a useless copy. NTextureData should be able to // take ownership of pre-allocated memory. // FIXME(loicm) Add support for big-endian systems. For performance // reasons, pixels are loaded by block of 4 bytes with the color // components bit-shifted considering little-endian ordering. Nux // doesn't seem to be big-endian aware anyway. // FIXME(loicm) Surface::Write32b does branching, splits the 32-bit value // as four 8-bit values(using bit-shifts) that are then stored // separately, that's slow considering it's meant to be used a lot in // deep loops. NTextureData* data = new NTextureData(BITFMT_R8G8B8A8, width, height, 1); ImageSurface& surface = data->GetSurface(0); if (gdk_pixbuf_get_has_alpha(pixbuf) == TRUE) { unsigned char* pixels_u8 = gdk_pixbuf_get_pixels(pixbuf); unsigned int* pixels_u32 = reinterpret_cast (pixels_u8); unsigned char* dest_u8 = surface.GetPtrRawData (); const int pitch = surface.GetPitch (); if (premultiply == true) { // Copy from pixbuf(RGBA) to surface(premultiplied RGBA). for (unsigned int i = 0; i < height; i++) { unsigned int* dest_u32 = reinterpret_cast(dest_u8); for (unsigned int j = 0; j < width; j++) { const unsigned int pixel = pixels_u32[j]; const unsigned int a = pixel >> 24; if (a == 0) { dest_u32[j] = 0; } else { const unsigned int b = (((pixel >> 16) & 0xff) * a) / 255; const unsigned int g = (((pixel >> 8) & 0xff) * a) / 255; const unsigned int r = ((pixel & 0xff) * a) / 255; const unsigned int p = a << 24 | b << 16 | g << 8 | r; dest_u32[j] = p; } } pixels_u8 += rowstride; pixels_u32 = reinterpret_cast (pixels_u8); dest_u8 += pitch; } } else { // Copy from pixbuf(RGBA) to surface(RGBA). for (unsigned int i = 0; i < height; i++) { Memcpy (dest_u8, pixels_u8, width * 4); pixels_u8 += rowstride; dest_u8 += pitch; } } } else { // Copy from pixbuf(RGB) to surface(RGBA). unsigned char* pixels = gdk_pixbuf_get_pixels(pixbuf); unsigned char* dest_u8 = surface.GetPtrRawData(); const int pitch = surface.GetPitch(); for (unsigned int i = 0; i < height; i++) { unsigned int* dest_u32 = reinterpret_cast(dest_u8); for (unsigned int j = 0; j < width; j++) { const unsigned char r = pixels[j*3]; const unsigned char g = pixels[j*3+1]; const unsigned char b = pixels[j*3+2]; const unsigned int p = 0xff000000 | b << 16 | g << 8 | r; dest_u32[j] = p; } pixels += rowstride; dest_u8 += pitch; } } // Create a 2D texture and upload the pixels. BaseTexture* texture = GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableTexture(); texture->Update(data); delete data; // data is deleted as texture->Update() copies it. return texture; } BaseTexture* CreateTexture2DFromFile(const char* filename, int max_size, bool premultiply) { NUX_RETURN_VALUE_IF_NULL(filename, get_null_texture("Empty filename")); GError* error = NULL; GdkPixbuf* pixbuf = gdk_pixbuf_new_from_file_at_size(filename, max_size, max_size, &error); if (error == NULL) { BaseTexture* texture = CreateTexture2DFromPixbuf(pixbuf, premultiply); g_object_unref(pixbuf); return texture; } else { std::string error_msg = (error->message ? error->message : "Unknown error"); g_error_free(error); return get_null_texture("Impossible to generate a pixbuf: "+error_msg); } } BaseTexture* CreateTextureFromPixbuf(GdkPixbuf* pixbuf) { NBitmapData* BitmapData = LoadGdkPixbuf(pixbuf); NUX_RETURN_VALUE_IF_NULL(BitmapData, get_null_texture("Invalid Pixbuf")); if (BitmapData->IsTextureData()) { BaseTexture* texture = GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableTexture(); texture->Update(BitmapData); return texture; } delete BitmapData; return get_null_texture("Invalid Pixbuf"); } BaseTexture* CreateTextureFromFile(const char* TextureFilename) { BaseTexture* texture = NULL; NBitmapData* BitmapData = LoadImageFile(TextureFilename); NUX_RETURN_VALUE_IF_NULL(BitmapData, get_null_texture("No data for '"+(TextureFilename ? std::string(TextureFilename) : "")+"'")); if (BitmapData->IsTextureData()) { texture = GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableTexture(); } else if (BitmapData->IsCubemapTextureData()) { texture = new TextureCube(); } else if (BitmapData->IsVolumeTextureData()) { texture = new TextureVolume(); } else if (BitmapData->IsAnimatedTextureData()) { texture = new TextureFrameAnimation(); } if (texture) { texture->Update(BitmapData); } else { nuxDebugMsg("[CreateTextureFromFile] Invalid texture format type for file(%s)", TextureFilename); texture = get_null_texture(); } delete BitmapData; return texture; } BaseTexture* CreateTextureFromBitmapData(const NBitmapData* BitmapData) { NUX_RETURN_VALUE_IF_NULL(BitmapData, get_null_texture("Invalid BitmapData")); if (BitmapData->IsTextureData()) { BaseTexture* texture = GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableTexture(); texture->Update(BitmapData); return texture; } else if (BitmapData->IsCubemapTextureData()) { TextureCube* texture = new TextureCube(); texture->Update(BitmapData); return texture; } else if (BitmapData->IsVolumeTextureData()) { TextureVolume* texture = new TextureVolume(); texture->Update(BitmapData); return texture; } else if (BitmapData->IsAnimatedTextureData()) { TextureFrameAnimation* texture = new TextureFrameAnimation(); texture->Update(BitmapData); return texture; } return get_null_texture(); } BaseTexture* LoadTextureFromFile(const std::string& filename) { NBitmapData* bitmap = LoadImageFile(filename.c_str()); NUX_RETURN_VALUE_IF_NULL(bitmap, get_null_texture("No Data for '"+filename+"'")); BaseTexture* texture = CreateTextureFromBitmapData(bitmap); delete bitmap; return texture; } BaseTexture::BaseTexture(NUX_FILE_LINE_DECL) : ResourceData(NUX_FILE_LINE_PARAM) { } BaseTexture::~BaseTexture() { } ObjectPtr < IOpenGLBaseTexture > BaseTexture::GetDeviceTexture() { ObjectPtr CachedTexture = GetGraphicsDisplay()->GetGraphicsEngine()->CacheResource(this); return CachedTexture->m_Texture; } ObjectPtr BaseTexture::GetCachedTexture() { return GetGraphicsDisplay()->GetGraphicsEngine()->CacheResource(this); } Texture2D::Texture2D(NUX_FILE_LINE_DECL) // TODO: Why can we create a texture without a texture? : BaseTexture(NUX_FILE_LINE_PARAM) { } Texture2D::Texture2D(const NTextureData& texture_data, NUX_FILE_LINE_DECL) : BaseTexture(NUX_FILE_LINE_PARAM), _image(texture_data) { } Texture2D::~Texture2D() { } bool Texture2D::Update(const NBitmapData* BitmapData, bool UpdateAndCacheResource) { nuxAssertMsg(BitmapData, "[Texture2D::Update] Argument BitmapData is NULL."); NUX_RETURN_VALUE_IF_NULL(BitmapData, false); if (!BitmapData->IsTextureData()) { nuxAssertMsg(0, "[Texture2D::Update] Argument BitmapData is not a 2D texture"); return false; } _image = *static_cast (BitmapData); if (UpdateAndCacheResource) { // call the texture manager and recreate the texture(CachedTexture2D) associated with this object if any. GetGraphicsDisplay()->GetGraphicsEngine()->UpdateResource(this); } return true; } bool Texture2D::Update(const char* filename, bool UpdateAndCacheResource) { NBitmapData* BitmapData = LoadImageFile(filename); nuxAssertMsg(BitmapData, "[Texture2D::Update] Bitmap for file(%s) is NULL.", filename); NUX_RETURN_VALUE_IF_NULL(BitmapData, false); bool ret = Update(BitmapData, UpdateAndCacheResource); NUX_SAFE_DELETE(BitmapData); return ret; } void Texture2D::GetData(void* Buffer, int MipIndex, int StrideY, int /* face */) { BYTE *Dest = (BYTE*) Buffer; const BYTE *Src = _image.GetSurface(MipIndex).GetPtrRawData(); int RowByteSize = _image.GetSurface(MipIndex).GetPitch(); int NumRows = _image.GetSurface(MipIndex).GetBlockHeight(); for ( int Y = 0; Y < NumRows; Y++ ) { // Take Min(RowByteSize, StrideY): the source and the destination may not have the same Pitch but // they contain the same amount of valid data since they have the same width, height and format. Memcpy(Dest + Y * StrideY, &Src[Y * RowByteSize], Min(RowByteSize, StrideY)); } } Texture2D* Texture2D::Clone() const { return new Texture2D(_image); } CachedBaseTexture::CachedBaseTexture(NResourceSet* ResourceManager) : CachedResourceData(ResourceManager), SourceWidth(0), SourceHeight(0), SourceDepth(0), SourceFormat(BITFMT_UNKNOWN) { } CachedBaseTexture::~CachedBaseTexture() { m_Texture.Release(); } bool CachedBaseTexture::UpdateResource(ResourceData* Resource) { UpdateTexture((BaseTexture*) Resource); return TRUE; } bool CachedBaseTexture::RecreateTexture(BaseTexture* Source) { if (!m_Texture) return false; int CurrentWidth = m_Texture->GetWidth(); int CurrentHeight = m_Texture->GetHeight(); int CurrentDepth = m_Texture->GetDepth(); int CurrentNumMipmap = m_Texture->GetNumMipLevel(); BitmapFormat CurrentFormat = m_Texture->GetPixelFormat(); bool Recreate = (CurrentWidth != Source->GetWidth()) || (CurrentHeight != Source->GetHeight()) || (CurrentDepth != Source->GetDepth()) || (CurrentNumMipmap != Source->GetNumMipLevel()) || (CurrentFormat != Source->GetFormat()); return Recreate; } CachedTexture2D::CachedTexture2D(NResourceSet* ResourceManager, Texture2D* SourceTexture) : CachedBaseTexture(ResourceManager) { if (SourceTexture->IsNull()) { m_Texture = ObjectPtr (0); return; } m_Texture = GetGraphicsDisplay()->GetGpuDevice()->CreateTexture(SourceTexture->GetWidth(), SourceTexture->GetHeight(), SourceTexture->GetNumMipLevel(), SourceTexture->GetFormat(), NUX_TRACKER_LOCATION); for (int i = 0; i < SourceTexture->GetNumMipLevel(); i++) { LoadMipLevel(SourceTexture, i); } } CachedTexture2D::~CachedTexture2D() { } void CachedTexture2D::UpdateTexture( BaseTexture* SourceTexture ) { if ((SourceTexture == 0) || SourceTexture->IsNull()) { m_Texture = ObjectPtr (0); return; } if (!SourceTexture->Type().IsObjectType(Texture2D::StaticObjectType)) { nuxAssertMsg(0, "[Texture2D::UpdateTexture] Source texture is not of type Texture2D."); return; } if ( RecreateTexture(SourceTexture)) { m_Texture = GetGraphicsDisplay()->GetGpuDevice()->CreateTexture(SourceTexture->GetWidth(), SourceTexture->GetHeight(), SourceTexture->GetNumMipLevel(), SourceTexture->GetFormat(), NUX_TRACKER_LOCATION); for (int i = 0; i < SourceTexture->GetNumMipLevel(); i++) { LoadMipLevel(SourceTexture, i); } } else { for (int i = 0; i < SourceTexture->GetNumMipLevel(); i++) { LoadMipLevel(SourceTexture, i); } } } void CachedTexture2D::LoadMipLevel(BaseTexture* SourceTexture, int MipLevel) { SURFACE_LOCKED_RECT LockedRect; ObjectPtr < IOpenGLTexture2D > Texture2D = m_Texture; //m_Texture.CastRef(); if (!Texture2D) return; OGL_CALL(Texture2D->LockRect(MipLevel, &LockedRect, NULL)); SourceTexture->GetData(LockedRect.pBits, MipLevel, LockedRect.Pitch); OGL_CALL(Texture2D->UnlockRect(MipLevel)); } TextureRectangle::TextureRectangle(NUX_FILE_LINE_DECL) : BaseTexture(NUX_FILE_LINE_PARAM) { } TextureRectangle::TextureRectangle(const NTextureData& texture, NUX_FILE_LINE_DECL) : BaseTexture(NUX_FILE_LINE_PARAM), _image(texture) { } TextureRectangle::~TextureRectangle() { } bool TextureRectangle::Update(const NBitmapData* BitmapData, bool UpdateAndCacheResource) { nuxAssertMsg(BitmapData, "[TextureRectangle::Update] Argument BitmapData is NULL."); NUX_RETURN_VALUE_IF_NULL(BitmapData, false); if (!BitmapData->IsTextureData()) { nuxAssertMsg(0, "[TextureRectangle::Update] Argument BitmapData is not a 2D texture"); return false; } _image = *static_cast (BitmapData); if (UpdateAndCacheResource) { // call the texture manager and recreate the texture(CachedTexture2D) associated with this object if any. GetGraphicsDisplay()->GetGraphicsEngine()->UpdateResource(this); } return true; } bool TextureRectangle::Update(const char* filename, bool /* UpdateAndCacheResource */) { bool b = false; NBitmapData* BitmapData = LoadImageFile(filename); nuxAssertMsg(BitmapData, "[TextureRectangle::Update] Bitmap for file(%s) is NULL.", filename); NUX_RETURN_VALUE_IF_NULL(BitmapData, false); b = Update(BitmapData); NUX_SAFE_DELETE(BitmapData); return b; } void TextureRectangle::GetData(void* Buffer, int MipIndex, int StrideY, int /* face */) { BYTE *Dest = (BYTE *) Buffer; const BYTE *Src = _image.GetSurface(MipIndex).GetPtrRawData(); int RowByteSize = _image.GetSurface(MipIndex).GetPitch(); int NumRows = _image.GetSurface(MipIndex).GetBlockHeight(); for ( int Y = 0; Y < NumRows; Y++ ) { // Take Min(RowByteSize, StrideY): the source and the destination may not have the same Pitch but // they contain the same amount of valid data since they have the same width, height and format. Memcpy(Dest + Y * StrideY, &Src[Y * RowByteSize], Min(RowByteSize, StrideY)); } } TextureRectangle* TextureRectangle::Clone() const { return new TextureRectangle(_image); } CachedTextureRectangle::CachedTextureRectangle(NResourceSet* ResourceManager, TextureRectangle* SourceTexture) : CachedBaseTexture(ResourceManager) { if (SourceTexture->IsNull()) { m_Texture = ObjectPtr (0); return; } m_Texture = GetGraphicsDisplay()->GetGpuDevice()->CreateRectangleTexture(SourceTexture->GetWidth(), SourceTexture->GetHeight(), SourceTexture->GetNumMipLevel(), SourceTexture->GetFormat(), NUX_TRACKER_LOCATION); for (int i = 0; i < SourceTexture->GetNumMipLevel(); i++) { LoadMipLevel(SourceTexture, i); } } CachedTextureRectangle::~CachedTextureRectangle() { } void CachedTextureRectangle::UpdateTexture( BaseTexture* SourceTexture ) { if ((SourceTexture == 0) || SourceTexture->IsNull()) { m_Texture = ObjectPtr (0); return; } if (!SourceTexture->Type().IsObjectType(TextureRectangle::StaticObjectType)) { nuxAssertMsg(0, "[CachedTextureRectangle::UpdateTexture] Source texture is not of type TextureRectangle."); return; } if ( RecreateTexture(SourceTexture)) { m_Texture = GetGraphicsDisplay()->GetGpuDevice()->CreateRectangleTexture(SourceTexture->GetWidth(), SourceTexture->GetHeight(), SourceTexture->GetNumMipLevel(), SourceTexture->GetFormat(), NUX_TRACKER_LOCATION); for (int i = 0; i < SourceTexture->GetNumMipLevel(); i++) { LoadMipLevel(SourceTexture, i); } } else { for (int i = 0; i < SourceTexture->GetNumMipLevel(); i++) { LoadMipLevel(SourceTexture, i); } } } void CachedTextureRectangle::LoadMipLevel(BaseTexture* SourceTexture, int MipLevel) { SURFACE_LOCKED_RECT LockedRect; ObjectPtr TextureRectangle = m_Texture; //m_Texture.CastRef(); if (!TextureRectangle) return; OGL_CALL(TextureRectangle->LockRect( MipLevel, &LockedRect, NULL)); SourceTexture->GetData( LockedRect.pBits, MipLevel, LockedRect.Pitch ); OGL_CALL(TextureRectangle->UnlockRect( MipLevel )); } TextureCube::TextureCube(NUX_FILE_LINE_DECL) // TODO: why can we have a texture without a texture? : BaseTexture(NUX_FILE_LINE_PARAM) { } TextureCube::TextureCube(const NCubemapData& Image) : _image(Image) { } TextureCube::~TextureCube() { } bool TextureCube::Update(const NBitmapData* BitmapData, bool UpdateAndCacheResource) { nuxAssertMsg(BitmapData, "[TextureCube::Update] Argument BitmapData is NULL."); NUX_RETURN_VALUE_IF_NULL(BitmapData, false); if (!BitmapData->IsCubemapTextureData()) { nuxAssertMsg(0, "[TextureCube::Update] Argument BitmapData is not a Cube texture"); return false; } _image = *static_cast (BitmapData); if (UpdateAndCacheResource) { // call the texture manager and recreate the texture(CachedTexture2D) associated with this object if any. GetGraphicsDisplay()->GetGraphicsEngine()->UpdateResource(this); } return true; } bool TextureCube::Update(const char* filename, bool /* UpdateAndCacheResource */) { NBitmapData* BitmapData = LoadImageFile(filename); nuxAssertMsg(BitmapData, "[TextureCube::Update] Bitmap for file(%s) is NULL.", filename); NUX_RETURN_VALUE_IF_NULL(BitmapData, false); bool ret = Update(BitmapData); NUX_SAFE_DELETE(BitmapData); return ret; } void TextureCube::GetData(void* Buffer, int MipIndex, int StrideY, int face) { BYTE *Dest = (BYTE *) Buffer; const BYTE *Src = _image.GetSurface(face, MipIndex).GetPtrRawData(); int RowByteSize = _image.GetSurface(face, MipIndex).GetPitch(); int NumRows = _image.GetSurface(face, MipIndex).GetBlockHeight(); for ( int Y = 0; Y < NumRows; Y++ ) { // Take Min(RowByteSize, StrideY): the source and the destination may not have the same Pitch but // they contain the same amount of valid data since they have the same width, height and format. Memcpy(Dest + Y * StrideY, &Src[Y * RowByteSize], Min(RowByteSize, StrideY)); } } TextureCube* TextureCube::Clone() const { return new TextureCube(_image); } CachedTextureCube::CachedTextureCube(NResourceSet* ResourceManager, TextureCube* SourceTexture) : CachedBaseTexture(ResourceManager) { if (SourceTexture->IsNull()) { m_Texture = ObjectPtr (0); return; } m_Texture = GetGraphicsDisplay()->GetGpuDevice()->CreateCubeTexture(SourceTexture->GetWidth(), SourceTexture->GetNumMipLevel(), SourceTexture->GetFormat()); for (int i = 0; i < SourceTexture->GetNumMipLevel(); i++) { LoadMipLevel(SourceTexture, i); } } CachedTextureCube::~CachedTextureCube() { } void CachedTextureCube::UpdateTexture( BaseTexture* SourceTexture ) { if ((SourceTexture == 0) || SourceTexture->IsNull()) { m_Texture = ObjectPtr (0); return; } if (!SourceTexture->Type().IsObjectType(TextureCube::StaticObjectType)) { nuxAssertMsg(0, "[CachedTextureCube::UpdateTexture] Source texture is not of type TextureCube."); return; } if ( RecreateTexture(SourceTexture)) { m_Texture = GetGraphicsDisplay()->GetGpuDevice()->CreateCubeTexture(SourceTexture->GetWidth(), SourceTexture->GetNumMipLevel(), SourceTexture->GetFormat()); for (int i = 0; i < SourceTexture->GetNumMipLevel(); i++) { LoadMipLevel(SourceTexture, i); } } else { for (int i = 0; i < SourceTexture->GetNumMipLevel(); i++) { LoadMipLevel(SourceTexture, i); } } } void CachedTextureCube::LoadMipLevel(BaseTexture* SourceTexture, int MipLevel) { SURFACE_LOCKED_RECT LockedRect; ObjectPtr CubemapTexture = m_Texture; //m_Texture.CastRef(); if (!CubemapTexture) return; for (int face = CUBEMAP_FACE_POSITIVE_X; face < GL_TEXTURE_CUBE_MAP_NEGATIVE_Z + 1; face++) { OGL_CALL( CubemapTexture->CubeLockRect(eCUBEMAP_FACES(face), MipLevel, &LockedRect, NULL)); SourceTexture->GetData(LockedRect.pBits, MipLevel, LockedRect.Pitch, face - CUBEMAP_FACE_POSITIVE_X); OGL_CALL( CubemapTexture->CubeUnlockRect(eCUBEMAP_FACES(face), MipLevel )); } } TextureVolume::TextureVolume(NUX_FILE_LINE_DECL) // TODO: why can we have a texture without a texture? : BaseTexture(NUX_FILE_LINE_PARAM) { } TextureVolume::TextureVolume(const NVolumeData& Image) : _image(Image) { } TextureVolume::~TextureVolume() { } bool TextureVolume::Update(const NBitmapData* BitmapData, bool UpdateAndCacheResource) { nuxAssertMsg(BitmapData, "[TextureVolume::Update] Argument BitmapData is NULL."); NUX_RETURN_VALUE_IF_NULL(BitmapData, false); if (!BitmapData->IsVolumeTextureData()) { nuxAssertMsg(0, "[TextureVolume::Update] Argument BitmapData is not a Volume texture"); return false; } _image = *static_cast (BitmapData); if (UpdateAndCacheResource) { // call the texture manager and recreate the texture(CachedTexture2D) associated with this object if any. GetGraphicsDisplay()->GetGraphicsEngine()->UpdateResource(this); } return true; } bool TextureVolume::Update(const char* filename, bool /* UpdateAndCacheResource */) { NBitmapData* BitmapData = LoadImageFile(filename); nuxAssertMsg(BitmapData, "[TextureVolume::Update] Bitmap for file(%s) is NULL.", filename); NUX_RETURN_VALUE_IF_NULL(BitmapData, false); bool ret = Update(filename); NUX_SAFE_DELETE(BitmapData); return ret; } void TextureVolume::GetData(void* Buffer, int MipIndex, int StrideY, int /* face */) { BYTE *Dest = (BYTE *) Buffer; // const BYTE* Src = _image.GetSurface(MipIndex, slice).GetPtrRawData(); // int RowByteSize = _image.GetSurface(MipIndex, slice).GetPitch(); // int NumRows = _image.GetSurface(MipIndex, slice).GetBlockHeight(); for (int slice = 0; slice < ImageSurface::GetLevelDim(_image.GetFormat(), _image.GetDepth(), MipIndex); slice++) { const BYTE *Src = _image.GetSurface(slice, MipIndex).GetPtrRawData(); int RowByteSize = _image.GetSurface(slice, MipIndex).GetPitch(); int NumRows = _image.GetSurface(slice, MipIndex).GetBlockHeight(); for ( int Y = 0; Y < NumRows; Y++ ) { // Take Min(RowByteSize, StrideY): the source and the destination may not have the same Pitch but // they contain the same amount of valid data since they have the same width, height and format. Memcpy(Dest + Y * StrideY, &Src[Y * RowByteSize], Min(RowByteSize, StrideY)); } Dest += NumRows * StrideY; } // BYTE* Dest = (BYTE*)Buffer; // const BYTE* Src = _image.GetSurface(MipIndex, slice).GetPtrRawData(); // int RowByteSize = _image.GetSurface(MipIndex, slice).GetPitch(); // int NumRows = _image.GetSurface(MipIndex, slice).GetBlockHeight(); // // for ( int Y = 0; Y < NumRows; Y++ ) // { // // Take Min(RowByteSize, StrideY): the source and the destination may not have the same Pitch but // // they contain the same amount of valid data since they have the same width, height and format. // Memcpy(Dest + Y * StrideY,&Src[Y * RowByteSize], Min(RowByteSize, StrideY)); // } } TextureVolume* TextureVolume::Clone() const { return new TextureVolume(_image); } CachedTextureVolume::CachedTextureVolume(NResourceSet* ResourceManager, TextureVolume* SourceTexture) : CachedBaseTexture(ResourceManager) { if (SourceTexture->IsNull()) { m_Texture = ObjectPtr (0); return; } m_Texture = GetGraphicsDisplay()->GetGpuDevice()->CreateVolumeTexture(SourceTexture->GetWidth(), SourceTexture->GetHeight(), SourceTexture->GetDepth(), SourceTexture->GetNumMipLevel(), SourceTexture->GetFormat()); for (int i = 0; i < SourceTexture->GetNumMipLevel(); i++) { LoadMipLevel(SourceTexture, i); } } CachedTextureVolume::~CachedTextureVolume() { } void CachedTextureVolume::UpdateTexture( BaseTexture* SourceTexture ) { if ((SourceTexture == 0) || SourceTexture->IsNull()) { m_Texture = ObjectPtr (0); return; } if (!SourceTexture->Type().IsObjectType(TextureVolume::StaticObjectType)) { nuxAssertMsg(0, "[CachedTextureVolume::UpdateTexture] Source texture is not of type TextureVolume."); return; } if ( RecreateTexture(SourceTexture)) { m_Texture = GetGraphicsDisplay()->GetGpuDevice()->CreateVolumeTexture(SourceTexture->GetWidth(), SourceTexture->GetHeight(), SourceTexture->GetDepth(), SourceTexture->GetNumMipLevel(), SourceTexture->GetFormat()); for (int i = 0; i < SourceTexture->GetNumMipLevel(); i++) { LoadMipLevel(SourceTexture, i); } } else { for (int i = 0; i < SourceTexture->GetNumMipLevel(); i++) { LoadMipLevel(SourceTexture, i); } } } void CachedTextureVolume::LoadMipLevel(BaseTexture* SourceTexture, int MipLevel) { VOLUME_LOCKED_BOX LockedBox; ObjectPtr VolumeTexture = m_Texture; //m_Texture.CastRef(); if (!VolumeTexture) return; //TextureVolume* Source = UpCastResource(SourceTexture); //for(int slice = 0; slice < ImageSurface::GetLevelDim(Source->GetFormat(), Source->GetDepth(), MipLevel); slice++) { OGL_CALL( VolumeTexture->LockBox(MipLevel, &LockedBox, NULL)); SourceTexture->GetData(LockedBox.pBits, MipLevel, LockedBox.RowPitch, 0); OGL_CALL( VolumeTexture->UnlockBox(MipLevel)); } // for (int slice = 0; slice < depth; slice++) // { // OGL_CALL( VolumeTexture->LockRect(slice, MipLevel, &LockedRect, NULL)); // SourceTexture->GetData(LockedRect.pBits, MipLevel, LockedRect.Pitch, slice); // OGL_CALL( VolumeTexture->UnlockRect(slice, MipLevel )); // } } TextureFrameAnimation::TextureFrameAnimation(NUX_FILE_LINE_DECL) // TODO: why can we have a texture without a texture? : BaseTexture(NUX_FILE_LINE_PARAM) { } TextureFrameAnimation::TextureFrameAnimation(const NAnimatedTextureData& Image) : _image(Image) { } TextureFrameAnimation::~TextureFrameAnimation() { } bool TextureFrameAnimation::Update(const NBitmapData* BitmapData, bool UpdateAndCacheResource) { nuxAssertMsg(BitmapData, "[TextureFrameAnimation::Update] Argument BitmapData is NULL."); NUX_RETURN_VALUE_IF_NULL(BitmapData, false); if (!BitmapData->IsAnimatedTextureData()) { nuxAssertMsg(0, "[TextureFrameAnimation::Update] Argument BitmapData is not a Animated texture"); return false; } _image = *static_cast (BitmapData); if (UpdateAndCacheResource) { // call the texture manager and recreate the texture(CachedTexture2D) associated with this object if any. GetGraphicsDisplay()->GetGraphicsEngine()->UpdateResource(this); } return true; } bool TextureFrameAnimation::Update(const char* filename, bool /* UpdateAndCacheResource */) { NBitmapData* BitmapData = LoadImageFile(filename); nuxAssertMsg(BitmapData, "[TextureFrameAnimation::Update] Bitmap for file(%s) is NULL.", filename); NUX_RETURN_VALUE_IF_NULL(BitmapData, false); bool ret = Update(BitmapData); NUX_SAFE_DELETE(BitmapData); return ret; } void TextureFrameAnimation::GetData(void* Buffer, int /* MipIndex */, int StrideY, int slice) { BYTE *Dest = (BYTE *) Buffer; //for(int slice = 0; slice < ImageSurface::GetLevelDim(_image.GetFormat(), _image.GetDepth(), MipIndex); slice++) { const BYTE *Src = _image.GetSurface(slice).GetPtrRawData(); int RowByteSize = _image.GetSurface(slice).GetPitch(); int NumRows = _image.GetSurface(slice).GetBlockHeight(); for (int Y = 0; Y < NumRows; Y++) { // Take Min(RowByteSize, StrideY): the source and the destination may not have the same Pitch but // they contain the same amount of valid data since they have the same width, height and format. Memcpy(Dest + Y * StrideY, &Src[Y * RowByteSize], Min(RowByteSize, StrideY)); } //Dest += NumRows * StrideY; } } int TextureFrameAnimation::GetFrameTime(int Frame) { return _image.GetFrameTime(Frame); } TextureFrameAnimation* TextureFrameAnimation::Clone() const { return new TextureFrameAnimation(_image); } CachedTextureFrameAnimation::CachedTextureFrameAnimation(NResourceSet* ResourceManager, TextureFrameAnimation* SourceTexture) : CachedBaseTexture(ResourceManager) { if (SourceTexture->IsNull()) { m_Texture = ObjectPtr (0); return; } m_Texture = GetGraphicsDisplay()->GetGpuDevice()->CreateAnimatedTexture(SourceTexture->GetWidth(), SourceTexture->GetHeight(), SourceTexture->GetDepth(), SourceTexture->GetFormat()); for (int i = 0; i < SourceTexture->GetNumMipLevel(); i++) { LoadMipLevel(SourceTexture, i); } } CachedTextureFrameAnimation::~CachedTextureFrameAnimation() { } void CachedTextureFrameAnimation::UpdateTexture( BaseTexture* SourceTexture ) { if ((SourceTexture == 0) || SourceTexture->IsNull()) { m_Texture = ObjectPtr (0); return; } if (!SourceTexture->Type().IsObjectType(TextureFrameAnimation::StaticObjectType)) { nuxAssertMsg(0, "[CachedTextureFrameAnimation::UpdateTexture] Source texture is not of type TextureFrameAnimation."); return; } if (RecreateTexture(SourceTexture)) { m_Texture = GetGraphicsDisplay()->GetGpuDevice()->CreateAnimatedTexture(SourceTexture->GetWidth(), SourceTexture->GetHeight(), SourceTexture->GetDepth(), SourceTexture->GetFormat()); for (int i = 0; i < SourceTexture->GetNumMipLevel(); i++) { LoadMipLevel(SourceTexture, i); } } else { for (int i = 0; i < SourceTexture->GetNumMipLevel(); i++) { LoadMipLevel(SourceTexture, i); } } } void CachedTextureFrameAnimation::LoadMipLevel(BaseTexture* SourceTexture, int /* MipLevel */) { SURFACE_LOCKED_RECT LockedRect; ObjectPtr AnimatedTexture = m_Texture; //m_Texture.CastRef(); if (!AnimatedTexture) return; TextureFrameAnimation* Source = UpCastResource (SourceTexture); for (int frame = 0; frame < Source->GetDepth(); frame++) { OGL_CALL( AnimatedTexture->LockRect(frame, &LockedRect, NULL)); SourceTexture->GetData(LockedRect.pBits, 0, LockedRect.Pitch, frame); OGL_CALL( AnimatedTexture->UnlockRect(frame)); AnimatedTexture->SetFrameTime(frame, Source->GetFrameTime(frame)); } } } ./NuxGraphics/GestureEvent.h0000644000004100000410000001302313313171755016274 0ustar www-datawww-data/* * Copyright 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Daniel d'Andrada * */ #ifndef NUX_GESTURE_EVENT_H #define NUX_GESTURE_EVENT_H #include "Nux/Features.h" #ifdef NUX_GESTURES_SUPPORT #include #include #include "Events.h" #include "NuxCore/Math/Point2D.h" namespace nux { //! Enumerates all possible gesture classes. enum GestureClass { DRAG_GESTURE = 1, //! A drag gesture PINCH_GESTURE = 2, //! A pinch gesture ROTATE_GESTURE = 4, //! A rotation gesture TAP_GESTURE = 8, //! A tap gesture. TOUCH_GESTURE = 16 /*! A touch gesture. It merely groups two or more touch points and send their information, without interpreting what gestures the touch points are performing. */ }; class TouchPoint { public: TouchPoint() : id(-1), x(0.0f), y(0.0f) {} TouchPoint(int id, float x, float y) : id(id), x(x), y(y) {} bool operator ==(const TouchPoint& other) const { return id == other.id; } int id; float x; float y; }; //! Gesture Event class class GestureEvent : public Event { public: //! Constructs a GestureEvent GestureEvent(); //! Accepts the gesture. void Accept(); //! Rejects the gesture. void Reject(); //! The gesture classes that this gesture belongs to. /*! A bitwise "or" of one or more gesture classes from GestureClass enumeration. A single physical gesture can comply/belong to more than one gesture class, such as a rotating pinch. */ int GetGestureClasses() const {return gesture_classes_;} //! Whether all gestures for the related touch points have been presented. /*! This property allows the client to determine if all the possible gestures from the set of touches in this event have already been presented. When this value is true, the client will have received all the information needed to make a gesture accept and reject decision based on potentially overlapping gestures. An example is when both one and two touch gestures are subscribed on the same window with the same gesture classes and thresholds. When this property is true for one touch gesture events, the client can be sure there are no other touches unless a two touch gesture event has already been sent. Another example is when you subscribe for three touches Touch and four touches Drag. As soon as a third finger is detected a three touches Touch gesture will begin, but you cannot be sure a fourth finger isn't coming right after (that can eventually cause a four touches Drag) until this property is true. */ bool IsConstructionFinished() const { return is_construction_finished_;} int GetGestureId() const {return gesture_id_;} bool IsDirectTouch() const {return is_direct_touch_;} int GetTimestamp() const {return timestamp_;} const Point2D &GetFocus() const {return focus_;} const Point2D &GetDelta() const {return delta_;} float GetAngle() const {return angle_;} float GetAngleDelta() const {return angle_delta_;} float GetAngularVelocity() const {return angular_velocity_;} //! Duration of a tap gesture, in milliseconds int GetTapDuration() const {return tap_duration_;} const Point2D &GetVelocity() {return velocity_;} float GetRadius() const {return radius_;} float GetRadiusDelta() const {return radius_delta_;} float GetRadialVelocity() const {return radial_velocity_;} const std::vector &GetTouches() const {return touches_;} virtual void Reset(); private: int gesture_id_; int gesture_classes_; bool is_direct_touch_; int timestamp_; Point2D focus_; Point2D delta_; float angle_; float angle_delta_; float angular_velocity_; int tap_duration_; Point2D velocity_; float radius_; float radius_delta_; float radial_velocity_; std::vector touches_; bool is_construction_finished_; Geis geis_; GeisGroup geis_group_; friend class GeisAdapter; friend class FakeGestureEvent; }; //! Enumerates possible requests regarding delivery of gesture events. enum class GestureDeliveryRequest { NONE, /*!< No request. Continue with current delivery policy. */ EXCLUSIVITY /*!< From this moment onwards, deliver events from the related gesture only to this target. Other targets for this gesture will receive an event of type EVENT_GESTURE_LOST instead of this event. Note that it doesn't affect targets that come before this one in the order of delivery. */ }; } // namespace nux #endif // NUX_GESTURES_SUPPORT #endif // NUX_GESTURE_EVENT_H ./NuxGraphics/ImageSurface.h0000644000004100000410000004113013313171755016207 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef IMAGESURFACE_H #define IMAGESURFACE_H #include "BitmapFormats.h" #include "NuxCore/Math/MathUtility.h" #include #define DEBUG_ENTER(a) #define DEBUG_WARNING(a) #define DEBUG_EXIT(a) namespace nux { class RawData { public: RawData() {}; ~RawData() {}; //! Get number of elements. unsigned int GetElementCount() { return 0; } //! Get the number of bytes per elements. unsigned int GetElementSize() { return 0; } void GetSize() {}; }; struct DXTColBlock { unsigned short col0; unsigned short col1; unsigned char row[4]; }; struct DXT3AlphaBlock { unsigned short row[4]; }; struct DXT5AlphaBlock { unsigned char alpha0; unsigned char alpha1; unsigned char row[6]; }; //! Image Surface class /*! Represent and image surface inside a complex data structure such as a 2D texture, Volume texture or Cube map. */ class ImageSurface { public: ImageSurface(); ImageSurface(BitmapFormat format, unsigned int width, unsigned int height); ImageSurface(const ImageSurface &); ImageSurface(ImageSurface&&); ImageSurface &operator = (ImageSurface); bool IsNull() const; int GetWidth() const { return width_; } int GetHeight() const { return height_; } void Allocate(BitmapFormat format, int width, int height); void Write32b(int i, int j, unsigned int value); void Write24b(int i, int j, unsigned int value); void Write16b(int i, int j, unsigned short value); void Write8b(int i, int j, unsigned char value); void Write(int i, int j, unsigned char r, unsigned char g, unsigned char b, unsigned char a); //! Read an element of the surface. /*! Return a 32 bits value representing the image element at coordinates(i, j). For the RGBA format, the LSB of the returned value represent the read value, and the MSB represents the alpha value. | LSB: Red | Green | Blue | MSB: Alpha| @return The image element at coordinates(i, j). */ unsigned int Read(int i, int j); //! Set all surface elements to 0. void Clear(); //! Flip the surface horizontally. void FlipHorizontal(); //! Flip the surface vertically. void FlipVertical(); //! Returns the surface pitch. int GetPitch() const; int GetBlockHeight() const; int GetAlignment() const; int GetSize() const; BitmapFormat GetFormat() const; const unsigned char *GetPtrRawData() const; unsigned char *GetPtrRawData(); static int GetLevelPitch(BitmapFormat format, int width, int height, int miplevel); static int GetLevelPitchNoMemAlignment(BitmapFormat format, int width, int height, int miplevel); static int GetLevelSize(BitmapFormat format, int width, int height, int miplevel); static int GetLevelSize(BitmapFormat format, int width, int height, int depth, int miplevel); static int GetLevelWidth(BitmapFormat format, int width, int miplevel); static int GetLevelHeight(BitmapFormat format, int height, int miplevel); static int GetLevelDim(BitmapFormat format, int length, int miplevel); static int GetNumMipLevel(BitmapFormat format, int width, int height); static int GetMemAlignment(BitmapFormat format); static int GetLevelBlockWidth(BitmapFormat format, int width, int miplevel); static int GetLevelBlockHeight(BitmapFormat format, int height, int miplevel); // for DXT // Image Processing //! Compute the average color of the image surface. /*! Sum up all the image elements and divide by the number of elements. @return The average color of the image. */ Color AverageColor(); private: void FlipDXTVertical(); void SwapBlocks(void *byte1, void *byte2, int size); void FlipBlocksDXT1(DXTColBlock *line, int numBlocks); void FlipBlocksDXT3(DXTColBlock *line, int numBlocks); void FlipBlocksDXT5(DXTColBlock *line, int numBlocks); void FlipDXT5Alpha(DXT5AlphaBlock *block); friend void swap(ImageSurface&, ImageSurface&); int width_; //!< Image width int height_; //!< Image height. BitmapFormat format_; //!< Image format. int m_Pitch; //!< Image pitch. int bpe_; //!< Number of byte per element. int Alignment_; //!< Data alignment. std::vector RawData_; }; void swap(ImageSurface&, ImageSurface&); class NBitmapData { public: NBitmapData(); virtual ~NBitmapData(); virtual const ImageSurface &GetSurface(int MipLevel) const = 0; virtual ImageSurface &GetSurface(int MipLevel) = 0; virtual const ImageSurface &GetSurface(int face, int MipLevel) const = 0; virtual ImageSurface &GetSurface(int face, int MipLevel) = 0; virtual bool IsTextureData() const { return false; }; virtual bool IsCubemapTextureData() const { return false; } virtual bool IsVolumeTextureData() const { return false; } virtual bool IsAnimatedTextureData() const { return false; } virtual int GetNumMipmap() const = 0; virtual int GetWidth() const = 0; virtual int GetHeight() const = 0; virtual int GetDepth() const { return 0; } virtual BitmapFormat GetFormat() const = 0; virtual bool IsNull() const = 0; virtual int GetMemorySize() const { return m_TotalMemorySize; } protected: unsigned int m_TotalMemorySize; //protected: // unsigned int m_Width; // unsigned int m_Height; // BitmapFormat m_Format; }; class NTextureData: public NBitmapData { public: NTextureData(BitmapFormat f = BITFMT_R8G8B8A8, int width = 16, int height = 16, int NumMipmap = 1); virtual ~NTextureData() {} //! Copy constructor. NTextureData(const NTextureData &); //! Assignment constructor. NTextureData &operator = (NTextureData); //! Move constructor NTextureData(NTextureData&&); virtual void Allocate(BitmapFormat f, int width, int height, int NumMipmap = 1); virtual void AllocateCheckBoardTexture(int width, int height, int NumMipmap, Color color0, Color color1, int TileWidth = 4, int TileHeight = 4); virtual void AllocateColorTexture(int width, int height, int NumMipmap, Color color0 = Color(0xFFFFFFF)); virtual const ImageSurface &GetSurface(int MipLevel) const { return m_MipSurfaceArray[MipLevel]; }; virtual ImageSurface &GetSurface(int MipLevel) { return const_cast ((const_cast< const NTextureData * > (this))->GetSurface(MipLevel)); } virtual const ImageSurface &GetSurface(int /* face */, int MipLevel) const { //nuxAssertMsg(0, "[NTextureData::GetSurface] Use GetSurface(unsigned int MipLevel) for NTextureData."); return GetSurface(MipLevel); } virtual ImageSurface &GetSurface(int /* face */, int MipLevel) { //nuxAssertMsg(0, "[NTextureData::GetSurface] Use GetSurface(unsigned int MipLevel) for NTextureData."); return GetSurface(MipLevel); } bool SetSurface(int MipLevel, const ImageSurface &object); virtual bool IsTextureData() const { return true; } virtual int GetNumMipmap() const; virtual int GetWidth() const { return m_MipSurfaceArray[0].GetWidth(); } virtual int GetHeight() const { return m_MipSurfaceArray[0].GetHeight(); } virtual BitmapFormat GetFormat() const { return m_MipSurfaceArray[0].GetFormat(); } virtual bool IsNull() const { return m_MipSurfaceArray[0].IsNull(); } private: void swap(NTextureData& other); int m_NumMipmap; std::vector m_MipSurfaceArray; #if defined(NUX_OS_WINDOWS) friend NBitmapData *read_tga_file(const TCHAR *file_name); #endif }; class NCubemapData: public NBitmapData { public: NCubemapData(BitmapFormat f = BITFMT_R8G8B8A8, int width = 16, int height = 16, int NumMipmap = 1); virtual ~NCubemapData(); //! Copy constructor NCubemapData(const NCubemapData &); //! Assignment constructor NCubemapData &operator = (const NCubemapData &); virtual void Allocate(BitmapFormat f, int width, int height, int NumMipmap = 1); virtual void AllocateCheckBoardTexture(int width, int height, int NumMipmap, Color color0, Color color1, int TileWidth = 4, int TileHeight = 4); virtual void AllocateColorTexture(int width, int height, int NumMipmap, Color color0 = Color(0xFFFFFFF)); virtual const ImageSurface &GetSurface(int face, int MipLevel) const { return *m_MipSurfaceArray[face][MipLevel]; }; virtual ImageSurface &GetSurface(int face, int MipLevel) { return const_cast ((const_cast< const NCubemapData * > (this))->GetSurface(face, MipLevel)); } virtual const ImageSurface &GetSurface(int MipLevel) const { nuxAssertMsg(0, "[NCubemapData::GetSurface] Use GetSurface(unsigned int face, unsigned int MipLevel) for NCubemapData."); return GetSurface(0, MipLevel); } virtual ImageSurface &GetSurface(int MipLevel) { nuxAssertMsg(0, "[NCubemapData::GetSurface] Use GetSurface(unsigned int face, unsigned int MipLevel) for NCubemapData."); return GetSurface(0, MipLevel); } bool SetSurface(int face, int MipLevel, const ImageSurface &object); virtual bool IsCubemapTextureData() const { return true; } virtual int GetNumMipmap() const; virtual int GetWidth() const { return m_MipSurfaceArray[0][0]->GetWidth(); } virtual int GetHeight() const { return m_MipSurfaceArray[0][0]->GetHeight(); } virtual BitmapFormat GetFormat() const { return m_MipSurfaceArray[0][0]->GetFormat(); } virtual bool IsNull() const { return m_MipSurfaceArray[0][0]->IsNull(); } private: void ClearData(); int m_NumMipmap; std::vector m_MipSurfaceArray[6]; }; class NVolumeData: public NBitmapData { public: NVolumeData(BitmapFormat f = BITFMT_R8G8B8A8, int width = 16, int height = 16, int slice = 1, int NumMipmap = 1); virtual ~NVolumeData(); //! Copy constructor NVolumeData(const NVolumeData &); //! Assignment constructor NVolumeData &operator = (const NVolumeData &); virtual void Allocate(BitmapFormat f, int width, int height, int slice, int NumMipmap = 1); virtual void AllocateCheckBoardTexture(int width, int height, int slice, int NumMipmap, Color color0, Color color1, int TileWidth = 4, int TileHeight = 4); virtual void AllocateColorTexture(int width, int height, int slice, int NumMipmap, Color color0 = Color(0xFFFFFFF)); virtual const ImageSurface &GetSurface(int slice, int MipLevel) const { return *m_MipSurfaceArray[MipLevel][slice]; }; virtual ImageSurface &GetSurface(int slice, int MipLevel) { return const_cast ((const_cast< const NVolumeData * > (this))->GetSurface(slice, MipLevel)); } virtual const ImageSurface &GetSurface(int MipLevel) const { nuxAssertMsg(0, "[NVolumeData::GetSurface] Use GetSurface(unsigned int MipLevel, unsigned int MipLevel) for NVolumeData."); return GetSurface(MipLevel, 0); } virtual ImageSurface &GetSurface(int MipLevel) { nuxAssertMsg(0, "[NVolumeData::GetSurface] Use GetSurface(unsigned int MipLevel, unsigned int MipLevel) for NVolumeData."); return GetSurface(MipLevel, 0); } bool SetSurface(int face, int MipLevel, const ImageSurface &object); virtual bool IsVolumeTextureData() const { return true; } int GetNumMipmap() const; virtual int GetWidth() const { return m_MipSurfaceArray[0][0]->GetWidth(); } virtual int GetHeight() const { return m_MipSurfaceArray[0][0]->GetHeight(); } virtual int GetDepth() const { return m_Depth; } virtual BitmapFormat GetFormat() const { return m_MipSurfaceArray[0][0]->GetFormat(); } virtual bool IsNull() const { return m_MipSurfaceArray[0][0]->IsNull(); } private: void ClearData(); int m_NumMipmap; int m_Depth; std::vector *m_MipSurfaceArray; }; class NAnimatedTextureData: public NBitmapData { public: NAnimatedTextureData(BitmapFormat f = BITFMT_R8G8B8A8, int width = 16, int height = 16, int slice = 1 /*, unsigned int NumMipmap = 1*/); virtual ~NAnimatedTextureData(); //! Copy constructor NAnimatedTextureData(const NAnimatedTextureData &); //! Assignment constructor NAnimatedTextureData &operator = (const NAnimatedTextureData &); virtual void Allocate(BitmapFormat f, int width, int height, int slice, int NumMipmap = 1); virtual void AllocateCheckBoardTexture(int width, int height, int slice, int NumMipmap, Color color0, Color color1, int TileWidth = 4, int TileHeight = 4); virtual void AllocateColorTexture(int width, int height, int slice, int NumMipmap, Color color0 = Color(0xFFFFFFF)); virtual const ImageSurface &GetSurface(int /* MipLevel */, int /* slice */) const { nuxAssertMsg(0, "[NAnimatedTextureData::GetSurface] Use GetSurface(unsigned int Frame) for NAnimatedTextureData."); return GetSurface(0); } virtual ImageSurface &GetSurface(int /* MipLevel */, int /* slice */) { nuxAssertMsg(0, "[NAnimatedTextureData::GetSurface] Use GetSurface(unsigned int Frame) for NAnimatedTextureData."); return GetSurface(0); } virtual const ImageSurface &GetSurface(int Frame) const { nuxAssert(Frame >= 0); nuxAssert(Frame < m_Depth); return *m_MipSurfaceArray[0][Frame]; } virtual ImageSurface &GetSurface(int Frame) { nuxAssert(Frame >= 0); nuxAssert(Frame < m_Depth); return const_cast ((const_cast< const NAnimatedTextureData * > (this))->GetSurface(Frame)); } bool SetSurface(int face, int MipLevel, const ImageSurface &object); virtual bool IsAnimatedTextureData() const { return true; } int GetFrameTime(int Frame) const { nuxAssert(Frame >= 0); nuxAssert(Frame < m_Depth); return m_FrameTimeArray[Frame]; } void AddFrameTime(unsigned int FrameTime) { m_FrameTimeArray.push_back(FrameTime); } int GetNumMipmap() const; virtual int GetWidth() const { return m_MipSurfaceArray[0][0]->GetWidth(); } virtual int GetHeight() const { return m_MipSurfaceArray[0][0]->GetHeight(); } virtual int GetDepth() const { return m_Depth; } virtual BitmapFormat GetFormat() const { return m_MipSurfaceArray[0][0]->GetFormat(); } virtual bool IsNull() const { return m_MipSurfaceArray[0][0]->IsNull(); } private: void ClearData(); int m_NumMipmap; int m_Depth; std::vector *m_MipSurfaceArray; std::vector m_FrameTimeArray; }; struct ImageInfo { bool isDelegate; // true if delegate knows this format int width ; // Image size(if known) int height; int bytes_per_pixel; // Bytes per pixel(if known) int planes; // Number of planes(if known) 0=mono, 3=color std::string format; // Additional image format information }; void MakeCheckBoardImage(ImageSurface& Image, int width, int height, Color const& dark, Color const& light, int TileWidth = 4, int TileHeight = 4); bool HasOpenEXRSupport(); /*! Return and object that has to be destroyed with delete. @return A bitmap source. Destroy it with delete. */ NBitmapData* LoadGdkPixbuf(GdkPixbuf *pixbuf); /*! Return and object that has to be destroyed with delete. @return A bitmap source. Destroy it with delete. */ NBitmapData* LoadImageFile(const TCHAR *Filename); } #endif // IMAGE_H ./NuxGraphics/GLTemplatePrimitiveBuffer.h0000644000004100000410000000502513313171755020700 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef TEMPLATEPRIMITIVEBUFFER_H #define TEMPLATEPRIMITIVEBUFFER_H namespace nux { class IOpenGLVertexBuffer; class IOpenGLIndexBuffer; class GpuDevice; typedef struct { Vector4 v0; Vector4 v1; Vector4 v2; Vector4 v3; } QuadAttributeParam; class TemplateQuadBuffer { public: TemplateQuadBuffer(GpuDevice *, ShaderType Type = SHADER_TYPE_GLSL, int NumQuads = 256); ~TemplateQuadBuffer(); //! Bind GLSL parameter void BindAttribute(INT AttributeLocation, UINT AttributeIndex); //! Bind NVidia CG parameter #if (NUX_ENABLE_CG_SHADERS) void BindCGAttribute(CGparameter AttributeLocation, UINT AttributeIndex); void UnBindCGAttribute(CGparameter AttributeLocation); #endif void UnBindAttribute(INT AttributeLocation); void UnBind(); void Render(INT NumPrimitives); //! Set the Vertices's attribute on a per quad basis. /*! Set the Vertices's attribute on a per quad basis. All vertex of the quad will have the same value for the attribute index. */ void SetPerQuadAttribute(UINT AttributeIndex, INT Num, Vector4 *); //! Set the Vertices's attribute on a per vertex basis. /*! Set the vertex attribute on a per vertex basis. */ void SetPerVertexAttribute(UINT AttributeIndex, INT Num, Vector4 *pVector); void UnSetQuadAttribute(UINT AttributeIndex); void SetNumQuads(int NumQuads); int GetNumQuads() const; protected: //IOpenGLVertexBuffer* m_VB; ObjectPtr m_IB; void FormatQuads(); private: ShaderType m_ShaderType; ObjectPtr VertexAttributeBuffer[16]; GpuDevice *m_pDeviceFactory; INT m_NumVertex; INT m_NumQuad; }; } #endif //TEMPLATEPRIMITIVEBUFFER_H ./NuxGraphics/GLRenderStates.cpp0000644000004100000410000003205313313171755017041 0ustar www-datawww-data/* * Copyright 2010-2012 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "GLResource.h" #include "GLRenderStates.h" namespace nux { const struct StateLookUpTable { StateLookUpTable() { // setup render state map #define UL_MAP(state__, default_value__, checked__) \ default_render_state[GFXRS_##state__].iValue = default_value__; \ default_render_state[GFXRS_##state__].Checked = checked__; #define UL_MAP_FLOAT(state__, default_value__, checked__) \ default_render_state[GFXRS_##state__].fValue = default_value__; \ default_render_state[GFXRS_##state__].Checked = checked__; \ #ifndef NUX_OPENGLES_20 UL_MAP(FRONT_POLYGONMODE , GL_FILL , 1); UL_MAP(BACK_POLYGONMODE , GL_FILL , 1); #endif UL_MAP(CULLFACEENABLE , GL_FALSE , 1); UL_MAP(CULLFACE , GL_BACK , 1); UL_MAP(FRONTFACE , GL_CCW , 1); UL_MAP(SCISSORTESTENABLE , GL_FALSE , 1); UL_MAP(ZTESTENABLE , GL_FALSE , 1); UL_MAP(ZWRITEENABLE , GL_TRUE , 1); UL_MAP(ZFUNC , GL_LESS , 1); UL_MAP_FLOAT(ZNEAR , static_cast (0.0f) , 1); UL_MAP_FLOAT(ZFAR , static_cast (1.0f) , 1); UL_MAP(ALPHABLENDENABLE , GL_FALSE , 1); UL_MAP(BLENDOP , GL_FUNC_ADD , 1); UL_MAP(BLENDOPALPHA , GL_FUNC_ADD , 1); UL_MAP(SRCBLEND , GL_ONE , 1); UL_MAP(DESTBLEND , GL_ZERO , 1); UL_MAP(SRCBLENDALPHA , GL_ONE , 1); UL_MAP(DESTBLENDALPHA , GL_ZERO , 1); UL_MAP(ALPHATESTENABLE , GL_FALSE , 1); UL_MAP(ALPHATESTREF , 0x0 , 1); UL_MAP(ALPHATESTFUNC , GL_ALWAYS , 1); UL_MAP(STENCILENABLE , GL_FALSE , 1); UL_MAP(TWOSIDEDSTENCILENABLE , GL_FALSE , 1); UL_MAP(FRONT_STENCILWRITEMASK , 0xFFFFFFFF , 1); UL_MAP(BACK_STENCILWRITEMASK , 0xFFFFFFFF , 1); UL_MAP(FRONT_STENCILFUNC , GL_ALWAYS , 1); UL_MAP(FRONT_STENCILREF , 0x0 , 1); UL_MAP(FRONT_STENCILMASK , 0xFF , 1); UL_MAP(FRONT_STENCILFAIL , GL_KEEP , 1); UL_MAP(FRONT_STENCILZFAIL , GL_KEEP , 1); UL_MAP(FRONT_STENCILZPASS , GL_KEEP , 1); UL_MAP(BACK_STENCILFUNC , GL_ALWAYS , 1); UL_MAP(BACK_STENCILREF , 0x0 , 1); UL_MAP(BACK_STENCILMASK , 0xFF , 1); UL_MAP(BACK_STENCILFAIL , GL_KEEP , 1); UL_MAP(BACK_STENCILZFAIL , GL_KEEP , 1); UL_MAP(BACK_STENCILZPASS , GL_KEEP , 1); UL_MAP(LINESMOOTHENABLE , GL_FALSE , 1); UL_MAP(LINEWIDTH , 1 , 1); UL_MAP(LINEHINT , GL_FASTEST , 1); UL_MAP(COLORWRITEENABLE_R , GL_TRUE , 1); UL_MAP(COLORWRITEENABLE_G , GL_TRUE , 1); UL_MAP(COLORWRITEENABLE_B , GL_TRUE , 1); UL_MAP(COLORWRITEENABLE_A , GL_TRUE , 1); #undef UL_MAP #undef UL_MAP_FLOAT }; RenderStateMap default_render_state[GFXRS_MAX_RENDERSTATES]; RenderStateMap sampler_state_map[GFXSS_MAX_SAMPLERSTATES]; } s_StateLUT; GpuRenderStates::GpuRenderStates(GpuBrand board, GpuInfo* info) { gpu_brand_ = board; gpu_info_ = info; Memcpy(&render_state_changes_, &s_StateLUT.default_render_state, sizeof(render_state_changes_)); } GpuRenderStates::~GpuRenderStates() { } void GpuRenderStates::ResetDefault() { HW__EnableCulling( s_StateLUT.default_render_state[GFXRS_CULLFACEENABLE].iValue ); HW__SetFrontFace( s_StateLUT.default_render_state[GFXRS_FRONTFACE].iValue ); HW__SetCullFace( s_StateLUT.default_render_state[GFXRS_CULLFACE].iValue ); HW__SetDepthMask( s_StateLUT.default_render_state[GFXRS_ZWRITEENABLE].iValue ); HW__SetDepthFunc( s_StateLUT.default_render_state[GFXRS_ZFUNC].iValue ); HW__SetEnableDepthTest( s_StateLUT.default_render_state[GFXRS_ZTESTENABLE].iValue ); HW__SetDepthRange( s_StateLUT.default_render_state[GFXRS_ZNEAR].fValue, s_StateLUT.default_render_state[GFXRS_ZFAR].fValue ); HW__EnableAlphaBlend( s_StateLUT.default_render_state[GFXRS_ALPHABLENDENABLE].iValue ); HW__SetAlphaBlendOp( s_StateLUT.default_render_state[GFXRS_BLENDOP].iValue, s_StateLUT.default_render_state[GFXRS_BLENDOPALPHA].iValue ); HW__SetSeparateAlphaBlendFactors( s_StateLUT.default_render_state[GFXRS_SRCBLEND].iValue, s_StateLUT.default_render_state[GFXRS_DESTBLEND].iValue, s_StateLUT.default_render_state[GFXRS_SRCBLENDALPHA].iValue, s_StateLUT.default_render_state[GFXRS_DESTBLENDALPHA ].iValue ); #ifndef NUX_OPENGLES_20 HW__EnableAlphaTest( s_StateLUT.default_render_state[GFXRS_ALPHATESTENABLE].iValue ); HW__SetAlphaTestFunc( s_StateLUT.default_render_state[GFXRS_ALPHATESTFUNC].iValue, s_StateLUT.default_render_state[GFXRS_ALPHATESTREF].iValue ); #endif HW__EnableStencil( s_StateLUT.default_render_state[GFXRS_STENCILENABLE].iValue ); HW__SetStencilFunc( s_StateLUT.default_render_state[GFXRS_FRONT_STENCILFUNC].iValue, s_StateLUT.default_render_state[GFXRS_FRONT_STENCILREF].iValue, s_StateLUT.default_render_state[GFXRS_FRONT_STENCILMASK].iValue); HW__SetStencilOp( s_StateLUT.default_render_state[GFXRS_FRONT_STENCILFAIL].iValue, s_StateLUT.default_render_state[GFXRS_FRONT_STENCILZFAIL].iValue, s_StateLUT.default_render_state[GFXRS_FRONT_STENCILZPASS].iValue); #ifndef NUX_OPENGLES_20 HW__EnableLineSmooth(s_StateLUT.default_render_state[GFXRS_LINESMOOTHENABLE].iValue); #endif HW__SetLineWidth(s_StateLUT.default_render_state[GFXRS_LINEWIDTH].iValue, s_StateLUT.default_render_state[GFXRS_LINEHINT].iValue); #if 0 HW__EnableTwoSidedStencil( s_StateLUT.default_render_state[GFXRS_TWOSIDEDSTENCILENABLE].iValue ); HW__SetFrontFaceStencilFunc( s_StateLUT.default_render_state[GFXRS_FRONT_STENCILFUNC].iValue, s_StateLUT.default_render_state[GFXRS_FRONT_STENCILREF].iValue, s_StateLUT.default_render_state[GFXRS_FRONT_STENCILMASK].iValue ); HW__SetFrontFaceStencilOp( s_StateLUT.default_render_state[GFXRS_FRONT_STENCILFAIL].iValue, s_StateLUT.default_render_state[GFXRS_FRONT_STENCILZFAIL].iValue, s_StateLUT.default_render_state[GFXRS_FRONT_STENCILZPASS].iValue ); HW__SetBackFaceStencilFunc( s_StateLUT.default_render_state[GFXRS_BACK_STENCILFUNC].iValue, s_StateLUT.default_render_state[GFXRS_BACK_STENCILREF].iValue, s_StateLUT.default_render_state[GFXRS_BACK_STENCILMASK].iValue ); HW__SetBackFaceStencilOp( s_StateLUT.default_render_state[GFXRS_BACK_STENCILFAIL].iValue, s_StateLUT.default_render_state[GFXRS_BACK_STENCILZFAIL].iValue, s_StateLUT.default_render_state[GFXRS_BACK_STENCILZPASS].iValue ); #endif HW__EnableScissor( s_StateLUT.default_render_state[GFXRS_SCISSORTESTENABLE].iValue ); } void GpuRenderStates::SubmitChangeStates() { HW__EnableCulling( render_state_changes_[GFXRS_CULLFACEENABLE].iValue ); HW__SetFrontFace( render_state_changes_[GFXRS_FRONTFACE].iValue ); HW__SetCullFace( render_state_changes_[GFXRS_CULLFACE].iValue ); HW__SetDepthMask( render_state_changes_[GFXRS_ZWRITEENABLE].iValue ); HW__SetDepthFunc( render_state_changes_[GFXRS_ZFUNC].iValue ); HW__SetEnableDepthTest( render_state_changes_[GFXRS_ZTESTENABLE].iValue ); HW__SetDepthRange( render_state_changes_[GFXRS_ZNEAR].fValue, render_state_changes_[GFXRS_ZFAR].fValue ); HW__EnableAlphaBlend( render_state_changes_[GFXRS_ALPHABLENDENABLE].iValue ); HW__SetAlphaBlendOp( render_state_changes_[GFXRS_BLENDOP].iValue, render_state_changes_[GFXRS_BLENDOPALPHA].iValue ); HW__SetSeparateAlphaBlendFactors( render_state_changes_[GFXRS_SRCBLEND].iValue, render_state_changes_[GFXRS_DESTBLEND].iValue, render_state_changes_[GFXRS_SRCBLENDALPHA].iValue, render_state_changes_[GFXRS_DESTBLENDALPHA ].iValue ); #ifndef NUX_OPENGLES_20 HW__EnableAlphaTest( render_state_changes_[GFXRS_ALPHATESTENABLE].iValue ); HW__SetAlphaTestFunc( render_state_changes_[GFXRS_ALPHATESTFUNC].iValue, render_state_changes_[GFXRS_ALPHATESTREF].iValue ); #endif HW__EnableStencil( render_state_changes_[GFXRS_STENCILENABLE].iValue ); HW__SetStencilFunc( render_state_changes_[GFXRS_FRONT_STENCILFUNC].iValue, render_state_changes_[GFXRS_FRONT_STENCILREF].iValue, render_state_changes_[GFXRS_FRONT_STENCILMASK].iValue); HW__SetStencilOp( render_state_changes_[GFXRS_FRONT_STENCILFAIL].iValue, render_state_changes_[GFXRS_FRONT_STENCILZFAIL].iValue, render_state_changes_[GFXRS_FRONT_STENCILZPASS].iValue); #ifndef NUX_OPENGLES_20 HW__EnableLineSmooth(render_state_changes_[GFXRS_LINESMOOTHENABLE].iValue); #endif HW__SetLineWidth(render_state_changes_[GFXRS_LINEWIDTH].iValue, render_state_changes_[GFXRS_LINEHINT].iValue); #if 0 HW__EnableTwoSidedStencil( s_StateLUT.default_render_state[GFXRS_TWOSIDEDSTENCILENABLE].iValue ); HW__SetFrontFaceStencilFunc( render_state_changes_[GFXRS_FRONT_STENCILFUNC].iValue, render_state_changes_[GFXRS_FRONT_STENCILREF].iValue, render_state_changes_[GFXRS_FRONT_STENCILMASK].iValue ); HW__SetFrontFaceStencilOp( render_state_changes_[GFXRS_FRONT_STENCILFAIL].iValue, render_state_changes_[GFXRS_FRONT_STENCILZFAIL].iValue, render_state_changes_[GFXRS_FRONT_STENCILZPASS].iValue ); HW__SetBackFaceStencilFunc( render_state_changes_[GFXRS_BACK_STENCILFUNC].iValue, render_state_changes_[GFXRS_BACK_STENCILREF].iValue, render_state_changes_[GFXRS_BACK_STENCILMASK].iValue ); HW__SetBackFaceStencilOp( render_state_changes_[GFXRS_BACK_STENCILFAIL].iValue, render_state_changes_[GFXRS_BACK_STENCILZFAIL].iValue, render_state_changes_[GFXRS_BACK_STENCILZPASS].iValue ); #endif HW__EnableScissor( render_state_changes_[GFXRS_SCISSORTESTENABLE].iValue ); } void GpuRenderStates::ResetStateChangeToDefault() { for (unsigned int i = 0; i < GFXRS_MAX_RENDERSTATES; i++) { if (render_state_changes_[i].Checked && ((render_state_changes_[i].iValue != s_StateLUT.default_render_state[i].iValue) || (render_state_changes_[i].fValue != s_StateLUT.default_render_state[i].fValue))) { render_state_changes_[i].iValue = s_StateLUT.default_render_state[i].iValue; render_state_changes_[i].fValue = s_StateLUT.default_render_state[i].fValue; } } } void GpuRenderStates::CheckStateChange() { for (unsigned int i = 0; i < GFXRS_MAX_RENDERSTATES; i++) { if (render_state_changes_[i].Checked && ((render_state_changes_[i].iValue != s_StateLUT.default_render_state[i].iValue) || (render_state_changes_[i].fValue != s_StateLUT.default_render_state[i].fValue))) { render_state_changes_[i].iValue = s_StateLUT.default_render_state[i].iValue; render_state_changes_[i].fValue = s_StateLUT.default_render_state[i].fValue; nuxError("[GpuRenderStates::Check] Render state doesn't have default value"); } } } } ./NuxGraphics/GLTextureStates.h0000644000004100000410000001435413313171755016733 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef GLTEXTURESTATES_H #define GLTEXTURESTATES_H #include "NuxCore/NuxCore.h" namespace nux { enum { GFXTS_ADDRESSU, // GL_REPEAT GFXTS_ADDRESSV, // GL_REPEAT GFXTS_ADDRESSW, // GL_REPEAT GFXTS_MINFILTER, // GL_NEAREST GFXTS_MAGFILTER, // GL_NEAREST GFXTS_MIPFILTER, // GL_NEAREST GFXTS_MIP_BASE_LEVEL, // 0 GFXTS_MIP_MAX_LEVEL, // 1000 GFXTS_MIN_LOD, // -1000 GFXTS_MAX_LOD, // +1000 GFXTS_BORDERCOLOR, // 0x00000000 GFXTS_MAX_TEXTURESTATES, }; struct TextureStateMap { bool Checked; unsigned int State; unsigned int Dirty; unsigned int iValue; float fValue; TextureStateMap() { Dirty = true; } }; class GpuDevice; class GLTextureStates { public: GLTextureStates(GLuint Type = GL_TEXTURE_2D); ~GLTextureStates(); void ResetDefault(); void ResetStateChangeToDefault(); void SetRenderStates(); void SetType(GLuint Type); void SetFiltering( unsigned int MIN = GL_NEAREST, unsigned int MAG = GL_NEAREST/*, unsigned int MIP = GL_NEAREST*/); void SetWrap( unsigned int U = GL_REPEAT, unsigned int V = GL_REPEAT, unsigned int W = GL_REPEAT); void SetLOD( float MinLod = -1000.0f, float MaxLod = +1000.0f); void SetMipLevel( unsigned int MinMip = 0, unsigned int MaxMip = 1000); void SetBorderColor( float R, float G, float B, float A); private: void HW_SetFiltering(); void HW_SetWrap(); void HW_SetLOD(); void HW_SetMipLevel(); void HW_SetBorderColor(); GLuint m_Type; TextureStateMap m_TextureStateChanges[GFXTS_MAX_TEXTURESTATES]; friend class GpuDevice; }; // #define SET_TS_VALUE(a, b) (a).iValue = (b); (a).Dirty = true; // #define TS_VALUE(a, b) (a).iValue // // #define SET_TS_VALUE_FLOAT(a, b) (a).fValue = (b); (a).Dirty = true; // #define TS_VALUE_FLOAT(a, b) (a).fValue // // // inline void GLTextureStates::SetFiltering( // unsigned int MIN, // unsigned int MAG // /*,unsigned int MIP*/) // { // nuxAssertMsg( // (MIN == GL_LINEAR) || // (MIN == GL_NEAREST) || // (MIN == GL_NEAREST_MIPMAP_NEAREST) || // (MIN == GL_LINEAR_MIPMAP_NEAREST) || // (MIN == GL_NEAREST_MIPMAP_LINEAR) || // (MIN == GL_LINEAR_MIPMAP_LINEAR), // "Error[GLTextureStates::SetFiltering]: Invalid Min. Filter State"); // // nuxAssertMsg( // (MAG == GL_LINEAR) || // (MAG == GL_NEAREST), // "Error[GLTextureStates::SetFiltering]: Invalid Mag. Filter State"); // // // nuxAssertMsg( // // (MIP == GL_LINEAR) || // // (MIP == GL_NEAREST), // // "Error[GLTextureStates::SetFiltering]: Invalid Mipmap Filter State"); // // SET_TS_VALUE(m_TextureStateChanges[GFXTS_MINFILTER], MIN); // SET_TS_VALUE(m_TextureStateChanges[GFXTS_MAGFILTER], MAG); // //SET_TS_VALUE(m_TextureStateChanges[GFXTS_MIPFILTER], MIP); // } // // inline void GLTextureStates::SetWrap( // unsigned int U, // unsigned int V, // unsigned int W) // { // nuxAssertMsg( // (U == GL_CLAMP) || // (U == GL_CLAMP_TO_EDGE) || // (U == GL_REPEAT), // "Error[GLTextureStates::SetWrap]: Invalid U Wrap State"); // nuxAssertMsg( // (V == GL_CLAMP) || // (V == GL_CLAMP_TO_EDGE) || // (V == GL_REPEAT), // "Error[GLTextureStates::SetWrap]: Invalid V Wrap State"); // nuxAssertMsg( // (W == GL_CLAMP) || // (W == GL_CLAMP_TO_EDGE) || // (W == GL_REPEAT), // "Error[GLTextureStates::SetWrap]: Invalid W Wrap State"); // // SET_TS_VALUE(m_TextureStateChanges[GFXTS_ADDRESSU], U); // SET_TS_VALUE(m_TextureStateChanges[GFXTS_ADDRESSV], V); // SET_TS_VALUE(m_TextureStateChanges[GFXTS_ADDRESSW], W); // // // } // // inline void GLTextureStates::SetLOD(float MinLod, // float MaxLod) // { // SET_TS_VALUE_FLOAT(m_TextureStateChanges[GFXTS_MIN_LOD], MinLod); // SET_TS_VALUE_FLOAT(m_TextureStateChanges[GFXTS_MAX_LOD], MaxLod); // } // // inline void GLTextureStates::SetMipLevel( // unsigned int MinMip, // unsigned int MaxMip) // { // SET_TS_VALUE(m_TextureStateChanges[GFXTS_MIP_BASE_LEVEL], MinMip); // SET_TS_VALUE(m_TextureStateChanges[GFXTS_MIP_MAX_LEVEL], MaxMip); // } // // inline void GLTextureStates::SetBorderColor( // float R, // float G, // float B, // float A) // { // unsigned int r, g, b, a; // r = 255 * Clamp(R, 0.0f, 1.0f); // g = 255 * Clamp(G, 0.0f, 1.0f); // b = 255 * Clamp(B, 0.0f, 1.0f); // a = 255 * Clamp(A, 0.0f, 1.0f); // unsigned int color = (unsigned int) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)); // // SET_TS_VALUE(m_TextureStateChanges[GFXTS_BORDERCOLOR], color); // } // // #undef SET_TS_VALUE // #undef TS_VALUE // // #undef SET_TS_VALUE_FLOAT // #undef TS_VALUE_FLOAT } #endif // GLTEXTURESTATES_H ./NuxGraphics/IOpenGLVolumeTexture.h0000644000004100000410000000521213313171755017663 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef IOPENGLVOLUMETEXTURE_H #define IOPENGLVOLUMETEXTURE_H namespace nux { class IOpenGLBaseTexture; class IOpenGLVolumeTexture: public IOpenGLBaseTexture { NUX_DECLARE_OBJECT_TYPE(IOpenGLVolumeTexture, IOpenGLBaseTexture); public: virtual ~IOpenGLVolumeTexture(); int GetVolumeLevel( int Level, IOpenGLVolume **ppVolumeLevel ); int VolumeLockRect( int Slice, int Level, SURFACE_LOCKED_RECT *pLockedRect, const SURFACE_RECT *pRect); int VolumeUnlockRect( int Slice, int Level ); int LockBox( int Level, VOLUME_LOCKED_BOX *pLockedVolume, const VOLUME_BOX *pBox); int UnlockBox( int Level ); int GetLevelDepth(int MipLevel) const { return ImageSurface::GetLevelDim(_PixelFormat, _Depth, MipLevel); } int GetLevelDesc( int Level, VOLUME_DESC *pDesc ) { nuxAssert(Level >= 0 ); nuxAssert(Level < _NumMipLevel); if ((Level < 0) || (Level > _NumMipLevel)) { pDesc->Width = 0; pDesc->Height = 0; pDesc->Depth = 0; pDesc->PixelFormat = BITFMT_UNKNOWN; pDesc->Type = _ResourceType; } else { pDesc->Width = Max (1, _Width >> Level); pDesc->Height = Max (1, _Height >> Level); pDesc->Depth = _Depth; pDesc->PixelFormat = _PixelFormat; pDesc->Type = _ResourceType; } return OGL_OK; } private: IOpenGLVolumeTexture( int Width , int Height , int Depth , int Levels , BitmapFormat PixelFormat); std::vector< ObjectPtr > *_VolumeSurfaceArray; std::vector< ObjectPtr > _VolumeArray; friend class GpuDevice; friend class IOpenGLSurface; }; } #endif // IOPENGLVOLUMETEXTURE_H ./NuxGraphics/GraphicsDisplayWin.cpp0000755000004100000410000022466713313171755020000 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "GLResource.h" #include "NuxGraphics.h" #include "GpuDevice.h" #include "GLDeviceObjects.h" #include "GLResourceManager.h" #include "GLTextureResourceManager.h" #include "GLVertexResourceManager.h" #include "GraphicsEngine.h" #include "GLWindowManager.h" #include "Events.h" #include "GraphicsDisplay.h" namespace nux { // Compute the frame rate every FRAME_RATE_PERIODE; #define FRAME_RATE_PERIODE 10 void ClipOrCenterRectToMonitor(LPRECT prc, unsigned int flags) { HMONITOR hMonitor; MONITORINFO mi; RECT rc; int w = prc->right - prc->left; int h = prc->bottom - prc->top; // // get the nearest monitor to the passed rect. // hMonitor = MonitorFromRect(prc, MONITOR_DEFAULTTONEAREST); // // get the work area or entire monitor rect. // mi.cbSize = sizeof(mi); GetMonitorInfo(hMonitor, &mi); //if(flags & MONITOR_WORKAREA) rc = mi.rcWork; // else // rc = mi.rcMonitor; // // center or clip the passed rect to the monitor rect // //if(flags & MONITOR_CENTER) { prc->left = rc.left + (rc.right - rc.left - w) / 2; prc->top = rc.top + (rc.bottom - rc.top - h) / 2; prc->right = prc->left + w; prc->bottom = prc->top + h; } // else // { // prc->left = Max(rc.left, Min(rc.right-w, prc->left)); // prc->top = Max(rc.top, Min(rc.bottom-h, prc->top)); // prc->right = prc->left + w; // prc->bottom = prc->top + h; // } } EventToNameStruct EventToName[] = { {NUX_NO_EVENT, "NUX_NO_EVENT" }, {NUX_MOUSE_PRESSED, "NUX_MOUSE_PRESSED" }, {NUX_MOUSE_RELEASED, "NUX_MOUSE_RELEASED" }, {NUX_KEYDOWN, "NUX_KEYDOWN" }, {NUX_KEYUP, "NUX_KEYUP" }, {NUX_MOUSE_MOVE, "NUX_MOUSE_MOVE" }, {NUX_SIZE_CONFIGURATION, "NUX_SIZE_CONFIGURATION" }, {NUX_NC_WINDOW_CONFIGURATION, "NUX_NC_WINDOW_CONFIGURATION" }, {NUX_WINDOW_ENTER_FOCUS, "NUX_WINDOW_ENTER_FOCUS" }, {NUX_WINDOW_EXIT_FOCUS, "NUX_WINDOW_EXIT_FOCUS" }, {NUX_WINDOW_DIRTY, "NUX_WINDOW_DIRTY" }, {NUX_WINDOW_MOUSELEAVE, "NUX_WINDOW_MOUSELEAVE" }, {NUX_TERMINATE_APP, "NUX_TERMINATE_APP" } }; //--------------------------------------------------------------------------------------------------------- HGLRC GraphicsDisplay::sMainGLRC = 0; HDC GraphicsDisplay::sMainDC = 0; GraphicsDisplay::GraphicsDisplay() : gfx_interface_created_(false) , fullscreen_(false) , screen_bit_depth_(32) , m_DeviceFactory(0) , m_GraphicsContext(0) , m_Style(WINDOWSTYLE_NORMAL) , cursor_(0) , m_PauseGraphicsRendering(false) , parent_window_(0) , window_extended_style_(0) , window_style_(0) , device_context_(NULL) , wnd_handle_(NULL) { // Initialize Direct2D and DirectWrite d2d_factory_ = NULL; dw_factory_ = NULL; wic_factory_ = NULL; HRESULT hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &d2d_factory_); if (hr == S_OK) { hr = DWriteCreateFactory( DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), reinterpret_cast(&dw_factory_)); } // Initialize COM CoInitialize(NULL); hr = CoCreateInstance( CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, (LPVOID*)&wic_factory_); inlSetThreadLocalStorage(_TLS_GraphicsDisplay, this); gfx_interface_created_ = false; GetDisplayInfo(); window_size_.width = 0; window_size_.height = 0; // A window never starts in a minimized state. window_minimized_ = false; //_dnd_source_grab_active = false; _global_keyboard_grab_data = 0; _global_pointer_grab_data = 0; } //--------------------------------------------------------------------------------------------------------- GraphicsDisplay::~GraphicsDisplay() { NUX_SAFE_DELETE( m_GraphicsContext ); NUX_SAFE_DELETE( m_DeviceFactory ); DestroyOpenGLWindow(); inlSetThreadLocalStorage(_TLS_GraphicsDisplay, 0); if (dw_factory_) { dw_factory_->Release(); dw_factory_ = NULL; } if (d2d_factory_) { d2d_factory_->Release(); d2d_factory_ = NULL; } if (wic_factory_) { wic_factory_->Release(); wic_factory_ = NULL; } } ID2D1Factory* GraphicsDisplay::GetDirect2DFactory() { return d2d_factory_; } IDWriteFactory* GraphicsDisplay::GetDirectWriteFactory() { return dw_factory_; } IWICImagingFactory* GraphicsDisplay::GetWICFactory() { return wic_factory_; } //--------------------------------------------------------------------------------------------------------- bool GraphicsDisplay::IsGfxInterfaceCreated() { return gfx_interface_created_; } //--------------------------------------------------------------------------------------------------------- static NCriticalSection CreateOpenGLWindow_CriticalSection; bool GraphicsDisplay::CreateOpenGLWindow(const char *WindowTitle, unsigned int WindowWidth, unsigned int WindowHeight, WindowStyle Style, const GraphicsDisplay *Parent, bool fullscreen_flag, bool create_rendering_data) { NScopeLock Scope(&CreateOpenGLWindow_CriticalSection); RECT WindowRect; // Grabs Rectangle Upper Left / Lower Right Values gfx_interface_created_ = false; // FIXME : put at the end viewport_size_.width = WindowWidth; viewport_size_.height = WindowHeight; window_size_.width = WindowWidth; window_size_.height = WindowHeight; // end of fixme WindowRect.left = (long) 0; WindowRect.right = (long) viewport_size_.width; WindowRect.top = (long) 0; WindowRect.bottom = (long) viewport_size_.height; fullscreen_ = fullscreen_flag; // Set The Global Fullscreen Flag if (fullscreen_) // Attempt Fullscreen Mode? { // check if resolution is supported bool mode_supported = false; for (int num_modes = 0 ; num_modes < m_num_gfx_device_modes; num_modes++) { if ((m_gfx_device_modes[num_modes].width == viewport_size_.width) && (m_gfx_device_modes[num_modes].height == viewport_size_.height) && (m_gfx_device_modes[num_modes].format == screen_bit_depth_)) { mode_supported = true; break; } } if (mode_supported == false) { if (inlWin32MessageBox(NULL, "Info", MBTYPE_Ok, MBICON_Information, MBMODAL_ApplicationModal, "The requested fullscreen mode is not supported by your monitor.\nUsing windowed mode instead.") == MBRES_Yes) { fullscreen_ = FALSE; // Windowed Mode Selected. Fullscreen = FALSE } } DEVMODE dmScreenSettings; // Device Mode memset(&dmScreenSettings, 0, sizeof(dmScreenSettings)); // Makes Sure Memory's Cleared dmScreenSettings.dmSize = sizeof(dmScreenSettings); // Size Of The Devmode Structure dmScreenSettings.dmPelsWidth = viewport_size_.width; // Selected Screen Width dmScreenSettings.dmPelsHeight = viewport_size_.height; // Selected Screen Height dmScreenSettings.dmBitsPerPel = screen_bit_depth_; // Selected Bits Per Pixel dmScreenSettings.dmDisplayFrequency = 60; dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY; // Try To Set Selected Mode And Get Results. NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar. if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) { if (inlWin32MessageBox(NULL, "Info", MBTYPE_Ok, MBICON_Information, MBMODAL_ApplicationModal, "The requested fullscreen mode is not supported by your monitor.\nUsing windowed mode instead.") == MBRES_Yes) { fullscreen_ = FALSE; // Windowed Mode Selected. Fullscreen = FALSE } else { // Pop Up A Message Box Letting User Know The Program Is Closing. MessageBox(NULL, "Program Will Now Close.", "ERROR", MB_OK | MB_ICONSTOP); } } } window_extended_style_ = 0; window_style_ = 0; if (fullscreen_) // Are We Still In Fullscreen Mode? { window_extended_style_ = WS_EX_APPWINDOW; // Window Extended Style window_style_ = WS_POPUP; // Windows Style ShowCursor(FALSE); // Hide Mouse Pointer } else { // Window Extended Style window_extended_style_ = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // Windows Style window_style_ = WS_OVERLAPPED; // Creates an overlapped window. An overlapped window has a title bar and a border // See Win32 Window Hierarchy and Styles: http://msdn.microsoft.com/en-us/library/ms997562.aspx //WS_EX_APPWINDOW // Forces a top-level window onto the taskbar when the window is visible //WS_EX_WINDOWEDGE // Specifies that a window has a border with a raised edge //WS_POPUP // Creates a pop-up window. This style cannot be used with the WS_CHILD style. //WS_SYSMENU // Creates a window that has a window menu on its title bar. The WS_CAPTION style must also be specified. //WS_SIZEBOX // Creates a window that has a sizing border. Same as the WS_THICKFRAME style. //WS_CAPTION // Creates a window that has a title bar(includes the WS_BORDER style). m_Style = Style; if (Style == WINDOWSTYLE_TOOL) { window_extended_style_ = WS_EX_TOOLWINDOW; window_style_ = WS_CAPTION | WS_SYSMENU; } else if (Style == WINDOWSTYLE_DIALOG) { window_extended_style_ = WS_EX_DLGMODALFRAME; window_style_ = WS_CAPTION | WS_SYSMENU; } else if (Style == WINDOWSTYLE_NOBORDER) { window_extended_style_ = WS_EX_TOPMOST | WS_EX_TOOLWINDOW; window_style_ = WS_POPUP; } else if (Style == WINDOWSTYLE_PANEL) { window_extended_style_ = 0; // Specifies that a window has a border with a raised edge window_style_ = WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SIZEBOX; } else { // Normal Window: NormalWindow window_extended_style_ = WS_EX_APPWINDOW | // Forces a top-level window onto the taskbar when the window is visible WS_EX_WINDOWEDGE; // Specifies that a window has a border with a raised edge window_style_ |= WS_CAPTION | // Creates a window that has a title bar. WS_SYSMENU | // Creates a window that has a window menu on its title bar. The WS_CAPTION style must also be specified. WS_THICKFRAME | // Creates a window that has a sizing border. WS_MINIMIZEBOX | // Creates a window that has a minimize button. WS_MAXIMIZEBOX | // Creates a window that has a maximize button. WS_BORDER; // Creates a window that has a thin-line border. } } // The AdjustWindowRectEx function calculates the required size of the window rectangle, // based on the desired size of the client rectangle. The window rectangle can then be passed to // the CreateWindowEx function to create a window whose client area is the desired size. AdjustWindowRectEx(&WindowRect, window_style_, FALSE, window_extended_style_); // Adjust Window To True Requested Size RECT rect; rect.top = 0; rect.bottom = WindowRect.bottom - WindowRect.top; rect.left = 0; rect.right = WindowRect.right - WindowRect.left; int WindowX = 0; int WindowY = 0; if (Parent) { parent_window_ = Parent->GetWindowHandle(); GetWindowRect(parent_window_, &rect); int width = rect.right - rect.left; int height = rect.bottom - rect.top; WindowX = rect.left + (width - (WindowRect.right - WindowRect.left)) / 2; WindowY = rect.top + (height - (WindowRect.bottom - WindowRect.top)) / 2; } else if (!fullscreen_) { ClipOrCenterRectToMonitor(&rect, 0); WindowX = rect.left; WindowY = rect.top; } window_title_ = WindowTitle; // Create The Window if (! (wnd_handle_ = ::CreateWindowEx(window_extended_style_, // Extended Style For The Window WINDOW_CLASS_NAME, // Class Name window_title_.c_str(), // Window Title window_style_ | // Defined Window Style WS_CLIPSIBLINGS | // Required Window Style WS_CLIPCHILDREN, // Required Window Style WindowX, WindowY, // Window Position WindowRect.right - WindowRect.left, // Calculate Window Width WindowRect.bottom - WindowRect.top, // Calculate Window Height parent_window_, // No Parent Window NULL, // No Menu gGLWindowManager.GetInstance(), // Instance NULL))) // Don't Pass Anything To WM_CREATE { DestroyOpenGLWindow(); MessageBox(NULL, "Window Creation Error.", "ERROR", MB_OK | MB_ICONERROR); // Return FALSE } static PIXELFORMATDESCRIPTOR pfd = // pfd Tells Windows How We Want Things To Be { sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor 1, // Version Number PFD_DRAW_TO_WINDOW | // Format Must Support Window PFD_SUPPORT_OPENGL | // Format Must Support OpenGL PFD_DOUBLEBUFFER, // Must Support Double Buffering PFD_TYPE_RGBA, // Request An RGBA Format 24, // cColorBits // Specifies the number of color bitplanes in each color buffer. // For RGBA pixel types, it is the size of the color buffer, excluding the alpha bitplanes. // For color-index pixels, it is the size of the color-index buffer. 0, // cRedBits // Specifies the number of red bitplanes in each RGBA color buffer. 0, // cRedShift // Specifies the shift count for red bitplanes in each RGBA color buffer. 0, // cGreenBits // Specifies the number of green bitplanes in each RGBA color buffer. 0, // cGreenShift // Specifies the shift count for green bitplanes in each RGBA color buffer. 0, // cBlueBits // Specifies the number of blue bitplanes in each RGBA color buffer. 0, // cBlueShift // Specifies the shift count for blue bitplanes in each RGBA color buffer. 0, // cAlphaBits // Specifies the number of alpha bitplanes in each RGBA color buffer. Alpha bitplanes are not supported. 0, // cAlphaShift // Specifies the shift count for alpha bitplanes in each RGBA color buffer. Alpha bitplanes are not supported. 0, // cAccumBits // Specifies the total number of bitplanes in the accumulation buffer. 0, // cAccumRedBits // Specifies the number of red bitplanes in the accumulation buffer. 0, // cAccumGreenBits // Specifies the number of green bitplanes in the accumulation buffer. 0, // cAccumBlueBits // Specifies the number of blue bitplanes in the accumulation buffer. 0, // cAccumAlphaBits // Specifies the number of alpha bitplanes in the accumulation buffer. 24,// cDepthBits // Specifies the depth of the depth(z-axis) buffer. 8, // cStencilBits // Specifies the depth of the stencil buffer. 0, // cAuxBuffers // Specifies the number of auxiliary buffers. Auxiliary buffers are not supported. PFD_MAIN_PLANE, // iLayerType // Ignored. Earlier implementations of OpenGL used this member, but it is no longer used. 0, // bReserved // Specifies the number of overlay and underlay planes. Bits 0 through 3 specify up to 15 overlay planes and bits 4 through 7 specify up to 15 underlay planes. 0, // dwLayerMask // Ignored. Earlier implementations of OpenGL used this member, but it is no longer used. 0, // dwVisibleMask // Specifies the transparent color or index of an underlay plane. When the pixel type is RGBA, dwVisibleMask is a transparent RGB color value. When the pixel type is color index, it is a transparent index value. 0, // dwDamageMask // Ignored. Earlier implementations of OpenGL used this member, but it is no longer used. }; device_context_ = GetDC(wnd_handle_); if (device_context_ == NULL) // Did We Get A Device Context? { DestroyOpenGLWindow(); MessageBox(NULL, "Can't Create A GL Device Context.", "ERROR", MB_OK | MB_ICONERROR); return FALSE; } if (! (pixel_format_ = ChoosePixelFormat(device_context_, &pfd))) // Did Windows Find A Matching Pixel Format? { DestroyOpenGLWindow(); MessageBox(NULL, "Can't Find A Suitable PixelFormat.", "ERROR", MB_OK | MB_ICONERROR); return FALSE; } if (!SetPixelFormat(device_context_, pixel_format_, &pfd)) // Are We Able To Set The Pixel Format? { DestroyOpenGLWindow(); MessageBox(NULL, "Can't Set The PixelFormat.", "ERROR", MB_OK | MB_ICONERROR); return FALSE; } if (!(opengl_rendering_context_ = wglCreateContext(device_context_))) // Are We Able To Get A Rendering Context? { DestroyOpenGLWindow(); MessageBox(NULL, "Can't Create A GL Rendering Context.", "ERROR", MB_OK | MB_ICONERROR); return FALSE; } if (sMainGLRC == 0) { sMainGLRC = opengl_rendering_context_; sMainDC = device_context_; } else { // wglMakeCurrent(device_context_, 0); // // Make the newly created context share it resources with all the other OpenGL context // if (wglShareLists(sMainGLRC, opengl_rendering_context_) == FALSE) // { // DWORD err = GetLastError(); // DestroyOpenGLWindow(); // MessageBox(NULL, "Can't share GL context.", "ERROR", MB_OK|MB_ICONERROR); // return FALSE; // } } // This creates a warning. It is a 64-bits compatibility issue. // When not in 64-bit you can disable the warning: // Project Properties --> C/C++ tab --> General --> Select "NO" for - Detect 64-bit Portability Issues. // See also SetWindowLongPtr SetWindowLongPtr(wnd_handle_, GWLP_USERDATA, (long) this); //::ShowWindow(wnd_handle_,SW_SHOW); // Show The Window ::SetForegroundWindow(wnd_handle_); // Slightly Higher Priority ::SetFocus(wnd_handle_); // Sets Keyboard Focus To The Window MakeGLContextCurrent(); glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); SwapBuffer(); gfx_interface_created_ = true; //m_GLEWContext = new GLEWContext(); //m_WGLEWContext = new WGLEWContext(); HGLRC new_opengl_rendering_context = opengl_rendering_context_; m_DeviceFactory = new GpuDevice(viewport_size_.width, viewport_size_.height, BITFMT_R8G8B8A8, device_context_, new_opengl_rendering_context, 1, 0, false); if (m_DeviceFactory->GetGpuInfo().Support_EXT_Framebuffer_Object()) m_DeviceFactory->GetFrameBufferObject()->SetupFrameBufferObject(); if (new_opengl_rendering_context != 0) { opengl_rendering_context_ = new_opengl_rendering_context; } m_GraphicsContext = new GraphicsEngine(*this, create_rendering_data); //EnableVSyncSwapControl(); //DisableVSyncSwapControl(); InitGlobalGrabWindow(); return true; } bool GraphicsDisplay::CreateFromOpenGLWindow(HWND WindowHandle, HDC WindowDCHandle, HGLRC OpenGLRenderingContext) { // Do not make the opengl context current // Do not swap the framebuffer // Do not clear the depth or color buffer // Do not enable/disable VSync wnd_handle_ = WindowHandle; device_context_ = WindowDCHandle; opengl_rendering_context_ = OpenGLRenderingContext; RECT rect; ::GetClientRect(wnd_handle_, &rect); window_size_ = Size(rect.right - rect.left, rect.bottom - rect.top); viewport_size_ = Size(rect.right - rect.left, rect.bottom - rect.top); // The opengl context should be made current by an external entity. gfx_interface_created_ = true; m_DeviceFactory = new GpuDevice(viewport_size_.width, viewport_size_.height, BITFMT_R8G8B8A8, device_context_, opengl_rendering_context_); if (m_DeviceFactory->GetGpuInfo().Support_EXT_Framebuffer_Object()) m_DeviceFactory->GetFrameBufferObject()->SetupFrameBufferObject(); m_GraphicsContext = new GraphicsEngine(*this); InitGlobalGrabWindow(); return true; } GraphicsEngine* GraphicsDisplay::GetGraphicsEngine() const { return m_GraphicsContext; } GpuDevice* GraphicsDisplay::GetGpuDevice() const { return m_DeviceFactory; } //--------------------------------------------------------------------------------------------------------- // NUXTODO: remove this call. Make a direct access to GpuInfo via GpuDevice. bool GraphicsDisplay::HasFrameBufferSupport() { return m_DeviceFactory->GetGpuInfo().Support_EXT_Framebuffer_Object(); } //--------------------------------------------------------------------------------------------------------- void GraphicsDisplay::GetWindowSize(int &w, int &h) { w = window_size_.width; h = window_size_.height; } //--------------------------------------------------------------------------------------------------------- int GraphicsDisplay::GetWindowWidth() { return window_size_.width; } //--------------------------------------------------------------------------------------------------------- int GraphicsDisplay::GetWindowHeight() { return window_size_.height; } void GraphicsDisplay::ResetWindowSize() { RECT rect; ::GetClientRect(wnd_handle_, &rect); window_size_ = Size(rect.right - rect.left, rect.bottom - rect.top); viewport_size_ = Size(rect.right - rect.left, rect.bottom - rect.top); } //--------------------------------------------------------------------------------------------------------- void GraphicsDisplay::SetWindowSize(int width, int height) { RECT window_rect; RECT new_rect; ::GetWindowRect(wnd_handle_, &window_rect); new_rect.left = 0; new_rect.right = width; new_rect.top = 0; new_rect.bottom = height; BOOL b = ::AdjustWindowRectEx(&new_rect, window_style_, FALSE, window_extended_style_); // Adjust Window To True Requested Size ::MoveWindow(wnd_handle_, window_rect.left, window_rect.top, (new_rect.right - new_rect.left), (new_rect.bottom - new_rect.top), TRUE); } //--------------------------------------------------------------------------------------------------------- void GraphicsDisplay::SetViewPort(int x, int y, int width, int height) { if (IsGfxInterfaceCreated()) { //do not rely on viewport_size_: glViewport can be called directly viewport_size_.width = width; viewport_size_.height = height; m_GraphicsContext->SetViewport(x, y, viewport_size_.width, viewport_size_.height); m_GraphicsContext->SetScissor(0, 0, width, height); } } Point GraphicsDisplay::GetMouseScreenCoord() { POINT pt; ::GetCursorPos(&pt); ScreenToClient(wnd_handle_, &pt); Point point(pt.x, pt.y); return point; } Point GraphicsDisplay::GetMouseWindowCoord() { POINT pt; ::GetCursorPos(&pt); ::ScreenToClient(wnd_handle_, &pt); Point point(pt.x, pt.y); return point; } Point GraphicsDisplay::GetWindowCoord() { RECT rect; ::GetWindowRect(wnd_handle_, &rect); Point point(rect.left, rect.top); return point; } Rect GraphicsDisplay::GetWindowGeometry() { RECT rect; ::GetClientRect(wnd_handle_, &rect); Rect geo(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top); return geo; } Rect GraphicsDisplay::GetNCWindowGeometry() { RECT rect; ::GetWindowRect(wnd_handle_, &rect); Rect geo(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top); return geo; } void GraphicsDisplay::MakeGLContextCurrent(bool b) { HGLRC glrc = opengl_rendering_context_; if (b == false) { glrc = 0; } if (!wglMakeCurrent(device_context_, glrc)) { std::string error = inlGetSystemErrorMessage(); DestroyOpenGLWindow(); MessageBox(NULL, "Can't Activate The GL Rendering Context.", "ERROR", MB_OK | MB_ICONERROR); } } void GraphicsDisplay::SwapBuffer(bool glswap) { if (IsPauseThreadGraphicsRendering()) return; if (glswap) { SwapBuffers(device_context_); } m_FrameTime = m_Timer.PassedMilliseconds(); // if (16.6f - m_FrameTime > 0) // { // SleepForMilliseconds(16.6f - m_FrameTime); // } // // m_FrameTime = m_Timer.PassedMilliseconds(); // m_Timer.Reset(); // m_PeriodeTime += m_FrameTime; // // m_FrameCounter++; // m_FramePeriodeCounter++; // if (m_FramePeriodeCounter >= FRAME_RATE_PERIODE) // { // m_FrameRate = m_FramePeriodeCounter * 1000.0f / m_PeriodeTime; // m_PeriodeTime = 0.0f; // m_FramePeriodeCounter = 0; // } } //--------------------------------------------------------------------------------------------------------- void GraphicsDisplay::DestroyOpenGLWindow() { if (gfx_interface_created_ == true) { if (fullscreen_) // Are We In Fullscreen Mode? { ChangeDisplaySettings(NULL, 0); // If So Switch Back To The Desktop ShowCursor(TRUE); // Show Mouse Pointer } if (opengl_rendering_context_) // Do We Have A Rendering Context? { if (!wglMakeCurrent(device_context_, NULL)) // Are We Able To Release The DC And RC Contexts? { MessageBox(NULL, "Release Of DC And RC Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); } if (!wglDeleteContext(opengl_rendering_context_)) // Are We Able To Delete The RC? { MessageBox(NULL, "Release Rendering Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); } opengl_rendering_context_ = NULL; // Set RC To NULL } if (device_context_ && (ReleaseDC(wnd_handle_, device_context_) == 0)) // Are We Able To Release The DC { MessageBox(NULL, "Release Device Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); } device_context_ = NULL; // Set DC To NULL if (wnd_handle_ && (::DestroyWindow(wnd_handle_) == 0)) // Are We Able To Destroy The Window? { MessageBox(NULL, "Could Not Release window handle.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); } wnd_handle_ = NULL; // Set Window Handle To NULL } gfx_interface_created_ = false; } // //--------------------------------------------------------------------------------------------------------- // // convert a MSWindows VK_x to an Fltk(X) Keysym: // // See also the inverse converter in Fl_get_key_win32.cxx // // This table is in numeric order by VK: // static const struct {unsigned short vk, fltk, extended;} vktab[] = { // {NUX_VK_BACK, NUX_BackSpace}, // {NUX_VK_TAB, NUX_Tab}, // {NUX_VK_CLEAR, NUX_Clear, 0xff0b/*XK_Clear*/}, // {NUX_VK_ENTER, NUX_Enter, NUX_KP_ENTER}, // {NUX_VK_SHIFT, NUX_Shift_L, NUX_EXT_Shift_R}, // {NUX_VK_CONTROL, NUX_Control_L, NUX_EXT_Control_R}, // {NUX_VK_MENU, NUX_Alt_L, NUX_EXT_Alt_R}, // {NUX_VK_PAUSE, NUX_Pause}, // {NUX_VK_CAPITAL, NUX_Caps_Lock}, // {NUX_VK_ESCAPE, NUX_Escape}, // {NUX_VK_SPACE, ' '}, // {NUX_VK_PAGE_UP, NUX_Page_Up /*KP+'9'*/, NUX_KP_PAGE_UP}, // {NUX_VK_PAGE_DOWN, NUX_Page_Down /*KP+'3'*/, NUX_KP_PAGE_DOWN}, // {NUX_VK_END, NUX_End /*KP+'1'*/, NUX_KP_END}, // {NUX_VK_HOME, NUX_Home /*KP+'7'*/, NUX_KP_HOME}, // {NUX_VK_LEFT, NUX_Left /*KP+'4'*/, NUX_KP_LEFT}, // {NUX_VK_UP, NUX_Up /*KP+'8'*/, NUX_KP_UP}, // {NUX_VK_RIGHT, NUX_Right /*KP+'6'*/, NUX_KP_RIGHT}, // {NUX_VK_DOWN, NUX_Down /*KP+'2'*/, NUX_KP_DOWN}, // {NUX_VK_SNAPSHOT, NUX_Print}, // does not work on NT // {NUX_VK_INSERT, NUX_Insert /*KP+'0'*/, NUX_KP_INSERT}, // {NUX_VK_DELETE, NUX_Delete /*KP+'.'*/, NUX_KP_DELETE}, // {NUX_VK_LWIN, NUX_LWin /*Meta_L*/}, // {NUX_VK_RWIN, NUX_RWin /*Meta_R*/}, // {NUX_VK_APPS, NUX_VK_APPS /*Menu*/}, // {NUX_VK_MULTIPLY, NUX_Multiply /*KP+'*'*/}, // {NUX_VK_ADD, NUX_Add /*KP+'+'*/}, // {NUX_VK_SUBTRACT, NUX_Subtract /*KP+'-'*/}, // {NUX_VK_DECIMAL, NUX_Decimal /*KP+'.'*/}, // {NUX_VK_DIVIDE, NUX_Divide /*KP+'/'*/}, // {NUX_VK_NUMLOCK, NUX_Numlock /*Num_Lock*/}, // {NUX_VK_SCROLL, NUX_Scroll /*Scroll_Lock*/}, // {0xba, ';'}, // {0xbb, '='}, // {0xbc, ','}, // {0xbd, '-'}, // {0xbe, '.'}, // {0xbf, '/'}, // {0xc0, '`'}, // {0xdb, '['}, // {0xdc, '\\'}, // {0xdd, ']'}, // {0xde, '\''} // }; /* The extended-key flag indicates whether the keystroke message originated from one of the additional keys on the enhanced keyboard. The extended keys consist of the ALT and CTRL keys on the right-hand side of the keyboard; the INS, DEL, HOME, END, PAGE UP, PAGE DOWN, and arrow keys in the clusters to the left of the numeric keypad; the NUM LOCK key; the BREAK(CTRL+PAUSE) key; the PRINT SCRN key; and the divide(/) and ENTER keys in the numeric keypad. The extended-key flag is set if the key is an extended key. */ //--------------------------------------------------------------------------------------------------------- /*static int ms2fltk(int vk, int extended) { static unsigned short vklut[256]; static unsigned short extendedlut[256]; if (!vklut[1]) { // init the table unsigned int i; for (i = 0; i < 256; i++) { vklut[i] = i; //tolower(i); } // for (i=VK_F1; i<=VK_F16; i++) // { // vklut[i] = i+(FL_F-(VK_F1-1)); // (FL_F + 1 -> VK_F1) ... (FL_F + 16 -> VK_F16) // } // for (i=VK_NUMPAD0; i<=VK_NUMPAD9; i++) // { // vklut[i] = i+(FL_KP+'0'-VK_NUMPAD0); // (FL_KP + '0' -> VK_NUMPAD0) ... (FL_KP + '9' = VK_NUMPAD9) // } for (i = 0; i < sizeof(vktab)/sizeof(*vktab); i++) { vklut[vktab[i].vk] = vktab[i].fltk; extendedlut[vktab[i].vk] = vktab[i].extended; } for (i = 0; i < 256; i++) { if (!extendedlut[i]) extendedlut[i] = vklut[i]; } } return extended ? extendedlut[vk] : vklut[vk]; }*/ //--------------------------------------------------------------------------------------------------------- static int InspectMouseEvent(HWND window, Event& event, int what, int button, WPARAM wParam, LPARAM lParam) { static int pmx, pmy; event.x = (signed short) LOWORD(lParam); event.y = (signed short) HIWORD(lParam); event.x_root = 0; event.y_root = 0; POINT EventScreenPosition; ClientToScreen(window, &EventScreenPosition); EventScreenPosition.x = event.x; EventScreenPosition.y = event.y; POINT WindowScreenPosition; WindowScreenPosition.x = WindowScreenPosition.y = 0; ClientToScreen(window, &WindowScreenPosition); // Erase mouse event and mouse doubleclick events. Keep the mouse states. ulong _mouse_state = event.mouse_state & 0x0F000000; // establish cause of the event // if (button == 1) // _mouse_state |= NUX_EVENT_BUTTON1; // else if (button == 2) // _mouse_state |= NUX_EVENT_BUTTON2; // else if (button == 3) // _mouse_state |= NUX_EVENT_BUTTON3; // else if (button == 4) { event.mouse_state |= NUX_EVENT_MOUSEWHEEL; event.type = NUX_MOUSE_WHEEL; int zDelta = GET_WHEEL_DELTA_WPARAM(wParam); int xPos = (int) (short) LOWORD(lParam) - WindowScreenPosition.x; int yPos = (int) (short) HIWORD(lParam) - WindowScreenPosition.y; event.x = xPos; event.y = yPos; event.wheel_delta = zDelta; return 1; } // set the cause of the event switch(what) { case 0: { // mouse down if (button == 1) { _mouse_state |= NUX_STATE_BUTTON1_DOWN; _mouse_state |= NUX_EVENT_BUTTON1_DOWN; } else if (button == 2) { _mouse_state |= NUX_STATE_BUTTON2_DOWN; _mouse_state |= NUX_EVENT_BUTTON2_DOWN; } else if (button == 3) { _mouse_state |= NUX_STATE_BUTTON3_DOWN; _mouse_state |= NUX_EVENT_BUTTON3_DOWN; } } break; case 1: { // double click if (button == 1) { _mouse_state |= NUX_EVENT_BUTTON1_DBLCLICK; _mouse_state |= NUX_STATE_BUTTON1_DOWN; _mouse_state |= NUX_EVENT_BUTTON1_DOWN; } else if (button == 2) { _mouse_state |= NUX_EVENT_BUTTON2_DBLCLICK; _mouse_state |= NUX_STATE_BUTTON2_DOWN; _mouse_state |= NUX_EVENT_BUTTON2_DOWN; } else if (button == 3) { _mouse_state |= NUX_EVENT_BUTTON3_DBLCLICK; _mouse_state |= NUX_STATE_BUTTON3_DOWN; _mouse_state |= NUX_EVENT_BUTTON3_DOWN; } } break; case 2: { // button up if (button == 1) { _mouse_state &= ~NUX_STATE_BUTTON1_DOWN; _mouse_state |= NUX_EVENT_BUTTON1_UP; } else if (button == 2) { _mouse_state &= ~NUX_STATE_BUTTON2_DOWN; _mouse_state |= NUX_EVENT_BUTTON2_UP; } else if (button == 3) { _mouse_state &= ~NUX_STATE_BUTTON3_DOWN; _mouse_state |= NUX_EVENT_BUTTON3_UP; } } break; } event.mouse_state = _mouse_state; switch(what) { static int px, py; case 1: // double-click if (event.is_click) { event.clicks++; // The SetCapture function sets the mouse capture to the specified window belonging to // the current thread. SetCapture captures mouse input either when the mouse is over the // capturing window, or when the mouse button was pressed while the mouse was over the // capturing window and the button is still down. Only one window at a time can capture the mouse. SetCapture(window); event.is_click = 1; px = pmx = event.x; py = pmy = event.y; event.type = NUX_MOUSE_DOUBLECLICK; return 1; } case 0: // single-click event.clicks = 0; // The SetCapture function sets the mouse capture to the specified window belonging to // the current thread. SetCapture captures mouse input either when the mouse is over the // capturing window, or when the mouse button was pressed while the mouse was over the // capturing window and the button is still down. Only one window at a time can capture the mouse. SetCapture(window); event.is_click = 1; px = pmx = event.x; py = pmy = event.y; event.type = NUX_MOUSE_PRESSED; return 1; case 2: // release: // The ReleaseCapture function releases the mouse capture from a window in the current thread // and restores normal mouse input processing. A window that has captured the mouse receives all // mouse input, regardless of the position of the cursor, except when a mouse button is clicked // while the cursor hot spot is in the window of another thread. ReleaseCapture(); event.type = NUX_MOUSE_RELEASED; return 1; case 3: // move: default: // avoid compiler warning // MSWindows produces extra events even if mouse does not move, ignore them. // http://blogs.msdn.com/oldnewthing/archive/2003/10/01/55108.aspx: Why do I get spurious WM_MOUSEMOVE messages? if (event.x == pmx && event.y == pmy) return 1; pmx = event.x; pmy = event.y; // if (abs(event.x - px)>5 || abs(event.y - py)>5) // event.is_click = 0; event.type = NUX_MOUSE_MOVE; return 1; } return 0; } unsigned int GetModifierKeyState() { unsigned int state = 0; unsigned short r = 0; // For CapsLock, we don't want to know if the key is pressed Down or Up. // We really want to know the state of the the CapsLock: on(keyboard light is on) or off? r = GetKeyState(VK_CAPITAL); if (r & 1) state |= NUX_STATE_CAPS_LOCK; // For NumLock, we don't want to know if the key is pressed Down or Up. // We really want to know the state of the the NumLock: on(keyboard light is on) or off? r = GetKeyState(VK_NUMLOCK); if (r & 1) state |= NUX_STATE_NUMLOCK; r = GetKeyState(VK_SCROLL); if (r & 0x8000) state |= NUX_STATE_SCROLLLOCK; r = GetKeyState(VK_CONTROL); if (r & 0x8000) state |= NUX_STATE_CTRL; r = GetKeyState(VK_SHIFT); if (r & 0x8000) state |= NUX_STATE_SHIFT; r = GetKeyState(VK_MENU); if (r & 0x8000) state |= NUX_STATE_ALT; if ((GetKeyState(VK_LWIN) | GetKeyState(VK_RWIN)) &~1) { // WIN32 bug? GetKeyState returns garbage if the user hit the // meta key to pop up start menu. Sigh. if ((GetAsyncKeyState(VK_LWIN) | GetAsyncKeyState(VK_RWIN)) &~1) state |= NUX_STATE_SUPER; } return state; } //--------------------------------------------------------------------------------------------------------- bool GraphicsDisplay::GetSystemEvent(Event *event) { MSG msg; event_.Reset(); // Erase mouse event and mouse doubleclick states. Keep the mouse states. event_.mouse_state &= 0x0F000000; bool got_event; // Always set the second parameter of PeekMessage to NULL. Indeed, many services creates // windows on the program behalf. If pass the main window as filter, we will miss all the // messages from the other windows. // Same with GetMessage. if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) // Is There A Message Waiting? If yes, remove it. { if (msg.message == NUX_THREADMSG_START_RENDERING) { m_PauseGraphicsRendering = false; MakeGLContextCurrent(true); } TranslateMessage(&msg); DispatchMessage(&msg); memcpy(event, &event_, sizeof(Event)); got_event = true; } else { memcpy(event, &event_, sizeof(Event)); got_event = false; } if (msg.message == WM_QUIT) { // Re-post the message that we retrieved so other modal loops will catch it. // See [Modality, part 3: The WM_QUIT message] http://blogs.msdn.com/oldnewthing/archive/2005/02/22/378018.aspx PostQuitMessage(msg.wParam); event_.type = NUX_TERMINATE_APP; memcpy(event, &event_, sizeof(Event)); } if (msg.message == -1) // error { event_.type = NUX_NO_EVENT; memcpy(event, &event_, sizeof(Event)); } return got_event; } void GraphicsDisplay::ProcessForeignWin32Event(HWND hWnd, MSG msg, WPARAM wParam, LPARAM lParam, Event *event) { event_.Reset(); // Erase mouse event and mouse doubleclick states. Keep the mouse states. event_.mouse_state &= 0x0F000000; // Always set the second parameter of PeekMessage to NULL. Indeed, many services creates // windows on the program behalf. If pass the main window as filter, we will miss all the // messages from the other windows. // Same with GetMessage. ProcessWin32Event(hWnd, msg.message, wParam, lParam); memcpy(event, &event_, sizeof(Event)); if (msg.message != WM_QUIT) { // Re-post the message that we retrieved so other modal loops will catch it. // See [Modality, part 3: The WM_QUIT message] http://blogs.msdn.com/oldnewthing/archive/2005/02/22/378018.aspx PostQuitMessage(msg.wParam); event_.type = NUX_TERMINATE_APP; memcpy(event, &event_, sizeof(Event)); } if (msg.message == -1) // error { event_.type = NUX_NO_EVENT; memcpy(event, &event_, sizeof(Event)); } } const Event& GraphicsDisplay::GetCurrentEvent() const { return event_; } //--------------------------------------------------------------------------------------------------------- LRESULT CALLBACK WndProcManager(HWND hWnd, // Handle For This Window UINT uMsg, // Message For This Window WPARAM wParam, // Additional Message Information LPARAM lParam) // Additional Message Information { // This creates a warning. It is a 64-bits compatibility issue. // When not in 64-bit you can disable the warning: // Project Properties --> C/C++ tab --> General --> Select "NO" for - Detect 64-bit Portability Issues. // See also GetWindowLongPtr GraphicsDisplay *GLWindow = reinterpret_cast (::GetWindowLongPtr(hWnd, GWLP_USERDATA)); if (GLWindow == 0) { switch(uMsg) { // These cases happens before GLWindow is set. So we must catch them here. case WM_NCCREATE: { // Non Client Area // WARNING: MUST RETURN TRUE TO CONTINUE WITH THE CREATION OF THE WINDOW // return TRUE; // WARNING: Continue with DefWindowProc if you want the title of the window to appears // or you have to set it yourself before returning true break; } case WM_CREATE: { // WARNING: MUST RETURN 0 TO CONTINUE WITH THE CREATION OF THE WINDOW return 0; } } return DefWindowProc(hWnd, uMsg, wParam, lParam); } return GLWindow->ProcessWin32Event(hWnd, uMsg, wParam, lParam); } LRESULT GraphicsDisplay::ProcessWin32Event(HWND hWnd, // Handle For This Window UINT uMsg, // Message For This Window WPARAM wParam, // Additional Message Information LPARAM lParam) // Additional Message Information { switch(uMsg) { case WM_DESTROY: { nuxDebugMsg("[GraphicsDisplay::WndProc]: Window \"%s\" received WM_DESTROY message.", window_title_.c_str()); break; } case WM_CLOSE: { nuxDebugMsg("[GraphicsDisplay::WndProc]: Window \"%s\" received WM_CLOSE message.", window_title_.c_str()); // close? yes or no? PostQuitMessage(0); return 0; } case WM_PAINT: { ValidateRect(hWnd, NULL); // validate the surface to avoid receiving WM_PAINT continuously event_.type = NUX_WINDOW_DIRTY; break; } case WM_CAPTURECHANGED: { // The WM_CAPTURECHANGED message is sent to the window that is losing the mouse capture if ((HWND) lParam == hWnd) { // Cancel everything about the mouse state and send a NUX_WINDOW_EXIT_FOCUS message. event_.mouse_state = 0; //nuxDebugMsg("Windows Msg: WM_CAPTURECHANGED/NUX_WINDOW_EXIT_FOCUS"); return 0; } break; } case WM_ENTERSIZEMOVE: { return 0; } case WM_EXITSIZEMOVE: { RECT clientrect; GetClientRect( hWnd, &clientrect); event_.type = NUX_SIZE_CONFIGURATION; event_.width = clientrect.right - clientrect.left; event_.height = clientrect.bottom - clientrect.top; return 0; } case WM_SIZE: { RECT clientrect; GetClientRect( hWnd, &clientrect); event_.type = NUX_NO_EVENT; //NUX_SIZE_CONFIGURATION; event_.width = clientrect.right - clientrect.left; event_.height = clientrect.bottom - clientrect.top; //setViewPort(0, 0, clientrect.right - clientrect.left, clientrect.bottom - clientrect.top); window_size_.width = clientrect.right - clientrect.left; window_size_.height = clientrect.bottom - clientrect.top; if ((wParam == SIZE_MAXHIDE) || (wParam == SIZE_MINIMIZED)) { window_minimized_ = true; } else { window_minimized_ = false; } if ((wParam == SIZE_MAXIMIZED) || (wParam == SIZE_RESTORED)) { event_.type = NUX_SIZE_CONFIGURATION; } return 0; } case WM_SETFOCUS: { event_.type = NUX_WINDOW_ENTER_FOCUS; event_.mouse_state = 0; // This causes the mouse to be outside of all widgets when it is tested in m_EventHandler.Process(). // Because WM_SETFOCUS can happen with the mouse outside of the client area, we set x and y so that the mouse will be // outside of all widgets. A subsequent mouse down or mouse move event will set the correct values for x and y. event_.x = 0xFFFFFFFF; event_.y = 0xFFFFFFFF; event_.dx = 0; event_.dy = 0; event_.virtual_code = 0; //nuxDebugMsg("Windows Msg: WM_SETFOCUS/NUX_WINDOW_ENTER_FOCUS"); break; } case WM_KILLFOCUS: { event_.type = NUX_WINDOW_EXIT_FOCUS; event_.mouse_state = 0; // This causes the mouse to be outside of all widgets when it is tested in m_EventHandler.Process() event_.x = 0xFFFFFFFF; event_.y = 0xFFFFFFFF; event_.dx = 0; event_.dy = 0; event_.virtual_code = 0; //nuxDebugMsg("Windows Msg: WM_KILLFOCUS/NUX_WINDOW_EXIT_FOCUS"); break; } case WM_NCHITTEST: { break; } case WM_ACTIVATE: { if (LOWORD(wParam) != WA_INACTIVE) { event_.type = NUX_WINDOW_ENTER_FOCUS; } else { event_.type = NUX_WINDOW_EXIT_FOCUS; } event_.mouse_state = 0; // This causes the mouse to be outside of all widgets when it is tested in m_EventHandler.Process(). // Because WM_SETFOCUS can happen with the mouse outside of the client area, we set x and y so that the mouse will be // outside of all widgets. A subsequent mouse down or mouse move event will set the correct values for x and y. event_.x = 0xFFFFFFFF; event_.y = 0xFFFFFFFF; event_.dx = 0; event_.dy = 0; event_.virtual_code = 0; event_.key_modifiers = GetModifierKeyState(); return 0; } case WM_ACTIVATEAPP: { if (wParam) { event_.type = NUX_WINDOW_ENTER_FOCUS; } else { event_.type = NUX_WINDOW_EXIT_FOCUS; } event_.mouse_state = 0; // This causes the mouse to be outside of all widgets when it is tested in m_EventHandler.Process(). // Because WM_SETFOCUS can happen with the mouse outside of the client area, we set x and y so that the mouse will be // outside of all widgets. A subsequent mouse down or mouse move event will set the correct values for x and y. event_.x = 0xFFFFFFFF; event_.y = 0xFFFFFFFF; event_.dx = 0; event_.dy = 0; event_.virtual_code = 0; event_.key_modifiers = GetModifierKeyState(); return 0; } case WM_SYSKEYDOWN: case WM_KEYDOWN: { event_.type = NUX_KEYDOWN; event_.key_modifiers = GetModifierKeyState(); event_.win32_keysym = wParam; if ((uMsg == WM_KEYDOWN) || (uMsg == WM_SYSKEYDOWN)) { event_.VirtualKeycodeState[GraphicsDisplay::Win32KeySymToINL(wParam) ] = 1; } if (wParam == VK_CONTROL) { if (lParam & (1 << 24)) { event_.win32_keysym = NUX_VK_RCONTROL; } else { event_.win32_keysym = NUX_VK_LCONTROL; } } if (wParam == VK_MENU) { if (lParam & (1 << 24)) { event_.win32_keysym = NUX_VK_RALT; } else { event_.win32_keysym = NUX_VK_LALT; } } if (wParam == VK_SHIFT) { if (HIWORD(GetAsyncKeyState(VK_LSHIFT))) { event_.win32_keysym = NUX_VK_LSHIFT; } else if (HIWORD(GetAsyncKeyState(VK_RSHIFT))) { event_.win32_keysym = NUX_VK_RSHIFT; } } break; } case WM_SYSKEYUP: case WM_KEYUP: { event_.type = NUX_KEYUP; event_.key_modifiers = GetModifierKeyState(); event_.win32_keysym = wParam; if ((uMsg == WM_KEYUP) || (uMsg == WM_SYSKEYUP)) { event_.VirtualKeycodeState[GraphicsDisplay::Win32KeySymToINL(wParam) ] = 0; } break; } case WM_DEADCHAR: case WM_SYSDEADCHAR: case WM_CHAR: case WM_SYSCHAR: { event_.key_modifiers = GetModifierKeyState(); // reset key repeat count to 0. event_.key_repeat_count = 0; if (lParam & (1 << 31)) { // key up events. event_.type = NUX_KEYUP; return 0; } else { // key down events. event_.type = NUX_KEYDOWN; event_.key_repeat_count = (int) (lParam & 0xff); } if ((wParam == '\b') || // backspace (wParam == '\t') || // tab (wParam == '\n') || // linefeed (wParam == '\r')) // carriage return { return 0; } wchar_t *utf16_str = new wchar_t [4]; std::memset(utf16_str, 0, sizeof(wchar_t) * 4); std::memcpy(utf16_str, (int*) &wParam, sizeof(wParam)); wchar_t *temp0 = utf16_str; unsigned char *utf8_str = new unsigned char [NUX_EVENT_TEXT_BUFFER_SIZE]; std::memset(utf8_str, 0, sizeof(unsigned char) * NUX_EVENT_TEXT_BUFFER_SIZE); unsigned char *temp1 = utf8_str; ConversionResult res = ConvertUTF16toUTF8((const wchar_t **) &temp0, utf16_str + sizeof(wchar_t) * 4, &temp1, utf8_str + NUX_EVENT_TEXT_BUFFER_SIZE, lenientConversion); if (res == conversionOK) { std::memcpy(event_.text, utf8_str, NUX_EVENT_TEXT_BUFFER_SIZE); } delete utf8_str; delete utf16_str; return 0; } case WM_UNICHAR: { if (wParam == UNICODE_NOCHAR) return 1; event_.key_modifiers = GetModifierKeyState(); // reset key repeat count to 0. event_.key_repeat_count = 0; if (lParam & (1 << 31)) { // key up events. event_.type = NUX_KEYUP; return 0; } else { // key down events. event_.type = NUX_KEYDOWN; event_.key_repeat_count = (int) (lParam & 0xff); } unsigned int *utf32_str = new unsigned int [4]; std::memset(utf32_str, 0, sizeof(unsigned int) * 4); std::memcpy(utf32_str, (int*) &wParam, sizeof(wParam)); unsigned int *temp0 = utf32_str; unsigned char *utf8_str = new unsigned char [NUX_EVENT_TEXT_BUFFER_SIZE]; std::memset(utf8_str, 0, sizeof(unsigned char) * NUX_EVENT_TEXT_BUFFER_SIZE); unsigned char *temp1 = utf8_str; ConversionResult res = ConvertUTF32toUTF8((const unsigned int**) &temp0, utf32_str + sizeof(unsigned int) * 4, &temp1, utf8_str + NUX_EVENT_TEXT_BUFFER_SIZE, lenientConversion); if (res == conversionOK) { std::memcpy(event_.text, utf8_str, NUX_EVENT_TEXT_BUFFER_SIZE); } delete utf8_str; delete utf32_str; } case WM_LBUTTONDOWN: { InspectMouseEvent(hWnd, event_, 0, 1, wParam, lParam); //nuxDebugMsg("Windows Msg: WM_LBUTTONDOWN"); return 0; } case WM_LBUTTONDBLCLK: { InspectMouseEvent(hWnd, event_, 1, 1, wParam, lParam); //nuxDebugMsg("Windows Msg: WM_LBUTTONDBLCLK"); return 0; } case WM_LBUTTONUP: { InspectMouseEvent(hWnd, event_, 2, 1, wParam, lParam); //nuxDebugMsg("Windows Msg: WM_LBUTTONUP"); return 0; } case WM_MBUTTONDOWN: { InspectMouseEvent(hWnd, event_, 0, 2, wParam, lParam); break; } case WM_MBUTTONDBLCLK: { InspectMouseEvent(hWnd, event_, 1, 2, wParam, lParam); break; } case WM_MBUTTONUP: { InspectMouseEvent(hWnd, event_, 2, 2, wParam, lParam); break; } case WM_RBUTTONDOWN: { InspectMouseEvent(hWnd, event_, 0, 3, wParam, lParam); break; } case WM_RBUTTONDBLCLK: { InspectMouseEvent(hWnd, event_, 1, 3, wParam, lParam); break; } case WM_RBUTTONUP: { InspectMouseEvent(hWnd, event_, 2, 3, wParam, lParam); break; } case WM_MOUSEWHEEL: { InspectMouseEvent(hWnd, event_, 0, 4, wParam, lParam); break; } case WM_NCLBUTTONDBLCLK: { event_.type = NUX_NC_WINDOW_CONFIGURATION; break; } case WM_NCLBUTTONDOWN: { event_.type = NUX_NC_WINDOW_CONFIGURATION; break; } case WM_NCLBUTTONUP: { event_.type = NUX_NC_WINDOW_CONFIGURATION; break; } case WM_NCMBUTTONDBLCLK: { event_.type = NUX_NC_WINDOW_CONFIGURATION; break; } case WM_NCMBUTTONDOWN: { event_.type = NUX_NC_WINDOW_CONFIGURATION; break; } case WM_NCMBUTTONUP: { event_.type = NUX_NC_WINDOW_CONFIGURATION; break; } case WM_NCRBUTTONDBLCLK: { event_.type = NUX_NC_WINDOW_CONFIGURATION; break; } case WM_NCRBUTTONDOWN: { event_.type = NUX_NC_WINDOW_CONFIGURATION; break; } case WM_NCRBUTTONUP: { event_.type = NUX_NC_WINDOW_CONFIGURATION; break; } case WM_MOUSEMOVE: { InspectMouseEvent(hWnd, event_, 3, 0, wParam, lParam); //nuxDebugMsg("Windows Msg: WM_MOUSEMOVE"); TRACKMOUSEEVENT tme = { sizeof(tme) }; // Enable NUX_WINDOW_MOUSELEAVE event. tme.dwFlags = TME_LEAVE; tme.hwndTrack = hWnd; TrackMouseEvent(&tme); break; } // Note: there is no WM_MOUSEENTER. WM_MOUSEENTER is equivalent to WM_MOUSEMOVE after a WM_MOUSELEAVE. case WM_MOUSELEAVE: { // All tracking requested by TrackMouseEvent is canceled when this message is generated. // The application must call TrackMouseEvent when the mouse reenters its window if // it requires further tracking of mouse hover behavior. event_.type = NUX_WINDOW_MOUSELEAVE; // This causes the mouse to be outside of all widgets when it is tested in m_EventHandler.Process() event_.x = 0xFFFFFFFF; event_.y = 0xFFFFFFFF; //nuxDebugMsg("Windows Msg: WM_MOUSELEAVE/NUX_WINDOW_MOUSELEAVE"); break; } case WM_SETCURSOR: if ((LOWORD(lParam) == HTCLIENT) && cursor_) { SetCursor(cursor_); return TRUE; //return FALSE; } else break; case WM_COMMAND: { nuxDebugMsg("[GraphicsDisplay::WndProc]: Window \"%s\" received WM_COMMAND message.", window_title_.c_str()); break;; } case WM_SYSCOMMAND: // Intercept System Commands { switch(wParam) // Check System Calls { case SC_CLOSE: break; case SC_CONTEXTHELP: break; case SC_DEFAULT: break; case SC_HOTKEY: break; case SC_HSCROLL: break; case SC_KEYMENU: break; case SC_MAXIMIZE: break; case SC_MINIMIZE: break; case SC_MONITORPOWER: break; case SC_MOUSEMENU: break; case SC_MOVE: break; case SC_NEXTWINDOW: break; case SC_PREVWINDOW: break; case SC_RESTORE: break; case SC_SCREENSAVE: break; case SC_SIZE: break; case SC_TASKLIST: break; case SC_VSCROLL: break; } break; // Exit } } return DefWindowProc(hWnd, uMsg, wParam, lParam); } int GraphicsDisplay::Win32VKToNuxKey(int vk) { switch(vk) { case VK_CANCEL: return NUX_VK_CANCEL; case VK_BACK: return NUX_VK_BACKSPACE; case VK_TAB: return NUX_VK_TAB; case VK_CLEAR: return NUX_VK_CLEAR; case VK_RETURN: return NUX_VK_ENTER; case VK_SHIFT: return NUX_VK_SHIFT; case VK_CONTROL: return NUX_VK_LCONTROL; case VK_LCONTROL: return NUX_VK_LCONTROL; case VK_RCONTROL: return NUX_VK_RCONTROL; case VK_MENU: return NUX_VK_LALT; case VK_LMENU: return NUX_VK_LALT; case VK_RMENU: return NUX_VK_RALT; case VK_PAUSE: return NUX_VK_PAUSE; case VK_CAPITAL: return NUX_VK_CAPITAL; case VK_ESCAPE: return NUX_VK_ESCAPE; case VK_PRIOR: return NUX_VK_PAGE_UP; case VK_NEXT: return NUX_VK_PAGE_DOWN; case VK_END: return NUX_VK_END; case VK_HOME: return NUX_VK_HOME; case VK_LEFT: return NUX_VK_LEFT; case VK_UP: return NUX_VK_UP; case VK_RIGHT: return NUX_VK_RIGHT; case VK_DOWN: return NUX_VK_DOWN; case VK_INSERT: return NUX_VK_INSERT; case VK_DELETE: return NUX_VK_DELETE; case 0x30: return NUX_VK_0; case 0x31: return NUX_VK_1; case 0x32: return NUX_VK_2; case 0x33: return NUX_VK_3; case 0x34: return NUX_VK_4; case 0x35: return NUX_VK_5; case 0x36: return NUX_VK_6; case 0x37: return NUX_VK_7; case 0x38: return NUX_VK_8; case 0x39: return NUX_VK_9; case 0x41: return NUX_VK_A; case 0x42: return NUX_VK_B; case 0x43: return NUX_VK_C; case 0x44: return NUX_VK_D; case 0x45: return NUX_VK_E; case 0x46: return NUX_VK_F; case 0x47: return NUX_VK_G; case 0x48: return NUX_VK_H; case 0x49: return NUX_VK_I; case 0x4A: return NUX_VK_J; case 0x4B: return NUX_VK_K; case 0x4C: return NUX_VK_L; case 0x4D: return NUX_VK_M; case 0x4E: return NUX_VK_N; case 0x4F: return NUX_VK_O; case 0x50: return NUX_VK_P; case 0x51: return NUX_VK_Q; case 0x52: return NUX_VK_R; case 0x53: return NUX_VK_S; case 0x54: return NUX_VK_T; case 0x55: return NUX_VK_U; case 0x56: return NUX_VK_V; case 0x57: return NUX_VK_W; case 0x58: return NUX_VK_X; case 0x59: return NUX_VK_Y; case 0x5A: return NUX_VK_Z; case VK_LWIN: return NUX_VK_LSUPER; // Windows key left case VK_RWIN: return NUX_VK_RSUPER; // Windows key right case VK_NUMLOCK: return NUX_VK_NUMLOCK; case VK_SCROLL: return NUX_VK_SCROLL; case VK_LSHIFT: return NUX_VK_LSHIFT; case VK_RSHIFT: return NUX_VK_RSHIFT; case VK_NUMPAD0: return NUX_KP_0; case VK_NUMPAD1: return NUX_KP_1; case VK_NUMPAD2: return NUX_KP_2; case VK_NUMPAD3: return NUX_KP_3; case VK_NUMPAD4: return NUX_KP_4; case VK_NUMPAD5: return NUX_KP_5; case VK_NUMPAD6: return NUX_KP_6; case VK_NUMPAD7: return NUX_KP_7; case VK_NUMPAD8: return NUX_KP_8; case VK_NUMPAD9: return NUX_KP_9; case VK_MULTIPLY: return NUX_KP_MULTIPLY; case VK_ADD: return NUX_KP_ADD; case VK_SEPARATOR: return NUX_KP_SEPARATOR; case VK_SUBTRACT: return NUX_VK_SUBTRACT; case VK_DECIMAL: return NUX_VK_DECIMAL; case VK_DIVIDE: return NUX_VK_SLASH; case VK_F1: return NUX_VK_F1; case VK_F2: return NUX_VK_F2; case VK_F3: return NUX_VK_F3; case VK_F4: return NUX_VK_F4; case VK_F5: return NUX_VK_F5; case VK_F6: return NUX_VK_F6; case VK_F7: return NUX_VK_F7; case VK_F8: return NUX_VK_F8; case VK_F9: return NUX_VK_F9; case VK_F10: return NUX_VK_F10; case VK_F11: return NUX_VK_F11; case VK_F12: return NUX_VK_F12; case VK_F13: return NUX_VK_F13; case VK_F14: return NUX_VK_F14; case VK_F15: return NUX_VK_F15; case VK_F16: return NUX_VK_F16; case VK_F17: return NUX_VK_F17; case VK_F18: return NUX_VK_F18; case VK_F19: return NUX_VK_F19; case VK_F20: return NUX_VK_F20; case VK_F21: return NUX_VK_F21; case VK_F22: return NUX_VK_F22; case VK_F23: return NUX_VK_F23; case VK_F24: return NUX_VK_F24; default: return 0x0; } } int GraphicsDisplay::Win32KeySymToINL(int Keysym) { return Keysym; // switch(Keysym) // { // case VK_CANCEL: // return NUX_VK_CANCEL; // case VK_BACK: // return NUX_VK_BACKSPACE; // case VK_TAB: // return NUX_VK_TAB; // case VK_CLEAR: // return NUX_VK_CLEAR; // case VK_RETURN: // return NUX_VK_ENTER; // case VK_SHIFT: // return NUX_VK_SHIFT; // case VK_CONTROL: // return NUX_VK_CONTROL; // case VK_MENU: // return NUX_VK_MENU; // ALT key // case VK_PAUSE: // return NUX_VK_PAUSE; // case VK_CAPITAL: // return NUX_VK_CAPITAL; // case VK_ESCAPE: // return NUX_VK_ESCAPE; // case VK_SPACE: // return NUX_VK_SPACE; // case VK_PRIOR: // return NUX_VK_PAGE_UP; // case VK_NEXT: // return NUX_VK_PAGE_DOWN; // case VK_END: // return NUX_VK_END; // case VK_HOME: // return NUX_VK_HOME; // case VK_LEFT: // return NUX_VK_LEFT; // case VK_UP: // return NUX_VK_UP; // case VK_RIGHT: // return NUX_VK_RIGHT; // case VK_DOWN: // return NUX_VK_DOWN; // case VK_SELECT: // return NUX_VK_SELECT; // case VK_PRINT: // return NUX_VK_PRINT; // case VK_EXECUTE: // return NUX_VK_EXECUTE; // case VK_INSERT: // return NUX_VK_INSERT; // case VK_DELETE: // return NUX_VK_DELETE; // case VK_HELP: // return NUX_VK_HELP; // case 0x30: // return NUX_VK_0; // case 0x31: // return NUX_VK_1; // case 0x32: // return NUX_VK_2; // case 0x33: // return NUX_VK_3; // case 0x34: // return NUX_VK_4; // case 0x35: // return NUX_VK_5; // case 0x36: // return NUX_VK_6; // case 0x37: // return NUX_VK_7; // case 0x38: // return NUX_VK_8; // case 0x39: // return NUX_VK_9; // case 0x41: // return NUX_VK_A; // case 0x42: // return NUX_VK_B; // case 0x43: // return NUX_VK_C; // case 0x44: // return NUX_VK_D; // case 0x45: // return NUX_VK_E; // case 0x46: // return NUX_VK_F; // case 0x47: // return NUX_VK_G; // case 0x48: // return NUX_VK_H; // case 0x49: // return NUX_VK_I; // case 0x4A: // return NUX_VK_J; // case 0x4B: // return NUX_VK_K; // case 0x4C: // return NUX_VK_L; // case 0x4D: // return NUX_VK_M; // case 0x4E: // return NUX_VK_N; // case 0x4F: // return NUX_VK_O; // case 0x50: // return NUX_VK_P; // case 0x51: // return NUX_VK_Q; // case 0x52: // return NUX_VK_R; // case 0x53: // return NUX_VK_S; // case 0x54: // return NUX_VK_T; // case 0x55: // return NUX_VK_U; // case 0x56: // return NUX_VK_V; // case 0x57: // return NUX_VK_W; // case 0x58: // return NUX_VK_X; // case 0x59: // return NUX_VK_Y; // case 0x5A: // return NUX_VK_Z; // case VK_LWIN: // return NUX_VK_LWIN; // Windows key left // case VK_RWIN: // return NUX_VK_RWIN; // Windows key right // case VK_NUMPAD0: // return NUX_VK_NUMPAD0; // case VK_NUMPAD1: // return NUX_VK_NUMPAD1; // case VK_NUMPAD2: // return NUX_VK_NUMPAD2; // case VK_NUMPAD3: // return NUX_VK_NUMPAD3; // case VK_NUMPAD4: // return NUX_VK_NUMPAD4; // case VK_NUMPAD5: // return NUX_VK_NUMPAD5; // case VK_NUMPAD6: // return NUX_VK_NUMPAD6; // case VK_NUMPAD7: // return NUX_VK_NUMPAD7; // case VK_NUMPAD8: // return NUX_VK_NUMPAD8; // case VK_NUMPAD9: // return NUX_VK_NUMPAD9; // case VK_MULTIPLY: // return NUX_VK_MULTIPLY; // case VK_ADD: // return NUX_VK_ADD; // case VK_SEPARATOR: // return NUX_VK_SEPARATOR; // case VK_SUBTRACT: // return NUX_VK_SUBTRACT; // case VK_DECIMAL: // return NUX_VK_DECIMAL; // case VK_DIVIDE: // return NUX_VK_DIVIDE; // case VK_F1: // return NUX_VK_F1; // case VK_F2: // return NUX_VK_F2; // case VK_F3: // return NUX_VK_F3; // case VK_F4: // return NUX_VK_F4; // case VK_F5: // return NUX_VK_F5; // case VK_F6: // return NUX_VK_F6; // case VK_F7: // return NUX_VK_F7; // case VK_F8: // return NUX_VK_F8; // case VK_F9: // return NUX_VK_F9; // case VK_F10: // return NUX_VK_F10; // case VK_F11: // return NUX_VK_F11; // case VK_F12: // return NUX_VK_F12; // case VK_F13: // return NUX_VK_F13; // case VK_F14: // return NUX_VK_F14; // case VK_F15: // return NUX_VK_F15; // case VK_F16: // return NUX_VK_F16; // case VK_F17: // return NUX_VK_F17; // case VK_F18: // return NUX_VK_F18; // case VK_F19: // return NUX_VK_F19; // case VK_F20: // return NUX_VK_F20; // case VK_F21: // return NUX_VK_F21; // case VK_F22: // return NUX_VK_F22; // case VK_F23: // return NUX_VK_F23; // case VK_F24: // return NUX_VK_F24; // case VK_NUMLOCK: // return NUX_VK_NUMLOCK; // case VK_SCROLL: // return NUX_VK_SCROLL; // case VK_LSHIFT: // return NUX_VK_LSHIFT; // case VK_RSHIFT: // return NUX_VK_RSHIFT; // case VK_LCONTROL: // return NUX_VK_LCONTROL; // case VK_RCONTROL: // return NUX_VK_RCONTROL; // case VK_LMENU: // return NUX_VK_LMENU; // case VK_RMENU: // return NUX_VK_RMENU; // default: // return 0x0; // } } void GraphicsDisplay::InitGlobalGrabWindow() { } bool GraphicsDisplay::GrabPointer(GrabReleaseCallback callback, void *data, bool replace_existing) { return false; } bool GraphicsDisplay::UngrabPointer(void *data) { return true; } bool GraphicsDisplay::PointerIsGrabbed() { return false; } bool GraphicsDisplay::GrabKeyboard(GrabReleaseCallback callback, void *data, bool replace_existing) { return _global_keyboard_grab_active; } bool GraphicsDisplay::UngrabKeyboard(void *data) { return true; } bool GraphicsDisplay::KeyboardIsGrabbed() { return _global_keyboard_grab_active; } //--------------------------------------------------------------------------------------------------------- void GraphicsDisplay::GetDisplayInfo() { DEVMODE devmode; INT iMode = 0; BOOL bRetVal; DeviceModes dm; m_num_gfx_device_modes = 0; do { bRetVal = ::EnumDisplaySettings(NULL, iMode, &devmode); iMode++; if (bRetVal) { dm.width = devmode.dmPelsWidth; dm.height = devmode.dmPelsHeight; dm.format = devmode.dmBitsPerPel; dm.refresh_rate = devmode.dmDisplayFrequency; m_gfx_device_modes.push_back(dm); m_num_gfx_device_modes++; } } while (bRetVal); } //--------------------------------------------------------------------------------------------------------- void GraphicsDisplay::ShowWindow() { ::ShowWindow(wnd_handle_, SW_SHOW); } //--------------------------------------------------------------------------------------------------------- void GraphicsDisplay::HideWindow() { ::ShowWindow(wnd_handle_, SW_HIDE); } bool GraphicsDisplay::IsWindowVisible() { return ::IsWindowVisible(wnd_handle_); } //--------------------------------------------------------------------------------------------------------- void GraphicsDisplay::EnterMaximizeWindow() { ::ShowWindow(wnd_handle_, SW_MAXIMIZE); } //--------------------------------------------------------------------------------------------------------- void GraphicsDisplay::ExitMaximizeWindow() { ::ShowWindow(wnd_handle_, SW_RESTORE); } //--------------------------------------------------------------------------------------------------------- void GraphicsDisplay::SetWindowTitle(const char *Title) { SetWindowText(wnd_handle_, Title); } //--------------------------------------------------------------------------------------------------------- // NUXTODO: remove this call. Make a direct access to GpuInfo via GpuDevice. bool GraphicsDisplay::HasVSyncSwapControl() const { return GetGpuDevice()->GetGpuInfo().Support_EXT_Swap_Control(); } //--------------------------------------------------------------------------------------------------------- void GraphicsDisplay::EnableVSyncSwapControl() { if (HasVSyncSwapControl()) { wglSwapIntervalEXT(1); } } //--------------------------------------------------------------------------------------------------------- void GraphicsDisplay::DisableVSyncSwapControl() { if (HasVSyncSwapControl()) { wglSwapIntervalEXT(0); } } float GraphicsDisplay::GetFrameTime() const { return m_FrameTime; } void GraphicsDisplay::ResetFrameTime() { m_Timer.Reset(); } bool GraphicsDisplay::StartOpenFileDialog(FileDialogOption &fdo) { return Win32OpenFileDialog(GetWindowHandle(), fdo); } bool GraphicsDisplay::StartSaveFileDialog(FileDialogOption &fdo) { return Win32SaveFileDialog(GetWindowHandle(), fdo); } bool GraphicsDisplay::StartColorDialog(ColorDialogOption &cdo) { return Win32ColorDialog(GetWindowHandle(), cdo); } //--------------------------------------------------------------------------------------------------------- void GraphicsDisplay::SetWindowCursor(HCURSOR cursor) { cursor_ = cursor; } //--------------------------------------------------------------------------------------------------------- HCURSOR GraphicsDisplay::GetWindowCursor() const { return cursor_; } //--------------------------------------------------------------------------------------------------------- void GraphicsDisplay::PauseThreadGraphicsRendering() { m_PauseGraphicsRendering = true; MakeGLContextCurrent(false); } //--------------------------------------------------------------------------------------------------------- bool GraphicsDisplay::IsPauseThreadGraphicsRendering() const { return m_PauseGraphicsRendering; } } ./NuxGraphics/IOpenGLIndexBuffer.cpp0000644000004100000410000000755613313171755017604 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "GpuDevice.h" #include "GLDeviceObjects.h" #include "IOpenGLIndexBuffer.h" namespace nux { NUX_IMPLEMENT_OBJECT_TYPE(IOpenGLIndexBuffer); IOpenGLIndexBuffer::IOpenGLIndexBuffer(unsigned int Length, VBO_USAGE Usage, INDEX_FORMAT Format, NUX_FILE_LINE_DECL) : IOpenGLResource(RTINDEXBUFFER, NUX_FILE_LINE_PARAM) , _Length(Length) , _Format(Format) , _Usage(Usage) , _MemMap(0) , _OffsetToLock(0) , _SizeToLock(0) { CHECKGL(glGenBuffersARB(1, &_OpenGLID)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, _OpenGLID)); CHECKGL(glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, _Length, NULL, Usage)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); GRunTimeStats.Register(this); } IOpenGLIndexBuffer::~IOpenGLIndexBuffer() { CHECKGL(glDeleteBuffersARB(1, &_OpenGLID)); _OpenGLID = 0; GRunTimeStats.UnRegister(this); } int IOpenGLIndexBuffer::Lock( unsigned int OffsetToLock, unsigned int SizeToLock, void **ppbData) { nuxAssert(SizeToLock <= _Length); nuxAssert(OffsetToLock + SizeToLock <= _Length); if (SizeToLock == 0) { if (OffsetToLock == 0) { // lock the entire buffer SizeToLock = _Length; } else return OGL_INVALID_CALL; } // If _MemMap, _OffsetToLock and _SizeToLock are not equal to zero, then we have already mapped the buffer // Unlock it before locking again. nuxAssert(_MemMap == 0); nuxAssert(_OffsetToLock == 0); nuxAssert(_SizeToLock == 0); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, _OpenGLID)); // Map the Entire buffer into system memory #ifndef NUX_OPENGLES_20 _MemMap = (BYTE *) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); // todo: use Format instead of GL_WRITE_ONLY_ARB CHECKGL_MSG(glMapBufferARB); *ppbData = (void *) (_MemMap + OffsetToLock); #else _MemMap = new BYTE[SizeToLock]; *ppbData = _MemMap; #endif _OffsetToLock = OffsetToLock; _SizeToLock = SizeToLock; CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); return OGL_OK; } int IOpenGLIndexBuffer::Unlock() { nuxAssert(_MemMap != 0); nuxAssert(_SizeToLock != 0); // No need to bind CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, _OpenGLID)); #ifndef NUX_OPENGLES_20 CHECKGL(glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB)); #else CHECKGL(glBufferSubData(GL_ELEMENT_ARRAY_BUFFER_ARB, _OffsetToLock, _SizeToLock, _MemMap)); delete [] _MemMap; #endif CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); _MemMap = 0; _OffsetToLock = 0; _SizeToLock = 0; return OGL_OK; } int IOpenGLIndexBuffer::GetStride() { if (_Format == INDEX_FORMAT_USHORT) { return 2; } else if (_Format == INDEX_FORMAT_UINT) { return 4; } else return 0; } void IOpenGLIndexBuffer::BindIndexBuffer() { CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, _OpenGLID)); } unsigned int IOpenGLIndexBuffer::GetSize() { return _Length; } } ./NuxGraphics/GLVertexResourceManager.h0000644000004100000410000001174513313171755020370 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef GLVERTEXRESOURCEMANAGER_H #define GLVERTEXRESOURCEMANAGER_H #include "GLResourceManager.h" #include "IOpenGLVertexBuffer.h" #include "IOpenGLIndexBuffer.h" #include "IOpenGLVertexDeclaration.h" #include "MeshData.h" namespace nux { class VertexBuffer: public ResourceData { NUX_DECLARE_OBJECT_TYPE(VertexBuffer, ResourceData); public: VertexBuffer(); virtual ~VertexBuffer(); VertexBuffer(int Size, int Stride); //! Allocate space for a "num_element", each of size "size". /*! @param num_element Number of elements. @param size Number of byte for every element. */ void Allocate(int num_index, int size); int GetSize() const; int GetStride() const; int GetNumElement() const; const void* GetPtrRawData() const; void* GetPtrRawData(); public: std::vector _Data; int _Stride; }; class IndexBuffer: public ResourceData { NUX_DECLARE_OBJECT_TYPE(IndexBuffer, ResourceData); // IndexBuffer is very similar to MeshBuffer except that vertex indices // are not inter-mixed with other vertex data. So the Stride here should be 2 bytes or 4 bytes. public: IndexBuffer(); virtual ~IndexBuffer(); IndexBuffer(int Size, int Stride); void Allocate(int Size, int Stride); int GetSize() const; int GetStride() const; int GetNumIndex() const; const void* GetPtrRawData() const; void* GetPtrRawData(); public: std::vector _Data; int _Stride; int _num_index; }; class VertexDeclaration: public ResourceData { NUX_DECLARE_OBJECT_TYPE(NVertexDeclaration, ResourceData); public: VertexDeclaration(); ~VertexDeclaration(); void AddVertexComponent(VERTEXELEMENT); std::vector _declaration; }; class CachedVertexBuffer: public CachedResourceData { NUX_DECLARE_OBJECT_TYPE(CachedVertexBuffer, CachedResourceData); public: CachedVertexBuffer(NResourceSet* ResourceManager, VertexBuffer* resource); ~CachedVertexBuffer(); ObjectPtr _vertex_buffer; bool UpdateResource(ResourceData* Resource); int GetElementSize() const; int GetBufferStride() const; private: void LoadVertexData(VertexBuffer* vertex_buffer); int _Size; int _Stride; }; class CachedIndexBuffer: public CachedResourceData { NUX_DECLARE_OBJECT_TYPE(CachedIndexBuffer, CachedResourceData); public: CachedIndexBuffer(NResourceSet* ResourceManager, IndexBuffer* resource); ~CachedIndexBuffer(); ObjectPtr _index_buffer; bool UpdateResource(ResourceData* Resource); int GetElementSize() const; int GetBufferStride() const; int GetNumIndex() const; private: void LoadIndexData(IndexBuffer* index_buffer); int _Size; int _Stride; int _num_index; }; class CachedVertexDeclaration: public CachedResourceData { NUX_DECLARE_OBJECT_TYPE(CachedVertexDeclaration, CachedResourceData); public: CachedVertexDeclaration(NResourceSet* ResourceManager, VertexDeclaration* Resource); ~CachedVertexDeclaration(); bool UpdateResource(ResourceData* Resource); ObjectPtr _declaration; }; class CachedMeshBuffer; class MeshBuffer: public ResourceData { NUX_DECLARE_OBJECT_TYPE(MeshBuffer, ResourceData); public: MeshBuffer(NUX_FILE_LINE_PROTO); virtual ~MeshBuffer(); bool Update(const MeshData* mesh_data); ObjectPtr GetCachedMeshBuffer(); public: VertexBuffer* _vertex_buffer; IndexBuffer* _index_buffer; VertexDeclaration* _vertex_declaration; NuxMeshPrimitiveType _mesh_primitive_type; }; class CachedMeshBuffer: public CachedResourceData { NUX_DECLARE_OBJECT_TYPE(CachedMeshBuffer, CachedResourceData); public: ObjectPtr _cached_vertex_buffer; ObjectPtr _cached_vertex_declaration; ObjectPtr _cached_index_buffer; NuxMeshPrimitiveType _mesh_primitive_type; CachedMeshBuffer(NResourceSet* ResourceManager, MeshBuffer* resource); ~CachedMeshBuffer(); bool UpdateResource(ResourceData* Resource); }; } #endif // GLVERTEXRESOURCEMANAGER_H ./NuxGraphics/OpenGLMapping.h0000644000004100000410000001142013313171755016313 0ustar www-datawww-data/* * Copyright 2011 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Travis Watkins * */ // A series of defines to map GL functions to GLES functions #ifndef OPENGLMAPPING_H #define OPENGLMAPPING_H #define GL_GLEXT_PROTOTYPES #define GLcharARB GLchar #define GL_COLOR_ATTACHMENT0_EXT GL_COLOR_ATTACHMENT0 #define GL_DEPTH_ATTACHMENT_EXT GL_DEPTH_ATTACHMENT #define GL_FRAMEBUFFER_EXT GL_FRAMEBUFFER #define GL_FRAMEBUFFER_BINDING_EXT GL_FRAMEBUFFER_BINDING #define GL_FRAMEBUFFER_COMPLETE_EXT GL_FRAMEBUFFER_COMPLETE #define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT #define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME #define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT #define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS #define GL_FRAMEBUFFER_UNSUPPORTED_EXT GL_FRAMEBUFFER_UNSUPPORTED #define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE #define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL #define GL_RENDERBUFFER_EXT GL_RENDERBUFFER #define GL_RENDERBUFFER_BINDING_EXT GL_RENDERBUFFER_BINDING #define GL_MAX_RENDERBUFFER_SIZE_EXT GL_MAX_RENDERBUFFER_SIZE #define GL_ARRAY_BUFFER_ARB GL_ARRAY_BUFFER #define GL_ELEMENT_ARRAY_BUFFER_ARB GL_ELEMENT_ARRAY_BUFFER // not sure if this will work in all cases #define GL_CLAMP GL_CLAMP_TO_EDGE // needs extra shader code but otherwise is equivalent #define GL_CLAMP_TO_BORDER GL_CLAMP_TO_EDGE #define GL_WRITE_ONLY_ARB GL_WRITE_ONLY_OES #define GL_VERTEX_SHADER_ARB GL_VERTEX_SHADER #define GL_FRAGMENT_SHADER_ARB GL_FRAGMENT_SHADER #define GL_OBJECT_ACTIVE_ATTRIBUTES_ARB GL_ACTIVE_ATTRIBUTES #define glActiveTextureARB glActiveTexture #define glGenBuffersARB glGenBuffers #define glDeleteBuffersARB glDeleteBuffers #define glBindBufferARB glBindBuffer #define glBufferDataARB glBufferData #define glMapBufferARB glMapBufferOES #define glUnmapBufferARB glUnmapBufferOES #define glBindBufferARB glBindBuffer #define glEnableVertexAttribArrayARB glEnableVertexAttribArray #define glDisableVertexAttribArrayARB glDisableVertexAttribArray #define glVertexAttribPointerARB glVertexAttribPointer #define glDeleteFramebuffersEXT glDeleteFramebuffers #define glBindFramebufferEXT glBindFramebuffer #define glGenFramebuffersEXT glGenFramebuffers #define glFramebufferTexture2DEXT glFramebufferTexture2D #define glCheckFramebufferStatusEXT glCheckFramebufferStatus #define glGetFramebufferAttachmentParameterivEXT glGetFramebufferAttachmentParameteriv #define glFramebufferRenderbufferEXT glFramebufferRenderbuffer #define glBindRenderbufferEXT glBindRenderbuffer #define glRenderbufferStorageEXT glRenderbufferStorage #define glGenRenderbuffersEXT glGenRenderbuffers #define glDeleteRenderbuffersEXT glDeleteRenderbuffers #define glUseProgramObjectARB glUseProgram #define glGetObjectParameteriv glGetProgramiv #define glUniform1iARB glUniform1i #define glUniform2iARB glUniform2i #define glUniform3iARB glUniform3i #define glUniform4iARB glUniform4i #define glUniform1ivARB glUniform1iv #define glUniform2ivARB glUniform2iv #define glUniform3ivARB glUniform3iv #define glUniform4ivARB glUniform4iv #define glUniform1fARB glUniform1f #define glUniform2fARB glUniform2f #define glUniform3fARB glUniform3f #define glUniform4fARB glUniform4f #define glUniform1fvARB glUniform1fv #define glUniform2fvARB glUniform2fv #define glUniform3fvARB glUniform3fv #define glUniform4fvARB glUniform4fv #define glGetUniformfvARB glGetUniformfv #define glGetUniformivARB glGetUniformiv #define glUniformMatrix2fvARB glUniformMatrix2fv #define glUniformMatrix3fvARB glUniformMatrix3fv #define glUniformMatrix4fvARB glUniformMatrix4fv #define glGetActiveAttribARB glGetActiveAttrib #define glGetActiveUniformARB glGetActiveUniform #define glGetObjectParameterivARB glGetObjectParameteriv #define glGetUniformLocationARB glGetUniformLocation #define glGetAttribLocationARB glGetAttribLocation #define glDepthRange glDepthRangef #define glClearDepth glClearDepthf #endif // OPENGLMAPPING_H ./NuxGraphics/IOpenGLFrameBufferObject.h0000644000004100000410000000745013313171755020354 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef IOPENGLFRAMEBUFFEROBJECT_H #define IOPENGLFRAMEBUFFEROBJECT_H namespace nux { class IOpenGLResource; class IOpenGLFrameBufferObject: public IOpenGLResource { NUX_DECLARE_OBJECT_TYPE(IOpenGLFrameBufferObject, IOpenGLResource); public: virtual ~IOpenGLFrameBufferObject(); void SetupFrameBufferObject(); int FormatFrameBufferObject(int Width, int Height, BitmapFormat PixelFormat); int SetRenderTarget(int color_attachment_index, ObjectPtr pRenderTargetSurface); int SetTextureAttachment(int color_attachment_index, ObjectPtr texture, int surface_level); int SetDepthSurface(ObjectPtr pDepthSurface); int SetDepthTextureAttachment(ObjectPtr depth_texture, int mip_level); ObjectPtr GetRenderTarget(int color_attachment_index); ObjectPtr GetDepthRenderTarget(); ObjectPtr TextureAttachment(int color_attachment_index); ObjectPtr DepthTextureAttachment(); int Clear(DWORD Flags, FLOAT red, FLOAT green, FLOAT blue, FLOAT alpha, FLOAT Z, DWORD Stencil); int Activate(bool WithClippingStack = false); //### Restore the original opengl back buffer as defined when creating the opengl context(color + depth + stencil). int Deactivate(); bool IsActive() { return _IsActive; } // For 2D screen operations std::vector _ClippingRegionStack; void PushClippingRegion(Rect const& rect); void PopClippingRegion(); void EmptyClippingRegion(); void ApplyClippingRegion(); //! Bypass the clipping rectangle stack and set a different clipping rectangle region. /*! You may restore the clipping rectangle stack with ApplyClippingRectangle. */ void SetClippingRectangle(const Rect &rect); void SetOpenGLClippingRectangle(int x, int y, int width, int height); Rect GetClippingRegion(); int GetNumberOfClippingRegions() const; int GetWidth() const { return attachment_width_; } int GetHeight() const { return attachment_height_; } private: struct Attachment { ObjectPtr texture; int level; }; IOpenGLFrameBufferObject(NUX_FILE_LINE_PROTO); int attachment_width_; int attachment_height_; BitmapFormat _PixelFormat; bool _IsActive; Rect _clipping_rect; ObjectPtr depth_surface_attachment_; ObjectPtr stencil_surface_attachment_; ObjectPtr depth_texture_attachment_; std::vector< ObjectPtr > surface_attachment_array_; std::vector< ObjectPtr > texture_attachment_array_; GLFramebufferObject _Fbo; // The framebuffer object used for rendering to the texture GLRenderbuffer _Rbo; bool platform_support_for_depth_texture_; friend class GpuDevice; }; } #endif // IOPENGLFRAMEBUFFEROBJECT_H ./NuxGraphics/IOpenGLCgShader.cpp0000644000004100000410000001165313313171755017054 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "GpuDevice.h" #include "GLDeviceObjects.h" #include "IOpenGLCgShader.h" namespace nux { NUX_IMPLEMENT_OBJECT_TYPE(ICgShader); NUX_IMPLEMENT_OBJECT_TYPE(ICgVertexShader); NUX_IMPLEMENT_OBJECT_TYPE(ICgPixelShader); ICgShader::ICgShader(NString ShaderName, OpenGLResourceType ResourceType) : IOpenGLResource(ResourceType) , _ShaderName(ShaderName) , _CgProgram(0) { } ICgShader::~ICgShader() { } const char *ICgShader::GetProgramString() { return cgGetProgramString( _CgProgram, CG_PROGRAM_SOURCE ); } const char *ICgShader::GetProgramBinary() { return cgGetProgramString( _CgProgram, CG_COMPILED_PROGRAM ); } CGparameter ICgShader::GetNamedParameter(const char *parameter) { return cgGetNamedParameter(_CgProgram, TCHAR_TO_ANSI(parameter)); } ICgVertexShader::ICgVertexShader(NString ShaderName) : _ready(0) , ICgShader(ShaderName, RT_GLSL_VERTEXSHADER) { } ICgVertexShader::~ICgVertexShader() { cgDestroyProgram(_CgProgram); _ready = 0; } void ICgVertexShader::CreateProgram(const ANSICHAR *ShaderCode, const ANSICHAR *EntryPoint) { CGprofile cg_vprofile = cgGLGetLatestProfile(CG_GL_VERTEX); nuxAssertMsg(ShaderCode != 0, "[ICgVertexShader::CreateProgram] Invalid shader code."); _ShaderCode = ANSI_TO_TCHAR(ShaderCode); _EntryPoint = ANSI_TO_TCHAR(EntryPoint); _CgProgram = cgCreateProgram(GetGpuDevice()->GetCgContext(), CG_SOURCE, ShaderCode, cg_vprofile, //CG_PROFILE_VP40 EntryPoint, 0); cgGLLoadProgram(_CgProgram); _ready = 0; } void ICgVertexShader::CreateProgramFromFileShaderCode(const char *Filename, const char *EntryPoint) { nuxAssertMsg(Filename != 0, "[ICgVertexShader::CreateProgramFromFileShaderCode] Invalid shader file."); if (Filename == 0) return; LoadFileToString(_ShaderCode, Filename); CreateProgram(TCHAR_TO_ANSI(&_ShaderCode[0]), TCHAR_TO_ANSI(EntryPoint)); _ready = 0; } bool ICgVertexShader::Compile() { return false; } void ICgVertexShader::BindProgram() { cgGLBindProgram(_CgProgram); } bool ICgVertexShader::IsValid() { return _ready; } ICgPixelShader::ICgPixelShader(NString ShaderName) : _ready(0) , ICgShader(ShaderName, RT_GLSL_PIXELSHADER) { } ICgPixelShader::~ICgPixelShader() { cgDestroyProgram(_CgProgram); _ready = 0; } void ICgPixelShader::CreateProgram(const ANSICHAR *ShaderCode, const ANSICHAR *EntryPoint) { CGprofile cg_fprofile = cgGLGetLatestProfile(CG_GL_FRAGMENT); nuxAssertMsg(ShaderCode != 0, "[ICgPixelShader::CreateProgram] Invalid shader code."); _ShaderCode = ANSI_TO_TCHAR(ShaderCode); _EntryPoint = ANSI_TO_TCHAR(EntryPoint); _CgProgram = cgCreateProgram(GetGpuDevice()->GetCgContext(), CG_SOURCE, ShaderCode, cg_fprofile, //CG_PROFILE_FP40, EntryPoint, 0); cgGLLoadProgram(_CgProgram); _ready = 0; } void ICgPixelShader::CreateProgramFromFileShaderCode(const char *Filename, const char *EntryPoint) { nuxAssertMsg(Filename != 0, "[ICgPixelShader::CreateProgramFromFileShaderCode] Invalid shader file."); if (Filename == 0) return; LoadFileToString(_ShaderCode, Filename); CreateProgram(TCHAR_TO_ANSI(&_ShaderCode[0]), TCHAR_TO_ANSI(EntryPoint)); _ready = 0; } bool ICgPixelShader::Compile() { return false; } void ICgPixelShader::BindProgram() { cgGLBindProgram(_CgProgram); } bool ICgPixelShader::IsValid() { return _ready; } void cgErrorCallback(void) { CGerror LastError = cgGetError(); if (LastError) { nuxDebugMsg("%s\n\n", cgGetErrorString(LastError)); nuxDebugMsg("%s\n", cgGetLastListing(GetGpuDevice()->GetCgContext())); nuxDebugMsg("Cg error, exiting...\n"); nuxAssertMsg(0, "[cgErrorCallback]: Cg Error."); } } } ./NuxGraphics/GLError.cpp0000644000004100000410000000556413313171755015536 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "GLResource.h" #include "FontTexture.h" #include "GLError.h" #include "NuxCore/Logger.h" namespace nux { DECLARE_LOGGER(logger, "nux.gl"); namespace { #ifdef NUX_DEBUG bool BreakOnGLErrors = false; #endif bool debug_glerror_stack() { // If the extra log environment variable is set the stack trace for failing // GLError checks will also get a backtrace. static bool extra_debugging(::getenv("NUX_DEBUG_GLERROR_STACK")); return extra_debugging; } } // WARNING: never call glGetError between glBegin and glEnd. void CheckGLError(const char * /* GLcall */, const char *file, int line) { GLenum glErr; std::string error_msg; while ((glErr = glGetError()) != GL_NO_ERROR) { switch(glErr) { case GL_INVALID_ENUM: error_msg += "[CheckGLError] GL_INVALID_ENUM"; break; case GL_INVALID_VALUE: error_msg += "[CheckGLError] GL_INVALID_VALUE"; break; case GL_INVALID_OPERATION: error_msg += "[CheckGLError] GL_INVALID_OPERATION"; break; #ifndef NUX_OPENGLES_20 case GL_STACK_OVERFLOW: error_msg += "[CheckGLError] GL_STACK_OVERFLOW"; break; case GL_STACK_UNDERFLOW: error_msg += "[CheckGLError] GL_STACK_UNDERFLOW"; break; #endif case GL_OUT_OF_MEMORY: error_msg += "[CheckGLError] GL_OUT_OF_MEMORY"; break; default: error_msg += "[CheckGLError] UNKNOWN ERROR, "; } if (Unwrap(logger).IsWarningEnabled() && !error_msg.empty()) { std::string stacktrace; #if defined(NUX_OS_LINUX) if (debug_glerror_stack()) stacktrace = "\n" + logging::Backtrace(); #endif logging::LogStream(logging::Warning, Unwrap(logger).module(), file, line).stream() #ifndef NUX_OPENGLES_20 << "[CheckGLError] OpenGL Error " << glErr << " (" << gluErrorString(glErr) << ")" #else << error_msg #endif << stacktrace; } #ifdef NUX_DEBUG // break on errors if asked to if (BreakOnGLErrors) inlDebugBreak(); #endif } } } ./NuxGraphics/IOpenGLVertexDeclaration.cpp0000644000004100000410000001035213313171755021012 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "GLResource.h" #include "GLDeviceObjects.h" #include "IOpenGLVertexDeclaration.h" namespace nux { NUX_IMPLEMENT_OBJECT_TYPE(IOpenGLVertexDeclaration); IOpenGLVertexDeclaration::IOpenGLVertexDeclaration(const VERTEXELEMENT* pVertexElements) : IOpenGLResource(RTVERTEXDECLARATION) { for (int i = 0; i < 8; i++) { _stride[i] = 0; vertex_buffer_array.push_back(ObjectPtr(NULL)); } int index = 0; _declarations_array.clear(); while (pVertexElements[index].Stream != 0xFF) { VERTEXELEMENT VtxElement = pVertexElements[index]; _declarations_array.push_back(VtxElement); _stride[VtxElement.Stream] += GetVertexElementSize(VtxElement); ++index; } // Add in the invalid vertex element stream at the end. //VERTEXELEMENT *pVtxElement = new VERTEXELEMENT; //pVtxElement->Stream = 0xFF; // invalid stream _declarations_array.push_back(DECL_END); }; IOpenGLVertexDeclaration::~IOpenGLVertexDeclaration() { // IOpenGLVertexDeclaration is an abstraction. Is does not have an opengl id. _OpenGLID = 0; } // int IOpenGLVertexDeclaration::GetDeclaration( // VERTEXELEMENT& pDecl, // unsigned int *pNumElements) // { // *pNumElements = (unsigned int) _declarations_array.size(); // pDecl = _declarations_array[0]; // // return 1; // } VERTEXELEMENT IOpenGLVertexDeclaration::GetUsage(ATTRIB_USAGE_DECL /* usage */) { VERTEXELEMENT vtxelt; return vtxelt; // vtxelt.Stream = 0xFF; // invalid stream; // // for (unsigned int i = 0; _declarations_array.size(); i++) // { // if (_declarations_array[i].Usage == usage) // { // vtxelt = _declarations_array[i]; // return vtxelt; // } // } // // return vtxelt; } // This is a simple check to comply with the documentation of DrawPrimitiveUP in DirectX bool IOpenGLVertexDeclaration::IsUsingMoreThanStreamZero() { for (unsigned int i = 0; i < _declarations_array.size(); i++) { if (_declarations_array[i].Stream != 0) { return true; } } return false; } int IOpenGLVertexDeclaration::GetStride(int vertex_input_number) { NUX_RETURN_VALUE_IF_FALSE(vertex_input_number >= 0, 0); NUX_RETURN_VALUE_IF_FALSE(vertex_input_number < 8, 0); return _stride[vertex_input_number]; } void IOpenGLVertexDeclaration::SetVertexBuffer(int input_index, ObjectPtr vertex_buffer) { NUX_RETURN_IF_FALSE(input_index >= 0); NUX_RETURN_IF_FALSE(input_index < 8); vertex_buffer_array[input_index] = vertex_buffer; } ObjectPtr IOpenGLVertexDeclaration::GetVertexBuffer(int input_index) { NUX_RETURN_VALUE_IF_FALSE(input_index >= 0, ObjectPtr(NULL)); NUX_RETURN_VALUE_IF_FALSE(input_index < 8, ObjectPtr(NULL)); return vertex_buffer_array[input_index]; } void IOpenGLVertexDeclaration::SetVertexShaderAttributeLocation(int input_index, int shader_attribute_location) { NUX_RETURN_IF_FALSE(input_index >= 0); NUX_RETURN_IF_FALSE(input_index < 8); shader_attribute_location_array[input_index] = shader_attribute_location; } int IOpenGLVertexDeclaration::GetVertexShaderAttributeLocation(int input_index) { NUX_RETURN_VALUE_IF_FALSE(input_index >= 0, -1); NUX_RETURN_VALUE_IF_FALSE(input_index < 8, -1); return shader_attribute_location_array[input_index]; } } ./NuxGraphics/XInputWindow.cpp0000644000004100000410000002765313313171755016644 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "XInputWindow.h" #include "GraphicsDisplayX11.h" #include "GLThread.h" namespace nux { std::vector XInputWindow::native_windows_; namespace atom { namespace { Atom WM_WINDOW_TYPE = 0; Atom WM_WINDOW_TYPE_DOCK = 0; Atom WM_STATE = 0; Atom WM_PID; Atom WM_CLIENT_MACHINE; Atom WM_TAKE_FOCUS = 0; Atom WM_STRUT_PARTIAL = 0; Atom X_DND_AWARE = 0; Atom OVERLAY_STRUT = 0; const unsigned STRUTS_SIZE = 12; const int X_DND_VERSION = 5; std::vector WM_STATES; void initialize(Display *dpy) { if (WM_WINDOW_TYPE) return; WM_WINDOW_TYPE = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); WM_WINDOW_TYPE_DOCK = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DOCK", False); WM_STATE = XInternAtom(dpy, "_NET_WM_STATE", False); WM_PID = XInternAtom(dpy, "_NET_WM_PID", False); WM_CLIENT_MACHINE = XInternAtom(dpy, "WM_CLIENT_MACHINE", False); WM_TAKE_FOCUS = XInternAtom(dpy, "WM_TAKE_FOCUS", False); X_DND_AWARE = XInternAtom(dpy, "XdndAware", False); WM_STATES.push_back(XInternAtom(dpy, "_NET_WM_STATE_STICKY", False)); WM_STATES.push_back(XInternAtom(dpy, "_NET_WM_STATE_SKIP_TASKBAR", False)); WM_STATES.push_back(XInternAtom(dpy, "_NET_WM_STATE_SKIP_PAGER", False)); } } } XInputWindow::XInputWindow(const char* title, bool take_focus, int override_redirect) : strutsEnabled_(false) , overlayStrutsEnabled_(false) , display_(GetGraphicsDisplay()->GetX11Display()) , geometry_(0, 0, 1, 1) , shown_(false) , mapped_(false) { XSetWindowAttributes attrib; char hostname[256]; attrib.override_redirect = override_redirect; attrib.event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask | ButtonMotionMask | PropertyChangeMask | StructureNotifyMask | FocusChangeMask; window_ = XCreateWindow(display_, XDefaultRootWindow(display_), geometry_.x, geometry_.y, geometry_.width, geometry_.height, 0, CopyFromParent, InputOutput, CopyFromParent, CWOverrideRedirect | CWEventMask, &attrib); native_windows_.push_back(window_); atom::initialize(display_); XChangeProperty(display_, window_, atom::WM_STATE, XA_ATOM, 32, PropModeReplace, (unsigned char *) atom::WM_STATES.data(), atom::WM_STATES.size()); XChangeProperty(display_, window_, atom::WM_WINDOW_TYPE, XA_ATOM, 32, PropModeReplace, (unsigned char *) &atom::WM_WINDOW_TYPE_DOCK, 1); if (gethostname(hostname, sizeof(hostname)) > -1) { hostname[sizeof(hostname)-1] = '\0'; XChangeProperty(display_, window_, atom::WM_CLIENT_MACHINE, XA_STRING, 8, PropModeReplace, (unsigned char *) hostname, strlen(hostname)); pid_t pid = getpid(); XChangeProperty(display_, window_, atom::WM_PID, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &pid, 1); } XStoreName(display_, window_, title); EnsureInputs(); if (take_focus) EnableTakeFocus(); EnableDnd(); } XInputWindow::~XInputWindow() { native_windows_.erase(std::find(native_windows_.begin(), native_windows_.end(), window_)); XDestroyWindow(display_, window_); } /* static */ std::vector const& XInputWindow::NativeHandleList() { return native_windows_; } std::vector XInputWindow::GetStrutsData() { int n_info; XineramaScreenInfo *info = XineramaQueryScreens(display_, &n_info); Region screen_region; Region total_screen_region = XCreateRegion(); Region input_window_region = XCreateRegion(); Region intersection = XCreateRegion(); XRectangle monitor; XRectangle tmp_rect; int largestWidth = 0, largestHeight = 0; int screenWidth, screenHeight; std::vector data(atom::STRUTS_SIZE, 0); /* Find the screen that this region intersects */ tmp_rect.x = geometry_.x; tmp_rect.y = geometry_.y; tmp_rect.width = geometry_.width; tmp_rect.height = geometry_.height; XUnionRectWithRegion(&tmp_rect, input_window_region, input_window_region); monitor = tmp_rect; /* If there is no Xinerama data available just use the geometry we have */ if (!info) { monitor = tmp_rect; n_info = 0; } for (int i = 0; i < n_info; i++) { tmp_rect.x = info[i].x_org; tmp_rect.y = info[i].y_org; tmp_rect.width = info[i].width; tmp_rect.height = info[i].height; screen_region = XCreateRegion(); XUnionRectWithRegion(&tmp_rect, screen_region, screen_region); XUnionRegion(screen_region, total_screen_region, total_screen_region); XIntersectRegion(screen_region, input_window_region, intersection); if (!XEmptyRegion(intersection)) { int width = intersection->extents.x2 - intersection->extents.x1; int height = intersection->extents.y2 - intersection->extents.y1; if ((width * height) > (largestWidth * largestHeight)) { largestWidth = width; largestHeight = height; monitor.x = info[i].x_org; monitor.y = info[i].y_org; monitor.width = info[i].width; monitor.height = info[i].height; } } XDestroyRegion(screen_region); } screenWidth = total_screen_region->extents.x2 - total_screen_region->extents.x1; screenHeight = total_screen_region->extents.y2 - total_screen_region->extents.y1; XDestroyRegion(input_window_region); XDestroyRegion(intersection); XDestroyRegion(total_screen_region); if (info) XFree(info); if (geometry_.width > geometry_.height) { if (geometry_.y - monitor.y < monitor.height / 2) { /* top */ data[2] = geometry_.y + geometry_.height; data[8] = geometry_.x; data[9] = geometry_.x + geometry_.width - 1; } else { /* bottom */ data[3] = (screenHeight - 1) - geometry_.y; data[10] = geometry_.x; data[11] = geometry_.x + geometry_.width - 1; } } else { if (geometry_.x - monitor.x < monitor.width / 2) { /* left */ data[0] = geometry_.x + geometry_.width; data[4] = geometry_.y; data[5] = geometry_.y + geometry_.height - 1; } else { /* right */ data[1] = (screenWidth - 1) - geometry_.y; data[6] = geometry_.y; data[7] = geometry_.y + geometry_.height - 1; } } return data; } void XInputWindow::SetStruts() { std::vector const& struts = GetStrutsData(); XChangeProperty(display_, window_, atom::WM_STRUT_PARTIAL, XA_CARDINAL, 32, PropModeReplace, (unsigned char*) struts.data(), struts.size()); } void XInputWindow::UnsetStruts() { XDeleteProperty(display_, window_, atom::WM_STRUT_PARTIAL); } void XInputWindow::SetOverlayStruts() { std::vector const& struts = GetStrutsData(); XChangeProperty(display_, window_, atom::OVERLAY_STRUT, XA_CARDINAL, 32, PropModeReplace, (unsigned char*) struts.data(), struts.size()); } void XInputWindow::UnsetOverlayStruts() { XDeleteProperty(display_, window_, atom::OVERLAY_STRUT); } void XInputWindow::EnableStruts(bool enable) { if (strutsEnabled_ == enable) return; if (!atom::WM_STRUT_PARTIAL) atom::WM_STRUT_PARTIAL = XInternAtom(display_, "_NET_WM_STRUT_PARTIAL", False); strutsEnabled_ = enable; if (enable) SetStruts(); else UnsetStruts(); } bool XInputWindow::StrutsEnabled() { return strutsEnabled_; } void XInputWindow::EnableOverlayStruts(bool enable) { if (overlayStrutsEnabled_ == enable) return; if (!atom::OVERLAY_STRUT) atom::OVERLAY_STRUT = XInternAtom(display_, "_COMPIZ_NET_OVERLAY_STRUT", False); overlayStrutsEnabled_ = enable; if (enable) SetOverlayStruts(); else UnsetOverlayStruts(); } bool XInputWindow::OverlayStrutsEnabled() { return overlayStrutsEnabled_; } void XInputWindow::EnsureInputs() { XSelectInput(display_, window_, KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask | ButtonMotionMask | PropertyChangeMask | StructureNotifyMask | FocusChangeMask); } void XInputWindow::EnableTakeFocus() { XWMHints wmHints; wmHints.flags = InputHint; wmHints.input = False; XSetWMHints(display_, window_, &wmHints); XSetWMProtocols(display_, window_, &atom::WM_TAKE_FOCUS, 1); } void XInputWindow::EnableDnd() { XChangeProperty(display_, window_, atom::X_DND_AWARE, XA_ATOM, 32, PropModeReplace, (unsigned char *) &atom::X_DND_VERSION, 1); } void XInputWindow::DisableDnd() { XDeleteProperty(display_, window_, atom::X_DND_AWARE); } //! Set the position and size of the window void XInputWindow::SetGeometry(Rect const& geo) { geometry_ = geo; if (shown_) XMoveResizeWindow(display_, window_, geo.x, geo.y, geo.width, geo.height); EnsureInputs(); if (strutsEnabled_) SetStruts(); if (overlayStrutsEnabled_) SetOverlayStruts(); } //! Set the position and size of the window void XInputWindow::SetGeometry(int x, int y, int width, int height) { SetGeometry(Rect(x, y, width, height)); } //! Get the window geometry. Rect const& XInputWindow::GetGeometry() const { return geometry_; } Window XInputWindow::GetWindow() { return window_; } void XInputWindow::SetInputFocus() { XSetInputFocus(display_, window_, RevertToParent, CurrentTime); XSync(display_, False); } void XInputWindow::Hide() { XMoveResizeWindow(display_, window_, -100 - geometry_.width, -100 - geometry_.height, geometry_.width, geometry_.height); shown_ = false; } void XInputWindow::Show() { shown_ = true; if (!mapped_) { XMapRaised(display_, window_); mapped_ = true; XEvent xevent; while (XCheckTypedWindowEvent(display_, window_, MapNotify, &xevent)); XSetInputFocus(display_, window_, RevertToParent, CurrentTime); } XMoveResizeWindow(display_, window_, geometry_.x, geometry_.y, geometry_.width, geometry_.height); } } ./NuxGraphics/NuxGraphicsObject.cpp0000644000004100000410000000000013313171755017560 0ustar www-datawww-data./NuxGraphics/Events.h0000644000004100000410000003757013313171755015135 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef EVENTS_H #define EVENTS_H #include "GLResource.h" #if defined(NUX_OS_WINDOWS) #include "VirtualKeyCodes.h" #elif defined(USE_X11) #include "VirtualKeyCodesX11.h" #elif defined(NO_X11) #include "VirtualKeyCodes.h" #else #error VirtualKeyCode file not Implemented. #endif namespace nux { const long I_ExposureMask = (1L << 15); const long I_StructureNotifyMask = (1L << 17); const long I_SubstructureNotifyMask = (1L << 19); #define NUX_BackSpace NUX_VK_BACK #define NUX_Tab NUX_VK_TAB #define NUX_Clear NUX_VK_CLEAR #define NUX_Enter NUX_VK_ENTER #define NUX_Shift_L NUX_VK_SHIFT #define NUX_Control_L NUX_VK_CONTROL #define NUX_Alt_L NUX_VK_MENU #define NUX_Pause NUX_VK_PAUSE #define NUX_Caps_Lock NUX_VK_CAPITAL #define NUX_Escape NUX_VK_ESCAPE #define NUX_SpaceBar NUX_VK_SPACE #define NUX_Page_Up NUX_VK_PAGE_UP #define NUX_Page_Down NUX_VK_PAGE_DOWN #define NUX_End NUX_VK_END #define NUX_Home NUX_VK_HOME #define NUX_Left NUX_VK_LEFT #define NUX_Up NUX_VK_UP #define NUX_Right NUX_VK_RIGHT #define NUX_Down NUX_VK_DOWN #define NUX_Print NUX_VK_SNAPSHOT #define NUX_Insert NUX_VK_INSERT #define NUX_Delete NUX_VK_DELETE #define NUX_LWin NUX_VK_LWIN #define NUX_RWin NUX_VK_RWIN #define NUX_APPS NUX_VK_APPS #define NUX_Multiply NUX_VK_MULTIPLY #define NUX_Add NUX_VK_ADD #define NUX_Subtract NUX_VK_SUBTRACT #define NUX_Decimal NUX_VK_DECIMAL #define NUX_Divide NUX_VK_DIVIDE #define NUX_Numlock NUX_VK_NUMLOCK #define NUX_Scroll NUX_VK_SCROLL #define NUX_EXT_Shift_R (0xff00 | NUX_VK_SHIFT) #define NUX_EXT_Control_R (0xff00 | NUX_VK_CONTROL) #define NUX_EXT_Alt_R (0xff00 | NUX_VK_MENU) #define NUX_KP_DOWN 0xFF99 #define NUX_KP_UP 0xFF97 #define NUX_KP_LEFT 0xFF96 #define NUX_KP_RIGHT 0xFF98 // #define NUX_KP_PAGE_UP (0xff00 | NUX_VK_PAGE_UP) // #define NUX_KP_PAGE_DOWN (0xff00 | NUX_VK_PAGE_DOWN) // #define NUX_KP_END (0xff00 | NUX_VK_END) // #define NUX_KP_HOME (0xff00 | NUX_VK_HOME) // #define NUX_KP_INSERT (0xff00 | NUX_VK_INSERT) // #define NUX_KP_DELETE (0xff00 | NUX_VK_DELETE) #define NUX_F1 NUX_VK_F1 #define NUX_F2 NUX_VK_F2 #define NUX_F3 NUX_VK_F3 #define NUX_F4 NUX_VK_F4 #define NUX_F5 NUX_VK_F5 #define NUX_F6 NUX_VK_F6 #define NUX_F7 NUX_VK_F7 #define NUX_F8 NUX_VK_F8 #define NUX_F9 NUX_VK_F9 #define NUX_F10 NUX_VK_F10 #define NUX_F11 NUX_VK_F11 #define NUX_F12 NUX_VK_F12 #define NUX_F13 NUX_VK_F13 #define NUX_F14 NUX_VK_F14 #define NUX_F15 NUX_VK_F15 #define NUX_F16 NUX_VK_F16 #define NUX_F17 NUX_VK_F17 #define NUX_F18 NUX_VK_F18 #define NUX_F19 NUX_VK_F19 #define NUX_F20 NUX_VK_F20 #define NUX_F21 NUX_VK_F21 #define NUX_F22 NUX_VK_F22 #define NUX_F23 NUX_VK_F23 #define NUX_F24 NUX_VK_F24 // These flags describe the mouse button responsible for the mouse event. // They are valid only for the current frame. // Go in mouse_state. #define NUX_EVENT_BUTTON1_UP 0x00001000 #define NUX_EVENT_BUTTON2_UP 0x00002000 #define NUX_EVENT_BUTTON3_UP 0x00004000 #define NUX_EVENT_BUTTON4_UP 0x00008000 #define NUX_EVENT_BUTTON1_DOWN 0x00010000 #define NUX_EVENT_BUTTON2_DOWN 0x00020000 #define NUX_EVENT_BUTTON3_DOWN 0x00040000 #define NUX_EVENT_BUTTON4_DOWN 0x00080000 #define NUX_EVENT_BUTTON1 0x00010000 #define NUX_EVENT_BUTTON2 0x00020000 #define NUX_EVENT_BUTTON3 0x00040000 #define NUX_EVENT_BUTTON4 0x00080000 #define NUX_EVENT_MOUSEWHEEL 0x00100000 // Describes the event as the first press in the double click event. #define NUX_STATE_FIRST_EVENT 0x00200000 // These flags describe the state of the mouse buttons. // They persist over several frame until the mouse buttons change state. // Go in mouse_state. #define NUX_STATE_BUTTON1_DOWN 0x01000000 #define NUX_STATE_BUTTON2_DOWN 0x02000000 #define NUX_STATE_BUTTON3_DOWN 0x04000000 #define NUX_STATE_BUTTON4_DOWN 0x08000000 // These flags are set if the event is a double click. // They are valid only for the current frame. // Go in mouse_state. #define NUX_EVENT_BUTTON1_DBLCLICK 0x10000000 #define NUX_EVENT_BUTTON2_DBLCLICK 0x20000000 #define NUX_EVENT_BUTTON3_DBLCLICK 0x40000000 #define NUX_MOUSEWHEEL_DELTA 120 // 120 correspond to one notch of the mouse wheel typedef unsigned char uchar; typedef unsigned long ulong; struct EventToNameStruct { int event; const char *EventName; }; enum MouseButton { MOUSE_BUTTON_INVALID = 0, MOUSE_BUTTON1 = 1, MOUSE_BUTTON2 = 2, MOUSE_BUTTON3 = 3, MOUSE_BUTTON4 = 4, MOUSE_BUTTON5 = 5, MOUSE_BUTTON6 = 6, MOUSE_BUTTON7 = 7, // The following values are deprecated. Use the ones above. NUX_INVALID_MOUSE_BUTTON = MOUSE_BUTTON_INVALID, NUX_MOUSE_BUTTON1 = MOUSE_BUTTON1, NUX_MOUSE_BUTTON2 = MOUSE_BUTTON2, NUX_MOUSE_BUTTON3 = MOUSE_BUTTON3, NUX_MOUSE_BUTTON4 = MOUSE_BUTTON4, NUX_MOUSE_BUTTON5 = MOUSE_BUTTON5, NUX_MOUSE_BUTTON6 = MOUSE_BUTTON6, NUX_LEFT_MOUSE = NUX_MOUSE_BUTTON1, // Deprecated NUX_MIDDLE_MOUSE = NUX_MOUSE_BUTTON2, // Deprecated NUX_RIGHT_MOUSE = NUX_MOUSE_BUTTON3, // Deprecated }; enum KeyModifier { KEY_MODIFIER_SHIFT = 0x00010000, KEY_MODIFIER_CAPS_LOCK = 0x00020000, KEY_MODIFIER_CTRL = 0x00040000, KEY_MODIFIER_ALT = 0x00080000, KEY_MODIFIER_NUMLOCK = 0x00100000, KEY_MODIFIER_SUPER = 0x00200000, KEY_MODIFIER_SCROLLLOCK = 0x00400000, // The following values are deprecated. Use the ones above. NUX_STATE_SHIFT = KEY_MODIFIER_SHIFT, NUX_STATE_CAPS_LOCK = KEY_MODIFIER_CAPS_LOCK, NUX_STATE_CTRL = KEY_MODIFIER_CTRL, NUX_STATE_ALT = KEY_MODIFIER_ALT, NUX_STATE_NUMLOCK = KEY_MODIFIER_NUMLOCK, NUX_STATE_SUPER = KEY_MODIFIER_SUPER, NUX_STATE_SCROLLLOCK = KEY_MODIFIER_SCROLLLOCK, }; enum EventType { EVENT_NONE = 0, EVENT_MOUSE_DOWN, EVENT_MOUSE_UP, EVENT_MOUSE_MOVE, EVENT_MOUSE_DOUBLECLICK, EVENT_MOUSE_WHEEL, EVENT_MOUSE_CANCEL, /*!< InputArea lost ownership over a pressed mouse. Any changes caused by the previous EVENT_MOUSE_PRESS should be undone. */ EVENT_KEY_DOWN, EVENT_KEY_UP, EVENT_WINDOW_SIZE_CONFIGURATION, EVENT_WINDOW_MAP, EVENT_WINDOW_UNMAP, EVENT_NC_WINDOW_CONFIGURATION, //!< Non-client event on the window borders. EVENT_WINDOW_ENTER_FOCUS, EVENT_WINDOW_EXIT_FOCUS, EVENT_WINDOW_DIRTY, EVENT_WINDOW_MOUSELEAVE, EVENT_DESTROY_WINDOW, EVENT_TERMINATE_APP, EVENT_TAKE_FOCUS, // ClientMessage for window with WM_TAKE_FOCUS protocol-atom set EVENT_DND_MOVE, EVENT_DND_DROP, EVENT_DND_ENTER, //!< Synthetic event generated when the dnd action enters an InputArea. This is not the event sent when the dnd action enters the window. EVENT_DND_LEAVE, //!< Synthetic event generated when the dnd action leaves an InputArea. This is not the event sent when the dnd action leaves the window. EVENT_DND_ENTER_WINDOW, //!< Emitted when the DND action goes inside(XdndLeave) a window. EVENT_DND_LEAVE_WINDOW, //!< Emitted when the DND action goes outside(XdndEnter) a window. EVENT_GESTURE_BEGIN, //!< Emitted when a gesture begins. Event class is GestureEvent. EVENT_GESTURE_UPDATE, //!< Emitted when a gesture is updated. Event class is GestureEvent. EVENT_GESTURE_END, //!< Emitted when a gesture ends. Event class is GestureEvent. EVENT_GESTURE_LOST, //!< Emitted when a gesture target loses a gesture. Event class is GestureEvent. // The following values are deprecated. Use the ones above. NUX_NO_EVENT = EVENT_NONE, NUX_MOUSE_PRESSED = EVENT_MOUSE_DOWN, NUX_MOUSE_RELEASED = EVENT_MOUSE_UP, NUX_MOUSE_MOVE = EVENT_MOUSE_MOVE, NUX_MOUSE_DOUBLECLICK = EVENT_MOUSE_DOUBLECLICK, NUX_MOUSE_WHEEL = EVENT_MOUSE_WHEEL, NUX_MOUSEWHEEL = EVENT_MOUSE_WHEEL, //!< Deprecated. Use NUX_MOUSE_WHEEL. NUX_KEYDOWN = EVENT_KEY_DOWN, NUX_KEYUP = EVENT_KEY_UP, NUX_SIZE_CONFIGURATION = EVENT_WINDOW_SIZE_CONFIGURATION, NUX_WINDOW_MAP = EVENT_WINDOW_MAP, NUX_WINDOW_UNMAP = EVENT_WINDOW_UNMAP, NUX_NC_WINDOW_CONFIGURATION = EVENT_NC_WINDOW_CONFIGURATION, NUX_WINDOW_ENTER_FOCUS = EVENT_WINDOW_ENTER_FOCUS, NUX_WINDOW_EXIT_FOCUS = EVENT_WINDOW_EXIT_FOCUS, NUX_WINDOW_DIRTY = EVENT_WINDOW_DIRTY, NUX_WINDOW_MOUSELEAVE = EVENT_WINDOW_MOUSELEAVE, NUX_DESTROY_WINDOW = EVENT_DESTROY_WINDOW, NUX_TERMINATE_APP = EVENT_TERMINATE_APP, NUX_TAKE_FOCUS = EVENT_TAKE_FOCUS, // ClientMessage for window with WM_TAKE_FOCUS protocol-atom set NUX_DND_MOVE = EVENT_DND_MOVE, NUX_DND_DROP = EVENT_DND_DROP, NUX_DND_ENTER = EVENT_DND_ENTER, //!< Synthetic event generated when the dnd action enters an InputArea. This is not the event sent when the dnd action enters the window. NUX_DND_LEAVE = EVENT_DND_LEAVE, //!< Synthetic event generated when the dnd action leaves an InputArea. This is not the event sent when the dnd action leaves the window. NUX_DND_ENTER_WINDOW = EVENT_DND_ENTER_WINDOW, //!< Emitted when the DND action goes inside(XdndLeave) a window. NUX_DND_LEAVE_WINDOW = EVENT_DND_LEAVE_WINDOW, //!< Emitted when the DND action goes outside(XdndEnter) a window. }; typedef EventType NuxEventType; // NuxEventType is deprecated. //! Returns index of the mouse button that triggered an event. /*! Given the mouse button states of and event, returns the index of the button that triggered an event. The index of the left mouse button is 1 and the index for the right mouse button is 2. If 0 is returned, then a mouse button didn't triggered the event. @param button_state The mouse button states of an event. @return The button that triggered the event. */ MouseButton GetEventButton(unsigned long button_state); //! Returns the state of a mouse button: pressed or released. /*! Given the mouse button states of and event, returns the state of a mouse button. True is the button is pressed. False otherwise. @param button_state The mouse button states of an event. @param button Button to query(1 for left mouse button). @return True is the button is pressed. False otherwise. */ bool GetButtonState(unsigned long button_state, MouseButton button); //! Returns the state of a special key: CTRL, Shift, Alt, NumLock... /*! Given the key modifiers states of and event, returns the state of a key modifier. True is the key is pressed. False otherwise. @param key_modifiers_state The key modifiers states of an event. @param key_modifier Key modifier be query. @return True is the key is pressed. False otherwise. */ bool GetKeyModifierState(unsigned long key_modifiers_states, KeyModifier key_modifier); #define NUX_EVENT_TEXT_BUFFER_SIZE 16 //! Nux event class. class Event { public: Event(); // Because an event is save in event_type instead of calling immediately the handling function, // we must clear the previous event each time before we test for new event in Gfx_OpenGLImpl::get_event. /*virtual*/ void Reset(); int GetX() const; int GetY() const; int GetRootX() const; int GetRootY() const; int GetDeltaX() const; int GetDeltaY() const; unsigned long GetKeyState() const; unsigned long GetMouseState() const; bool IsShiftDown() const; bool IsControlDown() const; bool IsCapsLockDown() const; bool IsAltDown() const; bool IsNumLockDown() const; bool IsScrollLockDown() const; bool IsSuperKeyDown() const; //! Returns index of the mouse button that triggered this event. /*! Returns the index of the button that triggered this event. The index of the left mouse button is 1 and the index for the right mouse button is 2. If 0 is returned, then a mouse button didn't triggered the event. @return The button that triggered the event. */ MouseButton GetEventButton() const; //! Returns the state of a mouse button: pressed or released. /*! Returns the state of a mouse button. True is the button is pressed. False otherwise. @param button_index Button index to query(1 for left mouse button). @return True is the button is pressed. False otherwise. */ bool GetButtonState(MouseButton button) const; //! Returns the state of a special key: CTRL, Shift, Alt, NumLock... /*! Returns the state of a key modifier. True is the key is pressed. False otherwise. @param key_modifier Key modifier be query. @return True is the key is pressed. False otherwise. */ bool GetKeyModifierState(KeyModifier key_modifier) const; //! Return virtual key code of the key that has triggered the last event. /*! Return virtual key code of the key that has triggered the last event. @return the virtual key code. */ unsigned long GetKeySym() const; unsigned short GetKeyRepeatCount() const; const char* GetText() const; //! Return the state of the Virtual key /*! Return the state of the Virtual key. @param VirtualKey virtual key code. @return 1 if the key is pressed, 0 if the key is released. */ unsigned long GetVirtualKeyState(unsigned long VirtualKey) const; unsigned long VirtualKeycodeState[NUX_MAX_VK]; int width, height; unsigned int ascii_code; int virtual_code; int x; int y; int x_root; int y_root; int dx; int dy; int clicks; int is_click; #if defined(NUX_OS_WINDOWS) int win32_keycode; // Not used. Just a place holder. int win32_keysym; #elif defined(USE_X11) Time x11_timestamp; //!< X11 timestamp. Window x11_window; //!< X11 window. unsigned int x11_key_state; //!< X11 key state (xevent.xkey.state). unsigned int x11_keycode; //!< X11 raw keycode. KeySym x11_keysym; //!< X11 keysym. #endif int wheel_delta; //!< Wheel delta. char text[NUX_EVENT_TEXT_BUFFER_SIZE]; char* dtext; //!< Dynamically allocated unsigned long key_modifiers; //!< Key modifiers. A bitwise inclusive OR of values in KeyModifier. unsigned long mouse_state; unsigned short key_repeat_count; //!< Number of time a key is repeated; EventType type; }; }; #endif // EVENTS_H ./NuxGraphics/IOpenGLResource.h0000644000004100000410000000664013313171755016630 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef IOPENGLRESOURCE_H #define IOPENGLRESOURCE_H namespace nux { class GpuDevice; class IOpenGLBaseTexture; class IOpenGLTexture2D; class IOpenGLRectangleTexture; class IOpenGLCubeTexture; class IOpenGLSurface; class IOpenGLVolumeTexture; class IOpenGLVolume; class IOpenGLQuery; class IOpenGLShader; class IOpenGLVertexShader; class IOpenGLPixelShader; template class ObjectPtr; #define NUM_VERTEX_SHADER_INPUT_ATTRIBUTE 16 enum VertexAttributeType { VAT_UNDEFINED = 0, VAT_FLOAT = 1, VAT_FLOAT2, VAT_FLOAT3, VAT_FLOAT4, VAT_FLOAT_MAT2, VAT_FLOAT_MAT3, VAT_FLOAT_MAT4, }; enum ShaderType { SHADER_TYPE_GLSL = 0, SHADER_TYPE_CG, SHADER_TYPE_FORCE_DWORD = 0x7fffffff /* force 32-bit size enum */ }; struct ShaderAttributeDefinition { int attribute_index; // 0 to 15 std::string attribute_name; int type; // 1, 2, 3 or 4 component, bool valid; // true is the attribute is used }; ////////////////////////////////////////////////////////////////////////// class IOpenGLResource: public Object { NUX_DECLARE_OBJECT_TYPE(IOpenGLResource, Object); public: IOpenGLResource(OpenGLResourceType ResourceType, NUX_FILE_LINE_PROTO) : Object(true, NUX_FILE_LINE_PARAM) , _OpenGLID(0) , _RefCount(0) , _ResourceType(ResourceType) { } virtual ~IOpenGLResource() { } virtual int RefCount() const { return GetReferenceCount(); } OpenGLResourceType GetResourceType() const { return _ResourceType; } GLuint GetOpenGLID() const { return _OpenGLID; } GLuint* GetOpenGLIDAsInParam() { return &_OpenGLID; } private: GLuint _OpenGLID; int _RefCount; OpenGLResourceType _ResourceType; friend class IOpenGLFrameBufferObject; friend class IOpenGLSurface; friend class IOpenGLBaseTexture; friend class IOpenGLCubeTexture; friend class IOpenGLVolumeTexture; friend class IOpenGLAnimatedTexture; friend class IOpenGLTexture2D; friend class IOpenGLRectangleTexture; friend class IOpenGLVolume; friend class IOpenGLQuery; friend class GpuDevice; friend class IOpenGLIndexBuffer; friend class IOpenGLVertexBuffer; friend class IOpenGLVertexDeclaration; friend class IOpenGLShader; friend class IOpenGLVertexShader; friend class IOpenGLPixelShader; friend class IOpenGLGeometryShader; friend class IOpenGLShaderProgram; friend class IOpenGLAsmShaderProgram; friend class IOpenGLPixelBufferObject; }; } #endif // IOPENGLRESOURCE_H ./NuxGraphics/VirtualKeyCodes.h0000644000004100000410000002664613313171755016750 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef VIRTUALKEYCODES_H #define VIRTUALKEYCODES_H namespace nux { // Virtual key codes // The following table shows the symbolic constant names, hexadecimal values, and mouse or keyboard equivalents for the virtual-key codes used by the system. The codes are listed in numeric order. // Symbolic constant name Value(hex) Mouse or keyboard equivalents #define NUX_VK_SPACE 0x020 #define NUX_VK_EXCLAM 0x021 #define NUX_VK_QUOTEDBL 0x022 #define NUX_VK_NUMBERSIGN 0x023 #define NUX_VK_DOLLAR 0x024 #define NUX_VK_PERCENT 0x025 #define NUX_VK_AMPERSAND 0x026 #define NUX_VK_APOSTROPHE 0x027 #define NUX_VK_QUOTERIGHT 0x027 /* deprecated */ #define NUX_VK_PARENLEFT 0x028 #define NUX_VK_PARENRIGHT 0x029 #define NUX_VK_MULTIPLY 0x02a #define NUX_VK_ADD 0x02b #define NUX_VK_COMMA 0x02c #define NUX_VK_SUBTRACT 0x02d #define NUX_VK_DECIMAL 0x02e #define NUX_VK_SLASH 0x02f #define NUX_VK_0 0x030 #define NUX_VK_1 0x031 #define NUX_VK_2 0x032 #define NUX_VK_3 0x033 #define NUX_VK_4 0x034 #define NUX_VK_5 0x035 #define NUX_VK_6 0x036 #define NUX_VK_7 0x037 #define NUX_VK_8 0x038 #define NUX_VK_9 0x039 #define NUX_VK_COLON 0x03a #define NUX_VK_SEMICOLON 0x03b #define NUX_VK_LESS 0x03c #define NUX_VK_EQUAL 0x03d #define NUX_VK_GREATER 0x03e #define NUX_VK_QUESTION 0x03f #define NUX_VK_AT 0x040 #define NUX_VK_A 0x041 #define NUX_VK_B 0x042 #define NUX_VK_C 0x043 #define NUX_VK_D 0x044 #define NUX_VK_E 0x045 #define NUX_VK_F 0x046 #define NUX_VK_G 0x047 #define NUX_VK_H 0x048 #define NUX_VK_I 0x049 #define NUX_VK_J 0x04a #define NUX_VK_K 0x04b #define NUX_VK_L 0x04c #define NUX_VK_M 0x04d #define NUX_VK_N 0x04e #define NUX_VK_O 0x04f #define NUX_VK_P 0x050 #define NUX_VK_Q 0x051 #define NUX_VK_R 0x052 #define NUX_VK_S 0x053 #define NUX_VK_T 0x054 #define NUX_VK_U 0x055 #define NUX_VK_V 0x056 #define NUX_VK_W 0x057 #define NUX_VK_X 0x058 #define NUX_VK_Y 0x059 #define NUX_VK_Z 0x05a #define NUX_VK_BRACKETLEFT 0x05b #define NUX_VK_BACKSLASH 0x05c #define NUX_VK_BRACKETRIGHT 0x05d #define NUX_VK_ASCIICIRCUM 0x05e #define NUX_VK_UNDERSCORE 0x05f #define NUX_VK_GRAVE 0x060 #define NUX_VK_QUOTELEFT 0x060 /* deprecated */ #define NUX_VK_a 0x061 #define NUX_VK_b 0x062 #define NUX_VK_c 0x063 #define NUX_VK_d 0x064 #define NUX_VK_e 0x065 #define NUX_VK_f 0x066 #define NUX_VK_g 0x067 #define NUX_VK_h 0x068 #define NUX_VK_i 0x069 #define NUX_VK_j 0x06a #define NUX_VK_k 0x06b #define NUX_VK_l 0x06c #define NUX_VK_m 0x06d #define NUX_VK_n 0x06e #define NUX_VK_o 0x06f #define NUX_VK_p 0x070 #define NUX_VK_q 0x071 #define NUX_VK_r 0x072 #define NUX_VK_s 0x073 #define NUX_VK_t 0x074 #define NUX_VK_u 0x075 #define NUX_VK_v 0x076 #define NUX_VK_w 0x077 #define NUX_VK_x 0x078 #define NUX_VK_y 0x079 #define NUX_VK_z 0x07a #define NUX_VK_BRACELEFT 0x07b #define NUX_VK_BAR 0x07c #define NUX_VK_BRACERIGHT 0x07d #define NUX_VK_ASCIITILDE 0x07e // Modifiers #define NUX_VK_LSHIFT 0xA0 // Left SHIFT key #define NUX_VK_RSHIFT 0xA1 // Right SHIFT key #define NUX_VK_LCONTROL 0xA2 // Left CONTROL key #define NUX_VK_RCONTROL 0xA3 // Right CONTROL key // To match VK in X11 file. #define NUX_VK_CONTROL NUX_VK_LCONTROL #define NUX_VK_CAPITAL 0x14 // CAPS LOCK key #define NUX_VK_LSUPER 0x5B // Left Windows key(Microsoft Natural Keyboard) #define NUX_VK_RSUPER 0x5C // Right Windows key(Microsoft Natural Keyboard) // To match VK in X11 file. #define NUX_VK_LWIN NUX_VK_LSUPER #define NUX_VK_RWIN NUX_VK_RSUPER #define NUX_VK_LALT 0xA4 // Left MENU key #define NUX_VK_RALT 0xA5 // Right MENU key // Cursor control and motion #define NUX_VK_HOME 0x24 // HOME key #define NUX_VK_LEFT 0x25 // LEFT ARROW key #define NUX_VK_UP 0x26 // UP ARROW key #define NUX_VK_RIGHT 0x27 // RIGHT ARROW key #define NUX_VK_DOWN 0x28 // DOWN ARROW key #define NUX_VK_PAGE_UP 0x21 // PAGE UP key #define NUX_VK_PAGE_DOWN 0x22 // PAGE DOWN key #define NUX_VK_END 0x23 // END key // Functions #define NUX_VK_BACKSPACE 0x08 // BACKSPACE key #define NUX_VK_ESCAPE 0x1B // ESC key #define NUX_VK_TAB 0x09 // TAB key #define NUX_VK_ENTER 0x0D // ENTER key #define NUX_VK_NUMLOCK 0x90 // NUM LOCK key #define NUX_VK_SCROLL 0x91 // SCROLL LOCK key #define NUX_VK_DELETE 0x2E // DEL key #define NUX_VK_INSERT 0x2D // INS key #define NUX_VK_CANCEL 0x03 // Control-break processing #define NUX_VK_CLEAR 0x0C // CLEAR key #define NUX_VK_SHIFT 0x10 // SHIFT key #define NUX_VK_PAUSE 0x13 // PAUSE key // #define NUX_VK_MULTIPLY 0x6A // Multiply key // #define NUX_VK_ADD 0x6B // Add key // #define NUX_VK_SEPARATOR 0x6C // Separator key // #define NUX_VK_SUBTRACT 0x6D // Subtract key // #define NUX_VK_DECIMAL 0x6E // Decimal key // #define NUX_VK_DIVIDE 0x6F // Divide key #define NUX_KP_0 0xFFB0 #define NUX_KP_1 0xFFB1 #define NUX_KP_2 0xFFB2 #define NUX_KP_3 0xFFB3 #define NUX_KP_4 0xFFB4 #define NUX_KP_5 0xFFB5 #define NUX_KP_6 0xFFB6 #define NUX_KP_7 0xFFB7 #define NUX_KP_8 0xFFB8 #define NUX_KP_9 0xFFB9 #define NUX_KP_HOME 0xFF95 #define NUX_KP_LEFT 0xFF96 #define NUX_KP_UP 0xFF97 #define NUX_KP_RIGHT 0xFF98 #define NUX_KP_DOWN 0xFF99 #define NUX_KP_PRIOR 0xFF9A #define NUX_KP_PAGE_UP 0xFF9A #define NUX_KP_NEXT 0xFF9B #define NUX_KP_PAGE_DOWN 0xFF9B #define NUX_KP_END 0xFF9C #define NUX_KP_BEGIN 0xFF9D #define NUX_KP_INSERT 0xFF9E #define NUX_KP_DELETE 0xFF9F #define NUX_KP_EQUAL 0xFFBD /* equals */ #define NUX_KP_MULTIPLY 0xFFAA #define NUX_KP_ADD 0xFFAB #define NUX_KP_SEPARATOR 0xFFAC /* separator, often comma */ #define NUX_KP_SUBTRACT 0xFFAD #define NUX_KP_DECIMAL 0xFFAE #define NUX_KP_DIVIDE 0xFFAF #define NUX_KP_ENTER 0xAAAA // todo #define NUX_VK_LEFT_TAB 0xAAAB // todo #define NUX_VK_F1 0x70 // F1 key #define NUX_VK_F2 0x71 // F2 key #define NUX_VK_F3 0x72 // F3 key #define NUX_VK_F4 0x73 // F4 key #define NUX_VK_F5 0x74 // F5 key #define NUX_VK_F6 0x75 // F6 key #define NUX_VK_F7 0x76 // F7 key #define NUX_VK_F8 0x77 // F8 key #define NUX_VK_F9 0x78 // F9 key #define NUX_VK_F10 0x79 // F10 key #define NUX_VK_F11 0x7A // F11 key #define NUX_VK_F12 0x7B // F12 key #define NUX_VK_F13 0x7C // F13 key #define NUX_VK_F14 0x7D // F14 key #define NUX_VK_F15 0x7E // F15 key #define NUX_VK_F16 0x7F // F16 key #define NUX_VK_F17 0x80 // F17 key #define NUX_VK_F18 0x81 // F18 key #define NUX_VK_F19 0x82 // F19 key #define NUX_VK_F20 0x83 // F20 key #define NUX_VK_F21 0x84 // F21 key #define NUX_VK_F22 0x85 // F22 key #define NUX_VK_F23 0x86 // F23 key #define NUX_VK_F24 0x87 // F24 key #define NUX_MAX_VK 256 } #endif // VIRTUALKEYCODES_H ./NuxGraphics/RenderingPipeGLSL.cpp0000644000004100000410000046420713313171755017442 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "NuxCore/NuxCore.h" #include "ImageSurface.h" #include "GpuDevice.h" #include "GLDeviceObjects.h" #include "GLResourceManager.h" #include "GLTextureResourceManager.h" #include "GLVertexResourceManager.h" #include "RenderingPipe.h" #include "GraphicsEngine.h" namespace nux { void GraphicsEngine::InitSlColorShader() { ObjectPtr VS = _graphics_display.m_DeviceFactory->CreateVertexShader(); ObjectPtr PS = _graphics_display.m_DeviceFactory->CreatePixelShader(); const char* VSString = NUX_VERTEX_SHADER_HEADER "uniform mat4 ViewProjectionMatrix; \n\ attribute vec4 AVertex; \n\ attribute vec4 VertexColor; \n\ varying vec4 vColor; \n\ void main() \n\ { \n\ gl_Position = ViewProjectionMatrix * AVertex; \n\ vColor = VertexColor; \n\ }"; VS->SetShaderCode(TCHAR_TO_ANSI(VSString)); const char* PSString = NUX_FRAGMENT_SHADER_HEADER "varying vec4 vColor; \n\ void main() \n\ { \n\ gl_FragColor = vColor; \n\ }"; PS->SetShaderCode(TCHAR_TO_ANSI(PSString)); m_SlColor = _graphics_display.m_DeviceFactory->CreateShaderProgram(); m_SlColor->ClearShaderObjects(); m_SlColor->AddShaderObject(VS); m_SlColor->AddShaderObject(PS); m_SlColor->Link(); } void GraphicsEngine::InitSlTextureShader() { ObjectPtr VS = _graphics_display.m_DeviceFactory->CreateVertexShader(); ObjectPtr PS = _graphics_display.m_DeviceFactory->CreatePixelShader(); const char* VSString = NUX_VERTEX_SHADER_HEADER "attribute vec4 AVertex; \n\ attribute vec4 MyTextureCoord0; \n\ attribute vec4 VertexColor; \n\ uniform mat4 ViewProjectionMatrix; \n\ varying vec4 varyTexCoord0; \n\ varying vec4 varyVertexColor; \n\ void main() \n\ { \n\ gl_Position = ViewProjectionMatrix * (AVertex); \n\ varyTexCoord0 = MyTextureCoord0; \n\ varyVertexColor = VertexColor; \n\ }"; const char* PSString = NUX_FRAGMENT_SHADER_HEADER "varying vec4 varyTexCoord0; \n\ varying vec4 varyVertexColor; \n\ uniform sampler2D TextureObject0; \n\ vec4 SampleTexture(sampler2D TexObject, vec4 TexCoord) \n\ { \n\ return texture2D(TexObject, TexCoord.st); \n\ } \n\ void main() \n\ { \n\ vec4 v = SampleTexture(TextureObject0, varyTexCoord0); \n\ gl_FragColor = v*varyVertexColor; \n\ }"; // Textured 2D Primitive Shader m_SlTextureModColor = _graphics_display.m_DeviceFactory->CreateShaderProgram(); VS->SetShaderCode(TCHAR_TO_ANSI(VSString)); PS->SetShaderCode(TCHAR_TO_ANSI(PSString), "#define SAMPLERTEX2D"); m_SlTextureModColor->ClearShaderObjects(); m_SlTextureModColor->AddShaderObject(VS); m_SlTextureModColor->AddShaderObject(PS); CHECKGL(glBindAttribLocation(m_SlTextureModColor->GetOpenGLID(), 0, "AVertex")); m_SlTextureModColor->Link(); } void GraphicsEngine::InitSlColorModTexMaskAlpha() { ObjectPtr VS = _graphics_display.m_DeviceFactory->CreateVertexShader(); ObjectPtr PS = _graphics_display.m_DeviceFactory->CreatePixelShader(); const char* VSString = NUX_VERTEX_SHADER_HEADER "attribute vec4 AVertex; \n\ attribute vec4 MyTextureCoord0; \n\ attribute vec4 VertexColor; \n\ uniform mat4 ViewProjectionMatrix; \n\ varying vec4 varyTexCoord0; \n\ varying vec4 varyVertexColor; \n\ void main() \n\ { \n\ gl_Position = ViewProjectionMatrix * (AVertex); \n\ varyTexCoord0 = MyTextureCoord0; \n\ varyVertexColor = VertexColor; \n\ }"; const char* PSString = NUX_FRAGMENT_SHADER_HEADER "varying vec4 varyTexCoord0; \n\ varying vec4 varyVertexColor; \n\ uniform sampler2D TextureObject0; \n\ vec4 SampleTexture(sampler2D TexObject, vec4 TexCoord) \n\ { \n\ return texture2D(TexObject, TexCoord.st); \n\ } \n\ void main() \n\ { \n\ float alpha = SampleTexture(TextureObject0, varyTexCoord0).w; \n\ gl_FragColor = vec4(varyVertexColor.xyz, alpha*varyVertexColor.a); \n\ }"; m_SlColorModTexMaskAlpha = _graphics_display.m_DeviceFactory->CreateShaderProgram(); VS->SetShaderCode(TCHAR_TO_ANSI(VSString)); PS->SetShaderCode(TCHAR_TO_ANSI(PSString), "#define SAMPLERTEX2D"); m_SlColorModTexMaskAlpha->ClearShaderObjects(); m_SlColorModTexMaskAlpha->AddShaderObject(VS); m_SlColorModTexMaskAlpha->AddShaderObject(PS); CHECKGL(glBindAttribLocation(m_SlColorModTexMaskAlpha->GetOpenGLID(), 0, "AVertex")); CHECKGL(glBindAttribLocation(m_SlColorModTexMaskAlpha->GetOpenGLID(), 1, "MyTextureCoord0")); CHECKGL(glBindAttribLocation(m_SlColorModTexMaskAlpha->GetOpenGLID(), 2, "VectexColor")); m_SlColorModTexMaskAlpha->Link(); } void GraphicsEngine::InitSl2TextureAdd() { ObjectPtr VS = _graphics_display.m_DeviceFactory->CreateVertexShader(); ObjectPtr PS = _graphics_display.m_DeviceFactory->CreatePixelShader(); // For some strange reason, make sure that the attribute holding the vertex position has a name that comes first in alphabetic order before all // other attributes. Otherwise you get a bug on NVidia! Why is that??? //////////////////////////////////////////////////////////////////////////////////////////////////// const char* VSString = NUX_VERTEX_SHADER_HEADER "uniform mat4 ViewProjectionMatrix; \n\ attribute vec4 AVertex; \n\ attribute vec4 MyTextureCoord0; \n\ attribute vec4 MyTextureCoord1; \n\ varying vec4 varyTexCoord0; \n\ varying vec4 varyTexCoord1; \n\ void main() \n\ { \n\ varyTexCoord0 = MyTextureCoord0; \n\ varyTexCoord1 = MyTextureCoord1; \n\ gl_Position = ViewProjectionMatrix * (AVertex); \n\ }"; const char* PSString = NUX_FRAGMENT_SHADER_HEADER "varying vec4 varyTexCoord0; \n\ varying vec4 varyTexCoord1; \n\ uniform vec4 color0; \n\ uniform vec4 color1; \n\ #ifdef SAMPLERTEX2D \n\ uniform sampler2D TextureObject0; \n\ uniform sampler2D TextureObject1; \n\ vec4 SampleTexture(sampler2D TexObject, vec4 TexCoord) \n\ { \n\ return texture2D(TexObject, TexCoord.st); \n\ } \n\ #elif defined SAMPLERTEX2DRECT \n\ uniform sampler2DRect TextureObject0; \n\ uniform sampler2DRect TextureObject1; \n\ vec4 SampleTexture(sampler2DRect TexObject, vec4 TexCoord) \n\ { \n\ return texture2DRect(TexObject, TexCoord.st); \n\ } \n\ #endif \n\ void main() \n\ { \n\ vec4 b0 = color0*SampleTexture(TextureObject0, varyTexCoord0); \n\ vec4 b1 = color1*SampleTexture(TextureObject1, varyTexCoord1); \n\ gl_FragColor = b0 + b1; \n\ }"; m_Sl2TextureAdd = _graphics_display.m_DeviceFactory->CreateShaderProgram(); VS->SetShaderCode(TCHAR_TO_ANSI(VSString)); PS->SetShaderCode(TCHAR_TO_ANSI(PSString), "#define SAMPLERTEX2D"); m_Sl2TextureAdd->ClearShaderObjects(); m_Sl2TextureAdd->AddShaderObject(VS); m_Sl2TextureAdd->AddShaderObject(PS); CHECKGL(glBindAttribLocation(m_Sl2TextureAdd->GetOpenGLID(), 0, "AVertex")); m_Sl2TextureAdd->Link(); } void GraphicsEngine::InitSl2TextureDepRead() { ObjectPtr VS = _graphics_display.m_DeviceFactory->CreateVertexShader(); ObjectPtr PS = _graphics_display.m_DeviceFactory->CreatePixelShader(); // For some strange reason, make sure that the attribute holding the vertex position has a name that comes first in alphabetic order before all // other attributes. Otherwise you get a bug on NVidia! Why is that??? //////////////////////////////////////////////////////////////////////////////////////////////////// const char* VSString = NUX_VERTEX_SHADER_HEADER "uniform mat4 ViewProjectionMatrix; \n\ attribute vec4 AVertex; \n\ attribute vec4 MyTextureCoord0; \n\ attribute vec4 MyTextureCoord1; \n\ varying vec4 varyTexCoord0; \n\ varying vec4 varyTexCoord1; \n\ void main() \n\ { \n\ varyTexCoord0 = MyTextureCoord0; \n\ varyTexCoord1 = MyTextureCoord1; \n\ gl_Position = ViewProjectionMatrix * (AVertex); \n\ }"; const char* PSString = NUX_FRAGMENT_SHADER_HEADER "varying vec4 varyTexCoord0; \n\ varying vec4 varyTexCoord1; \n\ uniform vec4 color0; \n\ uniform vec4 color1; \n\ uniform sampler2D TextureObject0; \n\ uniform sampler2D TextureObject1; \n\ vec4 SampleTexture(sampler2D TexObject, vec4 TexCoord) \n\ { \n\ return texture2D(TexObject, TexCoord.st); \n\ } \n\ void main() \n\ { \n\ vec4 noise = SampleTexture(TextureObject0, varyTexCoord0); \n\ vec4 noise_bx2 = color0 * (2.0 * noise - vec4(1.0, 1.0, 1.0, 1.0)); \n\ vec4 b1 = color1 * SampleTexture(TextureObject1, varyTexCoord1 + noise_bx2); \n\ gl_FragColor = b1; \n\ }"; m_Sl2TextureDepRead = _graphics_display.m_DeviceFactory->CreateShaderProgram(); VS->SetShaderCode(TCHAR_TO_ANSI(VSString)); PS->SetShaderCode(TCHAR_TO_ANSI(PSString)); m_Sl2TextureDepRead->ClearShaderObjects(); m_Sl2TextureDepRead->AddShaderObject(VS); m_Sl2TextureDepRead->AddShaderObject(PS); CHECKGL(glBindAttribLocation(m_Sl2TextureDepRead->GetOpenGLID(), 0, "AVertex")); m_Sl2TextureDepRead->Link(); } void GraphicsEngine::InitSl2TextureMod() { ObjectPtr VS = _graphics_display.m_DeviceFactory->CreateVertexShader(); ObjectPtr PS = _graphics_display.m_DeviceFactory->CreatePixelShader(); // For some strange reason, make sure that the attribute holding the vertex position has a name that comes first in alphabetic order before all // other attributes. Otherwise you get a bug on NVidia! Why is that??? //////////////////////////////////////////////////////////////////////////////////////////////////// const char* VSString = NUX_VERTEX_SHADER_HEADER "uniform mat4 ViewProjectionMatrix; \n\ attribute vec4 AVertex; \n\ attribute vec4 MyTextureCoord0; \n\ attribute vec4 MyTextureCoord1; \n\ varying vec4 varyTexCoord0; \n\ varying vec4 varyTexCoord1; \n\ void main() \n\ { \n\ varyTexCoord0 = MyTextureCoord0; \n\ varyTexCoord1 = MyTextureCoord1; \n\ gl_Position = ViewProjectionMatrix * (AVertex); \n\ }"; const char* PSString = NUX_FRAGMENT_SHADER_HEADER "varying vec4 varyTexCoord0; \n\ varying vec4 varyTexCoord1; \n\ uniform vec4 color0; \n\ uniform vec4 color1; \n\ #ifdef SAMPLERTEX2D \n\ uniform sampler2D TextureObject0; \n\ uniform sampler2D TextureObject1; \n\ vec4 SampleTexture(sampler2D TexObject, vec4 TexCoord) \n\ { \n\ return texture2D(TexObject, TexCoord.st); \n\ } \n\ #elif defined SAMPLERTEX2DRECT \n\ uniform sampler2DRect TextureObject0; \n\ uniform sampler2DRect TextureObject1; \n\ vec4 SampleTexture(sampler2DRect TexObject, vec4 TexCoord) \n\ { \n\ return texture2DRect(TexObject, TexCoord.st); \n\ } \n\ #endif \n\ void main() \n\ { \n\ vec4 b0 = color0*SampleTexture(TextureObject0, varyTexCoord0); \n\ vec4 b1 = color1*SampleTexture(TextureObject1, varyTexCoord1); \n\ gl_FragColor = b0 * b1; \n\ }"; m_Sl2TextureMod = _graphics_display.m_DeviceFactory->CreateShaderProgram(); VS->SetShaderCode(TCHAR_TO_ANSI(VSString)); PS->SetShaderCode(TCHAR_TO_ANSI(PSString), "#define SAMPLERTEX2D"); m_Sl2TextureMod->ClearShaderObjects(); m_Sl2TextureMod->AddShaderObject(VS); m_Sl2TextureMod->AddShaderObject(PS); CHECKGL(glBindAttribLocation(m_Sl2TextureMod->GetOpenGLID(), 0, "AVertex")); m_Sl2TextureMod->Link(); } void GraphicsEngine::InitSl4TextureAdd() { ObjectPtr VS = _graphics_display.m_DeviceFactory->CreateVertexShader(); ObjectPtr PS = _graphics_display.m_DeviceFactory->CreatePixelShader(); // For some strange reason, make sure that the attribute holding the vertex position has a name that comes first in alphabetic order before all // other attributes. Otherwise you get a bug on NVidia! Why is that??? //////////////////////////////////////////////////////////////////////////////////////////////////// const char* VSString = NUX_VERTEX_SHADER_HEADER "uniform mat4 ViewProjectionMatrix; \n\ attribute vec4 AVertex; \n\ attribute vec4 MyTextureCoord0; \n\ attribute vec4 MyTextureCoord1; \n\ attribute vec4 MyTextureCoord2; \n\ attribute vec4 MyTextureCoord3; \n\ varying vec4 varyTexCoord0; \n\ varying vec4 varyTexCoord1; \n\ varying vec4 varyTexCoord2; \n\ varying vec4 varyTexCoord3; \n\ void main() \n\ { \n\ varyTexCoord0 = MyTextureCoord0; \n\ varyTexCoord1 = MyTextureCoord1; \n\ varyTexCoord2 = MyTextureCoord2; \n\ varyTexCoord3 = MyTextureCoord3; \n\ gl_Position = ViewProjectionMatrix * (AVertex); \n\ }"; const char* PSString = NUX_FRAGMENT_SHADER_HEADER "varying vec4 varyTexCoord0; \n\ varying vec4 varyTexCoord1; \n\ varying vec4 varyTexCoord2; \n\ varying vec4 varyTexCoord3; \n\ uniform vec4 color0; \n\ uniform vec4 color1; \n\ uniform vec4 color2; \n\ uniform vec4 color3; \n\ uniform sampler2D TextureObject0; \n\ uniform sampler2D TextureObject1; \n\ uniform sampler2D TextureObject2; \n\ uniform sampler2D TextureObject3; \n\ vec4 SampleTexture(sampler2D TexObject, vec4 TexCoord) \n\ { \n\ return texture2D(TexObject, TexCoord.st); \n\ } \n\ void main() \n\ { \n\ vec4 b0 = color0*SampleTexture(TextureObject0, varyTexCoord0); \n\ vec4 b1 = color1*SampleTexture(TextureObject1, varyTexCoord1); \n\ vec4 b2 = color2*SampleTexture(TextureObject2, varyTexCoord2); \n\ vec4 b3 = color3*SampleTexture(TextureObject3, varyTexCoord3); \n\ gl_FragColor = b0+b1+b2+b3; \n\ }"; // Textured 2D Primitive Shader m_Sl4TextureAdd = _graphics_display.m_DeviceFactory->CreateShaderProgram(); VS->SetShaderCode(TCHAR_TO_ANSI(VSString)); PS->SetShaderCode(TCHAR_TO_ANSI(PSString)); m_Sl4TextureAdd->ClearShaderObjects(); m_Sl4TextureAdd->AddShaderObject(VS); m_Sl4TextureAdd->AddShaderObject(PS); CHECKGL(glBindAttribLocation(m_Sl4TextureAdd->GetOpenGLID(), 0, "AVertex")); m_Sl4TextureAdd->Link(); } void GraphicsEngine::InitSLPower() { ObjectPtr VS = _graphics_display.m_DeviceFactory->CreateVertexShader(); ObjectPtr PS = _graphics_display.m_DeviceFactory->CreatePixelShader(); const char* VSString = NUX_VERTEX_SHADER_HEADER "uniform mat4 ViewProjectionMatrix; \n\ attribute vec4 AVertex; \n\ attribute vec4 MyTextureCoord0; \n\ varying vec4 varyTexCoord0; \n\ void main() \n\ { \n\ varyTexCoord0 = MyTextureCoord0; \n\ gl_Position = ViewProjectionMatrix * (AVertex); \n\ }"; const char* PSString = NUX_FRAGMENT_SHADER_HEADER "varying vec4 varyTexCoord0; \n\ uniform sampler2D TextureObject0; \n\ uniform vec2 TextureSize0; \n\ uniform vec4 exponent; \n\ uniform vec4 color0; \n\ vec4 SampleTexture(sampler2D TexObject, vec2 TexCoord) \n\ { \n\ return texture2D(TexObject, TexCoord.st); \n\ } \n\ void main(void) \n\ { \n\ vec4 TexColor = SampleTexture(TextureObject0, varyTexCoord0.st); \n\ vec4 result = pow(TexColor, exponent); \n\ gl_FragColor = color0*result; \n\ }"; _component_exponentiation_prog = _graphics_display.m_DeviceFactory->CreateShaderProgram(); VS->SetShaderCode(TCHAR_TO_ANSI(VSString)); PS->SetShaderCode(TCHAR_TO_ANSI(PSString)); _component_exponentiation_prog->ClearShaderObjects(); _component_exponentiation_prog->AddShaderObject(VS); _component_exponentiation_prog->AddShaderObject(PS); CHECKGL(glBindAttribLocation(_component_exponentiation_prog->GetOpenGLID(), 0, "AVertex")); _component_exponentiation_prog->Link(); } void GraphicsEngine::InitSLAlphaReplicate() { ObjectPtr VS = _graphics_display.m_DeviceFactory->CreateVertexShader(); ObjectPtr PS = _graphics_display.m_DeviceFactory->CreatePixelShader(); const char* VSString = NUX_VERTEX_SHADER_HEADER "uniform mat4 ViewProjectionMatrix; \n\ attribute vec4 AVertex; \n\ attribute vec4 MyTextureCoord0; \n\ varying vec4 varyTexCoord0; \n\ void main() \n\ { \n\ varyTexCoord0 = MyTextureCoord0; \n\ gl_Position = ViewProjectionMatrix * (AVertex); \n\ }"; const char* PSString = NUX_FRAGMENT_SHADER_HEADER "varying vec4 varyTexCoord0; \n\ uniform sampler2D TextureObject0; \n\ uniform vec4 color0; \n\ vec4 SampleTexture(sampler2D TexObject, vec4 TexCoord) \n\ { \n\ return texture2D(TexObject, TexCoord.st); \n\ } \n\ void main() \n\ { \n\ vec4 v = SampleTexture(TextureObject0, varyTexCoord0); \n\ gl_FragColor = vec4(v.a, v.a, v.a, v.a) * color0; \n\ }"; _alpha_replicate_prog = _graphics_display.m_DeviceFactory->CreateShaderProgram(); VS->SetShaderCode(TCHAR_TO_ANSI(VSString)); PS->SetShaderCode(TCHAR_TO_ANSI(PSString)); _alpha_replicate_prog->ClearShaderObjects(); _alpha_replicate_prog->AddShaderObject(VS); _alpha_replicate_prog->AddShaderObject(PS); CHECKGL(glBindAttribLocation(_alpha_replicate_prog->GetOpenGLID(), 0, "AVertex")); _alpha_replicate_prog->Link(); } void GraphicsEngine::InitSLHorizontalHQGaussFilter(int sigma) { int k = Clamp(sigma, NUX_MIN_GAUSSIAN_SIGMA, NUX_MAX_GAUSSIAN_SIGMA); if (_horizontal_hq_gauss_filter_prog[k-1].IsValid()) { // Shader program already compiled return; } ObjectPtr VS = _graphics_display.m_DeviceFactory->CreateVertexShader(); ObjectPtr PS = _graphics_display.m_DeviceFactory->CreatePixelShader(); const char* VSString = NUX_VERTEX_SHADER_HEADER "uniform mat4 ViewProjectionMatrix; \n\ attribute vec4 AVertex; \n\ attribute vec4 MyTextureCoord0; \n\ attribute vec4 VertexColor; \n\ varying vec4 varyTexCoord0; \n\ varying vec4 varyVertexColor; \n\ void main() \n\ { \n\ varyTexCoord0 = MyTextureCoord0; \n\ varyVertexColor = VertexColor; \n\ gl_Position = ViewProjectionMatrix * (AVertex); \n\ }"; const char* PSString = NUX_FRAGMENT_SHADER_HEADER "varying vec4 varyTexCoord0; \n\ varying vec4 varyVertexColor; \n\ uniform sampler2D TextureObject0; \n\ uniform vec2 TextureSize0; \n\ vec4 SampleTexture(sampler2D TexObject, vec2 TexCoord) \n\ { \n\ return texture2D(TexObject, TexCoord.st); \n\ } \n\ #define NUM_SAMPLES %d \n\ uniform float W[NUM_SAMPLES]; \n\ void main() \n\ { \n\ vec4 sum = vec4(0.0, 0.0, 0.0, 0.0); \n\ vec2 delta = vec2(1.0 / TextureSize0.x, 0.0); \n\ vec2 texCoord = vec2(varyTexCoord0.s, varyTexCoord0.t); \n\ texCoord.x -= float((NUM_SAMPLES - 1) / 2) / TextureSize0.x; \n\ texCoord.y += 0.0 / TextureSize0.y; \n\ for (int i = 0; i < NUM_SAMPLES; i++) \n\ { \n\ sum += SampleTexture(TextureObject0, texCoord) * W[i]; \n\ texCoord += delta; \n\ } \n\ gl_FragColor = vec4(sum.x, sum.y, sum.z, 1.0); \n\ }"; int l = strlen(PSString); char* shader_prog = new char[l+10]; sprintf(shader_prog, PSString, 6 * k + 1); _horizontal_hq_gauss_filter_prog[k-1] = _graphics_display.m_DeviceFactory->CreateShaderProgram(); VS->SetShaderCode(TCHAR_TO_ANSI(VSString)); PS->SetShaderCode(shader_prog, "#define SAMPLERTEX2D"); delete [] shader_prog; _horizontal_hq_gauss_filter_prog[k-1]->ClearShaderObjects(); _horizontal_hq_gauss_filter_prog[k-1]->AddShaderObject(VS); _horizontal_hq_gauss_filter_prog[k-1]->AddShaderObject(PS); CHECKGL(glBindAttribLocation(_horizontal_hq_gauss_filter_prog[k-1]->GetOpenGLID(), 0, "AVertex")); _horizontal_hq_gauss_filter_prog[k-1]->Link(); } void GraphicsEngine::InitSLVerticalHQGaussFilter(int sigma) { int k = Clamp(sigma, NUX_MIN_GAUSSIAN_SIGMA, NUX_MAX_GAUSSIAN_SIGMA); if (_vertical_hq_gauss_filter_prog[k-1].IsValid()) { // Shader program already compiled return; } ObjectPtr VS = _graphics_display.m_DeviceFactory->CreateVertexShader(); ObjectPtr PS = _graphics_display.m_DeviceFactory->CreatePixelShader(); const char* VSString = NUX_VERTEX_SHADER_HEADER "uniform mat4 ViewProjectionMatrix; \n\ attribute vec4 AVertex; \n\ attribute vec4 MyTextureCoord0; \n\ attribute vec4 VertexColor; \n\ varying vec4 varyTexCoord0; \n\ varying vec4 varyVertexColor; \n\ void main() \n\ { \n\ varyTexCoord0 = MyTextureCoord0; \n\ varyVertexColor = VertexColor; \n\ gl_Position = ViewProjectionMatrix * (AVertex); \n\ }"; const char* PSString = NUX_FRAGMENT_SHADER_HEADER "varying vec4 varyTexCoord0; \n\ varying vec4 varyVertexColor; \n\ uniform sampler2D TextureObject0; \n\ uniform vec2 TextureSize0; \n\ vec4 SampleTexture(sampler2D TexObject, vec2 TexCoord) \n\ { \n\ return texture2D(TexObject, TexCoord.st); \n\ } \n\ #define NUM_SAMPLES %d \n\ uniform float W [NUM_SAMPLES]; \n\ void main() \n\ { \n\ vec4 sum = vec4(0.0, 0.0, 0.0, 0.0); \n\ vec2 delta = vec2(0.0, 1.0 / TextureSize0.y); \n\ vec2 texCoord = vec2(varyTexCoord0.s, varyTexCoord0.t); \n\ texCoord.x += 0.0 / TextureSize0.x; \n\ texCoord.y -= float((NUM_SAMPLES - 1) / 2) / TextureSize0.y; \n\ for (int i = 0; i < NUM_SAMPLES; ++i) \n\ { \n\ sum += SampleTexture(TextureObject0, texCoord) * W[i]; \n\ texCoord += delta; \n\ } \n\ gl_FragColor = vec4(sum.x, sum.y, sum.z, 1.0); \n\ }"; int l = strlen(PSString); char* shader_prog = new char[l+10]; sprintf(shader_prog, PSString, 6 * k + 1); _vertical_hq_gauss_filter_prog[k-1] = _graphics_display.m_DeviceFactory->CreateShaderProgram(); VS->SetShaderCode(TCHAR_TO_ANSI(VSString)); PS->SetShaderCode(shader_prog, "#define SAMPLERTEX2D"); delete [] shader_prog; _vertical_hq_gauss_filter_prog[k-1]->ClearShaderObjects(); _vertical_hq_gauss_filter_prog[k-1]->AddShaderObject(VS); _vertical_hq_gauss_filter_prog[k-1]->AddShaderObject(PS); CHECKGL(glBindAttribLocation(_vertical_hq_gauss_filter_prog[k-1]->GetOpenGLID(), 0, "AVertex")); _vertical_hq_gauss_filter_prog[k-1]->Link(); } void GraphicsEngine::InitSLHorizontalLSGaussFilter(int k) { if (_horizontal_ls_gauss_filter_prog[k-1].IsValid()) { // Shader program already compiled return; } ObjectPtr vs = _graphics_display.m_DeviceFactory->CreateVertexShader(); ObjectPtr ps = _graphics_display.m_DeviceFactory->CreatePixelShader(); std::string vs_string = NUX_VERTEX_SHADER_HEADER "uniform mat4 view_projection_matrix; \n\ attribute vec4 vertex; \n\ attribute vec4 tex_coord; \n\ varying vec4 v_tex_coord; \n\ void main() \n\ { \n\ v_tex_coord = tex_coord; \n\ gl_Position = view_projection_matrix * vertex; \n\ }"; std::string ps_string = NUX_FRAGMENT_SHADER_HEADER "varying vec4 v_tex_coord; \n\ uniform sampler2D tex_object; \n\ #define NUM_SAMPLES %d \n\ uniform vec2 taps[NUM_SAMPLES]; \n\ void main() \n\ { \n\ vec3 acc = texture2D(tex_object, v_tex_coord.st).rgb * taps[0][1]; \n\ for (int i = 1; i < NUM_SAMPLES; i++) \n\ { \n\ vec2 tap = taps[i]; \n\ vec2 offset = vec2(tap[0], 0.0); \n\ float weight = tap[1]; \n\ acc += texture2D(tex_object, v_tex_coord.st + offset).rgb * weight; \n\ acc += texture2D(tex_object, v_tex_coord.st - offset).rgb * weight; \n\ } \n\ gl_FragColor = vec4(acc, 1.0); \n\ }"; int l = ps_string.length(); char* shader_prog = new char[l+10]; sprintf(shader_prog, ps_string.c_str(), k); _horizontal_ls_gauss_filter_prog[k-1] = _graphics_display.m_DeviceFactory->CreateShaderProgram(); vs->SetShaderCode(vs_string.c_str()); ps->SetShaderCode(shader_prog); delete[] shader_prog; _horizontal_ls_gauss_filter_prog[k-1]->ClearShaderObjects(); _horizontal_ls_gauss_filter_prog[k-1]->AddShaderObject(vs); _horizontal_ls_gauss_filter_prog[k-1]->AddShaderObject(ps); CHECKGL(glBindAttribLocation(_horizontal_ls_gauss_filter_prog[k-1]->GetOpenGLID(), 0, "vertex")); _horizontal_ls_gauss_filter_prog[k-1]->Link(); } void GraphicsEngine::InitSLVerticalLSGaussFilter(int k) { if (_vertical_ls_gauss_filter_prog[k-1].IsValid()) { // Shader program already compiled return; } ObjectPtr vs = _graphics_display.m_DeviceFactory->CreateVertexShader(); ObjectPtr ps = _graphics_display.m_DeviceFactory->CreatePixelShader(); std::string vs_string = NUX_VERTEX_SHADER_HEADER "uniform mat4 view_projection_matrix; \n\ attribute vec4 vertex; \n\ attribute vec4 tex_coord; \n\ varying vec4 v_tex_coord; \n\ void main() \n\ { \n\ v_tex_coord = tex_coord; \n\ gl_Position = view_projection_matrix * vertex; \n\ }"; std::string ps_string = NUX_FRAGMENT_SHADER_HEADER "varying vec4 v_tex_coord; \n\ uniform sampler2D tex_object; \n\ #define NUM_SAMPLES %d \n\ uniform vec2 taps[NUM_SAMPLES]; \n\ void main() \n\ { \n\ vec3 acc = texture2D(tex_object, v_tex_coord.st).rgb * taps[0][1]; \n\ for (int i = 1; i < NUM_SAMPLES; i++) \n\ { \n\ vec2 tap = taps[i]; \n\ vec2 offset = vec2(0.0, tap[0]); \n\ float weight = tap[1]; \n\ acc += texture2D(tex_object, v_tex_coord.st + offset).rgb * weight; \n\ acc += texture2D(tex_object, v_tex_coord.st - offset).rgb * weight; \n\ } \n\ gl_FragColor = vec4(acc, 1.0); \n\ }"; int l = ps_string.length(); char* shader_prog = new char[l+10]; sprintf(shader_prog, ps_string.c_str(), k); _vertical_ls_gauss_filter_prog[k-1] = _graphics_display.m_DeviceFactory->CreateShaderProgram(); vs->SetShaderCode(vs_string.c_str()); ps->SetShaderCode(shader_prog); delete[] shader_prog; _vertical_ls_gauss_filter_prog[k-1]->ClearShaderObjects(); _vertical_ls_gauss_filter_prog[k-1]->AddShaderObject(vs); _vertical_ls_gauss_filter_prog[k-1]->AddShaderObject(ps); CHECKGL(glBindAttribLocation(_vertical_ls_gauss_filter_prog[k-1]->GetOpenGLID(), 0, "vertex")); _vertical_ls_gauss_filter_prog[k-1]->Link(); } void GraphicsEngine::InitSLColorMatrixFilter() { ObjectPtr VS = _graphics_display.m_DeviceFactory->CreateVertexShader(); ObjectPtr PS = _graphics_display.m_DeviceFactory->CreatePixelShader(); const char* VSString = NUX_VERTEX_SHADER_HEADER "uniform mat4 ViewProjectionMatrix; \n\ attribute vec4 AVertex; \n\ attribute vec4 MyTextureCoord0; \n\ varying vec4 varyTexCoord0; \n\ void main() \n\ { \n\ varyTexCoord0 = MyTextureCoord0; \n\ gl_Position = ViewProjectionMatrix * (AVertex); \n\ }"; const char* PSString = NUX_FRAGMENT_SHADER_HEADER "varying vec4 varyTexCoord0; \n\ uniform sampler2D TextureObject0; \n\ uniform vec4 color0; \n\ vec4 SampleTexture(sampler2D TexObject, vec2 TexCoord) \n\ { \n\ return texture2D(TexObject, TexCoord.st); \n\ } \n\ // Color Matrix \n\ uniform float CM0[5]; \n\ uniform float CM1[5]; \n\ uniform float CM2[5]; \n\ uniform float CM3[5]; \n\ void main(void) \n\ { \n\ vec4 tex0 = SampleTexture(TextureObject0, varyTexCoord0.st); \n\ float r = CM0[0]* tex0.r + CM0[1]* tex0.g + CM0[2]* tex0.b + CM0[3]* tex0.a + CM0[4]; \n\ float g = CM1[0]* tex0.r + CM1[1]* tex0.g + CM1[2]* tex0.b + CM1[3]* tex0.a + CM1[4]; \n\ float b = CM2[0]* tex0.r + CM2[1]* tex0.g + CM2[2]* tex0.b + CM2[3]* tex0.a + CM2[4]; \n\ float a = CM3[0]* tex0.r + CM3[1]* tex0.g + CM3[2]* tex0.b + CM3[3]* tex0.a + CM3[4]; \n\ gl_FragColor = color0 * vec4(r, g, b, tex0.a); \n\ }"; _color_matrix_filter_prog = _graphics_display.m_DeviceFactory->CreateShaderProgram(); VS->SetShaderCode(TCHAR_TO_ANSI(VSString)); PS->SetShaderCode(TCHAR_TO_ANSI(PSString), "#define SAMPLERTEX2D"); _color_matrix_filter_prog->ClearShaderObjects(); _color_matrix_filter_prog->AddShaderObject(VS); _color_matrix_filter_prog->AddShaderObject(PS); CHECKGL(glBindAttribLocation(_color_matrix_filter_prog->GetOpenGLID(), 0, "AVertex")); _color_matrix_filter_prog->Link(); } void GraphicsEngine::QRP_GLSL_Color(int x, int y, int width, int height, const Color &color) { QRP_GLSL_Color(x, y, width, height, color, color, color, color); } void GraphicsEngine::QRP_GLSL_Color(int x, int y, int width, int height, const Color &c0, const Color &c1, const Color &c2, const Color &c3) { if (!m_SlColor.IsValid()) InitSlColorShader(); m_quad_tex_stats++; float fx = x, fy = y; float VtxBuffer[] = { fx, fy, 0.0f, 1.0f, c0.red, c0.green, c0.blue, c0.alpha, fx, fy + height, 0.0f, 1.0f, c1.red, c1.green, c1.blue, c1.alpha, fx + width, fy + height, 0.0f, 1.0f, c2.red, c2.green, c2.blue, c2.alpha, fx + width, fy, 0.0f, 1.0f, c3.red, c3.green, c3.blue, c3.alpha, }; ObjectPtr ShaderProg = m_SlColor; CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); ShaderProg->Begin(); int VertexLocation = ShaderProg->GetAttributeLocation("AVertex"); int VertexColorLocation = ShaderProg->GetAttributeLocation("VertexColor"); int VPMatrixLocation = ShaderProg->GetUniformLocationARB("ViewProjectionMatrix"); Matrix4 MVPMatrix = GetOpenGLModelViewProjectionMatrix(); ShaderProg->SetUniformLocMatrix4fv((GLint) VPMatrixLocation, 1, false, (GLfloat *) & (MVPMatrix.m)); CHECKGL(glEnableVertexAttribArrayARB(VertexLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexLocation, 4, GL_FLOAT, GL_FALSE, 32, VtxBuffer)); if (VertexColorLocation != -1) { CHECKGL(glEnableVertexAttribArrayARB(VertexColorLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexColorLocation, 4, GL_FLOAT, GL_FALSE, 32, VtxBuffer + 4)); } CHECKGL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); CHECKGL(glDisableVertexAttribArrayARB(VertexLocation)); if (VertexColorLocation != -1) CHECKGL(glDisableVertexAttribArrayARB(VertexColorLocation)); ShaderProg->End(); } void GraphicsEngine::QRP_GLSL_1Tex(int x, int y, int width, int height, ObjectPtr DeviceTexture, TexCoordXForm &texxform0, const Color &color0) { if (!m_SlTextureModColor.IsValid()) InitSlTextureShader(); m_quad_tex_stats++; QRP_Compute_Texture_Coord(width, height, DeviceTexture, texxform0); float fx = x, fy = y; float VtxBuffer[] = { fx, fy, 0.0f, 1.0f, texxform0.u0, texxform0.v0, 0, 0, color0.red, color0.green, color0.blue, color0.alpha, fx, fy + height, 0.0f, 1.0f, texxform0.u0, texxform0.v1, 0, 0, color0.red, color0.green, color0.blue, color0.alpha, fx + width, fy + height, 0.0f, 1.0f, texxform0.u1, texxform0.v1, 0, 0, color0.red, color0.green, color0.blue, color0.alpha, fx + width, fy, 0.0f, 1.0f, texxform0.u1, texxform0.v0, 0, 0, color0.red, color0.green, color0.blue, color0.alpha, }; ObjectPtr ShaderProg; if (DeviceTexture->Type().IsDerivedFromType(IOpenGLTexture2D::StaticObjectType)) { ShaderProg = m_SlTextureModColor; } // if (DeviceTexture->Type().IsDerivedFromType(IOpenGLRectangleTexture::StaticObjectType) || // DeviceTexture->Type().IsDerivedFromType(IOpenGLAnimatedTexture::StaticObjectType)) // { // ShaderProg = m_TexturedRectProg; // } CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); ShaderProg->Begin(); int TextureObjectLocation = ShaderProg->GetUniformLocationARB("TextureObject0"); int VertexLocation = ShaderProg->GetAttributeLocation("AVertex"); int TextureCoord0Location = ShaderProg->GetAttributeLocation("MyTextureCoord0"); int VertexColorLocation = ShaderProg->GetAttributeLocation("VertexColor"); SetTexture(GL_TEXTURE0, DeviceTexture); CHECKGL(glUniform1iARB(TextureObjectLocation, 0)); int VPMatrixLocation = ShaderProg->GetUniformLocationARB("ViewProjectionMatrix"); Matrix4 MVPMatrix = GetOpenGLModelViewProjectionMatrix(); ShaderProg->SetUniformLocMatrix4fv((GLint) VPMatrixLocation, 1, false, (GLfloat *) & (MVPMatrix.m)); CHECKGL(glEnableVertexAttribArrayARB(VertexLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexLocation, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer)); if (TextureCoord0Location != -1) { CHECKGL(glEnableVertexAttribArrayARB(TextureCoord0Location)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord0Location, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 4)); } if (VertexColorLocation != -1) { CHECKGL(glEnableVertexAttribArrayARB(VertexColorLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexColorLocation, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 8)); } CHECKGL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); CHECKGL(glDisableVertexAttribArrayARB(VertexLocation)); if (TextureCoord0Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord0Location)); if (VertexColorLocation != -1) CHECKGL(glDisableVertexAttribArrayARB(VertexColorLocation)); ShaderProg->End(); } // Render the texture alpha into RGB and modulated by a color. void GraphicsEngine::QRP_GLSL_ColorModTexAlpha(int x, int y, int width, int height, ObjectPtr< IOpenGLBaseTexture> DeviceTexture, TexCoordXForm &texxform, const Color &color) { if (!m_SlColorModTexMaskAlpha.IsValid()) InitSlColorModTexMaskAlpha(); m_quad_tex_stats++; QRP_Compute_Texture_Coord(width, height, DeviceTexture, texxform); float fx = x, fy = y; float VtxBuffer[] = { fx, fy, 0.0f, 1.0f, texxform.u0, texxform.v0, 0, 0, color.red, color.green, color.blue, color.alpha, fx, fy + height, 0.0f, 1.0f, texxform.u0, texxform.v1, 0, 0, color.red, color.green, color.blue, color.alpha, fx + width, fy + height, 0.0f, 1.0f, texxform.u1, texxform.v1, 0, 0, color.red, color.green, color.blue, color.alpha, fx + width, fy, 0.0f, 1.0f, texxform.u1, texxform.v0, 0, 0, color.red, color.green, color.blue, color.alpha, }; ObjectPtr ShaderProg; // if (DeviceTexture->Type().IsDerivedFromType(IOpenGLTexture2D::StaticObjectType)) { ShaderProg = m_SlColorModTexMaskAlpha; } if (DeviceTexture->Type().IsDerivedFromType(IOpenGLRectangleTexture::StaticObjectType) || DeviceTexture->Type().IsDerivedFromType(IOpenGLAnimatedTexture::StaticObjectType)) { ShaderProg = m_SlColorModTexRectMaskAlpha; } CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); ShaderProg->Begin(); int TextureObjectLocation = ShaderProg->GetUniformLocationARB("TextureObject0"); int VertexLocation = ShaderProg->GetAttributeLocation("AVertex"); int TextureCoord0Location = ShaderProg->GetAttributeLocation("MyTextureCoord0"); int VertexColorLocation = ShaderProg->GetAttributeLocation("VertexColor"); SetTexture(GL_TEXTURE0, DeviceTexture); if (TextureObjectLocation != -1) { CHECKGL(glUniform1iARB(TextureObjectLocation, 0)); } int VPMatrixLocation = ShaderProg->GetUniformLocationARB("ViewProjectionMatrix"); Matrix4 MVPMatrix = GetOpenGLModelViewProjectionMatrix(); ShaderProg->SetUniformLocMatrix4fv((GLint) VPMatrixLocation, 1, false, (GLfloat *) & (MVPMatrix.m)); if (VertexLocation != -1) { CHECKGL(glEnableVertexAttribArrayARB(VertexLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexLocation, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer)); } if (TextureCoord0Location != -1) { CHECKGL(glEnableVertexAttribArray(TextureCoord0Location)); CHECKGL(glVertexAttribPointer((GLuint) TextureCoord0Location, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 4)); } if (VertexColorLocation != -1) { CHECKGL(glEnableVertexAttribArrayARB(VertexColorLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexColorLocation, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 8)); } CHECKGL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); if (VertexLocation != -1) CHECKGL(glDisableVertexAttribArrayARB(VertexLocation)); if (TextureCoord0Location != -1) { CHECKGL(glDisableVertexAttribArrayARB(TextureCoord0Location)); } if (VertexColorLocation != -1) { CHECKGL(glDisableVertexAttribArrayARB(VertexColorLocation)); } ShaderProg->End(); } // Blend 2 textures together void GraphicsEngine::QRP_GLSL_2Tex(int x, int y, int width, int height, ObjectPtr DeviceTexture0, TexCoordXForm &texxform0, const Color &color0, ObjectPtr DeviceTexture1, TexCoordXForm &texxform1, const Color &color1) { if (!m_Sl2TextureAdd.IsValid()) InitSl2TextureAdd(); ObjectPtr ShaderProg; ShaderProg = m_Sl2TextureAdd; QRP_Compute_Texture_Coord(width, height, DeviceTexture0, texxform0); QRP_Compute_Texture_Coord(width, height, DeviceTexture1, texxform1); float fx = x, fy = y; float VtxBuffer[] = { fx, fy, 0.0f, 1.0f, texxform0.u0, texxform0.v0, 0.0f, 1.0f, texxform1.u0, texxform1.v0, 0.0f, 1.0f, fx, fy + height, 0.0f, 1.0f, texxform0.u0, texxform0.v1, 0.0f, 1.0f, texxform1.u0, texxform1.v1, 0.0f, 1.0f, fx + width, fy + height, 0.0f, 1.0f, texxform0.u1, texxform0.v1, 0.0f, 1.0f, texxform1.u1, texxform1.v1, 0.0f, 1.0f, fx + width, fy, 0.0f, 1.0f, texxform0.u1, texxform0.v0, 0.0f, 1.0f, texxform1.u1, texxform1.v0, 0.0f, 1.0f, }; CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); ShaderProg->Begin(); int TextureObjectLocation0 = ShaderProg->GetUniformLocationARB("TextureObject0"); int TextureObjectLocation1 = ShaderProg->GetUniformLocationARB("TextureObject1"); int VertexLocation = ShaderProg->GetAttributeLocation("AVertex"); int TextureCoord0Location = ShaderProg->GetAttributeLocation("MyTextureCoord0"); int TextureCoord1Location = ShaderProg->GetAttributeLocation("MyTextureCoord1"); int TextureCoef0Location = ShaderProg->GetUniformLocationARB("color0"); int TextureCoef1Location = ShaderProg->GetUniformLocationARB("color1"); SetTexture(GL_TEXTURE0, DeviceTexture0); SetTexture(GL_TEXTURE1, DeviceTexture1); CHECKGL(glUniform1iARB(TextureObjectLocation0, 0)); CHECKGL(glUniform1iARB(TextureObjectLocation1, 1)); CHECKGL(glUniform4fARB(TextureCoef0Location, color0.red, color0.green, color0.blue, color0.alpha )); CHECKGL(glUniform4fARB(TextureCoef1Location, color1.red, color1.green, color1.blue, color1.alpha )); int VPMatrixLocation = ShaderProg->GetUniformLocationARB("ViewProjectionMatrix"); Matrix4 MVPMatrix = GetOpenGLModelViewProjectionMatrix(); ShaderProg->SetUniformLocMatrix4fv((GLint) VPMatrixLocation, 1, false, (GLfloat *) & (MVPMatrix.m)); CHECKGL(glEnableVertexAttribArrayARB(VertexLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexLocation, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer)); if (TextureCoord0Location != -1) { CHECKGL(glEnableVertexAttribArrayARB(TextureCoord0Location)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord0Location, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 4)); } if (TextureCoord1Location != -1) { CHECKGL(glEnableVertexAttribArrayARB(TextureCoord1Location)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord1Location, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 8)); } CHECKGL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); CHECKGL(glDisableVertexAttribArrayARB(VertexLocation)); if (TextureCoord0Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord0Location)); if (TextureCoord1Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord1Location)); ShaderProg->End(); } void GraphicsEngine::QRP_GLSL_DisturbedTexture( int x, int y, int width, int height, ObjectPtr distorsion_texture, TexCoordXForm &texxform0, const Color& c0, ObjectPtr src_device_texture, TexCoordXForm &texxform1, const Color& c1) { if (!m_Sl2TextureDepRead.IsValid()) InitSl2TextureDepRead(); ObjectPtr ShaderProg = m_Sl2TextureDepRead; QRP_Compute_Texture_Coord(width, height, distorsion_texture, texxform0); QRP_Compute_Texture_Coord(width, height, src_device_texture, texxform1); float fx = x, fy = y; float VtxBuffer [] = { fx, fy, 0.0f, 1.0f, texxform0.u0, texxform0.v0, 0.0f, 1.0f, texxform1.u0, texxform1.v0, 0.0f, 1.0f, fx, fy + height, 0.0f, 1.0f, texxform0.u0, texxform0.v1, 0.0f, 1.0f, texxform1.u0, texxform1.v1, 0.0f, 1.0f, fx + width, fy + height, 0.0f, 1.0f, texxform0.u1, texxform0.v1, 0.0f, 1.0f, texxform1.u1, texxform1.v1, 0.0f, 1.0f, fx + width, fy, 0.0f, 1.0f, texxform0.u1, texxform0.v0, 0.0f, 1.0f, texxform1.u1, texxform1.v0, 0.0f, 1.0f, }; CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); ShaderProg->Begin(); int TextureObjectLocation0 = ShaderProg->GetUniformLocationARB("TextureObject0"); int TextureObjectLocation1 = ShaderProg->GetUniformLocationARB("TextureObject1"); int VertexLocation = ShaderProg->GetAttributeLocation("AVertex"); int TextureCoord0Location = ShaderProg->GetAttributeLocation("MyTextureCoord0"); int TextureCoord1Location = ShaderProg->GetAttributeLocation("MyTextureCoord1"); int TextureCoef0Location = ShaderProg->GetUniformLocationARB("color0"); int TextureCoef1Location = ShaderProg->GetUniformLocationARB("color1"); SetTexture(GL_TEXTURE0, distorsion_texture); SetTexture(GL_TEXTURE1, src_device_texture); CHECKGL(glUniform1iARB(TextureObjectLocation0, 0)); CHECKGL(glUniform1iARB(TextureObjectLocation1, 1)); CHECKGL(glUniform4fARB(TextureCoef0Location, c0.red, c0.green, c0.blue, c0.alpha )); CHECKGL(glUniform4fARB(TextureCoef1Location, c1.red, c1.green, c1.blue, c1.alpha )); int VPMatrixLocation = ShaderProg->GetUniformLocationARB("ViewProjectionMatrix"); Matrix4 MVPMatrix = GetOpenGLModelViewProjectionMatrix(); ShaderProg->SetUniformLocMatrix4fv((GLint) VPMatrixLocation, 1, false, (GLfloat *) & (MVPMatrix.m)); CHECKGL(glEnableVertexAttribArrayARB(VertexLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexLocation, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer)); if (TextureCoord0Location != -1) { CHECKGL(glEnableVertexAttribArrayARB(TextureCoord0Location)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord0Location, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 4)); } if (TextureCoord1Location != -1) { CHECKGL(glEnableVertexAttribArrayARB(TextureCoord1Location)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord1Location, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 8)); } CHECKGL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); CHECKGL(glDisableVertexAttribArrayARB(VertexLocation)); if (TextureCoord0Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord0Location)); if (TextureCoord1Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord1Location)); ShaderProg->End(); } void GraphicsEngine::QRP_GLSL_2TexMod(int x, int y, int width, int height, ObjectPtr DeviceTexture0, TexCoordXForm &texxform0, const Color &color0, ObjectPtr DeviceTexture1, TexCoordXForm &texxform1, const Color &color1) { if (!m_Sl2TextureMod.IsValid()) InitSl2TextureMod(); ObjectPtr ShaderProg; { ShaderProg = m_Sl2TextureMod; } QRP_Compute_Texture_Coord(width, height, DeviceTexture0, texxform0); QRP_Compute_Texture_Coord(width, height, DeviceTexture1, texxform1); float fx = x, fy = y; float VtxBuffer[] = { fx, fy, 0.0f, 1.0f, texxform0.u0, texxform0.v0, 0.0f, 1.0f, texxform1.u0, texxform1.v0, 0.0f, 1.0f, fx, fy + height, 0.0f, 1.0f, texxform0.u0, texxform0.v1, 0.0f, 1.0f, texxform1.u0, texxform1.v1, 0.0f, 1.0f, fx + width, fy + height, 0.0f, 1.0f, texxform0.u1, texxform0.v1, 0.0f, 1.0f, texxform1.u1, texxform1.v1, 0.0f, 1.0f, fx + width, fy, 0.0f, 1.0f, texxform0.u1, texxform0.v0, 0.0f, 1.0f, texxform1.u1, texxform1.v0, 0.0f, 1.0f, }; CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); ShaderProg->Begin(); int TextureObjectLocation0 = ShaderProg->GetUniformLocationARB("TextureObject0"); int TextureObjectLocation1 = ShaderProg->GetUniformLocationARB("TextureObject1"); int VertexLocation = ShaderProg->GetAttributeLocation("AVertex"); int TextureCoord0Location = ShaderProg->GetAttributeLocation("MyTextureCoord0"); int TextureCoord1Location = ShaderProg->GetAttributeLocation("MyTextureCoord1"); int TextureCoef0Location = ShaderProg->GetUniformLocationARB("color0"); int TextureCoef1Location = ShaderProg->GetUniformLocationARB("color1"); SetTexture(GL_TEXTURE0, DeviceTexture0); SetTexture(GL_TEXTURE1, DeviceTexture1); CHECKGL(glUniform1iARB(TextureObjectLocation0, 0)); CHECKGL(glUniform1iARB(TextureObjectLocation1, 1)); CHECKGL(glUniform4fARB(TextureCoef0Location, color0.red, color0.green, color0.blue, color0.alpha )); CHECKGL(glUniform4fARB(TextureCoef1Location, color1.red, color1.green, color1.blue, color1.alpha )); int VPMatrixLocation = ShaderProg->GetUniformLocationARB("ViewProjectionMatrix"); Matrix4 MVPMatrix = GetOpenGLModelViewProjectionMatrix(); ShaderProg->SetUniformLocMatrix4fv((GLint) VPMatrixLocation, 1, false, (GLfloat *) & (MVPMatrix.m)); CHECKGL(glEnableVertexAttribArrayARB(VertexLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexLocation, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer)); if (TextureCoord0Location != -1) { CHECKGL(glEnableVertexAttribArrayARB(TextureCoord0Location)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord0Location, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 4)); } if (TextureCoord1Location != -1) { CHECKGL(glEnableVertexAttribArrayARB(TextureCoord1Location)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord1Location, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 8)); } CHECKGL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); CHECKGL(glDisableVertexAttribArrayARB(VertexLocation)); if (TextureCoord0Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord0Location)); if (TextureCoord1Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord1Location)); ShaderProg->End(); } void GraphicsEngine::QRP_GLSL_4Tex(int x, int y, int width, int height, ObjectPtr DeviceTexture0, TexCoordXForm &texxform0, const Color &color0, ObjectPtr DeviceTexture1, TexCoordXForm &texxform1, const Color &color1, ObjectPtr DeviceTexture2, TexCoordXForm &texxform2, const Color &color2, ObjectPtr DeviceTexture3, TexCoordXForm &texxform3, const Color &color3) { if (!m_Sl4TextureAdd.IsValid()) InitSl4TextureAdd(); QRP_Compute_Texture_Coord(width, height, DeviceTexture0, texxform0); QRP_Compute_Texture_Coord(width, height, DeviceTexture1, texxform1); QRP_Compute_Texture_Coord(width, height, DeviceTexture2, texxform2); QRP_Compute_Texture_Coord(width, height, DeviceTexture3, texxform3); ObjectPtr ShaderProg; ShaderProg = m_Sl4TextureAdd; float fx = x, fy = y; float VtxBuffer[] = { fx, fy, 0.0f, 1.0f, texxform0.u0, texxform0.v0, 0, 1.0f, texxform1.u0, texxform1.v0, 0, 1.0f, texxform2.u0, texxform2.v0, 0, 1.0f, texxform3.u0, texxform3.v0, 0, 1.0f, fx, fy + height, 0.0f, 1.0f, texxform0.u0, texxform0.v1, 0, 1.0f, texxform1.u0, texxform1.v1, 0, 1.0f, texxform2.u0, texxform2.v1, 0, 1.0f, texxform3.u0, texxform3.v1, 0, 1.0f, fx + width, fy + height, 0.0f, 1.0f, texxform0.u1, texxform0.v1, 0, 1.0f, texxform1.u1, texxform1.v1, 0, 1.0f, texxform2.u1, texxform2.v1, 0, 1.0f, texxform3.u1, texxform3.v1, 0, 1.0f, fx + width, fy, 0.0f, 1.0f, texxform0.u1, texxform0.v0, 0, 1.0f, texxform1.u1, texxform1.v0, 0, 1.0f, texxform2.u1, texxform2.v0, 0, 1.0f, texxform3.u1, texxform3.v0, 0, 1.0f, }; CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); ShaderProg->Begin(); int TextureObjectLocation0 = ShaderProg->GetUniformLocationARB("TextureObject0"); int TextureObjectLocation1 = ShaderProg->GetUniformLocationARB("TextureObject1"); int TextureObjectLocation2 = ShaderProg->GetUniformLocationARB("TextureObject2"); int TextureObjectLocation3 = ShaderProg->GetUniformLocationARB("TextureObject3"); int VertexLocation = ShaderProg->GetAttributeLocation("AVertex"); int TextureCoord0Location = ShaderProg->GetAttributeLocation("MyTextureCoord0"); int TextureCoord1Location = ShaderProg->GetAttributeLocation("MyTextureCoord1"); int TextureCoord2Location = ShaderProg->GetAttributeLocation("MyTextureCoord2"); int TextureCoord3Location = ShaderProg->GetAttributeLocation("MyTextureCoord3"); int TextureCoef0Location = ShaderProg->GetUniformLocationARB("color0"); int TextureCoef1Location = ShaderProg->GetUniformLocationARB("color1"); int TextureCoef2Location = ShaderProg->GetUniformLocationARB("color2"); int TextureCoef3Location = ShaderProg->GetUniformLocationARB("color3"); SetTexture(GL_TEXTURE0, DeviceTexture0); SetTexture(GL_TEXTURE1, DeviceTexture1); SetTexture(GL_TEXTURE2, DeviceTexture2); SetTexture(GL_TEXTURE3, DeviceTexture3); CHECKGL(glUniform1iARB(TextureObjectLocation0, 0)); CHECKGL(glUniform1iARB(TextureObjectLocation1, 1)); CHECKGL(glUniform1iARB(TextureObjectLocation2, 2)); CHECKGL(glUniform1iARB(TextureObjectLocation3, 3)); CHECKGL(glUniform4fARB(TextureCoef0Location, color0.red, color0.green, color0.blue, color0.alpha )); CHECKGL(glUniform4fARB(TextureCoef1Location, color1.red, color1.green, color1.blue, color1.alpha )); CHECKGL(glUniform4fARB(TextureCoef2Location, color2.red, color2.green, color2.blue, color2.alpha )); CHECKGL(glUniform4fARB(TextureCoef3Location, color3.red, color3.green, color3.blue, color3.alpha )); int VPMatrixLocation = ShaderProg->GetUniformLocationARB("ViewProjectionMatrix"); Matrix4 MVPMatrix = GetOpenGLModelViewProjectionMatrix(); ShaderProg->SetUniformLocMatrix4fv((GLint) VPMatrixLocation, 1, false, (GLfloat *) & (MVPMatrix.m)); CHECKGL(glEnableVertexAttribArrayARB(VertexLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexLocation, 4, GL_FLOAT, GL_FALSE, 80, VtxBuffer)); if (TextureCoord0Location != -1) { CHECKGL(glEnableVertexAttribArrayARB(TextureCoord0Location)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord0Location, 4, GL_FLOAT, GL_FALSE, 80, VtxBuffer + 4)); } if (TextureCoord1Location != -1) { CHECKGL(glEnableVertexAttribArrayARB(TextureCoord1Location)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord1Location, 4, GL_FLOAT, GL_FALSE, 80, VtxBuffer + 8)); } if (TextureCoord2Location != -1) { CHECKGL(glEnableVertexAttribArrayARB(TextureCoord2Location)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord2Location, 4, GL_FLOAT, GL_FALSE, 80, VtxBuffer + 12)); } if (TextureCoord3Location != -1) { CHECKGL(glEnableVertexAttribArrayARB(TextureCoord3Location)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord3Location, 4, GL_FLOAT, GL_FALSE, 80, VtxBuffer + 16)); } CHECKGL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); CHECKGL(glDisableVertexAttribArrayARB(VertexLocation)); if (TextureCoord0Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord0Location)); if (TextureCoord1Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord1Location)); if (TextureCoord2Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord2Location)); if (TextureCoord3Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord3Location)); ShaderProg->End(); } /////////////////////////////////////////// void GraphicsEngine::QRP_GLSL_Triangle(int x0, int y0, int x1, int y1, int x2, int y2, Color c0) { QRP_GLSL_Triangle(x0, y0, x1, y1, x2, y2, c0, c0, c0); } void GraphicsEngine::QRP_GLSL_Triangle(int x0, int y0, int x1, int y1, int x2, int y2, Color c0, Color c1, Color c2) { if (!m_SlColor.IsValid()) InitSlColorShader(); float VtxBuffer[] = { static_cast(x0), static_cast(y0), 0.0f, 1.0f, c0.red, c0.green, c0.blue, c0.alpha, static_cast(x1), static_cast(y1), 0.0f, 1.0f, c1.red, c1.green, c1.blue, c1.alpha, static_cast(x2), static_cast(y2), 0.0f, 1.0f, c2.red, c2.green, c2.blue, c2.alpha, }; CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); m_SlColor->Begin(); int VertexLocation = m_SlColor->GetAttributeLocation("AVertex"); int VertexColorLocation = m_SlColor->GetAttributeLocation("VertexColor"); int VPMatrixLocation = m_SlColor->GetUniformLocationARB("ViewProjectionMatrix"); Matrix4 MVPMatrix = GetOpenGLModelViewProjectionMatrix(); m_SlColor->SetUniformLocMatrix4fv((GLint) VPMatrixLocation, 1, false, (GLfloat *) & (MVPMatrix.m)); CHECKGL(glEnableVertexAttribArrayARB(VertexLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexLocation, 4, GL_FLOAT, GL_FALSE, 32, VtxBuffer)); CHECKGL(glEnableVertexAttribArrayARB(VertexColorLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexColorLocation, 4, GL_FLOAT, GL_FALSE, 32, VtxBuffer + 4)); CHECKGL(glDrawArrays(GL_TRIANGLES, 0, 3)); CHECKGL(glDisableVertexAttribArrayARB(VertexLocation)); CHECKGL(glDisableVertexAttribArrayARB(VertexColorLocation)); m_SlColor->End(); m_triangle_stats++; } ////////////////////// // DRAW LINES // ////////////////////// void GraphicsEngine::QRP_GLSL_Line(int x0, int y0, int x1, int y1, Color c0) { QRP_GLSL_Line(x0, y0, x1, y1, c0, c0); } void GraphicsEngine::QRP_GLSL_Line(int x0, int y0, int x1, int y1, Color c0, Color c1) { if (!m_SlColor.IsValid()) InitSlColorShader(); float VtxBuffer[] = { static_cast(x0), static_cast(y0), 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, c0.red, c0.green, c0.blue, c0.alpha, static_cast(x1), static_cast(y1), 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, c1.red, c1.green, c1.blue, c1.alpha, }; ObjectPtr ShaderProg = m_SlColor; CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); ShaderProg->Begin(); int TextureObjectLocation = ShaderProg->GetUniformLocationARB("TextureObject0"); int VertexLocation = ShaderProg->GetAttributeLocation("AVertex"); int TextureCoord0Location = ShaderProg->GetAttributeLocation("MyTextureCoord0"); int VertexColorLocation = ShaderProg->GetAttributeLocation("VertexColor"); CHECKGL(glUniform1iARB(TextureObjectLocation, 0)); int VPMatrixLocation = ShaderProg->GetUniformLocationARB("ViewProjectionMatrix"); Matrix4 MVPMatrix = GetOpenGLModelViewProjectionMatrix(); ShaderProg->SetUniformLocMatrix4fv((GLint) VPMatrixLocation, 1, false, (GLfloat *) & (MVPMatrix.m)); CHECKGL(glEnableVertexAttribArrayARB(VertexLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexLocation, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer)); if (TextureCoord0Location != -1) { CHECKGL(glEnableVertexAttribArrayARB(TextureCoord0Location)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord0Location, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 4)); } if (VertexColorLocation != -1) { CHECKGL(glEnableVertexAttribArrayARB(VertexColorLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexColorLocation, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 8)); } CHECKGL(glDrawArrays(GL_LINES, 0, 2)); CHECKGL(glDisableVertexAttribArrayARB(VertexLocation)); if (TextureCoord0Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord0Location)); if (VertexColorLocation != -1) CHECKGL(glDisableVertexAttribArrayARB(VertexColorLocation)); ShaderProg->End(); m_line_stats++; } void GraphicsEngine::QRP_GLSL_QuadWireframe(int x0, int y0, int width, int height, Color c0, Color c1, Color c2, Color c3) { if (!m_SlColor.IsValid()) InitSlColorShader(); float fx0 = x0, fy0 = y0; float VtxBuffer[] = { fx0, fy0, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, c0.red, c0.green, c0.blue, c0.alpha, fx0, fy0 + height - 1, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, c1.red, c1.green, c1.blue, c1.alpha, fx0 + width - 1, fy0 + height - 1, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, c2.red, c2.green, c2.blue, c2.alpha, fx0 + width - 1, fy0, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, c3.red, c3.green, c3.blue, c3.alpha, fx0, fy0, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, c0.red, c0.green, c0.blue, c0.alpha, }; ObjectPtr ShaderProg = m_SlColor; CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); ShaderProg->Begin(); int TextureObjectLocation = ShaderProg->GetUniformLocationARB("TextureObject0"); int VertexLocation = ShaderProg->GetAttributeLocation("AVertex"); int TextureCoord0Location = ShaderProg->GetAttributeLocation("MyTextureCoord0"); int VertexColorLocation = ShaderProg->GetAttributeLocation("VertexColor"); CHECKGL(glUniform1iARB(TextureObjectLocation, 0)); int VPMatrixLocation = ShaderProg->GetUniformLocationARB("ViewProjectionMatrix"); Matrix4 MVPMatrix = GetOpenGLModelViewProjectionMatrix(); ShaderProg->SetUniformLocMatrix4fv((GLint) VPMatrixLocation, 1, false, (GLfloat *) & (MVPMatrix.m)); CHECKGL(glEnableVertexAttribArrayARB(VertexLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexLocation, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer)); if (TextureCoord0Location != -1) { CHECKGL(glEnableVertexAttribArrayARB(TextureCoord0Location)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord0Location, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 4)); } if (VertexColorLocation != -1) { CHECKGL(glEnableVertexAttribArrayARB(VertexColorLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexColorLocation, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 8)); } CHECKGL(glDrawArrays(GL_LINE_STRIP, 0, 5)); CHECKGL(glDisableVertexAttribArrayARB(VertexLocation)); if (TextureCoord0Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord0Location)); if (VertexColorLocation != -1) CHECKGL(glDisableVertexAttribArrayARB(VertexColorLocation)); ShaderProg->End(); m_line_stats++; } void GraphicsEngine::QRP_GLSL_Power(int x, int y, int width, int height, ObjectPtr device_texture, TexCoordXForm &texxform0, const Color &c0, Vector4 exponent) { if (!_component_exponentiation_prog.IsValid()) InitSLPower(); m_quad_tex_stats++; QRP_Compute_Texture_Coord(width, height, device_texture, texxform0); float fx = x, fy = y; float VtxBuffer[] = { fx, fy, 0.0f, 1.0f, texxform0.u0, texxform0.v0, 0, 0, fx, fy + height, 0.0f, 1.0f, texxform0.u0, texxform0.v1, 0, 0, fx + width, fy + height, 0.0f, 1.0f, texxform0.u1, texxform0.v1, 0, 0, fx + width, fy, 0.0f, 1.0f, texxform0.u1, texxform0.v0, 0, 0, }; ObjectPtr ShaderProg; if (!device_texture->Type().IsDerivedFromType(IOpenGLTexture2D::StaticObjectType)) { return; } ShaderProg = _component_exponentiation_prog; CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); ShaderProg->Begin(); int TextureObjectLocation = ShaderProg->GetUniformLocationARB("TextureObject0"); int Color0Location = ShaderProg->GetUniformLocationARB("color0"); int ExponentLocation = ShaderProg->GetUniformLocationARB("exponent"); int VertexLocation = ShaderProg->GetAttributeLocation("AVertex"); int TextureCoord0Location = ShaderProg->GetAttributeLocation("MyTextureCoord0"); SetTexture(GL_TEXTURE0, device_texture); CHECKGL(glUniform1iARB(TextureObjectLocation, 0)); CHECKGL(glUniform4fARB(ExponentLocation, exponent.x, exponent.y, exponent.z, exponent.w )); CHECKGL(glUniform4fARB(Color0Location, c0.red, c0.green, c0.blue, c0.alpha)); int VPMatrixLocation = ShaderProg->GetUniformLocationARB("ViewProjectionMatrix"); Matrix4 MVPMatrix = GetOpenGLModelViewProjectionMatrix(); ShaderProg->SetUniformLocMatrix4fv((GLint) VPMatrixLocation, 1, false, (GLfloat *) & (MVPMatrix.m)); CHECKGL(glEnableVertexAttribArrayARB(VertexLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexLocation, 4, GL_FLOAT, GL_FALSE, 32, VtxBuffer)); if (TextureCoord0Location != -1) { CHECKGL(glEnableVertexAttribArrayARB(TextureCoord0Location)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord0Location, 4, GL_FLOAT, GL_FALSE, 32, VtxBuffer + 4)); } CHECKGL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); CHECKGL(glDisableVertexAttribArrayARB(VertexLocation)); if (TextureCoord0Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord0Location)); ShaderProg->End(); } void GraphicsEngine::QRP_GLSL_AlphaReplicate(int x, int y, int width, int height, ObjectPtr device_texture, TexCoordXForm &texxform0, const Color &c0) { if (!_alpha_replicate_prog.IsValid()) InitSLAlphaReplicate(); m_quad_tex_stats++; QRP_Compute_Texture_Coord(width, height, device_texture, texxform0); float fx = x, fy = y; float VtxBuffer[] = { fx, fy, 0.0f, 1.0f, texxform0.u0, texxform0.v0, 0, 0, fx, fy + height, 0.0f, 1.0f, texxform0.u0, texxform0.v1, 0, 0, fx + width, fy + height, 0.0f, 1.0f, texxform0.u1, texxform0.v1, 0, 0, fx + width, fy, 0.0f, 1.0f, texxform0.u1, texxform0.v0, 0, 0, }; ObjectPtr ShaderProg; if (!device_texture->Type().IsDerivedFromType(IOpenGLTexture2D::StaticObjectType)) { return; } ShaderProg = _alpha_replicate_prog; CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); ShaderProg->Begin(); int TextureObjectLocation = ShaderProg->GetUniformLocationARB("TextureObject0"); int Color0Location = ShaderProg->GetUniformLocationARB("color0"); int VertexLocation = ShaderProg->GetAttributeLocation("AVertex"); int TextureCoord0Location = ShaderProg->GetAttributeLocation("MyTextureCoord0"); SetTexture(GL_TEXTURE0, device_texture); CHECKGL(glUniform1iARB(TextureObjectLocation, 0)); CHECKGL(glUniform4fARB(Color0Location, c0.red, c0.green, c0.blue, c0.alpha)); int VPMatrixLocation = ShaderProg->GetUniformLocationARB("ViewProjectionMatrix"); Matrix4 MVPMatrix = GetOpenGLModelViewProjectionMatrix(); ShaderProg->SetUniformLocMatrix4fv((GLint) VPMatrixLocation, 1, false, (GLfloat *) & (MVPMatrix.m)); CHECKGL(glEnableVertexAttribArrayARB(VertexLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexLocation, 4, GL_FLOAT, GL_FALSE, 32, VtxBuffer)); if (TextureCoord0Location != -1) { CHECKGL(glEnableVertexAttribArrayARB(TextureCoord0Location)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord0Location, 4, GL_FLOAT, GL_FALSE, 32, VtxBuffer + 4)); } CHECKGL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); CHECKGL(glDisableVertexAttribArrayARB(VertexLocation)); if (TextureCoord0Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord0Location)); ShaderProg->End(); } void GraphicsEngine::InitSLHorizontalGaussFilter() { ObjectPtr VS = _graphics_display.m_DeviceFactory->CreateVertexShader(); ObjectPtr PS = _graphics_display.m_DeviceFactory->CreatePixelShader(); const char* VSString = NUX_VERTEX_SHADER_HEADER "uniform mat4 ViewProjectionMatrix; \n\ attribute vec4 AVertex; \n\ attribute vec4 MyTextureCoord0; \n\ varying vec4 varyTexCoord0; \n\ void main() \n\ { \n\ varyTexCoord0 = MyTextureCoord0; \n\ gl_Position = ViewProjectionMatrix * (AVertex); \n\ }"; const char* PSString = NUX_FRAGMENT_SHADER_HEADER "varying vec4 varyTexCoord0; \n\ uniform sampler2D TextureObject0; \n\ uniform vec2 TextureSize0; \n\ vec4 SampleTexture(sampler2D TexObject, vec2 TexCoord) \n\ { \n\ return texture2D(TexObject, TexCoord.st); \n\ } \n\ #define NUM_SAMPLES 7 \n\ uniform float W[NUM_SAMPLES]; \n\ void main() \n\ { \n\ vec4 sum = vec4(0.0, 0.0, 0.0, 0.0); \n\ vec2 delta = vec2(1.0 / TextureSize0.x, 0.0); \n\ vec2 texCoord = vec2(varyTexCoord0.s, varyTexCoord0.t); \n\ texCoord.x -= float((NUM_SAMPLES - 1) / 2) / TextureSize0.x; \n\ texCoord.y += 0.0 / TextureSize0.y; \n\ sum += SampleTexture(TextureObject0, texCoord) * W[0]; \n\ texCoord += delta; \n\ sum += SampleTexture(TextureObject0, texCoord) * W[1]; \n\ texCoord += delta; \n\ sum += SampleTexture(TextureObject0, texCoord) * W[2]; \n\ texCoord += delta; \n\ sum += SampleTexture(TextureObject0, texCoord) * W[3]; \n\ texCoord += delta; \n\ sum += SampleTexture(TextureObject0, texCoord) * W[4]; \n\ texCoord += delta; \n\ sum += SampleTexture(TextureObject0, texCoord) * W[5]; \n\ texCoord += delta; \n\ sum += SampleTexture(TextureObject0, texCoord) * W[6]; \n\ texCoord += delta; \n\ gl_FragColor = vec4(sum.x, sum.y, sum.z, sum.w); \n\ }"; _horizontal_gauss_filter_prog = _graphics_display.m_DeviceFactory->CreateShaderProgram(); VS->SetShaderCode(TCHAR_TO_ANSI(VSString)); PS->SetShaderCode(TCHAR_TO_ANSI(PSString)); _horizontal_gauss_filter_prog->ClearShaderObjects(); _horizontal_gauss_filter_prog->AddShaderObject(VS); _horizontal_gauss_filter_prog->AddShaderObject(PS); CHECKGL(glBindAttribLocation(_horizontal_gauss_filter_prog->GetOpenGLID(), 0, "AVertex")); _horizontal_gauss_filter_prog->Link(); } void GraphicsEngine::QRP_GLSL_HorizontalGauss(int x, int y, int width, int height, ObjectPtr device_texture, TexCoordXForm &texxform0, const Color & /* c0 */, float sigma) { if (!_horizontal_gauss_filter_prog.IsValid()) InitSLHorizontalGaussFilter(); m_quad_tex_stats++; QRP_Compute_Texture_Coord(width, height, device_texture, texxform0); float fx = x, fy = y; float VtxBuffer[] = { fx, fy, 0.0f, 1.0f, texxform0.u0, texxform0.v0, 0, 0, fx, fy + height, 0.0f, 1.0f, texxform0.u0, texxform0.v1, 0, 0, fx + width, fy + height, 0.0f, 1.0f, texxform0.u1, texxform0.v1, 0, 0, fx + width, fy, 0.0f, 1.0f, texxform0.u1, texxform0.v0, 0, 0, }; ObjectPtr ShaderProg; if (!device_texture->Type().IsDerivedFromType(IOpenGLTexture2D::StaticObjectType)) { return; } ShaderProg = _horizontal_gauss_filter_prog; CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); ShaderProg->Begin(); int TextureObjectLocation = ShaderProg->GetUniformLocationARB("TextureObject0"); int WeightsLocation = ShaderProg->GetUniformLocationARB("W"); int TextureSizeLocation = ShaderProg->GetUniformLocationARB("TextureSize0"); int VertexLocation = ShaderProg->GetAttributeLocation("AVertex"); int TextureCoord0Location = ShaderProg->GetAttributeLocation("MyTextureCoord0"); SetTexture(GL_TEXTURE0, device_texture); CHECKGL(glUniform1iARB(TextureObjectLocation, 0)); sigma = Clamp (sigma, 0.1f, 9.0f); // Set the Gaussian weights { float *W; GaussianWeights(&W, sigma, 7); CHECKGL(glUniform1fv(WeightsLocation, 7, W)); delete[] W; } CHECKGL(glUniform2fARB(TextureSizeLocation, width, height)); int VPMatrixLocation = ShaderProg->GetUniformLocationARB("ViewProjectionMatrix"); Matrix4 MVPMatrix = GetOpenGLModelViewProjectionMatrix(); ShaderProg->SetUniformLocMatrix4fv((GLint) VPMatrixLocation, 1, false, (GLfloat *) & (MVPMatrix.m)); CHECKGL(glEnableVertexAttribArrayARB(VertexLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexLocation, 4, GL_FLOAT, GL_FALSE, 32, VtxBuffer)); if (TextureCoord0Location != -1) { CHECKGL(glEnableVertexAttribArrayARB(TextureCoord0Location)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord0Location, 4, GL_FLOAT, GL_FALSE, 32, VtxBuffer + 4)); } CHECKGL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); CHECKGL(glDisableVertexAttribArrayARB(VertexLocation)); if (TextureCoord0Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord0Location)); ShaderProg->End(); } void GraphicsEngine::InitSLVerticalGaussFilter() { ObjectPtr VS = _graphics_display.m_DeviceFactory->CreateVertexShader(); ObjectPtr PS = _graphics_display.m_DeviceFactory->CreatePixelShader(); const char* VSString = NUX_VERTEX_SHADER_HEADER "uniform mat4 ViewProjectionMatrix; \n\ attribute vec4 AVertex; \n\ attribute vec4 MyTextureCoord0; \n\ varying vec4 varyTexCoord0; \n\ void main() \n\ { \n\ varyTexCoord0 = MyTextureCoord0; \n\ gl_Position = ViewProjectionMatrix * (AVertex); \n\ }"; const char* PSString = NUX_FRAGMENT_SHADER_HEADER "varying vec4 varyTexCoord0; \n\ uniform sampler2D TextureObject0; \n\ uniform vec2 TextureSize0; \n\ vec4 SampleTexture(sampler2D TexObject, vec2 TexCoord) \n\ { \n\ return texture2D(TexObject, TexCoord.st); \n\ } \n\ #define NUM_SAMPLES 7 \n\ uniform float W [NUM_SAMPLES]; \n\ void main() \n\ { \n\ vec4 sum = vec4(0.0, 0.0, 0.0, 0.0); \n\ vec2 delta = vec2(0.0, 1.0 / TextureSize0.y); \n\ vec2 texCoord = vec2(varyTexCoord0.s, varyTexCoord0.t); \n\ texCoord.x += 0.0 / TextureSize0.x; \n\ texCoord.y -= float((NUM_SAMPLES - 1) / 2) / TextureSize0.y; \n\ sum += SampleTexture(TextureObject0, texCoord) * W[0]; \n\ texCoord += delta; \n\ sum += SampleTexture(TextureObject0, texCoord) * W[1]; \n\ texCoord += delta; \n\ sum += SampleTexture(TextureObject0, texCoord) * W[2]; \n\ texCoord += delta; \n\ sum += SampleTexture(TextureObject0, texCoord) * W[3]; \n\ texCoord += delta; \n\ sum += SampleTexture(TextureObject0, texCoord) * W[4]; \n\ texCoord += delta; \n\ sum += SampleTexture(TextureObject0, texCoord) * W[5]; \n\ texCoord += delta; \n\ sum += SampleTexture(TextureObject0, texCoord) * W[6]; \n\ texCoord += delta; \n\ gl_FragColor = vec4(sum.x, sum.y, sum.z, sum.w); \n\ }"; _vertical_gauss_filter_prog = _graphics_display.m_DeviceFactory->CreateShaderProgram(); VS->SetShaderCode(TCHAR_TO_ANSI(VSString)); PS->SetShaderCode(TCHAR_TO_ANSI(PSString)); _vertical_gauss_filter_prog->ClearShaderObjects(); _vertical_gauss_filter_prog->AddShaderObject(VS); _vertical_gauss_filter_prog->AddShaderObject(PS); CHECKGL(glBindAttribLocation(_vertical_gauss_filter_prog->GetOpenGLID(), 0, "AVertex")); _vertical_gauss_filter_prog->Link(); } void GraphicsEngine::QRP_GLSL_VerticalGauss(int x, int y, int width, int height, ObjectPtr device_texture, TexCoordXForm &texxform0, const Color & /* c0 */, float sigma) { if (!_vertical_gauss_filter_prog.IsValid()) InitSLVerticalGaussFilter(); m_quad_tex_stats++; QRP_Compute_Texture_Coord(width, height, device_texture, texxform0); float fx = x, fy = y; float VtxBuffer[] = { fx, fy, 0.0f, 1.0f, texxform0.u0, texxform0.v0, 0, 0, fx, fy + height, 0.0f, 1.0f, texxform0.u0, texxform0.v1, 0, 0, fx + width, fy + height, 0.0f, 1.0f, texxform0.u1, texxform0.v1, 0, 0, fx + width, fy, 0.0f, 1.0f, texxform0.u1, texxform0.v0, 0, 0, }; ObjectPtr ShaderProg; if (!device_texture->Type().IsDerivedFromType(IOpenGLTexture2D::StaticObjectType)) { return; } ShaderProg = _vertical_gauss_filter_prog; CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); ShaderProg->Begin(); int TextureObjectLocation = ShaderProg->GetUniformLocationARB("TextureObject0"); int WeightsLocation = ShaderProg->GetUniformLocationARB("W"); int TextureSizeLocation = ShaderProg->GetUniformLocationARB("TextureSize0"); int VertexLocation = ShaderProg->GetAttributeLocation("AVertex"); int TextureCoord0Location = ShaderProg->GetAttributeLocation("MyTextureCoord0"); SetTexture(GL_TEXTURE0, device_texture); CHECKGL(glUniform1iARB(TextureObjectLocation, 0)); sigma = Clamp (sigma, 0.1f, 9.0f); // Set the Gaussian weights { float *W; GaussianWeights(&W, sigma, 7); CHECKGL(glUniform1fv(WeightsLocation, 7, W)); delete[] W; } CHECKGL(glUniform2fARB(TextureSizeLocation, width, height)); int VPMatrixLocation = ShaderProg->GetUniformLocationARB("ViewProjectionMatrix"); Matrix4 MVPMatrix = GetOpenGLModelViewProjectionMatrix(); ShaderProg->SetUniformLocMatrix4fv((GLint) VPMatrixLocation, 1, false, (GLfloat *) & (MVPMatrix.m)); CHECKGL(glEnableVertexAttribArrayARB(VertexLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexLocation, 4, GL_FLOAT, GL_FALSE, 32, VtxBuffer)); if (TextureCoord0Location != -1) { CHECKGL(glEnableVertexAttribArrayARB(TextureCoord0Location)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord0Location, 4, GL_FLOAT, GL_FALSE, 32, VtxBuffer + 4)); } CHECKGL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); CHECKGL(glDisableVertexAttribArrayARB(VertexLocation)); if (TextureCoord0Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord0Location)); ShaderProg->End(); } void GraphicsEngine::QRP_GLSL_HorizontalHQGauss(int x, int y, int width, int height, ObjectPtr device_texture, TexCoordXForm &texxform0, const Color & /* c0 */, float sigma) { int k = Clamp(sigma, NUX_MIN_GAUSSIAN_SIGMA, NUX_MAX_GAUSSIAN_SIGMA); if (_horizontal_hq_gauss_filter_prog[k-1].IsValid() == false) { InitSLHorizontalHQGaussFilter(k); } m_quad_tex_stats++; QRP_Compute_Texture_Coord(width, height, device_texture, texxform0); float fx = x, fy = y; float VtxBuffer[] = { fx, fy, 0.0f, 1.0f, texxform0.u0, texxform0.v0, 0, 0, fx, fy + height, 0.0f, 1.0f, texxform0.u0, texxform0.v1, 0, 0, fx + width, fy + height, 0.0f, 1.0f, texxform0.u1, texxform0.v1, 0, 0, fx + width, fy, 0.0f, 1.0f, texxform0.u1, texxform0.v0, 0, 0, }; ObjectPtr ShaderProg; if (!device_texture->Type().IsDerivedFromType(IOpenGLTexture2D::StaticObjectType)) { return; } ShaderProg = _horizontal_hq_gauss_filter_prog[k-1]; CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); ShaderProg->Begin(); int TextureObjectLocation = ShaderProg->GetUniformLocationARB("TextureObject0"); int WeightsLocation = ShaderProg->GetUniformLocationARB("W"); int TextureSizeLocation = ShaderProg->GetUniformLocationARB("TextureSize0"); int VertexLocation = ShaderProg->GetAttributeLocation("AVertex"); int TextureCoord0Location = ShaderProg->GetAttributeLocation("MyTextureCoord0"); SetTexture(GL_TEXTURE0, device_texture); CHECKGL(glUniform1iARB(TextureObjectLocation, 0)); sigma = Clamp (sigma, 0.1f, NUX_MAX_GAUSSIAN_SIGMA); // Set the Gaussian weights { float *W; GaussianWeights(&W, sigma, 6*k+1); CHECKGL(glUniform1fv(WeightsLocation, 6*k+1, W)); delete[] W; } CHECKGL(glUniform2fARB(TextureSizeLocation, width, height)); int VPMatrixLocation = ShaderProg->GetUniformLocationARB("ViewProjectionMatrix"); Matrix4 MVPMatrix = GetOpenGLModelViewProjectionMatrix(); ShaderProg->SetUniformLocMatrix4fv((GLint) VPMatrixLocation, 1, false, (GLfloat *) & (MVPMatrix.m)); CHECKGL(glEnableVertexAttribArrayARB(VertexLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexLocation, 4, GL_FLOAT, GL_FALSE, 32, VtxBuffer)); if (TextureCoord0Location != -1) { CHECKGL(glEnableVertexAttribArrayARB(TextureCoord0Location)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord0Location, 4, GL_FLOAT, GL_FALSE, 32, VtxBuffer + 4)); } CHECKGL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); CHECKGL(glDisableVertexAttribArrayARB(VertexLocation)); if (TextureCoord0Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord0Location)); ShaderProg->End(); } void GraphicsEngine::QRP_GLSL_VerticalHQGauss(int x, int y, int width, int height, ObjectPtr device_texture, TexCoordXForm &texxform0, const Color & /* c0 */, float sigma) { int k = Clamp(sigma, NUX_MIN_GAUSSIAN_SIGMA, NUX_MAX_GAUSSIAN_SIGMA); if (_vertical_hq_gauss_filter_prog[k-1].IsValid() == false) { InitSLVerticalHQGaussFilter(k); } m_quad_tex_stats++; QRP_Compute_Texture_Coord(width, height, device_texture, texxform0); float fx = x, fy = y; float VtxBuffer[] = { fx, fy, 0.0f, 1.0f, texxform0.u0, texxform0.v0, 0, 0, fx, fy + height, 0.0f, 1.0f, texxform0.u0, texxform0.v1, 0, 0, fx + width, fy + height, 0.0f, 1.0f, texxform0.u1, texxform0.v1, 0, 0, fx + width, fy, 0.0f, 1.0f, texxform0.u1, texxform0.v0, 0, 0, }; ObjectPtr ShaderProg; if (!device_texture->Type().IsDerivedFromType(IOpenGLTexture2D::StaticObjectType)) { return; } ShaderProg = _vertical_hq_gauss_filter_prog[k-1]; CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); ShaderProg->Begin(); int TextureObjectLocation = ShaderProg->GetUniformLocationARB("TextureObject0"); int WeightsLocation = ShaderProg->GetUniformLocationARB("W"); int TextureSizeLocation = ShaderProg->GetUniformLocationARB("TextureSize0"); int VertexLocation = ShaderProg->GetAttributeLocation("AVertex"); int TextureCoord0Location = ShaderProg->GetAttributeLocation("MyTextureCoord0"); SetTexture(GL_TEXTURE0, device_texture); CHECKGL(glUniform1iARB(TextureObjectLocation, 0)); sigma = Clamp (sigma, 0.1f, NUX_MAX_GAUSSIAN_SIGMA); // Set the Gaussian weights { float *W; GaussianWeights(&W, sigma, 6*k+1); CHECKGL(glUniform1fv(WeightsLocation, 6*k+1, W)); delete[] W; } CHECKGL(glUniform2fARB(TextureSizeLocation, width, height)); int VPMatrixLocation = ShaderProg->GetUniformLocationARB("ViewProjectionMatrix"); Matrix4 MVPMatrix = GetOpenGLModelViewProjectionMatrix(); ShaderProg->SetUniformLocMatrix4fv((GLint) VPMatrixLocation, 1, false, (GLfloat *) & (MVPMatrix.m)); CHECKGL(glEnableVertexAttribArrayARB(VertexLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexLocation, 4, GL_FLOAT, GL_FALSE, 32, VtxBuffer)); if (TextureCoord0Location != -1) { CHECKGL(glEnableVertexAttribArrayARB(TextureCoord0Location)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord0Location, 4, GL_FLOAT, GL_FALSE, 32, VtxBuffer + 4)); } CHECKGL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); CHECKGL(glDisableVertexAttribArrayARB(VertexLocation)); if (TextureCoord0Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord0Location)); ShaderProg->End(); } void GraphicsEngine::QRP_GLSL_HorizontalLSGauss(int x, int y, int width, int height, ObjectPtr device_texture, TexCoordXForm &texxform0, const Color & /* c0 */, float sigma) { std::vector weights(0); std::vector offsets(0); int num_samples = LinearSampleGaussianWeights(weights, offsets, sigma); if (_horizontal_ls_gauss_filter_prog[num_samples-1].IsValid() == false) { InitSLHorizontalLSGaussFilter(num_samples); } m_quad_tex_stats++; QRP_Compute_Texture_Coord(width, height, device_texture, texxform0); float fx = x, fy = y; float vtx_buffer[] = { fx, fy, 0.0f, 1.0f, texxform0.u0, texxform0.v0, 0, 0, fx, fy + height, 0.0f, 1.0f, texxform0.u0, texxform0.v1, 0, 0, fx + width, fy + height, 0.0f, 1.0f, texxform0.u1, texxform0.v1, 0, 0, fx + width, fy, 0.0f, 1.0f, texxform0.u1, texxform0.v0, 0, 0, }; ObjectPtr shader_prog; if (!device_texture->Type().IsDerivedFromType(IOpenGLTexture2D::StaticObjectType)) { return; } shader_prog = _horizontal_ls_gauss_filter_prog[num_samples-1]; CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); shader_prog->Begin(); int tex_object_location = shader_prog->GetUniformLocationARB("tex_object"); int taps_location = shader_prog->GetUniformLocationARB("taps"); int vertex_location = shader_prog->GetAttributeLocation("vertex"); int tex_coord_location = shader_prog->GetAttributeLocation("tex_coord"); SetTexture(GL_TEXTURE0, device_texture); CHECKGL(glUniform1iARB(tex_object_location, 0)); std::vector taps; for (int i = 0; i < num_samples; ++i) { taps.push_back(offsets[i] /= width); taps.push_back(weights[i]); } CHECKGL(glUniform2fv(taps_location, taps.size(), &taps[0])); int VPMatrixLocation = shader_prog->GetUniformLocationARB("view_projection_matrix"); Matrix4 MVPMatrix = GetOpenGLModelViewProjectionMatrix(); shader_prog->SetUniformLocMatrix4fv((GLint) VPMatrixLocation, 1, false, (GLfloat *) & (MVPMatrix.m)); CHECKGL(glEnableVertexAttribArrayARB(vertex_location)); CHECKGL(glVertexAttribPointerARB((GLuint) vertex_location, 4, GL_FLOAT, GL_FALSE, 32, vtx_buffer)); if (tex_coord_location != -1) { CHECKGL(glEnableVertexAttribArrayARB(tex_coord_location)); CHECKGL(glVertexAttribPointerARB((GLuint) tex_coord_location, 4, GL_FLOAT, GL_FALSE, 32, vtx_buffer + 4)); } CHECKGL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); CHECKGL(glDisableVertexAttribArrayARB(vertex_location)); if (tex_coord_location != -1) CHECKGL(glDisableVertexAttribArrayARB(tex_coord_location)); shader_prog->End(); } void GraphicsEngine::QRP_GLSL_VerticalLSGauss(int x, int y, int width, int height, ObjectPtr device_texture, TexCoordXForm &texxform0, const Color & /* c0 */, float sigma) { std::vector weights(0); std::vector offsets(0); int num_samples = LinearSampleGaussianWeights(weights, offsets, sigma); if (_vertical_ls_gauss_filter_prog[num_samples-1].IsValid() == false) { InitSLVerticalLSGaussFilter(num_samples); } m_quad_tex_stats++; QRP_Compute_Texture_Coord(width, height, device_texture, texxform0); float fx = x, fy = y; float vtx_buffer[] = { fx, fy, 0.0f, 1.0f, texxform0.u0, texxform0.v0, 0, 0, fx, fy + height, 0.0f, 1.0f, texxform0.u0, texxform0.v1, 0, 0, fx + width, fy + height, 0.0f, 1.0f, texxform0.u1, texxform0.v1, 0, 0, fx + width, fy, 0.0f, 1.0f, texxform0.u1, texxform0.v0, 0, 0, }; ObjectPtr shader_prog; if (!device_texture->Type().IsDerivedFromType(IOpenGLTexture2D::StaticObjectType)) { return; } shader_prog = _vertical_ls_gauss_filter_prog[num_samples-1]; CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); shader_prog->Begin(); int tex_object_location = shader_prog->GetUniformLocationARB("tex_object"); int taps_location = shader_prog->GetUniformLocationARB("taps"); int vertex_location = shader_prog->GetAttributeLocation("vertex"); int tex_coord_location = shader_prog->GetAttributeLocation("tex_coord"); SetTexture(GL_TEXTURE0, device_texture); CHECKGL(glUniform1iARB(tex_object_location, 0)); std::vector taps; for (int i = 0; i < num_samples; ++i) { taps.push_back(offsets[i] /= height); taps.push_back(weights[i]); } CHECKGL(glUniform2fv(taps_location, taps.size(), &taps[0])); int VPMatrixLocation = shader_prog->GetUniformLocationARB("view_projection_matrix"); Matrix4 MVPMatrix = GetOpenGLModelViewProjectionMatrix(); shader_prog->SetUniformLocMatrix4fv((GLint) VPMatrixLocation, 1, false, (GLfloat *) & (MVPMatrix.m)); CHECKGL(glEnableVertexAttribArrayARB(vertex_location)); CHECKGL(glVertexAttribPointerARB((GLuint) vertex_location, 4, GL_FLOAT, GL_FALSE, 32, vtx_buffer)); if (tex_coord_location != -1) { CHECKGL(glEnableVertexAttribArrayARB(tex_coord_location)); CHECKGL(glVertexAttribPointerARB((GLuint) tex_coord_location, 4, GL_FLOAT, GL_FALSE, 32, vtx_buffer + 4)); } CHECKGL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); CHECKGL(glDisableVertexAttribArrayARB(vertex_location)); if (tex_coord_location != -1) CHECKGL(glDisableVertexAttribArrayARB(tex_coord_location)); shader_prog->End(); } void GraphicsEngine::QRP_GLSL_ColorMatrix(int x, int y, int width, int height, ObjectPtr device_texture, TexCoordXForm &texxform0, const Color &c0, Matrix4 color_matrix, Vector4 offset) { if (!_color_matrix_filter_prog.IsValid()) InitSLColorMatrixFilter(); m_quad_tex_stats++; QRP_Compute_Texture_Coord(width, height, device_texture, texxform0); float fx = x, fy = y; float VtxBuffer[] = { fx, fy, 0.0f, 1.0f, texxform0.u0, texxform0.v0, 0, 0, fx, fy + height, 0.0f, 1.0f, texxform0.u0, texxform0.v1, 0, 0, fx + width, fy + height, 0.0f, 1.0f, texxform0.u1, texxform0.v1, 0, 0, fx + width, fy, 0.0f, 1.0f, texxform0.u1, texxform0.v0, 0, 0, }; ObjectPtr ShaderProg; if (!device_texture->Type().IsDerivedFromType(IOpenGLTexture2D::StaticObjectType)) { return; } ShaderProg = _color_matrix_filter_prog; CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); ShaderProg->Begin(); int TextureObjectLocation = ShaderProg->GetUniformLocationARB("TextureObject0"); int Color0Location = ShaderProg->GetUniformLocationARB("color0"); int MatrixRow0Location = ShaderProg->GetUniformLocationARB("CM0"); int MatrixRow1Location = ShaderProg->GetUniformLocationARB("CM1"); int MatrixRow2Location = ShaderProg->GetUniformLocationARB("CM2"); int MatrixRow3Location = ShaderProg->GetUniformLocationARB("CM3"); int VertexLocation = ShaderProg->GetAttributeLocation("AVertex"); int TextureCoord0Location = ShaderProg->GetAttributeLocation("MyTextureCoord0"); SetTexture(GL_TEXTURE0, device_texture); CHECKGL(glUniform1iARB(TextureObjectLocation, 0)); CHECKGL(glUniform4fARB(Color0Location, c0.red, c0.green, c0.blue, c0.alpha)); float v[5]; v[0] = color_matrix.m[0][0]; v[1] = color_matrix.m[0][1]; v[2] = color_matrix.m[0][2]; v[3] = color_matrix.m[0][3]; v[4] = offset.x; CHECKGL(glUniform1fvARB(MatrixRow0Location, 5, v)); v[0] = color_matrix.m[1][0]; v[1] = color_matrix.m[1][1]; v[2] = color_matrix.m[1][2]; v[3] = color_matrix.m[1][3]; v[4] = offset.y; CHECKGL(glUniform1fvARB(MatrixRow1Location, 5, v)); v[0] = color_matrix.m[2][0]; v[1] = color_matrix.m[2][1]; v[2] = color_matrix.m[2][2]; v[3] = color_matrix.m[2][3]; v[4] = offset.z; CHECKGL(glUniform1fvARB(MatrixRow2Location, 5, v)); v[0] = color_matrix.m[3][0]; v[1] = color_matrix.m[3][1]; v[2] = color_matrix.m[3][2]; v[3] = color_matrix.m[3][3]; v[4] = offset.w; CHECKGL(glUniform1fvARB(MatrixRow3Location, 5, v)); int VPMatrixLocation = ShaderProg->GetUniformLocationARB("ViewProjectionMatrix"); Matrix4 MVPMatrix = GetOpenGLModelViewProjectionMatrix(); ShaderProg->SetUniformLocMatrix4fv((GLint) VPMatrixLocation, 1, false, (GLfloat *) & (MVPMatrix.m)); CHECKGL(glEnableVertexAttribArrayARB(VertexLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexLocation, 4, GL_FLOAT, GL_FALSE, 32, VtxBuffer)); if (TextureCoord0Location != -1) { CHECKGL(glEnableVertexAttribArrayARB(TextureCoord0Location)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord0Location, 4, GL_FLOAT, GL_FALSE, 32, VtxBuffer + 4)); } CHECKGL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); CHECKGL(glDisableVertexAttribArrayARB(VertexLocation)); if (TextureCoord0Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord0Location)); ShaderProg->End(); } ObjectPtr GraphicsEngine::QRP_GLSL_GetBlurTexture( int x, int y, int buffer_width, int buffer_height, ObjectPtr device_texture, TexCoordXForm &texxform, const Color& c0, float sigma, int num_pass) { int quad_width = device_texture->GetWidth(); int quad_height = device_texture->GetHeight(); num_pass = Clamp (num_pass, 1, 50); ObjectPtr prevFBO = GetGraphicsDisplay()->GetGpuDevice()->GetCurrentFrameBufferObject(); int previous_width = 0; int previous_height = 0; if (prevFBO.IsValid()) { previous_width = prevFBO->GetWidth(); previous_height = prevFBO->GetHeight(); } else { previous_width = _graphics_display.GetWindowWidth(); previous_height = _graphics_display.GetWindowHeight(); } CHECKGL(glClearColor(0, 0, 0, 0)); _offscreen_color_rt0->SetWrap(GL_CLAMP, GL_CLAMP, GL_CLAMP); _offscreen_color_rt0->SetFiltering(GL_NEAREST, GL_NEAREST); _offscreen_color_rt1->SetWrap(GL_CLAMP, GL_CLAMP, GL_CLAMP); _offscreen_color_rt1->SetFiltering(GL_NEAREST, GL_NEAREST); SetFrameBufferHelper(_offscreen_fbo, _offscreen_color_rt0, _offscreen_depth_rt0, buffer_width, buffer_height); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); QRP_GLSL_1Tex(x, y, quad_width, quad_height, device_texture, texxform, color::White); TexCoordXForm texxform1; for (int i = 0; i < num_pass; i++) { SetFrameBufferHelper(_offscreen_fbo, _offscreen_color_rt1, _offscreen_depth_rt1, buffer_width, buffer_height); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); if (_offscreen_color_rt0.IsValid()) QRP_GLSL_HorizontalGauss(0, 0, buffer_width, buffer_height, _offscreen_color_rt0, texxform1, c0, sigma); SetFrameBufferHelper(_offscreen_fbo, _offscreen_color_rt0, _offscreen_depth_rt0, buffer_width, buffer_height); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); if (_offscreen_color_rt1.IsValid()) QRP_GLSL_VerticalGauss(0, 0, buffer_width, buffer_height, _offscreen_color_rt1, texxform1, c0, sigma); } _offscreen_fbo->Deactivate(); if (prevFBO.IsValid()) { prevFBO->Activate(true); SetViewport(0, 0, previous_width, previous_height); SetOrthographicProjectionMatrix(previous_width, previous_height); } else { SetViewport(0, 0, previous_width, previous_height); SetOrthographicProjectionMatrix(previous_width, previous_height); } return _offscreen_color_rt0; } ObjectPtr GraphicsEngine::QRP_GLSL_GetLSBlurTexture( int x, int y, int buffer_width, int buffer_height, ObjectPtr device_texture, TexCoordXForm &texxform, const Color& c0, float sigma, int num_pass) { int quad_width = device_texture->GetWidth(); int quad_height = device_texture->GetHeight(); num_pass = Clamp (num_pass, 1, 50); ObjectPtr prevFBO = GetGraphicsDisplay()->GetGpuDevice()->GetCurrentFrameBufferObject(); int previous_width = 0; int previous_height = 0; if (prevFBO.IsValid()) { previous_width = prevFBO->GetWidth(); previous_height = prevFBO->GetHeight(); } else { previous_width = _graphics_display.GetWindowWidth(); previous_height = _graphics_display.GetWindowHeight(); } CHECKGL(glClearColor(0, 0, 0, 0)); _offscreen_color_rt0->SetWrap(GL_CLAMP, GL_CLAMP, GL_CLAMP); _offscreen_color_rt0->SetFiltering(GL_NEAREST, GL_NEAREST); _offscreen_color_rt1->SetWrap(GL_CLAMP, GL_CLAMP, GL_CLAMP); _offscreen_color_rt1->SetFiltering(GL_NEAREST, GL_NEAREST); SetFrameBufferHelper(_offscreen_fbo, _offscreen_color_rt0, _offscreen_depth_rt0, buffer_width, buffer_height); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); QRP_GLSL_1Tex(x, y, quad_width, quad_height, device_texture, texxform, color::White); TexCoordXForm texxform1; for (int i = 0; i < num_pass; i++) { SetFrameBufferHelper(_offscreen_fbo, _offscreen_color_rt1, _offscreen_depth_rt1, buffer_width, buffer_height); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); QRP_GLSL_HorizontalLSGauss(0, 0, buffer_width, buffer_height, _offscreen_color_rt0, texxform1, c0, sigma); SetFrameBufferHelper(_offscreen_fbo, _offscreen_color_rt0, _offscreen_depth_rt0, buffer_width, buffer_height); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); QRP_GLSL_VerticalLSGauss(0, 0, buffer_width, buffer_height, _offscreen_color_rt1, texxform1, c0, sigma); } _offscreen_fbo->Deactivate(); if (prevFBO.IsValid()) { prevFBO->Activate(true); SetViewport(0, 0, previous_width, previous_height); SetOrthographicProjectionMatrix(previous_width, previous_height); } else { SetViewport(0, 0, previous_width, previous_height); SetOrthographicProjectionMatrix(previous_width, previous_height); } return _offscreen_color_rt0; } ObjectPtr GraphicsEngine::QRP_GLSL_GetPower( ObjectPtr device_texture, TexCoordXForm &texxform, const Color &c0, const Vector4 &exponent) { int quad_width = device_texture->GetWidth(); int quad_height = device_texture->GetHeight(); ObjectPtr prevFBO = GetGraphicsDisplay()->GetGpuDevice()->GetCurrentFrameBufferObject(); int previous_width = 0; int previous_height = 0; if (prevFBO.IsValid()) { previous_width = prevFBO->GetWidth(); previous_height = prevFBO->GetHeight(); } else { previous_width = _graphics_display.GetWindowWidth(); previous_height = _graphics_display.GetWindowHeight(); } CHECKGL(glClearColor(0, 0, 0, 0)); _offscreen_color_rt0->SetWrap(GL_CLAMP, GL_CLAMP, GL_CLAMP); _offscreen_color_rt0->SetFiltering(GL_NEAREST, GL_NEAREST); _offscreen_color_rt1->SetWrap(GL_CLAMP, GL_CLAMP, GL_CLAMP); _offscreen_color_rt1->SetFiltering(GL_NEAREST, GL_NEAREST); SetFrameBufferHelper(_offscreen_fbo, _offscreen_color_rt0, _offscreen_depth_rt0, quad_width, quad_height); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); QRP_GLSL_1Tex(0, 0, quad_width, quad_height, device_texture, texxform, color::White); SetFrameBufferHelper(_offscreen_fbo, _offscreen_color_rt1, _offscreen_depth_rt1, quad_width, quad_height); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); QRP_GLSL_Power(0, 0, quad_width, quad_height, _offscreen_color_rt0, texxform, c0, exponent); _offscreen_fbo->Deactivate(); if (prevFBO.IsValid()) { prevFBO->Activate(true); SetViewport(0, 0, previous_width, previous_height); SetOrthographicProjectionMatrix(previous_width, previous_height); } else { SetViewport(0, 0, previous_width, previous_height); SetOrthographicProjectionMatrix(previous_width, previous_height); } return _offscreen_color_rt1; } ObjectPtr GraphicsEngine::QRP_GLSL_GetAlphaTexture( ObjectPtr device_texture, TexCoordXForm &texxform, const Color & c0) { int quad_width = device_texture->GetWidth(); int quad_height = device_texture->GetHeight(); ObjectPtr prevFBO = GetGraphicsDisplay()->GetGpuDevice()->GetCurrentFrameBufferObject(); int previous_width = 0; int previous_height = 0; if (prevFBO.IsValid()) { previous_width = prevFBO->GetWidth(); previous_height = prevFBO->GetHeight(); } else { previous_width = _graphics_display.GetWindowWidth(); previous_height = _graphics_display.GetWindowHeight(); } CHECKGL(glClearColor(0, 0, 0, 0)); _offscreen_color_rt0->SetWrap(GL_CLAMP, GL_CLAMP, GL_CLAMP); _offscreen_color_rt0->SetFiltering(GL_NEAREST, GL_NEAREST); _offscreen_color_rt1->SetWrap(GL_CLAMP, GL_CLAMP, GL_CLAMP); _offscreen_color_rt1->SetFiltering(GL_NEAREST, GL_NEAREST); SetFrameBufferHelper(_offscreen_fbo, _offscreen_color_rt0, _offscreen_depth_rt0, quad_width, quad_height); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); QRP_GLSL_1Tex(0, 0, quad_width, quad_height, device_texture, texxform, color::White); SetFrameBufferHelper(_offscreen_fbo, _offscreen_color_rt1, _offscreen_depth_rt1, quad_width, quad_height); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); QRP_GLSL_AlphaReplicate(0, 0, quad_width, quad_height, _offscreen_color_rt0, texxform, c0); _offscreen_fbo->Deactivate(); if (prevFBO.IsValid()) { prevFBO->Activate(true); SetViewport(0, 0, previous_width, previous_height); SetOrthographicProjectionMatrix(previous_width, previous_height); } else { SetViewport(0, 0, previous_width, previous_height); SetOrthographicProjectionMatrix(previous_width, previous_height); } return _offscreen_color_rt1; } ObjectPtr GraphicsEngine::QRP_GLSL_GetColorMatrixTexture( ObjectPtr device_texture, TexCoordXForm &texxform, const Color & c0, Matrix4 color_matrix, Vector4 offset) { int quad_width = device_texture->GetWidth(); int quad_height = device_texture->GetHeight(); ObjectPtr prevFBO = GetGraphicsDisplay()->GetGpuDevice()->GetCurrentFrameBufferObject(); int previous_width = 0; int previous_height = 0; if (prevFBO.IsValid()) { previous_width = prevFBO->GetWidth(); previous_height = prevFBO->GetHeight(); } else { previous_width = _graphics_display.GetWindowWidth(); previous_height = _graphics_display.GetWindowHeight(); } CHECKGL(glClearColor(0, 0, 0, 0)); _offscreen_color_rt0->SetWrap(GL_CLAMP, GL_CLAMP, GL_CLAMP); _offscreen_color_rt0->SetFiltering(GL_NEAREST, GL_NEAREST); _offscreen_color_rt1->SetWrap(GL_CLAMP, GL_CLAMP, GL_CLAMP); _offscreen_color_rt1->SetFiltering(GL_NEAREST, GL_NEAREST); SetFrameBufferHelper(_offscreen_fbo, _offscreen_color_rt0, _offscreen_depth_rt0, quad_width, quad_height); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); QRP_GLSL_1Tex(0, 0, quad_width, quad_height, device_texture, texxform, color::White); SetFrameBufferHelper(_offscreen_fbo, _offscreen_color_rt1, _offscreen_depth_rt1, quad_width, quad_height); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); QRP_GLSL_ColorMatrix(0, 0, quad_width, quad_height, _offscreen_color_rt0, texxform, c0, color_matrix, offset); _offscreen_fbo->Deactivate(); if (prevFBO.IsValid()) { prevFBO->Activate(true); SetViewport(0, 0, previous_width, previous_height); SetOrthographicProjectionMatrix(previous_width, previous_height); } else { SetViewport(0, 0, previous_width, previous_height); SetOrthographicProjectionMatrix(previous_width, previous_height); } return _offscreen_color_rt1; } ObjectPtr GraphicsEngine::QRP_GLSL_GetLQBlur( int /* x */, int /* y */, int /* buffer_width */, int /* buffer_height */, ObjectPtr device_texture, TexCoordXForm &texxform, const Color& /* c0 */) { int quad_width = device_texture->GetWidth(); int quad_height = device_texture->GetHeight(); ObjectPtr prevFBO = GetGraphicsDisplay()->GetGpuDevice()->GetCurrentFrameBufferObject(); int previous_width = 0; int previous_height = 0; if (prevFBO.IsValid()) { previous_width = prevFBO->GetWidth(); previous_height = prevFBO->GetHeight(); } else { previous_width = _graphics_display.GetWindowWidth(); previous_height = _graphics_display.GetWindowHeight(); } CHECKGL(glClearColor(0, 0, 0, 0)); texxform.mag_filter = TEXFILTER_LINEAR; texxform.min_filter = TEXFILTER_LINEAR; SetFrameBufferHelper(_offscreen_fbo, _offscreen_color_rt0, _offscreen_depth_rt0, quad_width/2, quad_height/2); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); QRP_GLSL_1Tex(0, 0, quad_width / 2, quad_height / 2, device_texture, texxform, color::White); SetFrameBufferHelper(_offscreen_fbo, _offscreen_color_rt1, _offscreen_depth_rt1, quad_width/4, quad_height/4); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); QRP_GLSL_1Tex(0, 0, quad_width / 4, quad_height / 4, _offscreen_color_rt0, texxform, color::White); SetFrameBufferHelper(_offscreen_fbo, _offscreen_color_rt2, _offscreen_depth_rt2, quad_width/8, quad_height/8); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); QRP_GLSL_1Tex(0, 0, quad_width / 8, quad_height / 8, _offscreen_color_rt1, texxform, color::White); SetFrameBufferHelper(_offscreen_fbo, _offscreen_color_rt3, _offscreen_depth_rt3, quad_width, quad_height); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); TexCoordXForm texxform0; TexCoordXForm texxform1; TexCoordXForm texxform2; TexCoordXForm texxform3; texxform0.flip_v_coord = true; texxform2.flip_v_coord = true; QRP_GLSL_4Tex(0, 0, quad_width, quad_height, device_texture, texxform0, Color(0.25, 0.25, 0.25, 0.25), _offscreen_color_rt0, texxform1, Color(0.25, 0.25, 0.25, 0.25), _offscreen_color_rt1, texxform2, Color(0.25, 0.25, 0.25, 0.25), _offscreen_color_rt2, texxform3, Color(0.25, 0.25, 0.25, 0.25)); _offscreen_fbo->Deactivate(); if (prevFBO.IsValid()) { prevFBO->Activate(true); SetViewport(0, 0, previous_width, previous_height); SetOrthographicProjectionMatrix(previous_width, previous_height); } else { SetViewport(0, 0, previous_width, previous_height); SetOrthographicProjectionMatrix(previous_width, previous_height); } return _offscreen_color_rt3; } ObjectPtr GraphicsEngine::QRP_GLSL_GetHQBlur( int x, int y, int buffer_width, int buffer_height, ObjectPtr device_texture, TexCoordXForm &texxform, const Color& c0, float sigma, int num_pass) { int quad_width = device_texture->GetWidth(); int quad_height = device_texture->GetHeight(); num_pass = Clamp (num_pass, 1, 50); ObjectPtr prevFBO = GetGraphicsDisplay()->GetGpuDevice()->GetCurrentFrameBufferObject(); int previous_width = 0; int previous_height = 0; if (prevFBO.IsValid()) { previous_width = prevFBO->GetWidth(); previous_height = prevFBO->GetHeight(); } else { previous_width = _graphics_display.GetWindowWidth(); previous_height = _graphics_display.GetWindowHeight(); } CHECKGL(glClearColor(0, 0, 0, 0)); _offscreen_color_rt0->SetWrap(GL_CLAMP, GL_CLAMP, GL_CLAMP); _offscreen_color_rt0->SetFiltering(GL_NEAREST, GL_NEAREST); _offscreen_color_rt1->SetWrap(GL_CLAMP, GL_CLAMP, GL_CLAMP); _offscreen_color_rt1->SetFiltering(GL_NEAREST, GL_NEAREST); SetFrameBufferHelper(_offscreen_fbo, _offscreen_color_rt0, _offscreen_depth_rt0, buffer_width, buffer_height); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); QRP_GLSL_1Tex(x, y, quad_width, quad_height, device_texture, texxform, color::White); TexCoordXForm texxform1; for (int i = 0; i < num_pass; i++) { SetFrameBufferHelper(_offscreen_fbo, _offscreen_color_rt1, _offscreen_depth_rt1, buffer_width, buffer_height); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); QRP_GLSL_HorizontalHQGauss(0, 0, buffer_width, buffer_height, _offscreen_color_rt0, texxform1, c0, sigma); SetFrameBufferHelper(_offscreen_fbo, _offscreen_color_rt0, _offscreen_depth_rt0, buffer_width, buffer_height); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); QRP_GLSL_VerticalHQGauss(0, 0, buffer_width, buffer_height, _offscreen_color_rt1, texxform1, c0, sigma); } _offscreen_fbo->Deactivate(); if (prevFBO.IsValid()) { prevFBO->Activate(true); SetViewport(0, 0, previous_width, previous_height); SetOrthographicProjectionMatrix(previous_width, previous_height); } else { SetViewport(0, 0, previous_width, previous_height); SetOrthographicProjectionMatrix(previous_width, previous_height); } return _offscreen_color_rt0; } void GraphicsEngine::QRP_GLSL_GetHQBlurFx( int x, int y, int buffer_width, int buffer_height, FxStructure *fx_structure, TexCoordXForm &texxform, const Color& c0, float sigma, int num_pass) { int quad_width = fx_structure->src_texture->GetWidth(); int quad_height = fx_structure->src_texture->GetHeight(); num_pass = Clamp (num_pass, 1, 50); ObjectPtr prevFBO = GetGraphicsDisplay()->GetGpuDevice()->GetCurrentFrameBufferObject(); int previous_width = 0; int previous_height = 0; if (prevFBO.IsValid()) { previous_width = prevFBO->GetWidth(); previous_height = prevFBO->GetHeight(); } else { previous_width = _graphics_display.GetWindowWidth(); previous_height = _graphics_display.GetWindowHeight(); } CHECKGL(glClearColor(0, 0, 0, 0)); fx_structure->src_texture->SetWrap(GL_CLAMP, GL_CLAMP, GL_CLAMP); fx_structure->src_texture->SetFiltering(GL_NEAREST, GL_NEAREST); fx_structure->dst_texture->SetWrap(GL_CLAMP, GL_CLAMP, GL_CLAMP); fx_structure->dst_texture->SetFiltering(GL_NEAREST, GL_NEAREST); fx_structure->temp_texture->SetWrap(GL_CLAMP, GL_CLAMP, GL_CLAMP); fx_structure->temp_texture->SetFiltering(GL_NEAREST, GL_NEAREST); SetFrameBufferHelper(_offscreen_fbo, fx_structure->dst_texture, _offscreen_depth_rt0, buffer_width, buffer_height); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); QRP_GLSL_1Tex(x, y, quad_width, quad_height, fx_structure->src_texture, texxform, color::White); TexCoordXForm texxform1; for (int i = 0; i < num_pass; i++) { SetFrameBufferHelper(_offscreen_fbo, fx_structure->temp_texture, _offscreen_depth_rt1, buffer_width, buffer_height); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); QRP_GLSL_HorizontalGauss(0, 0, buffer_width, buffer_height, fx_structure->dst_texture, texxform1, c0, sigma); SetFrameBufferHelper(_offscreen_fbo, fx_structure->dst_texture, _offscreen_depth_rt0, buffer_width, buffer_height); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); QRP_GLSL_VerticalGauss(0, 0, buffer_width, buffer_height, fx_structure->temp_texture, texxform1, c0, sigma); } _offscreen_fbo->Deactivate(); if (prevFBO.IsValid()) { prevFBO->Activate(true); SetViewport(0, 0, previous_width, previous_height); SetOrthographicProjectionMatrix(previous_width, previous_height); } else { SetViewport(0, 0, previous_width, previous_height); SetOrthographicProjectionMatrix(previous_width, previous_height); } } void GraphicsEngine::QRP_GLSL_GetLSBlurFx( int x, int y, int buffer_width, int buffer_height, FxStructure *fx_structure, TexCoordXForm &texxform, const Color& c0, float sigma, int num_pass) { int quad_width = fx_structure->src_texture->GetWidth(); int quad_height = fx_structure->src_texture->GetHeight(); num_pass = Clamp (num_pass, 1, 50); ObjectPtr prevFBO = GetGraphicsDisplay()->GetGpuDevice()->GetCurrentFrameBufferObject(); int previous_width = 0; int previous_height = 0; if (prevFBO.IsValid()) { previous_width = prevFBO->GetWidth(); previous_height = prevFBO->GetHeight(); } else { previous_width = _graphics_display.GetWindowWidth(); previous_height = _graphics_display.GetWindowHeight(); } CHECKGL(glClearColor(0, 0, 0, 0)); fx_structure->src_texture->SetWrap(GL_CLAMP, GL_CLAMP, GL_CLAMP); fx_structure->src_texture->SetFiltering(GL_NEAREST, GL_NEAREST); fx_structure->dst_texture->SetWrap(GL_CLAMP, GL_CLAMP, GL_CLAMP); fx_structure->dst_texture->SetFiltering(GL_NEAREST, GL_NEAREST); fx_structure->temp_texture->SetWrap(GL_CLAMP, GL_CLAMP, GL_CLAMP); fx_structure->temp_texture->SetFiltering(GL_NEAREST, GL_NEAREST); SetFrameBufferHelper(_offscreen_fbo, fx_structure->dst_texture, _offscreen_depth_rt0, buffer_width, buffer_height); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); QRP_GLSL_1Tex(x, y, quad_width, quad_height, fx_structure->src_texture, texxform, color::White); TexCoordXForm texxform1; for (int i = 0; i < num_pass; i++) { SetFrameBufferHelper(_offscreen_fbo, fx_structure->temp_texture, _offscreen_depth_rt1, buffer_width, buffer_height); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); QRP_GLSL_HorizontalLSGauss(0, 0, buffer_width, buffer_height, fx_structure->dst_texture, texxform1, c0, sigma); SetFrameBufferHelper(_offscreen_fbo, fx_structure->dst_texture, _offscreen_depth_rt0, buffer_width, buffer_height); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); QRP_GLSL_VerticalLSGauss(0, 0, buffer_width, buffer_height, fx_structure->temp_texture, texxform1, c0, sigma); } _offscreen_fbo->Deactivate(); if (prevFBO.IsValid()) { prevFBO->Activate(true); SetViewport(0, 0, previous_width, previous_height); SetOrthographicProjectionMatrix(previous_width, previous_height); } else { SetViewport(0, 0, previous_width, previous_height); SetOrthographicProjectionMatrix(previous_width, previous_height); } } ObjectPtr GraphicsEngine::QRP_GLSL_GetDisturbedTexture( int x, int y, int width, int height, ObjectPtr distorsion_texture, TexCoordXForm &texxform0, const Color& c0, ObjectPtr src_device_texture, TexCoordXForm &texxform1, const Color& c1) { ObjectPtr prevFBO = GetGraphicsDisplay()->GetGpuDevice()->GetCurrentFrameBufferObject(); int previous_width = 0; int previous_height = 0; if (prevFBO.IsValid()) { previous_width = prevFBO->GetWidth(); previous_height = prevFBO->GetHeight(); } else { previous_width = _graphics_display.GetWindowWidth(); previous_height = _graphics_display.GetWindowHeight(); } CHECKGL(glClearColor(0, 0, 0, 0)); SetFrameBufferHelper(_offscreen_fbo, _offscreen_color_rt0, _offscreen_depth_rt0, width, height); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); QRP_GLSL_DisturbedTexture(x, y, width, height, distorsion_texture, texxform0, c0, src_device_texture, texxform1, c1); _offscreen_fbo->Deactivate(); if (prevFBO.IsValid()) { prevFBO->Activate(true); SetViewport(0, 0, previous_width, previous_height); SetOrthographicProjectionMatrix(previous_width, previous_height); } else { SetViewport(0, 0, previous_width, previous_height); SetOrthographicProjectionMatrix(previous_width, previous_height); } return _offscreen_color_rt0; } void GraphicsEngine::QRP_GLSL_GetDisturbedTextureFx( int x, int y, int width, int height, ObjectPtr distorsion_texture, TexCoordXForm &texxform0, const Color& c0, FxStructure *fx_structure, TexCoordXForm &texxform1, const Color& c1) { ObjectPtr prevFBO = GetGraphicsDisplay()->GetGpuDevice()->GetCurrentFrameBufferObject(); int previous_width = 0; int previous_height = 0; if (prevFBO.IsValid()) { previous_width = prevFBO->GetWidth(); previous_height = prevFBO->GetHeight(); } else { previous_width = _graphics_display.GetWindowWidth(); previous_height = _graphics_display.GetWindowHeight(); } CHECKGL(glClearColor(0, 0, 0, 0)); SetFrameBufferHelper(_offscreen_fbo, fx_structure->dst_texture, _offscreen_depth_rt0, width, height); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); QRP_GLSL_DisturbedTexture(x, y, width, height, distorsion_texture, texxform0, c0, fx_structure->src_texture, texxform1, c1); _offscreen_fbo->Deactivate(); if (prevFBO.IsValid()) { prevFBO->Activate(true); SetViewport(0, 0, previous_width, previous_height); SetOrthographicProjectionMatrix(previous_width, previous_height); } else { SetViewport(0, 0, previous_width, previous_height); SetOrthographicProjectionMatrix(previous_width, previous_height); } } void GraphicsEngine::InitSlPixelateShader() { ObjectPtr VS = _graphics_display.m_DeviceFactory->CreateVertexShader(); ObjectPtr PS = _graphics_display.m_DeviceFactory->CreatePixelShader(); const char* VSString = NUX_VERTEX_SHADER_HEADER "attribute vec4 AVertex; \n\ attribute vec4 MyTextureCoord0; \n\ attribute vec4 VertexColor; \n\ uniform mat4 ViewProjectionMatrix; \n\ varying vec4 varyTexCoord0; \n\ varying vec4 varyVertexColor; \n\ void main() \n\ { \n\ gl_Position = ViewProjectionMatrix * (AVertex); \n\ varyTexCoord0 = MyTextureCoord0; \n\ varyVertexColor = VertexColor; \n\ }"; const char* PSString = NUX_FRAGMENT_SHADER_HEADER "varying vec4 varyTexCoord0; \n\ varying vec4 varyVertexColor; \n\ uniform vec4 pixel_size; \n\ uniform vec4 pixel_size_inv; \n\ uniform sampler2D TextureObject0; \n\ vec4 SampleTexture(sampler2D TexObject, vec4 TexCoord) \n\ { \n\ return texture2D(TexObject, TexCoord.st); \n\ } \n\ void main() \n\ { \n\ vec4 tex_coord = floor(varyTexCoord0 * pixel_size_inv) * pixel_size; \n\ vec4 v = SampleTexture(TextureObject0, tex_coord); \n\ gl_FragColor = v*varyVertexColor; \n\ }"; // Textured 2D Primitive Shader m_SLPixelate = _graphics_display.m_DeviceFactory->CreateShaderProgram(); VS->SetShaderCode(TCHAR_TO_ANSI(VSString)); PS->SetShaderCode(TCHAR_TO_ANSI(PSString), "#define SAMPLERTEX2D"); m_SLPixelate->ClearShaderObjects(); m_SLPixelate->AddShaderObject(VS); m_SLPixelate->AddShaderObject(PS); CHECKGL(glBindAttribLocation(m_SLPixelate->GetOpenGLID(), 0, "AVertex")); m_SLPixelate->Link(); } void GraphicsEngine::QRP_GLSL_Pixelate(int x, int y, int width, int height, ObjectPtr DeviceTexture, TexCoordXForm &texxform0, const Color &color0, int pixel_size) { if (!m_SLPixelate.IsValid()) InitSlPixelateShader(); m_quad_tex_stats++; QRP_Compute_Texture_Coord(width, height, DeviceTexture, texxform0); float fx = x, fy = y; float VtxBuffer[] = { fx, fy, 0.0f, 1.0f, texxform0.u0, texxform0.v0, 0, 0, color0.red, color0.green, color0.blue, color0.alpha, fx, fy + height, 0.0f, 1.0f, texxform0.u0, texxform0.v1, 0, 0, color0.red, color0.green, color0.blue, color0.alpha, fx + width, fy + height, 0.0f, 1.0f, texxform0.u1, texxform0.v1, 0, 0, color0.red, color0.green, color0.blue, color0.alpha, fx + width, fy, 0.0f, 1.0f, texxform0.u1, texxform0.v0, 0, 0, color0.red, color0.green, color0.blue, color0.alpha, }; float tex_width = DeviceTexture->GetWidth(); float tex_height = DeviceTexture->GetHeight(); ObjectPtr ShaderProg; ShaderProg = m_SLPixelate; CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); ShaderProg->Begin(); int TextureObjectLocation = ShaderProg->GetUniformLocationARB("TextureObject0"); int PixelSizeLocation = ShaderProg->GetUniformLocationARB("pixel_size"); int PixelSizeInvLocation = ShaderProg->GetUniformLocationARB("pixel_size_inv"); int VertexLocation = ShaderProg->GetAttributeLocation("AVertex"); int TextureCoord0Location = ShaderProg->GetAttributeLocation("MyTextureCoord0"); int VertexColorLocation = ShaderProg->GetAttributeLocation("VertexColor"); SetTexture(GL_TEXTURE0, DeviceTexture); CHECKGL(glUniform1iARB(TextureObjectLocation, 0)); int VPMatrixLocation = ShaderProg->GetUniformLocationARB("ViewProjectionMatrix"); Matrix4 MVPMatrix = GetOpenGLModelViewProjectionMatrix(); ShaderProg->SetUniformLocMatrix4fv((GLint) VPMatrixLocation, 1, false, (GLfloat *) & (MVPMatrix.m)); ShaderProg->SetUniform4f((GLint) PixelSizeLocation, (float)pixel_size / (float)tex_width, (float)pixel_size / (float)tex_height, 1.0f, 1.0f); ShaderProg->SetUniform4f((GLint) PixelSizeInvLocation, (float)tex_width / (float)pixel_size, (float)tex_height / (float)pixel_size, 1.0f, 1.0f); CHECKGL(glEnableVertexAttribArrayARB(VertexLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexLocation, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer)); if (TextureCoord0Location != -1) { CHECKGL(glEnableVertexAttribArrayARB(TextureCoord0Location)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord0Location, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 4)); } if (VertexColorLocation != -1) { CHECKGL(glEnableVertexAttribArrayARB(VertexColorLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexColorLocation, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 8)); } CHECKGL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); CHECKGL(glDisableVertexAttribArrayARB(VertexLocation)); if (TextureCoord0Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord0Location)); if (VertexColorLocation != -1) CHECKGL(glDisableVertexAttribArrayARB(VertexColorLocation)); ShaderProg->End(); } ObjectPtr GraphicsEngine::QRP_GLSL_GetPixelBlocks( ObjectPtr device_texture, TexCoordXForm &texxform0, const Color& /* c0 */, int pixel_size) { int quad_width = device_texture->GetWidth(); int quad_height = device_texture->GetHeight(); ObjectPtr prevFBO = GetGraphicsDisplay()->GetGpuDevice()->GetCurrentFrameBufferObject(); int previous_width = 0; int previous_height = 0; if (prevFBO.IsValid()) { previous_width = prevFBO->GetWidth(); previous_height = prevFBO->GetHeight(); } else { previous_width = _graphics_display.GetWindowWidth(); previous_height = _graphics_display.GetWindowHeight(); } CHECKGL(glClearColor(0, 0, 0, 0)); SetFrameBufferHelper(_offscreen_fbo, _offscreen_color_rt0, _offscreen_depth_rt0, quad_width, quad_height); CHECKGL(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)); QRP_GLSL_Pixelate(0, 0, quad_width, quad_height, device_texture, texxform0, color::White, pixel_size); _offscreen_fbo->Deactivate(); if (prevFBO.IsValid()) { prevFBO->Activate(true); SetViewport(0, 0, previous_width, previous_height); SetOrthographicProjectionMatrix(previous_width, previous_height); } else { SetViewport(0, 0, previous_width, previous_height); SetOrthographicProjectionMatrix(previous_width, previous_height); } return _offscreen_color_rt0; } void GraphicsEngine::QRP_GLSL_GetCopyTexture( int width, int height, ObjectPtr& dst_device_texture, ObjectPtr& src_device_texture, TexCoordXForm &texxform0, const Color& c0) { if (src_device_texture.IsValid() == false) { return; } ObjectPtr prevFBO = GetGraphicsDisplay()->GetGpuDevice()->GetCurrentFrameBufferObject(); int previous_width = 0; int previous_height = 0; if (prevFBO.IsValid()) { previous_width = prevFBO->GetWidth(); previous_height = prevFBO->GetHeight(); } else { previous_width = _graphics_display.GetWindowWidth(); previous_height = _graphics_display.GetWindowHeight(); } if ((dst_device_texture.IsValid() == false) || (dst_device_texture->GetWidth() != width) || (dst_device_texture->GetHeight() != height) || (dst_device_texture->GetPixelFormat() != src_device_texture->GetPixelFormat())) { dst_device_texture = _graphics_display.GetGpuDevice()->CreateTexture(width, height, 1, src_device_texture->GetPixelFormat()); } CHECKGL(glClearColor(0, 0, 0, 0)); SetFrameBufferHelper(_offscreen_fbo, dst_device_texture, _offscreen_depth_rt0, width, height); CHECKGL(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)); QRP_GLSL_1Tex(0, 0, width, height, src_device_texture, texxform0, c0); _offscreen_fbo->Deactivate(); if (prevFBO.IsValid()) { prevFBO->Activate(true); SetViewport(0, 0, previous_width, previous_height); SetOrthographicProjectionMatrix(previous_width, previous_height); } else { SetViewport(0, 0, previous_width, previous_height); SetOrthographicProjectionMatrix(previous_width, previous_height); } } void GraphicsEngine::InitSlTexturePremultiplyShader() { ObjectPtr VS = _graphics_display.m_DeviceFactory->CreateVertexShader(); ObjectPtr PS = _graphics_display.m_DeviceFactory->CreatePixelShader(); std::string VSString; std::string PSString; VSString = NUX_VERTEX_SHADER_HEADER "attribute vec4 i_vertex; \n\ attribute vec4 i_texture_coord0; \n\ attribute vec4 i_vertex_color; \n\ uniform mat4 ViewProjectionMatrix; \n\ varying vec4 varyTexCoord0; \n\ varying vec4 varyVertexColor; \n\ void main() \n\ { \n\ gl_Position = ViewProjectionMatrix * (i_vertex); \n\ varyTexCoord0 = i_texture_coord0; \n\ varyVertexColor = i_vertex_color; \n\ }"; PSString = NUX_FRAGMENT_SHADER_HEADER "varying vec4 varyTexCoord0; \n\ varying vec4 varyVertexColor; \n\ uniform sampler2D TextureObject0; \n\ void main() \n\ { \n\ vec4 tex = texture2D(TextureObject0, varyTexCoord0.st); \n\ gl_FragColor = vec4(tex.r * tex.a, tex.g * tex.a, tex.b * tex.a, tex.a) * varyVertexColor; \n\ }"; // Textured 2D Primitive Shader m_SlTexturePremultiplyModColor = _graphics_display.m_DeviceFactory->CreateShaderProgram(); VS->SetShaderCode(VSString.c_str()); PS->SetShaderCode(PSString.c_str()); m_SlTexturePremultiplyModColor->ClearShaderObjects(); m_SlTexturePremultiplyModColor->AddShaderObject(VS); m_SlTexturePremultiplyModColor->AddShaderObject(PS); //CHECKGL(glBindAttribLocation(m_SlTexturePremultiplyModColor->GetOpenGLID(), 0, "i_vertex")); m_SlTexturePremultiplyModColor->Link(); } void GraphicsEngine::QRP_GLSL_1TexPremultiply(int x, int y, int width, int height, ObjectPtr DeviceTexture, TexCoordXForm &texxform0, const Color &color0) { if (DeviceTexture.IsNull() || (!DeviceTexture->Type().IsDerivedFromType(IOpenGLTexture2D::StaticObjectType))) { return; } if (!m_SlTexturePremultiplyModColor.IsValid()) InitSlTexturePremultiplyShader(); m_quad_tex_stats++; QRP_Compute_Texture_Coord(width, height, DeviceTexture, texxform0); float fx = x, fy = y; float VtxBuffer[] = { fx, fy, 0.0f, 1.0f, texxform0.u0, texxform0.v0, 0, 0, color0.red, color0.green, color0.blue, color0.alpha, fx, fy + height, 0.0f, 1.0f, texxform0.u0, texxform0.v1, 0, 0, color0.red, color0.green, color0.blue, color0.alpha, fx + width, fy + height, 0.0f, 1.0f, texxform0.u1, texxform0.v1, 0, 0, color0.red, color0.green, color0.blue, color0.alpha, fx + width, fy, 0.0f, 1.0f, texxform0.u1, texxform0.v0, 0, 0, color0.red, color0.green, color0.blue, color0.alpha, }; ObjectPtr ShaderProg = m_SlTexturePremultiplyModColor; CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); ShaderProg->Begin(); int TextureObjectLocation = ShaderProg->GetUniformLocationARB("TextureObject0"); int VertexLocation = ShaderProg->GetAttributeLocation("i_vertex"); int TextureCoord0Location = ShaderProg->GetAttributeLocation("i_texture_coord0"); int VertexColorLocation = ShaderProg->GetAttributeLocation("i_vertex_color"); SetTexture(GL_TEXTURE0, DeviceTexture); CHECKGL(glUniform1iARB(TextureObjectLocation, 0)); int VPMatrixLocation = ShaderProg->GetUniformLocationARB("ViewProjectionMatrix"); Matrix4 MVPMatrix = GetOpenGLModelViewProjectionMatrix(); ShaderProg->SetUniformLocMatrix4fv((GLint) VPMatrixLocation, 1, false, (GLfloat *) & (MVPMatrix.m)); CHECKGL(glEnableVertexAttribArrayARB(VertexLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexLocation, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer)); if (TextureCoord0Location != -1) { CHECKGL(glEnableVertexAttribArrayARB(TextureCoord0Location)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord0Location, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 4)); } if (VertexColorLocation != -1) { CHECKGL(glEnableVertexAttribArrayARB(VertexColorLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexColorLocation, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 8)); } CHECKGL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); CHECKGL(glDisableVertexAttribArrayARB(VertexLocation)); if (TextureCoord0Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord0Location)); if (VertexColorLocation != -1) CHECKGL(glDisableVertexAttribArrayARB(VertexColorLocation)); ShaderProg->End(); } void GraphicsEngine::InitSLDesaturation() { ObjectPtr VS = _graphics_display.m_DeviceFactory->CreateVertexShader(); ObjectPtr PS = _graphics_display.m_DeviceFactory->CreatePixelShader(); const char* VSString = NUX_VERTEX_SHADER_HEADER "attribute vec4 AVertex; \n\ attribute vec4 MyTextureCoord0; \n\ attribute vec4 VertexColor; \n\ uniform mat4 ViewProjectionMatrix; \n\ varying vec4 varyTexCoord0; \n\ varying vec4 varyVertexColor; \n\ void main() \n\ { \n\ gl_Position = ViewProjectionMatrix * (AVertex); \n\ varyTexCoord0 = MyTextureCoord0; \n\ varyVertexColor = VertexColor; \n\ }"; const char* PSString = NUX_FRAGMENT_SHADER_HEADER "varying vec4 varyTexCoord0; \n\ varying vec4 varyVertexColor; \n\ uniform sampler2D TextureObject0; \n\ uniform float desat_factor; \n\ uniform vec3 luma; \n\ void main() \n\ { \n\ vec4 texel = texture2D(TextureObject0, varyTexCoord0.st); \n\ vec4 desat_texel = vec4 (luma.r * texel.r + luma.g * texel.g + luma.b * texel.b); \n\ vec4 final = (vec4 (1.0, 1.0, 1.0, 1.0) - desat_factor) * desat_texel + desat_factor * texel; \n\ final.a = texel.a; \n\ gl_FragColor = final * varyVertexColor; \n\ }"; // Textured 2D Primitive Shader desaturation_prog_ = _graphics_display.m_DeviceFactory->CreateShaderProgram(); VS->SetShaderCode(TCHAR_TO_ANSI(VSString)); PS->SetShaderCode(TCHAR_TO_ANSI(PSString)); desaturation_prog_->ClearShaderObjects(); desaturation_prog_->AddShaderObject(VS); desaturation_prog_->AddShaderObject(PS); CHECKGL(glBindAttribLocation(desaturation_prog_->GetOpenGLID(), 0, "AVertex")); desaturation_prog_->Link(); } void GraphicsEngine::QRP_GLSL_TexDesaturate(int x, int y, int width, int height, ObjectPtr DeviceTexture, TexCoordXForm& texxform0, const Color& color0, float desaturation_factor) { if (!desaturation_prog_.IsValid()) InitSLDesaturation(); m_quad_tex_stats++; QRP_Compute_Texture_Coord(width, height, DeviceTexture, texxform0); float fx = x, fy = y; float VtxBuffer[] = { fx, fy, 0.0f, 1.0f, texxform0.u0, texxform0.v0, 0, 0, color0.red, color0.green, color0.blue, color0.alpha, fx, fy + height, 0.0f, 1.0f, texxform0.u0, texxform0.v1, 0, 0, color0.red, color0.green, color0.blue, color0.alpha, fx + width, fy + height, 0.0f, 1.0f, texxform0.u1, texxform0.v1, 0, 0, color0.red, color0.green, color0.blue, color0.alpha, fx + width, fy, 0.0f, 1.0f, texxform0.u1, texxform0.v0, 0, 0, color0.red, color0.green, color0.blue, color0.alpha, }; ObjectPtr ShaderProg; if (DeviceTexture->Type().IsDerivedFromType(IOpenGLTexture2D::StaticObjectType)) { ShaderProg = desaturation_prog_; } CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); ShaderProg->Begin(); int TextureObjectLocation = ShaderProg->GetUniformLocationARB("TextureObject0"); int luma_location = ShaderProg->GetUniformLocationARB("luma"); int desat_factor_location = ShaderProg->GetUniformLocationARB("desat_factor"); int VertexLocation = ShaderProg->GetAttributeLocation("AVertex"); int TextureCoord0Location = ShaderProg->GetAttributeLocation("MyTextureCoord0"); int VertexColorLocation = ShaderProg->GetAttributeLocation("VertexColor"); SetTexture(GL_TEXTURE0, DeviceTexture); CHECKGL(glUniform1iARB(TextureObjectLocation, 0)); float luma[3] = {color::LumaRed, color::LumaGreen, color::LumaBlue}; CHECKGL(glUniform3fv(luma_location, 3, luma)); CHECKGL(glUniform1f(desat_factor_location, desaturation_factor)); int VPMatrixLocation = ShaderProg->GetUniformLocationARB("ViewProjectionMatrix"); Matrix4 MVPMatrix = GetOpenGLModelViewProjectionMatrix(); ShaderProg->SetUniformLocMatrix4fv((GLint) VPMatrixLocation, 1, false, (GLfloat *) & (MVPMatrix.m)); CHECKGL(glEnableVertexAttribArrayARB(VertexLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexLocation, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer)); if (TextureCoord0Location != -1) { CHECKGL(glEnableVertexAttribArrayARB(TextureCoord0Location)); CHECKGL(glVertexAttribPointerARB((GLuint) TextureCoord0Location, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 4)); } if (VertexColorLocation != -1) { CHECKGL(glEnableVertexAttribArrayARB(VertexColorLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexColorLocation, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 8)); } CHECKGL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); CHECKGL(glDisableVertexAttribArrayARB(VertexLocation)); if (TextureCoord0Location != -1) CHECKGL(glDisableVertexAttribArrayARB(TextureCoord0Location)); if (VertexColorLocation != -1) CHECKGL(glDisableVertexAttribArrayARB(VertexColorLocation)); ShaderProg->End(); } } ./NuxGraphics/GLSh_DrawFunction.h0000644000004100000410000000325213313171755017137 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef GLSH_DRAWFUNCTION_H #define GLSH_DRAWFUNCTION_H #include "GLShader.h" #include "GLShaderParameter.h" #include "NuxCore/Color.h" #include "NuxCore/Math/Matrix4.h" #include "GLDeviceObjects.h" namespace nux { class TemplateQuadBuffer; class GLSh_DrawFunction { public: GLSh_DrawFunction(); ~GLSh_DrawFunction(); void SetBackgroundColor(Color const& color); void SetTextureFunction(ObjectPtr device_texture); void Render(int x, int y, int z, int width, int height, int WindowWidth, int WindowHeight); void SetScreenPositionOffset(float x, float y); private: Color background_color_; ObjectPtr sprog; #ifndef NUX_OPENGLES_20 ObjectPtr m_AsmProg; #endif float _ScreenOffsetX, _ScreenOffsetY; ObjectPtr m_device_texture; }; } #endif // GLSH_DRAWFUNCTION_H ./NuxGraphics/IOpenGLVertexBuffer.h0000644000004100000410000000326713313171755017452 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef IOPENGLVERTEXBUFFER_H #define IOPENGLVERTEXBUFFER_H #include "IOpenGLResource.h" namespace nux { class IOpenGLResource; class IOpenGLVertexBuffer: public IOpenGLResource { NUX_DECLARE_OBJECT_TYPE(IOpenGLVertexBuffer, IOpenGLResource); public: virtual ~IOpenGLVertexBuffer(); int Lock( unsigned int OffsetToLock, unsigned int SizeToLock, void **ppbData); int Unlock(); int GetDescription(VERTEXBUFFER_DESC *desc) const { desc->Usage = _Usage; desc->Size = _Length; return OGL_OK; } void BindVertexBuffer(); unsigned int GetSize(); private: IOpenGLVertexBuffer(unsigned int Length, VBO_USAGE Usage, NUX_FILE_LINE_PROTO); unsigned int _Length; VBO_USAGE _Usage; BYTE *_MemMap; unsigned int _OffsetToLock; unsigned int _SizeToLock; friend class GpuDevice; }; } #endif // IOPENGLVERTEXBUFFER_H ./NuxGraphics/BitmapFormats.h0000644000004100000410000000610413313171755016426 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef BITMAPFORMATS_H #define BITMAPFORMATS_H namespace nux { typedef struct { const TCHAR *Name; int BlockSizeX; int BlockSizeY; int BlockSizeZ; int BlockBytes; int NumComponents; unsigned int PlatformFormat; // internal format int Format; int type; int RowMemoryAlignment; // best memory alignment in a row unsigned int Flags; bool Supported; } PixelFormatInfo; typedef struct { const TCHAR *Name; int BlockBytes; int NumComponents; unsigned int Format; int type; unsigned int Flags; bool Supported; } ReadBackPixelFormatInfo; typedef enum { BITFMT_UNKNOWN = 0, BITFMT_R8G8B8A8, // 32-bit RGBA pixel format with alpha, using 8 bits per channel. BITFMT_B8G8R8A8, // 32-bit BGRA pixel format with alpha, using 8 bits per channel. BITFMT_R8G8B8, // 24-bit RGB pixel format with 8 bits per channel. BITFMT_R5G6B5, // 16-bit RGB pixel format with 5 bits for red, 6 bits for green, and 5 bits for blue. BITFMT_D24S8, BITFMT_A8, // Gray level 8 bits BITFMT_DXT1, BITFMT_DXT2, BITFMT_DXT3, BITFMT_DXT4, BITFMT_DXT5, #ifndef NUX_OPENGLES_20 BITFMT_A8R8G8B8, // 32-bit ARGB pixel format with alpha, using 8 bits per channel. BITFMT_A8B8G8R8, // 32-bit ABGR pixel format with alpha, using 8 bits per channel. BITFMT_B8G8R8, // 24-bit RGB pixel format with 8 bits per channel. BITFMT_RGBA16F, BITFMT_RGB32F, BITFMT_RGBA32F, BITFMT_R10G10B10A2, // 32-bit pixel format using 10 bits for each color and 2 bits for alpha. BITFMT_B10G10R10A2, // 32-bit pixel format using 10 bits for each color and 2 bits for alpha. BITFMT_A2R10G10B10, // 32-bit pixel format using 10 bits for each color and 2 bits for alpha. BITFMT_A2B10G10R10, // 32-bit pixel format using 10 bits for each color and 2 bits for alpha. #endif BITFMT_END_GFX_FORMATS, } BitmapFormat; extern PixelFormatInfo GPixelFormats[]; extern ReadBackPixelFormatInfo GReadBackPixelFormats[]; } #endif // BITMAPFORMATS_H ./NuxGraphics/GLSh_DrawFunction.cpp0000644000004100000410000002245413313171755017477 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "GLResource.h" #include "GLResourceManager.h" #include "GpuDevice.h" #include "GLTemplatePrimitiveBuffer.h" #include "GraphicsEngine.h" #include "GLSh_DrawFunction.h" namespace nux { static std::string VtxShader = " \n\ uniform mat4 ViewProjectionMatrix; \n\ attribute vec4 AVertex; \n\ attribute vec4 VertexColor; \n\ void main() \n\ { \n\ gl_Position = ViewProjectionMatrix * AVertex; \n\ }"; static std::string FrgShader = " \n\ #ifdef GL_ES \n\ precision mediump float; \n\ #endif \n\ uniform sampler2D TextureFunction; \n\ uniform vec4 RectPosition; \n\ uniform vec4 RectDimension; \n\ uniform vec4 Color; \n\ void main() \n\ { \n\ float x = (gl_FragCoord.x - RectPosition.x) / RectDimension.x; \n\ float y = (gl_FragCoord.y - RectPosition.y) / RectDimension.y; \n\ float s = texture2D(TextureFunction, vec2(x, 0.0)).r; \n\ if (y > s) \n\ { \n\ s = 0.0; \n\ gl_FragColor = Color; \n\ discard; \n\ } \n\ else \n\ { \n\ s = 1.0 - (s-y) / s; \n\ gl_FragColor = Color; \n\ } \n\ }"; static std::string AsmVtxShader = "!!ARBvp1.0 \n\ ATTRIB iPos = vertex.position; \n\ PARAM mvp[4] = {state.matrix.mvp}; \n\ OUTPUT oPos = result.position; \n\ # Transform the vertex to clip coordinates. \n\ DP4 oPos.x, mvp[0], iPos; \n\ DP4 oPos.y, mvp[1], iPos; \n\ DP4 oPos.z, mvp[2], iPos; \n\ DP4 oPos.w, mvp[3], iPos; \n\ END"; std::string AsmFrgShader = "!!ARBfp1.0 \n\ PARAM RectPosition = program.local[0]; \n\ PARAM RectDimension = program.local[1]; \n\ PARAM Color = program.local[2]; \n\ TEMP temp0; \n\ TEMP temp1; \n\ TEMP tex0; \n\ SUB temp0.x, fragment.position.x, RectPosition.x; \n\ SUB temp0.y, fragment.position.y, RectPosition.y; \n\ RCP temp1.x, RectDimension.x; \n\ RCP temp1.y, RectDimension.y; \n\ MUL temp1.xy, temp0, temp1; \n\ TEX tex0, temp1, texture[0], 2D; \n\ SUB temp0, tex0.xxxx, temp1.yyyy; \n\ KIL temp0; \n\ MOV result.color, Color; \n\ END"; GLSh_DrawFunction::GLSh_DrawFunction() : _ScreenOffsetX(0) , _ScreenOffsetY(0) { if (GetGraphicsDisplay()->GetGraphicsEngine()->UsingGLSLCodePath() && (GetGraphicsDisplay()->GetGpuDevice()->GetGPUBrand() != GPU_BRAND_INTEL)) { sprog = GetGraphicsDisplay()->GetGpuDevice()->CreateShaderProgram(); sprog->LoadVertexShader(VtxShader.c_str(), NULL); sprog->LoadPixelShader(FrgShader.c_str(), NULL); sprog->Link(); } else { #ifndef NUX_OPENGLES_20 m_AsmProg = GetGraphicsDisplay()->GetGpuDevice()->CreateAsmShaderProgram(); m_AsmProg->LoadVertexShader(AsmVtxShader.c_str()); m_AsmProg->LoadPixelShader(AsmFrgShader.c_str()); m_AsmProg->Link(); #endif } } GLSh_DrawFunction::~GLSh_DrawFunction() { sprog = ObjectPtr (0); } void GLSh_DrawFunction::SetBackgroundColor(Color const& color) { background_color_ = color; } void GLSh_DrawFunction::Render(int x, int y, int z, int width, int height, int /* WindowWidth */, int WindowHeight) { float fx = x, fy = y; float VtxBuffer[] = { fx, fy, 0.0f, 1.0f, fx, fy + height, 0.0f, 1.0f, fx + width, fy + height, 0.0f, 1.0f, fx + width, fy, 0.0f, 1.0f, }; if (GetGraphicsDisplay()->GetGraphicsEngine()->UsingGLSLCodePath() && (GetGraphicsDisplay()->GetGpuDevice()->GetGPUBrand() != GPU_BRAND_INTEL)) { CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); sprog->Begin(); int VertexLocation = sprog->GetAttributeLocation("AVertex"); int VPMatrixLocation = sprog->GetUniformLocationARB("ViewProjectionMatrix"); Matrix4 MVPMatrix = GetGraphicsDisplay()->GetGraphicsEngine()->GetOpenGLModelViewProjectionMatrix(); sprog->SetUniformLocMatrix4fv((GLint) VPMatrixLocation, 1, false, (GLfloat *) & (MVPMatrix.m)); GetGraphicsDisplay()->GetGraphicsEngine()->SetTexture(GL_TEXTURE0, m_device_texture); int ColorBase = sprog->GetUniformLocationARB("Color"); int RectPosition = sprog->GetUniformLocationARB("RectPosition"); int RectDimension = sprog->GetUniformLocationARB("RectDimension"); int TextureFunction = sprog->GetUniformLocationARB("TextureFunction"); if (ColorBase != -1) CHECKGL(glUniform4fARB(ColorBase, background_color_.red, background_color_.green, background_color_.blue, background_color_.alpha)); if (RectPosition != -1) CHECKGL(glUniform4fARB(RectPosition, x + _ScreenOffsetX, WindowHeight - y - height - _ScreenOffsetY, z, 0.0f)); if (RectDimension != -1) CHECKGL(glUniform4fARB(RectDimension, width, height, 0.0f, 0.0f)); if (TextureFunction != -1) CHECKGL(glUniform1iARB(TextureFunction, 0)); CHECKGL(glEnableVertexAttribArrayARB(VertexLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexLocation, 4, GL_FLOAT, GL_FALSE, 16, VtxBuffer)); CHECKGL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); CHECKGL(glDisableVertexAttribArrayARB(VertexLocation)); sprog->End(); } #ifndef NUX_OPENGLES_20 else { CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); m_AsmProg->Begin(); CHECKGL(glMatrixMode(GL_MODELVIEW)); CHECKGL(glLoadIdentity()); CHECKGL(glLoadMatrixf((FLOAT *) GetGraphicsDisplay()->GetGraphicsEngine()->GetOpenGLModelViewMatrix().m)); CHECKGL(glMatrixMode(GL_PROJECTION)); CHECKGL(glLoadIdentity()); CHECKGL(glLoadMatrixf((FLOAT *) GetGraphicsDisplay()->GetGraphicsEngine()->GetOpenGLProjectionMatrix().m)); int VertexLocation = VTXATTRIB_POSITION; GetGraphicsDisplay()->GetGraphicsEngine()->SetTexture(GL_TEXTURE0, m_device_texture); CHECKGL(glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, x + _ScreenOffsetX, WindowHeight - y - height - _ScreenOffsetY, z, 0.0f)); CHECKGL(glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, width, height, 0.0f, 0.0f)); CHECKGL(glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 2, background_color_.red, background_color_.green, background_color_.blue, background_color_.alpha)); CHECKGL(glEnableVertexAttribArrayARB(VertexLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexLocation, 4, GL_FLOAT, GL_FALSE, 16, VtxBuffer)); CHECKGL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); CHECKGL(glDisableVertexAttribArrayARB(VertexLocation)); m_AsmProg->End(); } #endif } void GLSh_DrawFunction::SetTextureFunction(ObjectPtr device_texture) { m_device_texture = device_texture; } void GLSh_DrawFunction::SetScreenPositionOffset(float x, float y) { _ScreenOffsetX = x; _ScreenOffsetY = y; } } ./NuxGraphics/IOpenGLVertexBuffer.cpp0000644000004100000410000000676113313171755020007 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "GpuDevice.h" #include "GLDeviceObjects.h" #include "IOpenGLVertexBuffer.h" namespace nux { NUX_IMPLEMENT_OBJECT_TYPE(IOpenGLVertexBuffer); IOpenGLVertexBuffer::IOpenGLVertexBuffer(unsigned int Length, VBO_USAGE Usage, NUX_FILE_LINE_DECL) : IOpenGLResource(RTVERTEXBUFFER, NUX_FILE_LINE_PARAM) , _Length(Length) , _Usage(Usage) , _MemMap(0) , _OffsetToLock(0) , _SizeToLock(0) { CHECKGL(glGenBuffersARB(1, &_OpenGLID)); CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, _OpenGLID)); CHECKGL(glBufferDataARB(GL_ARRAY_BUFFER_ARB, _Length, NULL, Usage)); CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); GRunTimeStats.Register(this); } IOpenGLVertexBuffer::~IOpenGLVertexBuffer() { CHECKGL(glDeleteBuffersARB(1, &_OpenGLID)); _OpenGLID = 0; GRunTimeStats.UnRegister(this); } int IOpenGLVertexBuffer::Lock( unsigned int OffsetToLock, unsigned int SizeToLock, void **ppbData) { nuxAssert(SizeToLock <= _Length); nuxAssert(OffsetToLock + SizeToLock <= _Length); if (SizeToLock == 0) { if (OffsetToLock == 0) { // lock the entire buffer SizeToLock = _Length; } else { nuxDebugMsg("[IOpenGLVertexBuffer::Lock] Invalid parameters."); return OGL_INVALID_CALL; } } // If _MemMap, _OffsetToLock and _SizeToLock are not equal to zero, then we have already mapped the buffer // Unlock it before locking again. nuxAssert(_MemMap == 0); nuxAssert(_OffsetToLock == 0); nuxAssert(_SizeToLock == 0); CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, _OpenGLID)); #ifndef NUX_OPENGLES_20 // Map the Entire buffer into system memory _MemMap = (BYTE *) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); CHECKGL_MSG(glMapBufferARB); *ppbData = (void *) (_MemMap + OffsetToLock); #else _MemMap = new BYTE[SizeToLock]; *ppbData = _MemMap; #endif _OffsetToLock = OffsetToLock; _SizeToLock = SizeToLock; CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); return OGL_OK; } int IOpenGLVertexBuffer::Unlock() { CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, _OpenGLID)); #ifndef NUX_OPENGLES_20 CHECKGL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB)); #else CHECKGL(glBufferSubData(GL_ARRAY_BUFFER_ARB, _OffsetToLock, _SizeToLock, _MemMap)); delete [] _MemMap; #endif CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); _MemMap = 0; _OffsetToLock = 0; _SizeToLock = 0; return OGL_OK; } void IOpenGLVertexBuffer::BindVertexBuffer() { CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, _OpenGLID)); } unsigned int IOpenGLVertexBuffer::GetSize() { return _Length; } } ./NuxGraphics/GpuDeviceVertex.cpp0000755000004100000410000003655613313171755017303 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "GLResource.h" #include "GpuDevice.h" #include "GLDeviceObjects.h" #include "GLResourceManager.h" #include "GLTextureResourceManager.h" #include "GLVertexResourceManager.h" #include "GLDeviceFrameBufferObject.h" #include "GLTemplatePrimitiveBuffer.h" #include "GraphicsEngine.h" namespace nux { static STREAMSOURCE _StreamSource[MAX_NUM_STREAM]; ObjectPtr GpuDevice::CreateVertexBuffer(int Length, VBO_USAGE Usage) { ObjectPtr result; result.Adopt(new IOpenGLVertexBuffer(Length, Usage, NUX_TRACKER_LOCATION)); return result; } ObjectPtr GpuDevice::CreateIndexBuffer(int Length, VBO_USAGE Usage , INDEX_FORMAT Format) { ObjectPtr result; result.Adopt(new IOpenGLIndexBuffer(Length, Usage, Format, NUX_TRACKER_LOCATION)); return result; } ObjectPtr GpuDevice::CreatePixelBufferObject(int Size, VBO_USAGE Usage) { ObjectPtr result; result.Adopt(new IOpenGLPixelBufferObject(Size, Usage, NUX_TRACKER_LOCATION)); return result; } ObjectPtr GpuDevice::CreateVertexDeclaration( const VERTEXELEMENT *pVertexElements) { ObjectPtr result; result.Adopt(new IOpenGLVertexDeclaration(pVertexElements)); return result; } void GpuDevice::InvalidateVertexBuffer() { CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); } void GpuDevice::InvalidateIndexBuffer() { CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); } int GpuDevice::DrawIndexedPrimitive(ObjectPtr IndexBuffer, ObjectPtr VertexDeclaration, PRIMITIVE_TYPE PrimitiveType, int index_count) { nuxAssert(VertexDeclaration.IsValid()); if (!VertexDeclaration.IsValid()) return OGL_ERROR; int decl = 0; for (int i = 0; i < 16; i++) { VertexDeclaration->_valid_vertex_input[i] = 0; } while (VertexDeclaration->_declarations_array[decl].Stream != 0xFF) { VERTEXELEMENT vtxelement = VertexDeclaration->_declarations_array[decl]; int shader_attribute_location = VertexDeclaration->GetVertexShaderAttributeLocation(decl); if (shader_attribute_location == -1) { ++decl; continue; } VertexDeclaration->GetVertexBuffer(vtxelement.Stream)->BindVertexBuffer(); glEnableVertexAttribArrayARB(shader_attribute_location); CHECKGL(glVertexAttribPointer(shader_attribute_location, vtxelement.NumComponent, vtxelement.Type, GL_FALSE, vtxelement.stride_, (void*)vtxelement.Offset)); VertexDeclaration->_valid_vertex_input[shader_attribute_location] = 1; ++decl; } { IndexBuffer->BindIndexBuffer(); GLenum primitive = PrimitiveType; GLenum index_format = GL_UNSIGNED_SHORT; if (IndexBuffer->GetStride() == 4) index_format = GL_UNSIGNED_INT; // switch(PrimitiveType) // { // case PRIMITIVE_TYPE_POINTLIST: // ElementCount = PrimitiveCount; // break; // // case PRIMITIVE_TYPE_LINELIST: // ElementCount = PrimitiveCount * 2; // break; // // case PRIMITIVE_TYPE_LINESTRIP: // ElementCount = PrimitiveCount + 1; // break; // // case PRIMITIVE_TYPE_TRIANGLELIST: // ElementCount = PrimitiveCount * 3; // break; // // case PRIMITIVE_TYPE_TRIANGLEFAN: // case PRIMITIVE_TYPE_TRIANGLESTRIP: // ElementCount = PrimitiveCount + 2; // break; // default: // // Unknown primitive type. This should not happen. // nuxAssertMsg(0, "[GpuDevice::DrawIndexedPrimitive] Unknown Primitive Type."); // } CHECKGL(glDrawElements(primitive, index_count, index_format, 0)); } { for (int index = 0; index < 16; index++) { if (VertexDeclaration->_valid_vertex_input[index]) glDisableVertexAttribArrayARB(index); } InvalidateVertexBuffer(); InvalidateIndexBuffer(); } // for (int i = 0; i < 8; i++) // { // CHECKGL(glClientActiveTexture(GL_TEXTURE0 + i)); // CHECKGL(glDisable(GL_TEXTURE_3D)); // CHECKGL(glDisable(GL_TEXTURE_2D)); // CHECKGL(glDisable(GL_TEXTURE_1D)); // CHECKGL(glDisable(GL_TEXTURE_CUBE_MAP_ARB)); // CHECKGL(glEnable(GL_TEXTURE_2D)); // CHECKGL(glBindTexture(GL_TEXTURE_2D, 0)); // } return OGL_OK; } #ifndef NUX_OPENGLES_20 // Draw Primitive without index buffer int GpuDevice::DrawPrimitive(ObjectPtr /* VertexDeclaration */, PRIMITIVE_TYPE /* PrimitiveType */, unsigned /* vtx_start_ */, unsigned /* PrimitiveCount */) { // return OGL_OK; // glDisable(GL_CULL_FACE); // glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // // // Maps a vertex declaration usage to a vertex shader input index. // // I want to make this a static array defined outside of this function but their seems to be a problem // // with initialization... // /*static*/ // int sVertexInputMap[] = // { // 0, // ATTRIB_USAGE_DECL_POSITION // 14, // ATTRIB_USAGE_DECL_BLENDWEIGHT // 15, // ATTRIB_USAGE_DECL_BLENDINDICES // 1, // ATTRIB_USAGE_DECL_NORMAL // 4, // ATTRIB_USAGE_DECL_COLOR, ATTRIB_USAGE_DECL_COLOR0 // 5, // ATTRIB_USAGE_DECL_COLOR1 // 6, // ATTRIB_USAGE_DECL_FOGCOORD // 7, // ATTRIB_USAGE_DECL_PSIZE // 8, // ATTRIB_USAGE_DECL_TEXCOORD, ATTRIB_USAGE_DECL_TEXCOORD0 // 9, // ATTRIB_USAGE_DECL_TEXCOORD1 // 10, // ATTRIB_USAGE_DECL_TEXCOORD2 // 11, // ATTRIB_USAGE_DECL_TEXCOORD3 // 12, // ATTRIB_USAGE_DECL_TEXCOORD4 // 13, // ATTRIB_USAGE_DECL_TEXCOORD5 // 14, // ATTRIB_USAGE_DECL_TEXCOORD6 // 15, // ATTRIB_USAGE_DECL_TEXCOORD7 // 2, // ATTRIB_USAGE_DECL_TANGENT // 3, // ATTRIB_USAGE_DECL_BINORMAL // }; // // nuxAssert(VertexDeclaration.IsValid()); // // if (!VertexDeclaration.IsValid()) // return OGL_ERROR; // // int decl = 0; // // for (int i = 0; i < 16; i++) // VertexDeclaration->_valid_vertex_input[i] = 0; // // while (VertexDeclaration->_declarations_array[decl].Stream != 0xFF) // { // VERTEXELEMENT vtxelement = VertexDeclaration->_declarations_array[decl]; // int vtxInput = sVertexInputMap[vtxelement.Usage + vtxelement.UsageIndex]; // // nuxAssert(vtxInput < GetGpuInfo().GetMaxFboAttachment()); // // Eneble the vertex attribute(0 to 10) // glEnableVertexAttribArrayARB( vtxInput ); // // Bind the vertex buffer // _StreamSource[vtxelement.Stream].VertexBuffer->BindVertexBuffer(); // // CHECKGL(glVertexAttribPointer(vtxInput, // vtxelement.NumComponent, // vtxelement.Type, // GL_FALSE, // _StreamSource[vtxelement.Stream].StreamStride, // (GLvoid *) (&_StreamSource[vtxelement.Stream].StreamOffset + vtxelement.Offset))); // // VertexDeclaration->_valid_vertex_input[sVertexInputMap[vtxelement.Usage + vtxelement.UsageIndex]] = 1; // decl++; // } // // { // InvalidateIndexBuffer(); // // GLenum primitive = PrimitiveType; // int ElementCount = 0; // // switch(PrimitiveType) // { // case PRIMITIVE_TYPE_POINTLIST: // ElementCount = PrimitiveCount; // break; // // case PRIMITIVE_TYPE_LINELIST: // ElementCount = PrimitiveCount * 2; // break; // // case PRIMITIVE_TYPE_LINESTRIP: // ElementCount = PrimitiveCount + 1; // break; // // case PRIMITIVE_TYPE_TRIANGLELIST: // ElementCount = PrimitiveCount * 3; // break; // // case PRIMITIVE_TYPE_TRIANGLEFAN: // case PRIMITIVE_TYPE_TRIANGLESTRIP: // ElementCount = PrimitiveCount + 2; // break; // default: // // Unknown primitive type. This should not happen. // nuxAssertMsg(0, "[GpuDevice::DrawPrimitive] Unknown Primitive Type."); // return OGL_ERROR; // } // // CHECKGL(glDrawArrays(primitive, // ElementCount, // vtx_start_)); // } // // { // for (int index = 0; index < 16; index++) // { // if (VertexDeclaration->_valid_vertex_input[index]) // glDisableVertexAttribArrayARB( index ); // } // // InvalidateVertexBuffer(); // InvalidateIndexBuffer(); // } // // // for (int i = 0; i < 8; i++) // // { // // CHECKGL(glClientActiveTexture(GL_TEXTURE0 + i)); // // CHECKGL(glDisable(GL_TEXTURE_3D)); // // CHECKGL(glDisable(GL_TEXTURE_2D)); // // CHECKGL(glDisable(GL_TEXTURE_1D)); // // CHECKGL(glDisable(GL_TEXTURE_CUBE_MAP_ARB)); // // CHECKGL(glEnable(GL_TEXTURE_2D)); // // CHECKGL(glBindTexture(GL_TEXTURE_2D, 0)); // // } return OGL_OK; } // Draw Primitive without index buffer, and use a user pointer for the source of the stream. int GpuDevice::DrawPrimitiveUP(ObjectPtr /* VertexDeclaration */, PRIMITIVE_TYPE /* PrimitiveType */, unsigned int /* PrimitiveCount */, const void * /* pVertexStreamZeroData */, unsigned int /* VertexStreamZeroStride */) { // nuxAssertMsg(VertexDeclaration->IsUsingMoreThanStreamZero(), "[GpuDevice::DrawPrimitiveUP] Declaration is using more than stream 0."); // VERTEXELEMENT vtxelement = VertexDeclaration->GetUsage(ATTRIB_USAGE_DECL_POSITION); // int Stream = vtxelement.Stream; // // if (Stream != 0xFF) // { // glDisable(GL_CULL_FACE); // glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // // InvalidateVertexBuffer(); // InvalidateVertexBuffer(); // // size_t ptr = * (size_t *) pVertexStreamZeroData + _StreamSource[vtxelement.Stream].StreamOffset; // CHECKGL(glEnableClientState(GL_VERTEX_ARRAY)); // CHECKGL(glVertexPointer( vtxelement.NumComponent, // vtxelement.Type, // VertexStreamZeroStride, // (GLvoid *) &ptr)); // // InvalidateIndexBuffer(); // // GLenum primitive = PrimitiveType; // int ElementCount = 0; // // switch(PrimitiveType) // { // case PRIMITIVE_TYPE_POINTLIST: // ElementCount = PrimitiveCount; // break; // // case PRIMITIVE_TYPE_LINELIST: // ElementCount = PrimitiveCount * 2; // break; // // case PRIMITIVE_TYPE_LINESTRIP: // ElementCount = PrimitiveCount + 1; // break; // // case PRIMITIVE_TYPE_TRIANGLELIST: // ElementCount = PrimitiveCount * 3; // break; // // case PRIMITIVE_TYPE_TRIANGLEFAN: // case PRIMITIVE_TYPE_TRIANGLESTRIP: // ElementCount = PrimitiveCount + 2; // break; // default: // // Unknown primitive type. This should not happen. // nuxAssertMsg(0, "[GpuDevice::DrawPrimitiveUP] Unknown Primitive Type."); // return OGL_ERROR; // } // // CHECKGL(glDrawArrays(primitive, // ElementCount, // 0)); // // CHECKGL(glDisableClientState(GL_VERTEX_ARRAY)); // // } // // // for (int i = 0; i < 8; i++) // // { // // CHECKGL(glClientActiveTexture(GL_TEXTURE0 + i)); // // CHECKGL(glDisable(GL_TEXTURE_3D)); // // CHECKGL(glDisable(GL_TEXTURE_2D)); // // CHECKGL(glDisable(GL_TEXTURE_1D)); // // CHECKGL(glDisable(GL_TEXTURE_CUBE_MAP_ARB)); // // CHECKGL(glEnable(GL_TEXTURE_2D)); // // CHECKGL(glBindTexture(GL_TEXTURE_2D, 0)); // // } return OGL_OK; } #endif // // DirectX Matrix // // | 2/W 0 0 -(W+1)/W | // // | 0 -2/H 0 (H+1)/H | // // | 0 0 1 0 | // // | 0 0 0 1 | // // // // Screen Quad(0, 0, W, H) // // Normalized Coord (Xn+1)/2 * W Screen Coord // // X: 0 ---> -(1+1/W) ---> -0.5 // // X: W ---> 1-1/W ---> W-0.5 // // -(Yn-1)/2 * H // // Y: 0 ---> (1+1/H) ---> -0.5 // // Y: W ---> -1-1/H ---> H-0.5 // // // // The Matrix above is good to do quad on screen in DirectX. DirectX requires that the vertex coordinates be shifted // // by(-0.5,-0.5) in order for the center of texel to be located at the center of pixel. // // Note: OpenGL maps integral texture coordinates to the texel center // // whereas Direct3D maps integral texture coordinates to the upper, left texel corner. // // // In OpenGL we will use this matrix instead: // // | 2/W 0 0 -1 | // // | 0 -2/H 0 1 | // // | 0 0 1 0 | // // | 0 0 0 1 | // // // // Screen Quad(0, 0, W, H) // // Normalized Coord (Xn+1)/2 * W Screen Coord // // X: 0 ---> -1 ---> 0.0 // // X: W ---> 1 ---> W // // -(Yn-1)/2 * H // // Y: 0 ---> 1 ---> 0.0 // // Y: W ---> -1 int GpuDevice::SetStreamSource( unsigned int StreamNumber, ObjectPtr pStreamData, unsigned int OffsetInBytes, unsigned int Stride) { nuxAssert(StreamNumber < MAX_NUM_STREAM); _StreamSource[StreamNumber].Stream = StreamNumber; _StreamSource[StreamNumber].StreamOffset = OffsetInBytes; _StreamSource[StreamNumber].VertexBuffer = pStreamData; _StreamSource[StreamNumber].StreamStride = Stride; return OGL_OK; } } ./NuxGraphics/IOpenGLFrameBufferObject.cpp0000644000004100000410000003713013313171755020705 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "GLResource.h" #include "GraphicsDisplay.h" #include "GpuDevice.h" #include "GLDeviceObjects.h" #include "IOpenGLFrameBufferObject.h" #include "GraphicsEngine.h" namespace nux { NUX_IMPLEMENT_OBJECT_TYPE(IOpenGLFrameBufferObject); IOpenGLFrameBufferObject::IOpenGLFrameBufferObject(NUX_FILE_LINE_DECL) : IOpenGLResource(RTFRAMEBUFFEROBJECT, NUX_FILE_LINE_PARAM) , platform_support_for_depth_texture_(false) { attachment_width_ = 1; attachment_height_ = 1; _PixelFormat = BITFMT_R8G8B8A8; _IsActive = false; SetupFrameBufferObject(); GRunTimeStats.Register(this); } void IOpenGLFrameBufferObject::SetupFrameBufferObject() { if (!GetGraphicsDisplay()->GetGpuDevice()) return; auto const& gpu_info = GetGraphicsDisplay()->GetGpuDevice()->GetGpuInfo(); texture_attachment_array_.resize(gpu_info.GetMaxFboAttachment()); surface_attachment_array_.resize(gpu_info.GetMaxFboAttachment()); platform_support_for_depth_texture_ = gpu_info.Support_Depth_Buffer(); FormatFrameBufferObject(attachment_width_, attachment_height_, _PixelFormat); } IOpenGLFrameBufferObject::~IOpenGLFrameBufferObject() { // IOpenGLFrameBufferObject is an abstraction. Is does not have an opengl id. // _Fbo has an opengl id that is destroyed when the destructor is called. _OpenGLID = 0; GRunTimeStats.UnRegister(this); } int IOpenGLFrameBufferObject::FormatFrameBufferObject(int Width, int Height, BitmapFormat PixelFormat) { Deactivate(); texture_attachment_array_.clear(); surface_attachment_array_.clear(); depth_surface_attachment_ = ObjectPtr (0); stencil_surface_attachment_ = ObjectPtr (0); if ((attachment_width_ == Width) && (attachment_height_ == Height) && (_PixelFormat == PixelFormat)) return 1; // #ifndef NUX_OPENGLES_20 // _Rbo.Set(GL_DEPTH_COMPONENT, Width, Height); // #endif nuxAssertMsg(Width>0, "[IOpenGLFrameBufferObject::FormatFrameBufferObject] Invalid surface size."); nuxAssertMsg(Height>0, "[IOpenGLFrameBufferObject::FormatFrameBufferObject] Invalid surface size."); attachment_width_ = Width; attachment_height_ = Height; _PixelFormat = PixelFormat; // Clear clipping region stack EmptyClippingRegion(); return 1; } int IOpenGLFrameBufferObject::SetRenderTarget(int color_attachment_index, ObjectPtr pRenderTargetSurface) { nuxAssert(color_attachment_index < GetGraphicsDisplay()->GetGpuDevice()->GetGpuInfo().GetMaxFboAttachment()); if (pRenderTargetSurface.IsNull()) { // Invalid. texture_attachment_array_[color_attachment_index] = ObjectPtr (0); surface_attachment_array_[color_attachment_index] = ObjectPtr (0); return 0; } if (surface_attachment_array_[color_attachment_index] == pRenderTargetSurface) { // Already set. Return. return 1; } if (! (attachment_width_ == pRenderTargetSurface->GetWidth() && attachment_height_ == pRenderTargetSurface->GetHeight())) { nuxAssertMsg(0, "[IOpenGLFrameBufferObject::SetRenderTarget] Invalid surface size."); return 0; } texture_attachment_array_[color_attachment_index] = ObjectPtr (0); surface_attachment_array_[color_attachment_index] = pRenderTargetSurface; if (_IsActive) { Activate(); } return 1; } int IOpenGLFrameBufferObject::SetTextureAttachment(int color_attachment_index, ObjectPtr texture, int mip_level) { nuxAssert(color_attachment_index < GetGraphicsDisplay()->GetGpuDevice()->GetGpuInfo().GetMaxFboAttachment()); if (texture.IsNull()) { // Invalid. texture_attachment_array_[color_attachment_index] = ObjectPtr (0); surface_attachment_array_[color_attachment_index] = ObjectPtr (0); return 0; } if (!surface_attachment_array_.empty()) { if ((texture_attachment_array_[color_attachment_index] == texture) && (surface_attachment_array_[color_attachment_index] == texture->GetSurfaceLevel(mip_level))) { // Already set. Return. return 1; } } ObjectPtr surface = texture->GetSurfaceLevel(mip_level); if ((attachment_width_ != surface->GetWidth()) || (attachment_height_ != surface->GetHeight())) { nuxAssertMsg(0, "[IOpenGLFrameBufferObject::SetRenderTarget] Invalid surface size."); return 0; } texture_attachment_array_[color_attachment_index] = texture; surface_attachment_array_[color_attachment_index] = texture->GetSurfaceLevel(mip_level); if (_IsActive) { Activate(); } return 1; } ObjectPtr IOpenGLFrameBufferObject::TextureAttachment(int color_attachment_index) { return texture_attachment_array_[color_attachment_index]; } int IOpenGLFrameBufferObject::SetDepthSurface(ObjectPtr pDepthSurface) { if (!platform_support_for_depth_texture_) { return 0; } if (pDepthSurface.IsNull()) { depth_surface_attachment_ = ObjectPtr (0); stencil_surface_attachment_ = ObjectPtr (0); return 1; } if (! (attachment_width_ == pDepthSurface->GetWidth() && attachment_height_ == pDepthSurface->GetHeight())) { nuxAssertMsg(0, "The depth surface size is not compatible with the frame buffer size."); return 0; } if (depth_surface_attachment_ == pDepthSurface) return 1; // We rely on the fact that the depth texture is actually a D24_S8 texture. // That is, the surface for the depth and stencil attachment is the same. When we bound, the surface, // we explicitly bind the depth attachment and the stencil attachment with the same surface. depth_surface_attachment_ = pDepthSurface; stencil_surface_attachment_ = pDepthSurface; if (_IsActive) { Activate(); } return 1; } int IOpenGLFrameBufferObject::SetDepthTextureAttachment(ObjectPtr depth_texture, int mip_level) { if (!platform_support_for_depth_texture_) { return 0; } if (depth_texture.IsNull()) { depth_surface_attachment_ = ObjectPtr (0); stencil_surface_attachment_ = ObjectPtr (0); depth_texture_attachment_ = ObjectPtr (0); return 1; } if (depth_texture_attachment_ == depth_texture && depth_surface_attachment_ == depth_texture->GetSurfaceLevel(mip_level)) { return 1; } ObjectPtr depth_surface = depth_texture->GetSurfaceLevel(mip_level); if ((attachment_width_ != depth_surface->GetWidth()) || (attachment_height_ != depth_surface->GetHeight())) { nuxAssertMsg(0, "The depth surface size is not compatible with the frame buffer size."); return 0; } // We rely on the fact that the depth texture is actually a D24_S8 texture. // That is, the surface for the depth and stencil attachment is the same. When we bound, the surface, // we explicitly bind the depth attachment and the stencil attachment with the same surface. depth_surface_attachment_ = depth_surface; stencil_surface_attachment_ = depth_surface; depth_texture_attachment_ = depth_texture; if (_IsActive) { Activate(); } return 1; } ObjectPtr IOpenGLFrameBufferObject::DepthTextureAttachment() { return depth_texture_attachment_; } ObjectPtr IOpenGLFrameBufferObject::GetRenderTarget(int ColorAttachmentIndex) { nuxAssert(ColorAttachmentIndex < GetGraphicsDisplay()->GetGpuDevice()->GetGpuInfo().GetMaxFboAttachment()); return surface_attachment_array_[ColorAttachmentIndex]; } ObjectPtr IOpenGLFrameBufferObject::GetDepthRenderTarget() { return depth_surface_attachment_; } int IOpenGLFrameBufferObject::Activate(bool WithClippingStack) { GLuint NumBuffers = 0; _Fbo.Bind(); if (!GetGraphicsDisplay()->GetGpuDevice()) return 0; GetGraphicsDisplay()->GetGpuDevice()->SetCurrentFrameBufferObject(ObjectPtr (this)); for (int i = 0; i < GetGraphicsDisplay()->GetGpuDevice()->GetGpuInfo().GetMaxFboAttachment(); ++i) { if (surface_attachment_array_[i].IsValid()) { GLenum target = surface_attachment_array_[i]->GetSurfaceTarget(); GLenum glID = surface_attachment_array_[i]->GetOpenGLID(); GLint level = surface_attachment_array_[i]->GetMipLevel(); CHECKGL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + i, target, glID, level)); #ifndef NUX_OPENGLES_20 CHECKGL(glDrawBuffer(GL_COLOR_ATTACHMENT0 + i)); #endif NumBuffers++; } else { CHECKGL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, 0, 0)); } } if (platform_support_for_depth_texture_) { if (depth_surface_attachment_.IsValid()) { GLenum target = depth_surface_attachment_->GetSurfaceTarget(); GLenum glID = depth_surface_attachment_->GetOpenGLID(); GLint level = depth_surface_attachment_->GetMipLevel(); CHECKGL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, target, glID, level)); } else { CHECKGL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0)); // On the PC you need to bing the same D24S8 surface to the depth and the stencil attachment. } } else { CHECKGL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0)); } nuxAssert( _Fbo.IsValid() == true ); if (GetGraphicsDisplay()->GetGraphicsEngine()) GetGraphicsDisplay()->GetGraphicsEngine()->SetViewport(0, 0, attachment_width_, attachment_height_); if (WithClippingStack) ApplyClippingRegion(); _IsActive = true; return 1; } // Restore the original opengl back buffer as defined when creating the opengl context(color + depth + stencil). int IOpenGLFrameBufferObject::Deactivate() { #ifdef NUX_OPENGLES_20 GLenum binding = GL_FRAMEBUFFER; #else GLenum binding = GL_DRAW_FRAMEBUFFER_EXT; #endif CHECKGL(glBindFramebufferEXT( binding, 0 )); #ifndef NUX_OPENGLES_20 CHECKGL(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0)); #endif if (GetGraphicsDisplay()->GetGpuDevice()) GetGraphicsDisplay()->GetGpuDevice()->SetCurrentFrameBufferObject(ObjectPtr (0)); if (GetGraphicsDisplay()->GetGraphicsEngine()) GetGraphicsDisplay()->GetGraphicsEngine()->SetScissor(0, 0, attachment_width_, attachment_height_); _IsActive = false; return 1; } void IOpenGLFrameBufferObject::PushClippingRegion(Rect const& rect) { Rect r0; if (GetGraphicsDisplay()->GetGraphicsEngine()) { r0 = GetGraphicsDisplay()->GetGraphicsEngine()->ModelViewXFormRect(rect); } Rect current_clip_rect; unsigned int stacksize = (unsigned int) _ClippingRegionStack.size(); if (stacksize == 0) { current_clip_rect.Set(0, 0, attachment_width_, attachment_height_); } else { current_clip_rect = _ClippingRegionStack[stacksize-1]; } Rect r1; if (GetGraphicsDisplay()->GetGraphicsEngine()) r1 = GetGraphicsDisplay()->GetGraphicsEngine()->GetViewportRect(); r0.OffsetPosition(r1.x, attachment_height_ - (r1.y + r1.GetHeight())); Rect Intersection = current_clip_rect.Intersect(r0); if (!Intersection.IsNull()) { _clipping_rect = Intersection; _ClippingRegionStack.push_back(Intersection); SetOpenGLClippingRectangle(Intersection.x + GetGraphicsDisplay()->GetGraphicsEngine()->GetViewportX(), attachment_height_ - Intersection.y - Intersection.GetHeight() - GetGraphicsDisplay()->GetGraphicsEngine()->GetViewportY(), Intersection.GetWidth(), Intersection.GetHeight()); } else { _clipping_rect.Set(0, 0, 0, 0); _ClippingRegionStack.push_back(Rect(0, 0, 0, 0)); SetOpenGLClippingRectangle(0, 0, 0, 0); } } void IOpenGLFrameBufferObject::PopClippingRegion() { _ClippingRegionStack.pop_back(); int stacksize = (int) _ClippingRegionStack.size(); if (stacksize == 0) { _clipping_rect.Set(0, 0, attachment_width_, attachment_height_); SetOpenGLClippingRectangle(0, 0, attachment_width_, attachment_height_); } else { _clipping_rect = _ClippingRegionStack [stacksize-1]; Rect current_clip_rect = _ClippingRegionStack [stacksize-1]; SetOpenGLClippingRectangle(current_clip_rect.x, attachment_height_ - current_clip_rect.y - current_clip_rect.GetHeight(), current_clip_rect.GetWidth(), current_clip_rect.GetHeight()); } } void IOpenGLFrameBufferObject::EmptyClippingRegion() { _ClippingRegionStack.clear(); { _clipping_rect.Set(0, 0, attachment_width_, attachment_height_); SetOpenGLClippingRectangle(0, 0, attachment_width_, attachment_height_); } } void IOpenGLFrameBufferObject::ApplyClippingRegion() { int stacksize = (int) _ClippingRegionStack.size(); if (stacksize == 0) { _clipping_rect.Set(0, 0, attachment_width_, attachment_height_); SetOpenGLClippingRectangle(0, 0, attachment_width_, attachment_height_); } else { _clipping_rect = _ClippingRegionStack [stacksize-1]; Rect current_clip_rect = _ClippingRegionStack [stacksize-1]; SetOpenGLClippingRectangle(current_clip_rect.x, attachment_height_ - current_clip_rect.y - current_clip_rect.GetHeight(), current_clip_rect.GetWidth(), current_clip_rect.GetHeight()); } } void IOpenGLFrameBufferObject::SetClippingRectangle(const Rect &rect) { if (GetGraphicsDisplay()->GetGraphicsEngine()) { _clipping_rect = rect; GetGraphicsDisplay()->GetGraphicsEngine()->SetScissor(rect.x, attachment_height_ - rect.y - rect.height, rect.width, rect.height); } } void IOpenGLFrameBufferObject::SetOpenGLClippingRectangle(int x, int y, int width, int height) { if (GetGraphicsDisplay()->GetGraphicsEngine()) { _clipping_rect.Set(x, y, width, height); GetGraphicsDisplay()->GetGraphicsEngine()->SetScissor(x, y, width, height); } } Rect IOpenGLFrameBufferObject::GetClippingRegion() { return _clipping_rect; // unsigned int stacksize = (unsigned int) _ClippingRegionStack.size(); // // if (stacksize == 0) // { // return Rect(0, 0, attachment_width_, attachment_height_); // } // else // { // Rect r = _ClippingRegionStack [stacksize-1]; // return r; // } } int IOpenGLFrameBufferObject::GetNumberOfClippingRegions() const { return _ClippingRegionStack.size(); } } ./NuxGraphics/MeshFileLoader-OBJ.cpp0000644000004100000410000001063713313171755017452 0ustar www-datawww-data #include "GLResource.h" #include "MeshFileLoader-OBJ.h" #include "MeshData.h" #include "NuxCore/Math/Vector3.h" #include "NuxCore/Math/Vector2.h" namespace nux { #define TOKEN_VERTEX_POS "v" #define TOKEN_VERTEX_NOR "vn" #define TOKEN_VERTEX_TEX "vt" #define TOKEN_FACE "f" struct ObjMeshVertex { nux::Vector3 pos; nux::Vector2 texcoord; nux::Vector3 normal; }; /* This is a triangle, that we can render */ struct ObjMeshFace { ObjMeshVertex vertices[3]; }; /* This contains a list of triangles */ struct ObjMesh { std::vector faces; }; /* Internal structure */ struct _ObjMeshFaceIndex { int pos_index[3]; int tex_index[3]; int nor_index[3]; }; MeshData* LoadMeshFile_OBJ(const char* filename) { std::vector positions; std::vector texcoords; std::vector normals; std::vector<_ObjMeshFaceIndex> faces; /** * Load file, parse it * Lines beginning with: * '#' are comments can be ignored * 'v' are vertices positions(3 floats that can be positive or negative) * 'vt' are vertices texcoords(2 floats that can be positive or negative) * 'vn' are vertices normals (3 floats that can be positive or negative) * 'f' are faces, 3 values that contain 3 values which are separated by / and */ std::ifstream filestream; filestream.open(filename); std::string line_stream; // No longer depending on char arrays thanks to: Dale Weiler while (std::getline(filestream, line_stream)) { std::stringstream str_stream(line_stream); std::string type_str; str_stream >> type_str; if (type_str == TOKEN_VERTEX_POS) { nux::Vector4 pos; str_stream >> pos.x >> pos.y >> pos.z; pos.w = 1.0f; positions.push_back(pos); } else if (type_str == TOKEN_VERTEX_TEX) { nux::Vector2 tex; str_stream >> tex.x >> tex.y; texcoords.push_back(tex); } else if (type_str == TOKEN_VERTEX_NOR) { nux::Vector3 nor; str_stream >> nor.x >> nor.y >> nor.z; normals.push_back(nor); } else if (type_str == TOKEN_FACE) { _ObjMeshFaceIndex face_index; char interupt; for (int i = 0; i < 3; ++i) { str_stream >> face_index.pos_index[i] >> interupt >> face_index.tex_index[i] >> interupt >> face_index.nor_index[i]; } faces.push_back(face_index); } } // Explicit closing of the file filestream.close(); nux::MeshData* md = new nux::MeshData; md->Allocate(faces.size(), nux::NUX_MESH_TRIANGLE, 3*faces.size(), 16 + 12 + 8); //md->_mesh_primitive_type = nux::NuxMeshPrimitiveType::NUX_MESH_TRIANGLE; size_t i = 0; float* vertex_buffer = (float*)md->_vertex_data; // for (i = 0; i < positions.size(); i++) // { // vertex_buffer[9*i + 0] = positions[i].x; // vertex_buffer[9*i + 1] = positions[i].y; // vertex_buffer[9*i + 2] = positions[i].z; // vertex_buffer[9*i + 3] = positions[i].w; // // vertex_buffer[9*i + 4] = normals[i].x; // vertex_buffer[9*i + 5] = normals[i].y; // vertex_buffer[9*i + 6] = normals[i].z; // // vertex_buffer[9*i + 7] = texcoords[i].x; // vertex_buffer[9*i + 8] = texcoords[i].y; // } int* index_buffer = (int*)md->_index_data; for (i = 0; i < faces.size(); i++) { index_buffer[3*i + 0] = 3*i + 0; //faces[i].pos_index[0]-1; index_buffer[3*i + 1] = 3*i + 1; //faces[i].pos_index[1]-1; index_buffer[3*i + 2] = 3*i + 2; //faces[i].pos_index[2]-1; for (int j = 0; j < 3; j++) { int vi = faces[i].pos_index[j]-1; int ni = faces[i].nor_index[j]-1; int ti = faces[i].tex_index[j]-1; vertex_buffer[27*i + 9*j + 0] = positions[vi].x; vertex_buffer[27*i + 9*j + 1] = positions[vi].y; vertex_buffer[27*i + 9*j + 2] = positions[vi].z; vertex_buffer[27*i + 9*j + 3] = positions[vi].w; vertex_buffer[27*i + 9*j + 4] = normals[ni].x; vertex_buffer[27*i + 9*j + 5] = normals[ni].y; vertex_buffer[27*i + 9*j + 6] = normals[ni].z; vertex_buffer[27*i + 9*j + 7] = texcoords[ti].x; vertex_buffer[27*i + 9*j + 8] = texcoords[ti].y; } } return md; } } ./NuxGraphics/Events.cpp0000644000004100000410000001425613313171755015464 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "GLResource.h" #include "Events.h" namespace nux { MouseButton GetEventButton(unsigned long button_state) { if ((button_state & NUX_EVENT_BUTTON1_DOWN) || (button_state & NUX_EVENT_BUTTON1_UP)) return NUX_MOUSE_BUTTON1; else if ((button_state & NUX_EVENT_BUTTON2_DOWN) || (button_state & NUX_EVENT_BUTTON2_UP)) return NUX_MOUSE_BUTTON2; else if ((button_state & NUX_EVENT_BUTTON3_DOWN) || (button_state & NUX_EVENT_BUTTON3_UP)) return NUX_MOUSE_BUTTON3; else if ((button_state & NUX_EVENT_BUTTON4_DOWN) || (button_state & NUX_EVENT_BUTTON4_UP)) return NUX_MOUSE_BUTTON4; return NUX_INVALID_MOUSE_BUTTON; } bool GetButtonState(unsigned long button_state, MouseButton button) { if (button == NUX_MOUSE_BUTTON1) return (button_state & NUX_STATE_BUTTON1_DOWN); else if (button == NUX_MOUSE_BUTTON2) return (button_state & NUX_STATE_BUTTON2_DOWN); else if (button == NUX_MOUSE_BUTTON3) return (button_state & NUX_STATE_BUTTON3_DOWN); else if (button == NUX_MOUSE_BUTTON4) return (button_state & NUX_STATE_BUTTON4_DOWN); return false; } bool GetKeyModifierState(unsigned long key_modifiers_states, KeyModifier key_modifier) { return((key_modifiers_states & key_modifier) != 0); } Event::Event() { Memset(text, 0, sizeof(text)); dtext = nullptr; for (int i = 0; i < NUX_MAX_VK; i++) { VirtualKeycodeState[i] = 0; } ascii_code = 0; virtual_code = 0; key_modifiers = 0; key_repeat_count = 0; mouse_state = 0; x = -1; y = -1; x_root = 0; y_root = 0; dx = 0; dy = 0; clicks = 0; is_click = 0; wheel_delta = 0; #if defined(NUX_OS_WINDOWS) win32_keycode = 0; win32_keysym = 0; #endif #if defined(USE_X11) x11_keycode = 0; x11_keysym = 0; x11_timestamp = 0; x11_window = 0; x11_key_state = 0; #endif //Application = 0; } void Event::Reset() { type = NUX_NO_EVENT; Memset(text, 0, sizeof(text)); #if defined(NUX_OS_WINDOWS) win32_keycode = 0; win32_keysym = 0; #endif #if defined(USE_X11) x11_keycode = 0; x11_keysym = 0; x11_key_state = 0; #endif delete[] dtext; dtext = nullptr; key_repeat_count = 0; key_modifiers = 0; wheel_delta = 0; } int Event::GetX() const { return x; } int Event::GetY() const { return y; } int Event::GetRootX() const { return x_root; } int Event::GetRootY() const { return y_root; } int Event::GetDeltaX() const { return dx; } int Event::GetDeltaY() const { return dy; } unsigned long Event::GetKeyState() const { return key_modifiers; } unsigned long Event::GetMouseState() const { return mouse_state; } MouseButton Event::GetEventButton() const { if ((mouse_state & NUX_EVENT_BUTTON1_DOWN) || (mouse_state & NUX_EVENT_BUTTON1_UP)) return NUX_MOUSE_BUTTON1; else if ((mouse_state & NUX_EVENT_BUTTON2_DOWN) || (mouse_state & NUX_EVENT_BUTTON2_UP)) return NUX_MOUSE_BUTTON2; else if ((mouse_state & NUX_EVENT_BUTTON3_DOWN) || (mouse_state & NUX_EVENT_BUTTON3_UP)) return NUX_MOUSE_BUTTON3; else if ((mouse_state & NUX_EVENT_BUTTON4_DOWN) || (mouse_state & NUX_EVENT_BUTTON4_UP)) return NUX_MOUSE_BUTTON4; return NUX_INVALID_MOUSE_BUTTON; } bool Event::GetButtonState(MouseButton button) const { if (button == 1) return (mouse_state & NUX_STATE_BUTTON1_DOWN); else if (button == 2) return (mouse_state & NUX_STATE_BUTTON2_DOWN); else if (button == 3) return (mouse_state & NUX_STATE_BUTTON3_DOWN); else if (button == 4) return (mouse_state & NUX_STATE_BUTTON4_DOWN); return false; } bool Event::GetKeyModifierState(KeyModifier key_modifier) const { return((key_modifiers & key_modifier) != 0); } //! Return virtual key code of the key that has triggered the last event. /*! Return virtual key code of the key that has triggered the last event. @return the virtual key code. */ unsigned long Event::GetKeySym() const { #if defined(NUX_OS_WINDOWS) return win32_keysym; #elif defined(USE_X11) return x11_keysym; #else return 0; #endif } unsigned short Event::GetKeyRepeatCount() const { return key_repeat_count; } const char* Event::GetText() const { return dtext; } //! Return the state of the Virtual key /*! Return the state of the Virtual key. @param VirtualKey virtual key code. @return 1 if the key is pressed, 0 if the key is released. */ unsigned long Event::GetVirtualKeyState(unsigned long VirtualKey) const { if (VirtualKey >= NUX_MAX_VK) return 0; if (VirtualKey <= 0) return 0; return VirtualKeycodeState[VirtualKey]; } bool Event::IsShiftDown() const { return (key_modifiers & NUX_STATE_SHIFT); } bool Event::IsControlDown() const { return (key_modifiers & NUX_STATE_CTRL); } bool Event::IsCapsLockDown() const { return (key_modifiers & NUX_STATE_CAPS_LOCK); } bool Event::IsAltDown() const { return (key_modifiers & NUX_STATE_ALT); } bool Event::IsNumLockDown() const { return (key_modifiers & NUX_STATE_NUMLOCK); } bool Event::IsScrollLockDown() const { return (key_modifiers & NUX_STATE_SCROLLLOCK); } bool Event::IsSuperKeyDown() const { return (key_modifiers & NUX_STATE_SCROLLLOCK); } } ./NuxGraphics/IOpenGLAsmShader.cpp0000644000004100000410000002310313313171755017234 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "GLResource.h" #include "GraphicsDisplay.h" #include "GpuDevice.h" #include "GLDeviceObjects.h" #include "IOpenGLAsmShader.h" #include "NuxCore/Logger.h" namespace nux { DECLARE_LOGGER(logger, "nux.graphics"); NUX_IMPLEMENT_OBJECT_TYPE(IOpenGLAsmShader); NUX_IMPLEMENT_OBJECT_TYPE(IOpenGLAsmVertexShader); NUX_IMPLEMENT_OBJECT_TYPE(IOpenGLAsmPixelShader); NUX_IMPLEMENT_OBJECT_TYPE(IOpenGLAsmShaderProgram); bool ExtractShaderString3(const std::string& ShaderToken, const std::string& ShaderSource, std::string& RetSource, std::string ShaderPreprocessorDefines); IOpenGLAsmShader::IOpenGLAsmShader(std::string const& shader_name, GLint shader_type, OpenGLResourceType ResourceType) : IOpenGLResource(ResourceType) , shader_name_(shader_name) , shader_type_(shader_type) , compiled_and_ready_(false) { #ifndef NUX_OPENGLES_20 CHECKGL(glGenProgramsARB(1, GetOpenGLIDAsInParam())); #endif } IOpenGLAsmShader::~IOpenGLAsmShader() { #ifndef NUX_OPENGLES_20 CHECKGL(glDeleteProgramsARB(1, GetOpenGLIDAsInParam())); #endif } void IOpenGLAsmShader::SetShaderCode(std::string const& shader_code) { compiled_and_ready_ = false; shader_code_ = shader_code; } bool IOpenGLAsmShader::IsValid() { return compiled_and_ready_; } bool IOpenGLAsmShader::Compile() { if (compiled_and_ready_) { return true; } #ifndef NUX_OPENGLES_20 if (shader_code_.empty()) { LOG_DEBUG(logger) << shader_name_ << " source code is empty."; } CHECKGL(glBindProgramARB(shader_type_, GetOpenGLID())); glProgramStringARB(shader_type_, GL_PROGRAM_FORMAT_ASCII_ARB, shader_code_.size(), shader_code_.c_str()); if (GL_INVALID_OPERATION == glGetError()) { // Find the error position GLint errPos; glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos ); // Print implementation-dependent program // errors and warnings string. LOG_ERROR(logger) << "Error in " << shader_name_ << " at position: " << errPos << "\n\t" << glGetString(GL_PROGRAM_ERROR_STRING_ARB); return false; } compiled_and_ready_ = true; #endif return compiled_and_ready_; } IOpenGLAsmVertexShader::IOpenGLAsmVertexShader() #ifndef NUX_OPENGLES_20 : IOpenGLAsmShader("VertexProgram", GL_VERTEX_PROGRAM_ARB, RT_GLSL_VERTEXSHADER) #else : IOpenGLAsmShader("VertexProgram", 0, RT_GLSL_VERTEXSHADER) #endif { } IOpenGLAsmPixelShader::IOpenGLAsmPixelShader() #ifndef NUX_OPENGLES_20 : IOpenGLAsmShader("PixelProgram", GL_FRAGMENT_PROGRAM_ARB, RT_GLSL_PIXELSHADER) #else : IOpenGLAsmShader("PixelProgram", 0, RT_GLSL_PIXELSHADER) #endif { } IOpenGLAsmShaderProgram::IOpenGLAsmShaderProgram(std::string ShaderProgramName) : IOpenGLResource(RT_GLSL_SHADERPROGRAM) , _ShaderProgramName(ShaderProgramName) { _OpenGLID = 0; m_AsmVertexProgram = GetGraphicsDisplay()->GetGpuDevice()->CreateAsmVertexShader(); m_AsmFragmentProgram = GetGraphicsDisplay()->GetGpuDevice()->CreateAsmPixelShader(); } IOpenGLAsmShaderProgram::~IOpenGLAsmShaderProgram() { _OpenGLID = 0; } void IOpenGLAsmShaderProgram::LoadIShaderFile(const char *ShaderFileName) { nuxAssertMsg(ShaderFileName, "[IOpenGLAsmShaderProgram::LoadIShaderFile] Invalid shader file name."); NUX_RETURN_IF_NULL(ShaderFileName); std::string SourceCode; LoadFileToString(SourceCode, ShaderFileName); LoadIShader(&SourceCode[0]); } void IOpenGLAsmShaderProgram::LoadIShader(const char* ShaderCode) { nuxAssertMsg(ShaderCode, "[IOpenGLAsmShaderProgram::LoadIShader] Invalid shader code."); NUX_RETURN_IF_NULL(ShaderCode); std::string VertexShaderSource; ExtractShaderString3("[Vertex Shader]", ShaderCode, VertexShaderSource, std::string("")); std::string PixelShaderSource; ExtractShaderString3("[Fragment Shader]", ShaderCode, PixelShaderSource, std::string("")); m_AsmVertexProgram->SetShaderCode(&VertexShaderSource[0]); m_AsmFragmentProgram->SetShaderCode(&PixelShaderSource[0]); m_AsmVertexProgram->Compile(); m_AsmFragmentProgram->Compile(); } void IOpenGLAsmShaderProgram::LoadVertexShader(const char* glslshader) { nuxAssertMsg(glslshader, "[IOpenGLAsmShaderProgram::LoadVertexShader] Invalid shader code."); NUX_RETURN_IF_NULL(glslshader); m_AsmVertexProgram->SetShaderCode(glslshader); m_AsmVertexProgram->Compile(); } void IOpenGLAsmShaderProgram::LoadPixelShader(const char *glslshader) { nuxAssertMsg(glslshader, "[IOpenGLAsmShaderProgram::LoadPixelShader] Invalid shader code."); NUX_RETURN_IF_NULL(glslshader); m_AsmFragmentProgram->SetShaderCode(glslshader); m_AsmFragmentProgram->Compile(); } void IOpenGLAsmShaderProgram::Link() { m_AsmVertexProgram->Compile(); m_AsmFragmentProgram->Compile(); } bool IOpenGLAsmShaderProgram::IsValid() { if (m_AsmVertexProgram->IsValid() && m_AsmFragmentProgram->IsValid()) return true; return false; } void IOpenGLAsmShaderProgram::Begin(void) { #ifndef NUX_OPENGLES_20 CHECKGL(glEnable(GL_VERTEX_PROGRAM_ARB)); CHECKGL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, m_AsmVertexProgram->GetOpenGLID())); CHECKGL(glEnable(GL_FRAGMENT_PROGRAM_ARB)); CHECKGL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_AsmFragmentProgram->GetOpenGLID())); #endif } void IOpenGLAsmShaderProgram::End(void) { #ifndef NUX_OPENGLES_20 CHECKGL(glDisable(GL_VERTEX_PROGRAM_ARB)); CHECKGL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0)); CHECKGL(glDisable(GL_FRAGMENT_PROGRAM_ARB)); CHECKGL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, 0)); #endif } #ifndef NUX_OPENGLES_20 void IOpenGLAsmShaderProgram::SetVertexEnvParameter4dARB(unsigned int index, double x, double y, double z, double w) { CHECKGL(glProgramEnvParameter4dARB(GL_VERTEX_PROGRAM_ARB, index, x, y, z, w)); } void IOpenGLAsmShaderProgram::SetVertexEnvParameter4dvARB(unsigned int index, const double *params) { CHECKGL(glProgramEnvParameter4dvARB(GL_VERTEX_PROGRAM_ARB, index, params)); } void IOpenGLAsmShaderProgram::SetVertexEnvParameter4fARB(unsigned int index, float x, float y, float z, float w) { CHECKGL(glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB, index, x, y, z, w)); } void IOpenGLAsmShaderProgram::SetVertexEnvParameter4fvARB(unsigned int index, const float *params) { CHECKGL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, index, params)); } void IOpenGLAsmShaderProgram::SetVertexLocalParameter4dARB(unsigned int index, double x, double y, double z, double w) { CHECKGL(glProgramEnvParameter4dARB(GL_VERTEX_PROGRAM_ARB, index, x, y, z, w)); } void IOpenGLAsmShaderProgram::SetVertexLocalParameter4dvARB(unsigned int index, const double *params) { CHECKGL(glProgramEnvParameter4dvARB(GL_VERTEX_PROGRAM_ARB, index, params)); } void IOpenGLAsmShaderProgram::SetVertexLocalParameter4fARB(unsigned int index, float x, float y, float z, float w) { CHECKGL(glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB, index, x, y, z, w)); } void IOpenGLAsmShaderProgram::SetVertexLocalParameter4fvARB(unsigned int index, const float *params) { CHECKGL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, index, params)); } void IOpenGLAsmShaderProgram::SetFragmentEnvParameter4dARB(unsigned int index, double x, double y, double z, double w) { CHECKGL(glProgramEnvParameter4dARB(GL_FRAGMENT_PROGRAM_ARB, index, x, y, z, w)); } void IOpenGLAsmShaderProgram::SetFragmentEnvParameter4dvARB(unsigned int index, const double *params) { CHECKGL(glProgramEnvParameter4dvARB(GL_FRAGMENT_PROGRAM_ARB, index, params)); } void IOpenGLAsmShaderProgram::SetFragmentEnvParameter4fARB(unsigned int index, float x, float y, float z, float w) { CHECKGL(glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, index, x, y, z, w)); } void IOpenGLAsmShaderProgram::SetFragmentEnvParameter4fvARB(unsigned int index, const float *params) { CHECKGL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, index, params)); } void IOpenGLAsmShaderProgram::SetFragmentLocalParameter4dARB(unsigned int index, double x, double y, double z, double w) { CHECKGL(glProgramEnvParameter4dARB(GL_FRAGMENT_PROGRAM_ARB, index, x, y, z, w)); } void IOpenGLAsmShaderProgram::SetFragmentLocalParameter4dvARB(unsigned int index, const double *params) { CHECKGL(glProgramEnvParameter4dvARB(GL_FRAGMENT_PROGRAM_ARB, index, params)); } void IOpenGLAsmShaderProgram::SetFragmentLocalParameter4fARB(unsigned int index, float x, float y, float z, float w) { CHECKGL(glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, index, x, y, z, w)); } void IOpenGLAsmShaderProgram::SetFragmentLocalParameter4fvARB(unsigned int index, const float *params) { CHECKGL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, index, params)); } #endif } ./NuxGraphics/GpuDevice.h0000755000004100000410000004172613313171755015545 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef GLDEVICEFACTORY_H #define GLDEVICEFACTORY_H #include "GLResource.h" #include "GLDeviceFrameBufferObject.h" #include "GLDeviceObjects.h" #include "GLTextureStates.h" #include "GLTemplatePrimitiveBuffer.h" namespace nux { class GpuRenderStates; //! Brand of GPUs. typedef enum { GPU_VENDOR_UNKNOWN = 0, GPU_BRAND_AMD, GPU_BRAND_NVIDIA, GPU_BRAND_INTEL, } GpuBrand; template class ObjectPtr; struct STREAMSOURCE { WORD Stream; ObjectPtr VertexBuffer; unsigned short StreamOffset; unsigned short StreamStride; STREAMSOURCE() { Stream = 0; //VertexBuffer = 0; StreamOffset = 0; StreamStride = 0; } void ResetStreamSource() { Stream = 0; StreamOffset = 0; VertexBuffer = ObjectPtr (0); StreamStride = 0; } }; // GPU Graphics information. class GpuInfo { public: GpuInfo(); bool SupportOpenGL11() const {return _support_opengl_version_11;} bool SupportOpenGL12() const {return _support_opengl_version_12;} bool SupportOpenGL13() const {return _support_opengl_version_13;} bool SupportOpenGL14() const {return _support_opengl_version_14;} bool SupportOpenGL15() const {return _support_opengl_version_15;} bool SupportOpenGL20() const {return _support_opengl_version_20;} bool SupportOpenGL21() const {return _support_opengl_version_21;} bool SupportOpenGL30() const {return _support_opengl_version_30;} bool SupportOpenGL31() const {return _support_opengl_version_31;} bool SupportOpenGL32() const {return _support_opengl_version_32;} bool SupportOpenGL33() const {return _support_opengl_version_33;} bool SupportOpenGL40() const {return _support_opengl_version_40;} bool SupportOpenGL41() const {return _support_opengl_version_41;} bool Support_EXT_Swap_Control() const {return _support_ext_swap_control;} bool Support_ARB_Texture_Rectangle() const {return _support_arb_texture_rectangle;} bool Support_ARB_Vertex_Program() const {return _support_arb_vertex_program;} bool Support_ARB_Fragment_Program() const {return _support_arb_fragment_program;} bool Support_ARB_Shader_Objects() const {return _support_arb_shader_objects;} bool Support_ARB_Vertex_Shader() const {return _support_arb_vertex_shader;} bool Support_ARB_Fragment_Shader() const {return _support_arb_fragment_shader;} bool Support_ARB_Vertex_Buffer_Object() const {return _support_arb_vertex_buffer_object;} bool Support_ARB_Texture_Non_Power_Of_Two() const {return _support_arb_texture_non_power_of_two;} bool Support_EXT_Framebuffer_Object() const {return _support_ext_framebuffer_object;} bool Support_EXT_Draw_Range_Elements() const {return _support_ext_draw_range_elements;} bool Support_EXT_Stencil_Two_Side() const {return _support_ext_stencil_two_side;} bool Support_EXT_Texture_Rectangle() const {return _support_ext_texture_rectangle;} bool Support_NV_Texture_Rectangle() const {return _support_nv_texture_rectangle;} bool Support_ARB_Pixel_Buffer_Object() const {return _support_arb_pixel_buffer_object;} bool Support_EXT_Blend_Equation_Separate() const {return _support_ext_blend_equation_separate;} bool Support_Depth_Buffer() const {return _support_depth_buffer;} #ifndef NUX_OPENGLES_20 bool Support_EXT_Texture_sRGB() const {return _support_ext_texture_srgb;} bool Support_EXT_Texture_Decode() const {return _support_ext_texture_srgb_decode;} bool Support_EXT_Framebuffer_sRGB() const {return _support_ext_framebuffer_srgb;} bool Support_ARB_Framebuffer_sRGB() const {return _support_arb_framebuffer_srgb;} #endif int GetMaxFboAttachment() const {return _opengl_max_fb_attachment;} int GetMaxTextureSize() const {return _opengl_max_texture_size;} private: void Setup(); bool _support_opengl_version_11; bool _support_opengl_version_12; bool _support_opengl_version_13; bool _support_opengl_version_14; bool _support_opengl_version_15; bool _support_opengl_version_20; bool _support_opengl_version_21; bool _support_opengl_version_30; bool _support_opengl_version_31; bool _support_opengl_version_32; bool _support_opengl_version_33; bool _support_opengl_version_40; bool _support_opengl_version_41; int _opengl_max_texture_size; int _opengl_max_texture_units; int _opengl_max_texture_coords; int _opengl_max_texture_image_units; int _opengl_max_fb_attachment; int _opengl_max_vertex_attributes; bool _support_ext_swap_control; bool _support_arb_vertex_program; bool _support_arb_fragment_program; bool _support_arb_shader_objects; bool _support_arb_vertex_shader; bool _support_arb_fragment_shader; bool _support_arb_vertex_buffer_object; bool _support_arb_texture_non_power_of_two; bool _support_ext_framebuffer_object; bool _support_ext_draw_range_elements; bool _support_ext_stencil_two_side; bool _support_ext_texture_rectangle; bool _support_arb_texture_rectangle; //!< Promoted from GL_EXT_TEXTURE_RECTANGLE to ARB. bool _support_nv_texture_rectangle; bool _support_arb_pixel_buffer_object; bool _support_ext_blend_equation_separate; bool _support_depth_buffer; #ifndef NUX_OPENGLES_20 bool _support_ext_texture_srgb; bool _support_ext_texture_srgb_decode; bool _support_ext_framebuffer_srgb; bool _support_arb_framebuffer_srgb; #endif friend class GpuDevice; }; //! The interface to the GPU. /*! This is the object that serves as the interface between the program and the GPU device. The GpuDevice creates the opengl primitives used for rendering. */ class GpuDevice { private: static STREAMSOURCE _StreamSource[MAX_NUM_STREAM]; public: ObjectPtr CreateTexture( int Width, int Height, int Levels, BitmapFormat PixelFormat, NUX_FILE_LINE_PROTO); ObjectPtr CreateTexture2DFromID(int id, int Width, int Height, int Levels, BitmapFormat PixelFormat, NUX_FILE_LINE_PROTO); ObjectPtr CreateRectangleTexture( int Width , int Height , int Levels , BitmapFormat PixelFormat, NUX_FILE_LINE_PROTO); ObjectPtr CreateCubeTexture( int EdgeLength , int Levels , BitmapFormat PixelFormat, NUX_FILE_LINE_PROTO); ObjectPtr CreateVolumeTexture( int Width , int Height , int Depth , int Levels , BitmapFormat PixelFormat, NUX_FILE_LINE_PROTO); ObjectPtr CreateAnimatedTexture( int Width , int Height , int Depth , BitmapFormat PixelFormat); ObjectPtr CreateVertexBuffer( int Length , VBO_USAGE Usage); ObjectPtr CreateIndexBuffer( int Length , VBO_USAGE Usage // Dynamic or WriteOnly , INDEX_FORMAT Format); ObjectPtr CreatePixelBufferObject(int Size, VBO_USAGE Usage); ObjectPtr CreateQuery( QUERY_TYPE Type); ObjectPtr CreateVertexDeclaration( const VERTEXELEMENT *pVertexElements); //! Create an return an ObjectPtr that encapsulates OpenGL framebuffer object. /*! Create an return an ObjectPtr that encapsulates OpenGL framebuffer object. This function has side effects. It will change the framebuffer object that is set in the GPU. */ ObjectPtr CreateFrameBufferObject(); ObjectPtr CreateShaderProgram(); ObjectPtr CreateVertexShader(); ObjectPtr CreatePixelShader(); #ifndef NUX_OPENGLES_20 ObjectPtr CreateAsmShaderProgram(); ObjectPtr CreateAsmVertexShader(); ObjectPtr CreateAsmPixelShader(); #endif #if (NUX_ENABLE_CG_SHADERS) ObjectPtr CreateCGVertexShader(); ObjectPtr CreateCGPixelShader(); #endif // This is for the fixed pipeline // When using shaders see how a shader sampler parameter links to a texture with a call to setTexture. int SetTexture(unsigned int TextureUnit, IOpenGLBaseTexture *texture); int DrawIndexedPrimitive( ObjectPtr IndexBuffer, ObjectPtr VertexDeclaration, PRIMITIVE_TYPE PrimitiveType, int PrimitiveCount ); // Draw Primitive without index buffer int DrawPrimitive( ObjectPtr VertexDeclaration, PRIMITIVE_TYPE pt_, unsigned vtx_start_, unsigned num_prims_); // Draw Primitive without index buffer, and use a user pointer for the source of the stream. int DrawPrimitiveUP( ObjectPtr VertexDeclaration, PRIMITIVE_TYPE PrimitiveType, unsigned int PrimitiveCount, const void *pVertexStreamZeroData, unsigned int VertexStreamZeroStride ); int SetStreamSource( unsigned int StreamNumber, ObjectPtr pStreamData, unsigned int OffsetInBytes, unsigned int Stride); //! Setup a NULL vertex buffer void InvalidateVertexBuffer(); //! Setup a NULL index buffer void InvalidateIndexBuffer(); //! Setup a NULL texture void InvalidateTextureUnit(int TextureUnitIndex); int AllocateUnpackPixelBufferIndex(int *index); int FreeUnpackPixelBufferIndex(const int index); int BindUnpackPixelBufferIndex(const int index); int BindPackPixelBufferIndex(const int index); void *LockUnpackPixelBufferIndex(const int index, const int Size); void *LockPackPixelBufferIndex(const int index, const int Size); void UnlockUnpackPixelBufferIndex(const int index); void UnlockPackPixelBufferIndex(const int index); // All these operations are done on the default frame buffer object: _FrameBufferObject. int FormatFrameBufferObject(unsigned int Width, unsigned int Height, BitmapFormat PixelFormat); int SetColorRenderTargetSurface(unsigned int ColorAttachmentIndex, ObjectPtr pRenderTargetSurface); int SetDepthRenderTargetSurface(ObjectPtr pDepthSurface); ObjectPtr GetColorRenderTargetSurface(unsigned int ColorAttachmentIndex); ObjectPtr GetDepthRenderTargetSurface(); // Activate and Deactivate the default framebuffer: _FrameBufferObject. void ActivateFrameBuffer(); //! Restore the backbuffer as the render target. void DeactivateFrameBuffer(); unsigned int GetPixelStoreAlignment() const; public: void SetCurrentFrameBufferObject(ObjectPtr fbo); ObjectPtr GetFrameBufferObject() const; ObjectPtr GetCurrentFrameBufferObject(); ObjectPtr ActiveFboTextureAttachment(int color_attachment_index); ObjectPtr ActiveFboDepthTextureAttachment(); int GetOpenGLMajorVersion() const; int GetOpenGLMinorVersion() const; private: // Default FrameBufferobject ObjectPtr _FrameBufferObject; ObjectPtr active_framebuffer_object_; struct PixelBufferObject { ObjectPtr PBO; bool IsReserved; }; public: #if (NUX_ENABLE_CG_SHADERS) CGcontext GetCgContext() { return m_Cgcontext; } CGcontext m_Cgcontext; #endif bool UsePixelBufferObjects() const; GpuBrand GetGPUBrand() const; GpuRenderStates& GetRenderStates(); const GpuInfo& GetGpuInfo() const; void ResetRenderStates(); void VerifyRenderStates(); //! Create a texture that the system supports. Rectangle texture or 2D texture. /*! @Width Texture width. @Height Texture height. @Levels Texture number of mipmaps. If 0, all the mipmaps levels are created @PixelFormat Texture format. @return A device texture. Depending on the system capabilities returns a ObjectPtr or ObjectPtr. */ ObjectPtr CreateSystemCapableDeviceTexture( int Width , int Height , int Levels , BitmapFormat PixelFormat, NUX_FILE_LINE_PROTO); //! Created a cached texture /*! @return A cached texture. Depending on the system capabilities, returns a Texture2D or TextureRectangle. */ BaseTexture* CreateSystemCapableTexture(NUX_FILE_LINE_PROTO); bool SUPPORT_GL_ARB_TEXTURE_NON_POWER_OF_TWO() const { return gpu_info_->Support_ARB_Texture_Non_Power_Of_Two(); } bool SUPPORT_GL_EXT_TEXTURE_RECTANGLE() const { return gpu_info_->Support_EXT_Texture_Rectangle(); } bool SUPPORT_GL_ARB_TEXTURE_RECTANGLE() const { return gpu_info_->Support_ARB_Texture_Rectangle(); } private: // int _glsl_version_major; //!< GLSL major version. int _glsl_version_minor; //!< GLSL major version. int opengl_major_; //!< OpenGL major version. int opengl_minor_; //!< OpenGL minor version. std::string _board_vendor_string; //!< GPU vendor sting. std::string _board_renderer_string; //!< GPU renderer sting. std::string _openGL_version_string; //!< OpenGL version string. GpuBrand gpu_brand_; //!< GPU brand. bool use_pixel_buffer_object_; unsigned int pixel_store_alignment_; std::vector _PixelBufferArray; bool OGL_EXT_SWAP_CONTROL; bool GL_ARB_VERTEX_PROGRAM; bool GL_ARB_FRAGMENT_PROGRAM; bool GL_ARB_SHADER_OBJECTS; bool GL_ARB_VERTEX_SHADER; bool GL_ARB_FRAGMENT_SHADER; bool GL_ARB_VERTEX_BUFFER_OBJECT; bool GL_ARB_TEXTURE_NON_POWER_OF_TWO; bool GL_EXT_FRAMEBUFFER_OBJECT; bool GL_EXT_DRAW_RANGE_ELEMENTS; bool GL_EXT_STENCIL_TWO_SIDE; bool GL_EXT_TEXTURE_RECTANGLE; bool GL_ARB_TEXTURE_RECTANGLE; //!< Promoted from GL_EXT_TEXTURE_RECTANGLE to ARB. bool GL_NV_TEXTURE_RECTANGLE; GpuRenderStates* gpu_render_states_; GpuInfo* gpu_info_; public: ObjectPtr backup_texture0_; #if defined(NUX_OS_WINDOWS) GpuDevice(unsigned int DeviceWidth, unsigned int DeviceHeight, BitmapFormat DeviceFormat, HDC device_context, HGLRC &opengl_rendering_context, int req_opengl_major = 1, // requested opengl major version. int req_opengl_minor = 0, // requested opengl minor version. bool opengl_es_20 = false); #elif defined(USE_X11) #ifdef NUX_OPENGLES_20 GpuDevice(unsigned int DeviceWidth, unsigned int DeviceHeight, BitmapFormat DeviceFormat, Display *display, Window window, bool has_new_glx_support, EGLConfig fb_config, EGLContext &opengl_rendering_context, int req_opengl_major = 2, int req_opengl_minor = 0, bool opengl_es_20 = true); #else GpuDevice(unsigned int DeviceWidth, unsigned int DeviceHeight, BitmapFormat DeviceFormat, Display *display, Window window, bool has_new_glx_support, GLXFBConfig fb_config, GLXContext &opengl_rendering_context, int req_opengl_major = 1, // requested opengl major version. int req_opengl_minor = 0, // requested opengl minor version. bool opengl_es_20 = false); #endif #elif defined(NO_X11) GpuDevice(unsigned int DeviceWidth, unsigned int DeviceHeight, BitmapFormat DeviceFormat, EGLDisplay display, EGLConfig fb_config, EGLContext &opengl_rendering_context, int req_opengl_major, int req_opengl_minor); #endif ~GpuDevice(); friend class IOpenGLSurface; friend class GraphicsEngine; }; } #endif // GLDEVICEFACTORY_H ./NuxGraphics/GLTemplatePrimitiveBuffer.cpp0000644000004100000410000002676213313171755021246 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "GpuDevice.h" #include "GLTemplatePrimitiveBuffer.h" namespace nux { TemplateQuadBuffer::TemplateQuadBuffer(GpuDevice *pDeviceFactory, ShaderType Type, int NumQuads) : m_ShaderType(Type) { Memset(VertexAttributeBuffer, 0, 16); nuxAssert(pDeviceFactory); m_pDeviceFactory = pDeviceFactory; m_NumQuad = NumQuads; nuxAssert(m_NumQuad > 0); if (m_NumQuad < 0) m_NumQuad = 256; m_NumVertex = m_NumQuad * 6; FormatQuads(); } TemplateQuadBuffer::~TemplateQuadBuffer() { m_IB.Release(); for (unsigned int i = 0; i < 16; i++) { VertexAttributeBuffer[i].Release(); } } void TemplateQuadBuffer::FormatQuads() { // create vertex buffers for quad rendering // NumQuads * (4 vertices per Quad) * (4 Bytes per vertices) VertexAttributeBuffer[0] = m_pDeviceFactory->CreateVertexBuffer(m_NumQuad * 4 * 16, VBO_USAGE_DYNAMIC); // fill quad vertex buffer unsigned idx = 0; //BYTE* data0; float *data0; VertexAttributeBuffer[0]->Lock(0, m_NumQuad * 4 * 16, (void **) &data0); for (INT i = 0; i < m_NumQuad; ++i) { // (0, 0) _________(1, 0) // | /| // | / | // | / | // | / | // | / | // | / | // |/ | // (0, 1) --------- (1, 1) ((float *) data0) [idx++] = 0; // x ((float *) data0) [idx++] = 0; // y ((float *) data0) [idx++] = 0; // z ((float *) data0) [idx++] = 1.0f; // w ((float *) data0) [idx++] = 0; // x ((float *) data0) [idx++] = 1.0f; // y ((float *) data0) [idx++] = 0; // z ((float *) data0) [idx++] = 1; // w ((float *) data0) [idx++] = 1.0f; // x ((float *) data0) [idx++] = 1.0f; // y ((float *) data0) [idx++] = 0; // z ((float *) data0) [idx++] = 1; // w ((float *) data0) [idx++] = 1.0f; // x ((float *) data0) [idx++] = 0; // y ((float *) data0) [idx++] = 0; // z ((float *) data0) [idx++] = 1; // w // ((DWORD*)data0)[idx++]=((255*(0&1)))|((255*((0&2)>>1))<<8)|(0<<16)|(255<<24); // ((DWORD*)data0)[idx++]=((255*(1&1)))|((255*((1&2)>>1))<<8)|(0<<16)|(255<<24); // ((DWORD*)data0)[idx++]=((255*(3&1)))|((255*((3&2)>>1))<<8)|(0<<16)|(255<<24); // ((DWORD*)data0)[idx++]=((255*(2&1)))|((255*((2&2)>>1))<<8)|(0<<16)|(255<<24); } VertexAttributeBuffer[0]->Unlock(); // create index buffers for quad rendering // NumQuads * (6 index per Quad) * (2 Bytes per index) : each quad is 2 triangles => 6 indices. m_IB = m_pDeviceFactory->CreateIndexBuffer(m_NumQuad * 6 * 2, VBO_USAGE_DYNAMIC, INDEX_FORMAT_USHORT); // Fill quad index buffer // The index buffers defines 2 triangles for each quad. // Triangles are arranged as strips(that is 6 triangle index for a quad). WORD *data1; m_IB->Lock(0, m_NumQuad * 6 * 2, (void **) &data1); for (INT i = 0; i < m_NumQuad; ++i) { // // (0) _________(1) // | /| // | / | // | / | // | / | // | / | // | / | // |/ | // (3) --------- (2) // ((WORD *) data1) [i*6+0] = i * 4 + 0; ((WORD *) data1) [i*6+1] = i * 4 + 1; ((WORD *) data1) [i*6+2] = i * 4 + 3; ((WORD *) data1) [i*6+3] = i * 4 + 3; ((WORD *) data1) [i*6+4] = i * 4 + 1; ((WORD *) data1) [i*6+5] = i * 4 + 2; } m_IB->Unlock(); } void TemplateQuadBuffer::SetNumQuads(int NumQuads) { m_NumQuad = NumQuads; nuxAssert(m_NumQuad > 0); if (m_NumQuad < 0) m_NumQuad = 256; m_NumVertex = m_NumQuad * 6; m_IB = ObjectPtr (0);; for (int i = 0; i < 16; i++) VertexAttributeBuffer[i] = ObjectPtr (0); FormatQuads(); } int TemplateQuadBuffer::GetNumQuads() const { return m_NumQuad; } void TemplateQuadBuffer::UnBind() { m_pDeviceFactory->InvalidateIndexBuffer(); m_pDeviceFactory->InvalidateVertexBuffer(); } void TemplateQuadBuffer::BindAttribute(INT AttributeLocation, UINT AttributeIndex) { if (AttributeLocation < 0) { // Exclude Attribute Location that are not valid. Not valid does not mean the program is wrong! return; } nuxAssert(AttributeIndex < 16); if (VertexAttributeBuffer[AttributeIndex].IsNull()) return; if (m_ShaderType == SHADER_TYPE_GLSL) { if (AttributeIndex == 0) { VertexAttributeBuffer[AttributeIndex]->BindVertexBuffer(); CHECKGL(glEnableVertexAttribArrayARB(AttributeLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) AttributeLocation, 4, GL_FLOAT, GL_FALSE, 0, NUX_BUFFER_OFFSET(0))); } else { VertexAttributeBuffer[AttributeIndex]->BindVertexBuffer(); CHECKGL(glEnableVertexAttribArrayARB(AttributeLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) AttributeLocation, 4, GL_FLOAT, GL_FALSE, 0, NUX_BUFFER_OFFSET(0))); } } else { nuxAssertMsg(0, "[TemplateQuadBuffer::BindCgAttribute] Use BindCGAttribute for CG attributes."); } } #if (NUX_ENABLE_CG_SHADERS) void TemplateQuadBuffer::BindCGAttribute(CGparameter AttributeLocation, UINT AttributeIndex) { if (AttributeLocation < 0) { // Exclude Attribute Location that are not valid. Not valid does not mean the program is wrong! return; } nuxAssert(AttributeIndex >= 0); // Index 0 is the vertex position attribute. This on is set in the constructor. nuxAssert(AttributeIndex < 16); nuxAssert(AttributeLocation >= 0); if (VertexAttributeBuffer[AttributeIndex].IsNull()) return; if (m_ShaderType == SHADER_TYPE_CG) { if (AttributeIndex == 0) { VertexAttributeBuffer[AttributeIndex]->BindVertexBuffer(); CHECKGL(cgGLEnableClientState((CGparameter) AttributeLocation)); CHECKGL(cgGLSetParameterPointer((CGparameter) AttributeLocation, 4, GL_FLOAT, 0, NUX_BUFFER_OFFSET(0))); } else { VertexAttributeBuffer[AttributeIndex]->BindVertexBuffer(); CHECKGL(cgGLEnableClientState((CGparameter) AttributeLocation)); CHECKGL(cgGLSetParameterPointer((CGparameter) AttributeLocation, 4, GL_FLOAT, 0, NUX_BUFFER_OFFSET(0))); } } else { nuxAssertMsg(0, "[TemplateQuadBuffer::BindCGAttribute] Use BindAttribute for GLSL attributes."); } } #endif void TemplateQuadBuffer::UnBindAttribute(INT AttributeLocation) { if (AttributeLocation < 0) { // Exclude Attribute Location that are not valid. Not valid does not mean the program is wrong! return; } if (m_ShaderType == SHADER_TYPE_GLSL) { CHECKGL(glDisableVertexAttribArrayARB(AttributeLocation)); } else { nuxAssertMsg(0, "[TemplateQuadBuffer::UnBindAttribute] Use UnBindCGAttribute for CG attributes."); } } #if (NUX_ENABLE_CG_SHADERS) void TemplateQuadBuffer::UnBindCGAttribute(CGparameter AttributeLocation) { if (AttributeLocation < 0) { // Exclude Attribute Location that are not valid. Not valid does not mean the program is wrong! return; } if (m_ShaderType == SHADER_TYPE_CG) { CHECKGL(cgGLDisableClientState((CGparameter) AttributeLocation)); } else { nuxAssertMsg(0, "[TemplateQuadBuffer::UnBindCGAttribute] Use UnBindAttribute for GLSL attributes."); } } #endif void TemplateQuadBuffer::Render(INT NumPrimitives) { INT NumVertex = NumPrimitives * 6; // each quad is 2 triangles = 6 indices if (NumVertex > m_NumVertex) { NumVertex = m_NumVertex; } m_IB->BindIndexBuffer(); CHECKGL(glDrawElements( GL_TRIANGLES, NumVertex, GL_UNSIGNED_SHORT, NUX_BUFFER_OFFSET(0))); m_pDeviceFactory->InvalidateIndexBuffer(); } void TemplateQuadBuffer::SetPerQuadAttribute(UINT AttributeIndex, INT Num, Vector4 *pVector) { nuxAssert(AttributeIndex > 0); // Index 0 is the vertex position attribute. This on is set in the constructor. nuxAssert(AttributeIndex < 16); // Destroy the vertex buffer by setting it to NULL; VertexAttributeBuffer[AttributeIndex] = ObjectPtr (0);; VertexAttributeBuffer[AttributeIndex] = m_pDeviceFactory->CreateVertexBuffer(m_NumQuad * 4 * sizeof(Vector4), VBO_USAGE_DYNAMIC); FLOAT *data; VertexAttributeBuffer[AttributeIndex]->Lock(0, m_NumQuad * 4 * sizeof(Vector4), (void **) &data); INT i; for (i = 0; (i < m_NumQuad) && (i < Num); i++) { for (INT j = 0; j < 4; j++) { data[16*i + 4*j + 0] = pVector[i].x; data[16*i + 4*j + 1] = pVector[i].y; data[16*i + 4*j + 2] = pVector[i].z; data[16*i + 4*j + 3] = pVector[i].w; } } while (i < m_NumQuad) { // this happens if Num < m_NumQuad. // Fill the rest with the last element of the parameter array passed as argument of the function. for (INT j = 0; j < 4; j++) { data[16*i + 4*j + 0] = pVector[Num-1].x; data[16*i + 4*j + 1] = pVector[Num-1].y; data[16*i + 4*j + 2] = pVector[Num-1].z; data[16*i + 4*j + 3] = pVector[Num-1].w; } i++; } VertexAttributeBuffer[AttributeIndex]->Unlock(); } void TemplateQuadBuffer::SetPerVertexAttribute(UINT AttributeIndex, INT Num, Vector4 *pVector) { nuxAssert(AttributeIndex > 0); // Index 0 is the vertex position attribute. This on is set in the constructor. nuxAssert(AttributeIndex < 16); // Destroy the vertex buffer by setting it to NULL; VertexAttributeBuffer[AttributeIndex] = ObjectPtr (0);; VertexAttributeBuffer[AttributeIndex] = m_pDeviceFactory->CreateVertexBuffer(m_NumQuad * 4 * sizeof(Vector4), VBO_USAGE_DYNAMIC); FLOAT *data; VertexAttributeBuffer[AttributeIndex]->Lock(0, m_NumQuad * 4 * sizeof(Vector4), (void **) &data); INT i; for (i = 0; (i < m_NumQuad * 4) && (i < Num); i++) { data[4*i+0] = pVector[i].x; data[4*i+1] = pVector[i].y; data[4*i+2] = pVector[i].z; data[4*i+3] = pVector[i].w; } while (i < m_NumQuad * 4) { // this happens if Num < m_NumQuad. // Fill the rest with the last element of the parameter array passed as argument of the function. data[4*i+0] = pVector[Num-1].x; data[4*i+1] = pVector[Num-1].y; data[4*i+2] = pVector[Num-1].z; data[4*i+3] = pVector[Num-1].w; i++; } VertexAttributeBuffer[AttributeIndex]->Unlock(); } void TemplateQuadBuffer::UnSetQuadAttribute(UINT /* AttributeIndex */) { } } ./NuxGraphics/GraphicsDisplayX11.h0000755000004100000410000003401313313171755017241 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef GRAPHICSDISPLAYX11_H #define GRAPHICSDISPLAYX11_H #include "Gfx_Interface.h" #include "GLTimer.h" #include "GLDeviceObjects.h" #include "GLRenderStates.h" /* Xlib.h is the default header that is included and has the core functionallity */ #include /* Xatom.h includes functionallity for creating new protocol messages */ #include /* keysym.h contains keysymbols which we use to resolv what keys that are being pressed */ #include #include #include namespace nux { class Event; class MainFBO; class GpuDevice; class GraphicsEngine; class IOpenGLFrameBufferObject; enum WindowStyle { WINDOWSTYLE_NORMAL, WINDOWSTYLE_PANEL, WINDOWSTYLE_DIALOG, WINDOWSTYLE_TOOL, WINDOWSTYLE_NOBORDER, }; enum DndAction { DNDACTION_COPY, DNDACTION_MOVE, DNDACTION_LINK, DNDACTION_ASK, DNDACTION_PRIVATE, DNDACTION_NONE, }; #define NUX_THREADMSG (WM_APP+0) #define NUX_THREADMSG_START_RENDERING (WM_APP+1) // Connection established // start at WM_APP #define NUX_THREADMSG_CHILD_WINDOW_TERMINATED (WM_APP+2) // General failure - Wait Connection failed #define NUX_THREADMSG_THREAD_TERMINATED (WM_APP+3) // Set wParam = Thread ID, lParam = 0 #define _xdnd_max_type 100 #define xdnd_version 5 // This will become GLWindow class GraphicsDisplay : public GraphicSystem { private: Display *m_X11Display; int m_X11Screen; Window m_X11Window; XVisualInfo *m_X11VisualInfo; XIC m_current_xic; int parent_window_; #ifndef NUX_OPENGLES_20 GLXContext m_GLCtx; GLXFBConfig _fb_config; GLXWindow glx_window_; #else EGLContext m_GLCtx; EGLSurface m_GLSurface; EGLConfig _fb_config; #endif XSetWindowAttributes m_X11Attr; int m_NumVideoModes; XF86VidModeModeInfo **m_X11VideoModes; /* original desktop mode which we save so we can restore it later */ XF86VidModeModeInfo m_X11OriginalVideoMode; Atom m_WMDeleteWindow; Colormap m_X11Colormap; int m_BorderPixel; int _x11_major; int _x11_minor; int _glx_major; int _glx_minor; bool _has_glx_13; XEvent m_X11LastEvent; Bool m_X11RepeatKey; char m_WindowClassName[256]; GLuint m_PixelFormat; // Holds The Results After Searching For A Match std::string window_title_; // size, position Size viewport_size_; Size window_size_; Point m_WindowPosition; //! Full screen mode. bool fullscreen_; //! Screen bit depth unsigned int screen_bit_depth_; //! State of the graphics interface. bool gfx_interface_created_; // Device information void GetDisplayInfo(); bool m_CreatedFromForeignWindow; Time last_click_time_; /*! Maximum time allowed between the end of the last click (mouse up) and the next mouse down to be considered as a double click event. */ static Time double_click_time_delay; int double_click_counter_; public: typedef void(*GrabReleaseCallback) (bool replaced, void *user_data); typedef struct _DndSourceFuncs { nux::NBitmapData * (*get_drag_image) (void * data); std::list (*get_drag_types) (void * data); const char * (*get_data_for_type) (const char * type, int *size, int *format, void * data); void (*drag_finished) (DndAction result, void * data); } DndSourceFuncs; bool HasXPendingEvent() const; Display *GetX11Display() { return m_X11Display; } // Event object Event *m_pEvent; bool IsGfxInterfaceCreated(); //! Create a window with and OpenGL context. /*! @param WindowTitle The window title. @param WindowWidth Initial window width. @param WindowHeight Initial window height. @param Style The window style. @param ParentWindow The parent window. @param fullscreen_flag Full screen flag. */ bool CreateOpenGLWindow( const char *WindowTitle, unsigned int WindowWidth, unsigned int WindowHeight, WindowStyle Style, const GraphicsDisplay *Parent, bool fullscreen_flag = false, bool create_rendering_data = true); //! Create a GLWindow from a display and window created externally. /*! @param X11Display Provided display. @param X11Window Provided window. */ #ifdef NUX_OPENGLES_20 bool CreateFromOpenGLWindow(Display *X11Display, Window X11Window, EGLContext OpenGLContext); #else bool CreateFromOpenGLWindow(Display *X11Display, Window X11Window, GLXContext OpenGLContext); #endif void DestroyOpenGLWindow(); void SetWindowTitle(const char *Title); //! Set the window size. /*! Actively set the window size to the provided parameters. \sa ResetWindowSize */ void SetWindowSize(int width, int height); //! Set the window position. void SetWindowPosition(int width, int height); //! Set the OpenGL Viewport. void SetViewPort(int x, int y, int width, int height); Point GetMouseScreenCoord(); Point GetMouseWindowCoord(); Point GetWindowCoord(); Rect GetWindowGeometry(); Rect GetNCWindowGeometry(); void MakeGLContextCurrent(); void SwapBuffer(bool glswap = true); // Event methods /*! Returns true if there was a pending event to be fetched and false otherwise */ bool GetSystemEvent(Event *evt); // Os specific int GetGlXMajor() const; int GetGlXMinor() const; #if defined(NUX_OS_LINUX) void InjectXEvent(Event *evt, XEvent xevent); typedef struct _EventFilterArg { bool (*filter) (XEvent event, void * data); void * data; } EventFilterArg; void AddEventFilter (EventFilterArg arg); void RemoveEventFilter (void *owner); std::list _event_filters; #endif Event &GetCurrentEvent(); // That method is deprecated, it always returns false and still here in // order to maintain API compatibility. bool isWindowMinimized() const { return false; } void ShowWindow(); void HideWindow(); bool IsWindowVisible(); void EnterMaximizeWindow(); void ExitMaximizeWindow(); Window GetWindowHandle() const { return m_X11Window; } bool IsChildWindow() const { return parent_window_ != 0; } // Return true if VSync swap control is available bool HasVSyncSwapControl() const; void EnableVSyncSwapControl(); void DisableVSyncSwapControl(); // m_FrameRate float GetFrameTime() const; void ResetFrameTime(); GraphicsEngine* GetGraphicsEngine() const; GpuDevice* GetGpuDevice() const; void SetCurrentXIC(XIC xic); // Dialog /*bool StartOpenFileDialog(FileDialogOption& fdo); bool StartSaveFileDialog(FileDialogOption& fdo); bool StartColorDialog(ColorDialogOption& cdo);*/ void GetDesktopSize(int &w, int &h); void GetWindowSize(int &w, int &h); int GetWindowWidth(); int GetWindowHeight(); //! Get the window size and reset the GraphicsEngine and GpuDevice accordingly. /*! This is a passive way to set the window size through out the NuxGraphics system. This call gets the current window size and sets its accordingly to all sub-system. \sa SetWindowSize */ void ResetWindowSize(); bool HasFrameBufferSupport(); /*void SetWindowCursor(HCURSOR cursor); HCURSOR GetWindowCursor() const;*/ //! Pause graphics rendering. /*! Pause graphics rendering. This function also sets the current openGL context to 0 for this window. This is useful while a child window is being created and is sharing openGL objects with this context. For wglShareLists to work, both OpenGL context must be set to 0 in their respective thread. Send NUX_THREADMSG_START_RENDERING(PostThreadMessage) to this window to reactivate rendering. Never call this function while doing rendering. Call it only when processing events. */ void PauseThreadGraphicsRendering(); bool IsPauseThreadGraphicsRendering() const; void ProcessForeignX11Event(XEvent *xevent, Event *nux_event); void ProcessXEvent(XEvent xevent, bool foreign); void RecalcXYPosition(Window TheMainWindow, XEvent xevent, int &x, int &y); void RecalcXYPosition(int x_root, int y_root, int &x_recalc, int &y_recalc); void SendDndStatus (bool accept, DndAction action, Rect region); void SendDndFinished(bool accepted, DndAction performed_action); std::list GetDndMimeTypes(); char * GetDndData (char *property); void StartDndDrag(const DndSourceFuncs &funcs, void *user_data); bool GrabPointer (GrabReleaseCallback callback, void *data, bool replace_existing); bool UngrabPointer(void *data); bool PointerIsGrabbed(); bool GrabKeyboard (GrabReleaseCallback callback, void *data, bool replace_existing); bool UngrabKeyboard(void *data); bool KeyboardIsGrabbed(); void * KeyboardGrabData() { return _global_keyboard_grab_data; } void * PointerGrabData() { return _global_pointer_grab_data; } private: void InitGlobalGrabWindow(); void HandleXDndPosition(XEvent event, Event* nux_event); void HandleXDndEnter (XEvent event); void HandleXDndStatus (XEvent event); void HandleXDndLeave (XEvent event); void HandleXDndDrop (XEvent event, Event* nux_event); void HandleXDndFinished(XEvent event); void SendXDndStatus(Display *display, Window source, Window target, bool accept, Atom action, Rect box); bool GetXDndSelectionEvent(Display *display, Window target, Atom property, long time, XEvent *result, int attempts); void SendXDndFinished(Display *display, Window source, Window target, bool result, Atom action); char * GetXDndData(Display *display, Window requestor, Atom property, long time); void EndDndDrag(DndAction action); bool GrabDndSelection(Display *display, Window window, Time time); void HandleDndDragSourceEvent(XEvent event); void HandleDndSelectionRequest(XEvent event); Window GetDndTargetWindowForPos(int x, int y); void DrawDndSourceWindow(); void SendDndSourcePosition(Window target, int x, int y, Time time); void SendDndSourceEnter(Window target); void SendDndSourceLeave(Window target); void SendDndSourceDrop(Window target, Time time); void SetDndSourceTargetWindow(Window target); static gboolean OnDragEndTimeout(gpointer data); Point _last_dnd_position; bool m_PauseGraphicsRendering; GLTimer m_Timer; float m_FrameTime; GpuDevice *m_DeviceFactory; GraphicsEngine *m_GraphicsContext; WindowStyle m_Style; Atom _xdnd_types[_xdnd_max_type + 1]; Display *_drag_display; Window _drag_window; Window _drag_source; long _drag_drop_timestamp; void * _dnd_source_data; DndSourceFuncs _dnd_source_funcs; Window _dnd_source_window; Window _dnd_source_target_window; Window _global_grab_window; void *_global_pointer_grab_data; bool _global_pointer_grab_active; GrabReleaseCallback _global_pointer_grab_callback; void *_global_keyboard_grab_data; bool _global_keyboard_grab_active; GrabReleaseCallback _global_keyboard_grab_callback; bool _dnd_is_drag_source; bool _dnd_source_target_accepts_drop; bool _dnd_source_grab_active; bool _dnd_source_drop_sent; public: ~GraphicsDisplay(); #ifndef NUX_OPENGLES_20 GLEWContext *GetGLEWContext() { return &m_GLEWContext; } GLXEWContext *GetGLXEWContext() { return &m_GLXEWContext; } #endif std::string FindResourceLocation(const char *ResourceFileName, bool ErrorOnFail = false); std::string FindUITextureLocation(const char *ResourceFileName, bool ErrorOnFail = false); std::string FindShaderLocation(const char *ResourceFileName, bool ErrorOnFail = false); std::string FindFontLocation(const char *ResourceFileName, bool ErrorOnFail = false); const std::vector& GetFontSearchPath() const { return m_FontSearchPath; } const std::vector& GetShaderSearchPath() const { return m_ShaderSearchPath; } const std::vector& GetUITextureSearchPath() const { return m_UITextureSearchPath; } private: std::vector m_FontSearchPath; std::vector m_ShaderSearchPath; std::vector m_UITextureSearchPath; FilePath m_ResourcePathLocation; GraphicsDisplay(); GraphicsDisplay(const GraphicsDisplay &); // Does not make sense for a singleton. This is a self assignment. GraphicsDisplay &operator= (const GraphicsDisplay &); #ifndef NUX_OPENGLES_20 GLEWContext m_GLEWContext; GLXEWContext m_GLXEWContext; #endif int MouseMove(XEvent xevent, Event *event); int MousePress(XEvent xevent, Event *event); int MouseRelease(XEvent xevent, Event *event); friend class DisplayAccessController; friend class GraphicsEngine; }; } #endif //GRAPHICSDISPLAYX11_H ./NuxGraphics/IOpenGLVolumeTexture.cpp0000644000004100000410000001346613313171755020230 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "GLDeviceObjects.h" #include "IOpenGLVolumeTexture.h" namespace nux { NUX_IMPLEMENT_OBJECT_TYPE(IOpenGLVolumeTexture); IOpenGLVolumeTexture::IOpenGLVolumeTexture( int Width , int Height , int Depth , int Levels , BitmapFormat PixelFormat) : IOpenGLBaseTexture(RTVOLUMETEXTURE, Width, Height, Depth, Levels, PixelFormat) { #ifndef NUX_OPENGLES_20 CHECKGL(glGenTextures(1, &_OpenGLID)); CHECKGL(glBindTexture(GL_TEXTURE_3D, _OpenGLID)); _VolumeSurfaceArray = new std::vector< ObjectPtr >[_NumMipLevel]; for (int mip = 0; mip < _NumMipLevel; mip++) { for (int slice = 0; slice < ImageSurface::GetLevelDim(_PixelFormat, _Depth, mip); slice++) { //IOpenGLSurface* surface = new IOpenGLSurface(this, _OpenGLID, GL_TEXTURE_3D, GL_TEXTURE_3D, mip, slice); //surface->InitializeLevel(); IOpenGLSurface* surface = new IOpenGLSurface(this, _OpenGLID, GL_TEXTURE_3D, GL_TEXTURE_3D, mip, slice); _VolumeSurfaceArray[mip].push_back(ObjectPtr (surface)); surface->UnReference(); } } for (int mip = 0; mip < _NumMipLevel; mip++) { IOpenGLVolume *volume = new IOpenGLVolume(this, _OpenGLID, GL_TEXTURE_3D, GL_TEXTURE_3D, mip); volume->InitializeLevel(); _VolumeArray.push_back(ObjectPtr (volume)); } CHECKGL(glBindTexture(GL_TEXTURE_3D, _OpenGLID)); SetFiltering(GL_NEAREST, GL_NEAREST); SetWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); SetRenderStates(); GRunTimeStats.Register(this); #endif } IOpenGLVolumeTexture::~IOpenGLVolumeTexture() { for (int mip = 0; mip < _NumMipLevel; mip++) { for (int slice = 0; slice < ImageSurface::GetLevelDim(_PixelFormat, _Depth, mip); slice++) { // destroying a surface _VolumeSurfaceArray[mip][slice] = ObjectPtr (0); } _VolumeSurfaceArray[mip].clear(); } NUX_SAFE_DELETE_ARRAY(_VolumeSurfaceArray); for (int mip = 0; mip < _NumMipLevel; mip++) { // destroying a IOpenGLVolume _VolumeArray[mip] = ObjectPtr (0); } CHECKGL(glDeleteTextures(1, &_OpenGLID)); _OpenGLID = 0; GRunTimeStats.UnRegister(this); } int IOpenGLVolumeTexture::VolumeLockRect( int Slice, int Level, SURFACE_LOCKED_RECT *pLockedRect, const SURFACE_RECT *pRect) { nuxAssertMsg(pLockedRect, "[IOpenGLVolumeTexture::LockRect] Invalid parameter 'pLockedRect'."); nuxAssertMsg(Level >= 0, "[IOpenGLVolumeTexture::LockRect] Invalid mipmap level."); nuxAssertMsg(Level < _NumMipLevel, "[IOpenGLVolumeTexture::LockRect] Invalid mipmap level."); nuxAssertMsg(Slice >= 0, "[IOpenGLVolumeTexture::LockRect] Invalid slice index."); nuxAssertMsg(Slice < ImageSurface::GetLevelDim(_PixelFormat, _Depth, Level), "[IOpenGLVolumeTexture::LockRect] Invalid slice index."); if (Slice < 0) Slice = 0; if (Slice >= _Depth) Slice = _Depth - 1; if (Level < _NumMipLevel) { ObjectPtr pVolumeSurfaceLevel = _VolumeSurfaceArray[Level][Slice]; return pVolumeSurfaceLevel->LockRect(pLockedRect, pRect); } else { pLockedRect->pBits = 0; pLockedRect->Pitch = 0; return OGL_INVALID_SURFACE_LEVEL; } return OGL_OK; } int IOpenGLVolumeTexture::VolumeUnlockRect( int Slice, int Level ) { nuxAssertMsg(Level >= 0, "[IOpenGLVolumeTexture::LockRect] Invalid mipmap level."); nuxAssertMsg(Level < _NumMipLevel, "[IOpenGLVolumeTexture::LockRect] Invalid mipmap level."); if (Level < _NumMipLevel) { ObjectPtr pVolumeSurfaceLevel = _VolumeSurfaceArray[Level][Slice]; return pVolumeSurfaceLevel->UnlockRect(); } else { return OGL_INVALID_SURFACE_LEVEL; } return OGL_OK; } int IOpenGLVolumeTexture::LockBox(int Level, VOLUME_LOCKED_BOX *pLockedVolume, const VOLUME_BOX *pBox) { nuxAssertMsg(pLockedVolume, "[IOpenGLVolumeTexture::LockBox] Invalid parameter 'pLockedRect'."); nuxAssertMsg(Level >= 0, "[IOpenGLVolumeTexture::LockBox] Invalid mipmap level."); nuxAssertMsg(Level < _NumMipLevel, "[IOpenGLVolumeTexture::LockBox] Invalid mipmap level."); if (pBox) { nuxAssertMsg(pBox->Front >= 0, "[IOpenGLVolumeTexture::LockBox] Invalid slice index."); nuxAssertMsg(pBox->Front < pBox->Back, "[IOpenGLVolumeTexture::LockBox] Invalid slice index."); nuxAssertMsg(pBox->Back <= ImageSurface::GetLevelDim(_PixelFormat, _Depth, Level), "[IOpenGLVolumeTexture::LockBox] Invalid slice index."); } return _VolumeArray[Level]->LockBox(pLockedVolume, pBox); } int IOpenGLVolumeTexture::UnlockBox(int Level) { nuxAssertMsg(Level >= 0, "[IOpenGLVolumeTexture::LockBox] Invalid mipmap level."); nuxAssertMsg(Level < _NumMipLevel, "[IOpenGLVolumeTexture::LockBox] Invalid mipmap level."); return _VolumeArray[Level]->UnlockBox(); } } ./NuxGraphics/GpuDeviceShader.cpp0000644000004100000410000000511013313171755017207 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "GLResource.h" #include "GpuDevice.h" #include "GLDeviceObjects.h" #include "GLResourceManager.h" #include "GLTextureResourceManager.h" #include "GLVertexResourceManager.h" #include "GLDeviceFrameBufferObject.h" #include "GLTemplatePrimitiveBuffer.h" #include "GraphicsEngine.h" namespace nux { ObjectPtr GpuDevice::CreateShaderProgram() { ObjectPtr result; result.Adopt(new IOpenGLShaderProgram()); return result; } ObjectPtr GpuDevice::CreateVertexShader() { ObjectPtr result; result.Adopt(new IOpenGLVertexShader()); return result; } ObjectPtr GpuDevice::CreatePixelShader() { ObjectPtr result; result.Adopt(new IOpenGLPixelShader()); return result; } #ifndef NUX_OPENGLES_20 ObjectPtr GpuDevice::CreateAsmShaderProgram() { ObjectPtr result; result.Adopt(new IOpenGLAsmShaderProgram()); return result; } ObjectPtr GpuDevice::CreateAsmVertexShader() { ObjectPtr result; result.Adopt(new IOpenGLAsmVertexShader()); return result; } ObjectPtr GpuDevice::CreateAsmPixelShader() { ObjectPtr result; result.Adopt(new IOpenGLAsmPixelShader()); return result; } #endif #if (NUX_ENABLE_CG_SHADERS) ObjectPtr GpuDevice::CreateCGVertexShader() { ObjectPtr result; result.Adopt(new ICgVertexShader()); return result; } ObjectPtr GpuDevice::CreateCGPixelShader() { ObjectPtr result; result.Adopt(new ICgPixelShader()); return result; } #endif } ./NuxGraphics/GdkGraphics.cpp0000644000004100000410000000537513313171755016410 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "NuxCore/NuxCore.h" #include "ImageSurface.h" #include "GdkGraphics.h" #include "NuxCore/Logger.h" namespace nux { DECLARE_LOGGER(logger, "nux.image"); GdkGraphics::GdkGraphics() : pixbuf_(0) { } GdkGraphics::GdkGraphics(GdkPixbuf* pixbuf) : pixbuf_(pixbuf) { } GdkGraphics::GdkGraphics(const char* filename) : pixbuf_(0) { LoadImage(filename); } GdkGraphics::~GdkGraphics() { if (pixbuf_) g_object_unref(pixbuf_); } bool GdkGraphics::LoadImage(const char* filename) { if (pixbuf_) g_object_unref(pixbuf_); GError* error = 0; pixbuf_ = gdk_pixbuf_new_from_file(filename, &error); if (error) { LOG_ERROR(logger) << error->message; g_error_free(error); return false; } return true; } NBitmapData* GdkGraphics::GetBitmap() const { if (!pixbuf_) { LOG_WARN(logger) << "No pixbuf loaded"; return 0; } unsigned int width = gdk_pixbuf_get_width(pixbuf_); unsigned int height = gdk_pixbuf_get_height(pixbuf_); int channels = gdk_pixbuf_get_n_channels(pixbuf_); int src_pitch = gdk_pixbuf_get_rowstride(pixbuf_); NTextureData* texture = NULL; if (channels == 4) { texture = new NTextureData(BITFMT_R8G8B8A8, width, height, 1); } else if (channels == 3) { texture = new NTextureData(BITFMT_R8G8B8, width, height, 1); } else if (channels == 1) { texture = new NTextureData(BITFMT_A8, width, height, 1); } else { LOG_ERROR(logger) << __func__ << ": Invalid number of channels"; return 0; } ImageSurface& image_surface = texture->GetSurface(0); unsigned char* dest = image_surface.GetPtrRawData(); int dest_pitch = image_surface.GetPitch(); guchar* src = gdk_pixbuf_get_pixels(pixbuf_); for (unsigned int i = 0; i < height; ++i) { Memcpy(dest, src + i*src_pitch, width*channels); dest += dest_pitch; } return texture; } } ./NuxGraphics/GdiImageLoader.h0000644000004100000410000000212113313171755016446 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef GDIIMAGELOADER_H #define GDIIMAGELOADER_H #ifdef NUX_OS_WINDOWS #include // Needed for GDI+ #include #include #include "ImageSurface.h" #endif namespace nux { NBitmapData* GdiLoadImageFile(const TCHAR* filename); } #endif // GDIIMAGELOADER_H ./NuxGraphics/GpuDeviceTexture.cpp0000644000004100000410000001553113313171755017451 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "GLResource.h" #include "GpuDevice.h" #include "GLDeviceObjects.h" #include "GLResourceManager.h" #include "GLTextureResourceManager.h" #include "GLVertexResourceManager.h" #include "GLDeviceFrameBufferObject.h" #include "GLTemplatePrimitiveBuffer.h" #include "GraphicsEngine.h" namespace nux { ObjectPtr GpuDevice::CreateTexture( int Width , int Height , int Levels , BitmapFormat pixel_format , NUX_FILE_LINE_DECL) { if ((pixel_format == BITFMT_D24S8) && (!GetGpuInfo().Support_Depth_Buffer())) { // No support for depth buffers return ObjectPtr(); } GpuInfo gpu_info = GetGpuInfo(); int msz = gpu_info.GetMaxTextureSize(); if(Width <= 0 || Height <= 0 || Width > msz || Height > msz) { return ObjectPtr(); } unsigned int NumTotalMipLevel = 1 + floorf(Log2(Max(Width, Height))); unsigned int NumMipLevel = 0; if (Levels == 0) { NumMipLevel = NumTotalMipLevel; } else if (Levels > (int)NumTotalMipLevel) { NumMipLevel = NumTotalMipLevel; } else { NumMipLevel = Levels; } ObjectPtr result; result.Adopt(new IOpenGLTexture2D(Width, Height, NumMipLevel, pixel_format, false, NUX_FILE_LINE_PARAM)); return result; } ObjectPtr GpuDevice::CreateTexture2DFromID(int id , int width , int height , int levels , BitmapFormat pixel_format , NUX_FILE_LINE_DECL) { if ((pixel_format == BITFMT_D24S8) && (!GetGpuInfo().Support_Depth_Buffer())) { // No support for depth buffers return ObjectPtr(); } GpuInfo gpu_info = GetGpuInfo(); int msz = gpu_info.GetMaxTextureSize(); if(width <= 0 || height <=0 || width > msz || height > msz) { return ObjectPtr(); } ObjectPtr result; result.Adopt(new IOpenGLTexture2D(width, height, levels, pixel_format, true, NUX_FILE_LINE_PARAM)); /* Assign the external id to the internal id. This allows us * to use the foreign texture as if it were a native one. * * This is really important. Don't remove it */ result->_OpenGLID = id; return result; } ObjectPtr GpuDevice::CreateRectangleTexture( int Width , int Height , int Levels , BitmapFormat pixel_format , NUX_FILE_LINE_DECL) { if ((pixel_format == BITFMT_D24S8) && (!GetGpuInfo().Support_Depth_Buffer())) { // No support for depth buffers return ObjectPtr(); } GpuInfo gpu_info = GetGpuInfo(); int msz = gpu_info.GetMaxTextureSize(); if(Width <= 0 || Height <= 0 || Width > msz || Height > msz) { return ObjectPtr(); } unsigned int NumTotalMipLevel = 1 + floorf(Log2(Max(Width, Height))); unsigned int NumMipLevel = 0; if (Levels == 0) { NumMipLevel = 1; } else if (Levels > (int)NumTotalMipLevel) { NumMipLevel = 1; } else { NumMipLevel = 1; } ObjectPtr result; result.Adopt(new IOpenGLRectangleTexture(Width, Height, NumMipLevel, pixel_format, false, NUX_FILE_LINE_PARAM)); return result; } ObjectPtr GpuDevice::CreateCubeTexture( int EdgeLength , int Levels , BitmapFormat pixel_format , const char * /* __Nux_FileName__ */ , int /* __Nux_LineNumber__ */) { if ((pixel_format == BITFMT_D24S8) && (!GetGpuInfo().Support_Depth_Buffer())) { // No support for depth buffers return ObjectPtr(); } unsigned int NumTotalMipLevel = 1 + floorf(Log2(EdgeLength)); unsigned int NumMipLevel = 0; if (Levels == 0) { NumMipLevel = NumTotalMipLevel; } else if (Levels > (int)NumTotalMipLevel) { NumMipLevel = NumTotalMipLevel; } else { NumMipLevel = Levels; } ObjectPtr result; result.Adopt(new IOpenGLCubeTexture(EdgeLength, NumMipLevel, pixel_format)); return result; } ObjectPtr GpuDevice::CreateVolumeTexture( int Width , int Height , int Depth , int Levels , BitmapFormat pixel_format , const char * /* __Nux_FileName__ */ , int /* __Nux_LineNumber__ */) { if ((pixel_format == BITFMT_D24S8) && (!GetGpuInfo().Support_Depth_Buffer())) { // No support for depth buffers return ObjectPtr(); } GpuInfo gpu_info = GetGpuInfo(); int msz = gpu_info.GetMaxTextureSize(); if(Width <= 0 || Height <= 0 || Width > msz || Height > msz) { return ObjectPtr(); } unsigned int NumTotalMipLevel = 1 + floorf(Log2(Max(Max(Width, Height), Depth))); unsigned int NumMipLevel = 0; if (Levels == 0) { NumMipLevel = NumTotalMipLevel; } else if (Levels > (int)NumTotalMipLevel) { NumMipLevel = NumTotalMipLevel; } else { NumMipLevel = Levels; } ObjectPtr result; result.Adopt(new IOpenGLVolumeTexture(Width, Height, Depth, NumMipLevel, pixel_format)); return result; } ObjectPtr GpuDevice::CreateAnimatedTexture( int Width , int Height , int Depth , BitmapFormat pixel_format) { if ((pixel_format == BITFMT_D24S8) && (!GetGpuInfo().Support_Depth_Buffer())) { // No support for depth buffers return ObjectPtr(); } GpuInfo gpu_info = GetGpuInfo(); int msz = gpu_info.GetMaxTextureSize(); if(Width <= 0 || Height <= 0 || Width > msz || Height > msz) { return ObjectPtr(); } ObjectPtr result; result.Adopt(new IOpenGLAnimatedTexture(Width, Height, Depth, pixel_format)); return result; } ObjectPtr GpuDevice::CreateQuery(QUERY_TYPE Type) { ObjectPtr result; result.Adopt(new IOpenGLQuery(Type)); return result; } } ./NuxGraphics/IOpenGLVertexDeclaration.h0000644000004100000410000000376313313171755020467 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef IOPENGLVERTEXDECLARATION_H #define IOPENGLVERTEXDECLARATION_H namespace nux { class IOpenGLResource; class IOpenGLVertexDeclaration: public IOpenGLResource { NUX_DECLARE_OBJECT_TYPE(IOpenGLVertexDeclaration, IOpenGLResource); public: virtual ~IOpenGLVertexDeclaration(); VERTEXELEMENT GetUsage(ATTRIB_USAGE_DECL usage); bool IsUsingMoreThanStreamZero(); int GetStride(int vertex_input_number); void SetVertexShaderAttributeLocation(int input_index, int shader_attribute_location); int GetVertexShaderAttributeLocation(int input_index); private: void SetVertexBuffer(int input_index, ObjectPtr vertex_buffer); ObjectPtr GetVertexBuffer(int input_index); IOpenGLVertexDeclaration(const VERTEXELEMENT *pVertexElements); int _stride[8]; //!< Stride for each stream int _valid_vertex_input[16]; // Vertex Input valid for this vertex declaration int shader_attribute_location_array[8]; std::vector > vertex_buffer_array; std::vector _declarations_array; friend class GpuDevice; friend class CachedMeshBuffer; }; } #endif // IOPENGLVERTEXDECLARATION_H ./NuxGraphics/Readme.txt0000644000004100000410000001411513313171755015444 0ustar www-datawww-data Using GLSL texture: ------------------- // Get the sampler uniform location. GLint BumpMapLoc = glGetUniformLocationARB(prog, "BumpTex"); // Bind the texture to texture unit i. glActiveTexture(GL_TEXTURE0 + i); glBindTexture(GL_TEXTURE_2D, texture_gl_object_id); // Pass i as an integer by glUniform. glUniform1iARB(BumpMapLoc, i); GLSL Built-in vertex attribute(Deprecated in GLSL 1.30) ------------------------------- Built-in vertex attribute name Incompatible aliased vertex attribute index gl_Vertex 0 gl_Normal 2 gl_Color 3 gl_SecondaryColor 4 gl_FogCoord 5 gl_MultiTexCoord0 8 gl_MultiTexCoord1 9 gl_MultiTexCoord2 10 gl_MultiTexCoord3 11 gl_MultiTexCoord4 12 gl_MultiTexCoord5 13 gl_MultiTexCoord6 14 gl_MultiTexCoord7 15 gl_Vertex: - glVertex{234sifd} - glEnableClientState/glDisableClientState(GL_VERTEX_ARRAY); glVertexPointer(...); gl_Normal: - glNormal{3sifd} - glEnableClientState/glDisableClientState(GL_NORMAL_ARRAY); glNormalPointer(...); gl_Color: - glColor{34sifd} - glEnableClientState/glDisableClientState(GL_COLOR_ARRAY); glColorPointer(...); gl_SecondaryColor(requires GL_EXT_secondary_color) - glSecondaryColor3{bsifd}; - glEnableClientState/glDisableClientState(SECONDARY_COLOR_ARRAY_EXT); glSecondaryColorPointerEXT(...); gl_FogCoord(requires GL_EXT_fog_coord) - glFogCoord{fd}; - glEnableClientState/glDisableClientState(FOG_COORDINATE_ARRAY_EXT); glFogCoordPointerEXT(...); gl_MultiTexCoordXXX - glMultiTexCoord{234fd} - glClientActiveTextureARB(GL_TEXTUREXXX_ARB); glEnableClientState/glDisableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(...); GLSL Vertex Shader Special output variables(write) ---------------------------------------------------- gl_Position (must be written to) gl_PointSize (may be written to) gl_ClipVertex (may be written to) GLSL Vertex Shader Built-in varying(write) GLSL Fragment Shader Built-in varying(read) ------------------------------------------- ------------------------------------------- varying vec4 gl_FrontColor; ----> gl_Color varying vec4 gl_BackColor; ----> gl_Color varying vec4 gl_FrontSecondaryColor; ----> gl_SecondaryColor varying vec4 gl_BackSecondaryColor; ----> gl_SecondaryColor varying vec4 gl_TexCoord[]; ----> gl_TexCoord[] varying float gl_FogFragCoord; ----> gl_FogFragCoord GLSL Fragment Built-in variables -------------------------------- vec4 gl_FragCoord (read only) bool gl_FrontFacing (read only) vec2 gl_PointCoord (read only) GLSL Fragment Shader Special output variables --------------------------------------------- vec4 gl_FragColor (may be written to) vec4 gl_FragData[gl_MaxDrawBuffers] (may be written to) float gl_FragDepth (may be written to) vec2 gl_PointCoord (read only) Binding Semantics for Cg programs Binding Semantics for Varying Input/Output Data ----------------------------------------------- Table 23 summarizes the valid binding semantics for varying input parameters in the vp30 profile. One can also use TANGENT and BINORMAL instead of TEXCOORD6 and TEXCOORD7. These binding semantics map to NV_vertex_program2 input attribute parameters. The two sets act as aliases to each other. Table 23 vp30 Varying Input Binding Semantics Binding Semantics Name Corresponding Data POSITION, ATTR0 Input Vertex, Generic Attribute 0 BLENDWEIGHT, ATTR1 Input vertex weight, Generic Attribute 1 NORMAL, ATTR2 Input normal, Generic Attribute 2 COLOR0, DIFFUSE, ATTR3 Input primary color, Generic Attribute 3 COLOR1, SPECULAR, ATTR4 Input secondary color, Generic Attribute 4 TESSFACTOR, FOGCOORD, ATTR5 Input fog coordinate, Generic Attribute 5 PSIZE, ATTR6 Input point size, Generic Attribute 6 BLENDINDICES, ATTR7 Generic Attribute 7 TEXCOORD0-TEXCOORD7, ATTR8-ATTR15 Input texture coordinates(texcoord0-texcoord7), Generic Attributes 815 TANGENT, ATTR14 Generic Attribute 14 BINORMAL, ATTR15 Generic Attribute 15 Table 24 summarizes the valid binding semantics for varying output parameters in the vp30 profile. These binding semantics map to NV_vertex_program2 output registers. The two sets act as aliases to each other. Table 24 vp30 Varying Output Binding Semantics Binding Semantics Name Corresponding Data POSITION, HPOS Output position PSIZE, PSIZ Output point size FOG, FOGC Output fog coordinate COLOR0, COL0 Output primary color COLOR1, COL1 Output secondary color BCOL0 Output backface primary color BCOL1 Output backface secondary color TEXCOORD0-TEXCOORD7, TEX0-TEX7 Output texture coordinates CLP0-CL5 Output Clip distances Using NVidia CG texture: ------------------------ CGparameter BumpMapParam = cgGetNamedParameter(cgprog, "BumpTexture"); cgGLSetTextureParameter(BumpMapParam, texture_gl_object_id); cgGLEnableTextureParameter(BumpMapParam);./NuxGraphics/GLThread.h0000644000004100000410000000153213313171755015310 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef GLTHREAD_H #define GLTHREAD_H #endif // GLTHREAD_H ./NuxGraphics/RenderingPipeAsm.h0000644000004100000410000000160513313171755017053 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef RENDERINGPIPEASM_H #define RENDERINGPIPEASM_H namespace nux { } #endif // RENDERINGPIPEASM_H ./NuxGraphics/MeshData.cpp0000644000004100000410000000322313313171755015676 0ustar www-datawww-data#include "GLResource.h" #include "MeshData.h" namespace nux { MeshData::MeshData() { _num_index = 0; _index_size = 0; _num_element = 0; _vertex_data = 0; _index_data = 0; } MeshData::~MeshData() { NUX_SAFE_DELETE_ARRAY(_vertex_data); NUX_SAFE_DELETE_ARRAY(_index_data); } bool MeshData::Allocate(int num_mesh_primitive, NuxMeshPrimitiveType primitive_type, int num_element, int element_size) { NUX_RETURN_VALUE_IF_FALSE(num_element > 0, false); NUX_RETURN_VALUE_IF_FALSE(element_size > 0, false); NUX_SAFE_DELETE_ARRAY(_vertex_data); NUX_SAFE_DELETE_ARRAY(_index_data); _num_element = num_element; _element_size = element_size; _mesh_primitive_type = primitive_type; switch(primitive_type) { case NUX_MESH_TRIANGLE: _num_index = num_mesh_primitive * 3; break; case NUX_MESH_TRIANGLE_STRIP: case NUX_MESH_TRIANGLE_FAN: _num_index = num_mesh_primitive + 2; break; case NUX_MESH_LINE: _num_index = num_mesh_primitive * 2; break; case NUX_MESH_LINE_STRIP: case NUX_MESH_LINE_LOOP: _num_index = num_mesh_primitive + 1; break; case NUX_MESH_QUAD: _num_index = num_mesh_primitive * 4; break; case NUX_MESH_QUAD_STRIP: _num_index = num_mesh_primitive + 2; break; case NUX_MESH_POINT: _num_index = num_mesh_primitive; break; case NUX_MESH_PRIMITIVE_UNKNOWN: return false; break; } _index_size = 4; _vertex_data = new unsigned char[num_element * element_size]; _index_data = new unsigned char[_num_index * _index_size]; return true; } } ./NuxGraphics/NuxGraphicsObject.h0000644000004100000410000000000013313171755017225 0ustar www-datawww-data./NuxGraphics/GestureEvent.cpp0000644000004100000410000000402213313171755016626 0ustar www-datawww-data/* * Copyright 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Daniel d'Andrada * */ #include "GestureEvent.h" #include "NuxCore/Logger.h" using namespace nux; DECLARE_LOGGER(logger, "nux.gestureevent"); GestureEvent::GestureEvent() { // that's how many fingers you have on your hand (duh). // Can't have gestures with more than that many touch points. touches_.reserve(5); } void GestureEvent::Accept() { GeisStatus status; status = geis_gesture_accept(geis_, geis_group_, gesture_id_); if (status != GEIS_STATUS_SUCCESS) { LOG_WARNING(logger) << "Failed to accept gesture with id " << gesture_id_; } } void GestureEvent::Reject() { GeisStatus status; status = geis_gesture_reject(geis_, geis_group_, gesture_id_); if (status != GEIS_STATUS_SUCCESS) { LOG_WARNING(logger) << "Failed to reject gesture with id " << gesture_id_; } } void GestureEvent::Reset() { Event::Reset(); gesture_id_ = -1; gesture_classes_ = 0; timestamp_ = -1; focus_.x = focus_.y = 0.0f; delta_.x = delta_.y = 0.0f; angle_ = 0.0f; angle_delta_ = 0.0f; angular_velocity_ = 0.0f; tap_duration_ = -1; velocity_.x = velocity_.y = 0.0f; radius_ = 0.0f; radius_delta_ = 0.0f; radial_velocity_ = 0.0f; is_construction_finished_ = false; touches_.clear(); geis_ = nullptr; geis_group_ = nullptr; } ./NuxGraphics/GLResourceManager.cpp0000644000004100000410000001407213313171755017521 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "GLResource.h" #include "IOpenGLResource.h" #include "GLResourceManager.h" #include "GraphicsEngine.h" #include "GLTextureResourceManager.h" #include "GLVertexResourceManager.h" namespace nux { extern PixelFormatInfo GPixelFormats[]; NUX_IMPLEMENT_OBJECT_TYPE(ResourceData); NUX_IMPLEMENT_OBJECT_TYPE(CachedResourceData); ResourceData::ResourceData(NUX_FILE_LINE_DECL) : Object(true, NUX_FILE_LINE_PARAM) , m_ResourceIndex(NUX_INVALID_INDEX) { #define GET_UNIQUE_RESOURCE_INDEX NUX_GLOBAL_OBJECT_INSTANCE(UniqueIndex) m_ResourceIndex = GET_UNIQUE_RESOURCE_INDEX.GetUniqueIndex(); #undef GET_UNIQUE_RESOURCE_INDEX } ResourceData::~ResourceData() { // If the windows thread is deleted before any texture type resource, the // graphics display will not exist. GraphicsDisplay* display = GetGraphicsDisplay(); if (display) display->GetGraphicsEngine()->FlushCachedResourceData(this); } int ResourceData::GetResourceIndex() const { return m_ResourceIndex; } NResourceSet::NResourceSet() : FirstResource( NULL ) { if ( 1 ) { } } CachedResourceData::CachedResourceData(NResourceSet *ResourceManager) : Set(ResourceManager) , _cached(0) , NumRefs(0) , ResourceType(NULL) , Size(0) , UpdateHint(RUH_Static) { PrevResource = NULL; NextResource = Set->FirstResource; Set->FirstResource = this; if (NextResource) { NextResource->PrevResource = this; } } CachedResourceData::~CachedResourceData() { if (PrevResource) { PrevResource->NextResource = NextResource; } else { Set->FirstResource = NextResource; } if (NextResource) { NextResource->PrevResource = PrevResource; } if (_cached) { Set->FlushResource(this); _cached = false; } } void NResourceCache::InitializeResourceFactories() { // Define the factory pair ResourceData - CachedResourceData #define NUX_DEFINE_RESOURCE_FACTORY_PAIR(SourceTypeName, ResourceTypeName) \ static TGLResourceFactory Factory##SourceTypeName(&SourceTypeName::StaticObjectType); \ GetResourceFactories().push_back(&Factory##SourceTypeName); NUX_DEFINE_RESOURCE_FACTORY_PAIR(Texture2D, CachedTexture2D); NUX_DEFINE_RESOURCE_FACTORY_PAIR(TextureRectangle, CachedTextureRectangle); NUX_DEFINE_RESOURCE_FACTORY_PAIR(TextureCube, CachedTextureCube); NUX_DEFINE_RESOURCE_FACTORY_PAIR(TextureVolume, CachedTextureVolume); NUX_DEFINE_RESOURCE_FACTORY_PAIR(TextureFrameAnimation, CachedTextureFrameAnimation); NUX_DEFINE_RESOURCE_FACTORY_PAIR(VertexBuffer, CachedVertexBuffer); NUX_DEFINE_RESOURCE_FACTORY_PAIR(IndexBuffer, CachedIndexBuffer); NUX_DEFINE_RESOURCE_FACTORY_PAIR(VertexDeclaration, CachedVertexDeclaration); NUX_DEFINE_RESOURCE_FACTORY_PAIR(MeshBuffer, CachedMeshBuffer); #undef NUX_DEFINE_RESOURCE_FACTORY_PAIR // Define the factory updater for and ResourceData #define NUX_DEFINE_RESOURCE_UPDATER(SourceTypeName) \ static NResourceUpdater Updater##SourceTypeName(&SourceTypeName::StaticObjectType); \ GetResourceUpdaters().push_back(&Updater##SourceTypeName); NUX_DEFINE_RESOURCE_UPDATER(Texture2D); NUX_DEFINE_RESOURCE_UPDATER(TextureRectangle); NUX_DEFINE_RESOURCE_UPDATER(TextureCube); NUX_DEFINE_RESOURCE_UPDATER(TextureVolume); NUX_DEFINE_RESOURCE_UPDATER(TextureFrameAnimation); NUX_DEFINE_RESOURCE_UPDATER(VertexBuffer); NUX_DEFINE_RESOURCE_UPDATER(IndexBuffer); NUX_DEFINE_RESOURCE_UPDATER(VertexDeclaration); NUX_DEFINE_RESOURCE_UPDATER(MeshBuffer); #undef NUX_DEFINE_RESOURCE_UPDATER } ObjectPtr NResourceCache::GetCachedResource(ResourceData *Source) { NUX_RETURN_VALUE_IF_NULL(Source, ObjectPtr(0)); // check to see if it already exists ObjectPtr CachedResource = TResourceCache::FindCachedResourceById(Source->GetResourceIndex()); if (CachedResource.IsNull()) { // iterate over the list of factory types for (unsigned int i = 0; i < GetResourceFactories().size(); ++i) { NResourceFactory *ResourceFactory = GetResourceFactories() [i]; // check if the factory is valid for the source resource type if (ResourceFactory->BuildsThisResource(Source)) { // cache the device resource CachedResourceData* ptr = ResourceFactory->BuildResource(this, Source); CachedResource = ObjectPtr (ptr); ptr->UnReference(); break; } } // make sure the result is valid if (CachedResource.IsNull()) { nuxError("Cannot cache resource type %s", Source->Type().name ); } else { // Get resource type CachedResource->ResourceType = & (Source->Type()); // add it to the pool of cached resources AddCachedResource(Source->GetResourceIndex(), CachedResource); } } return CachedResource; } bool NResourceCache::IsCachedResource(ResourceData *Source) { ObjectPtr CachedResource = TResourceCache< int, CachedResourceData >::FindCachedResourceById(Source->GetResourceIndex()); return(CachedResource.IsValid()); } } ./NuxGraphics/GLRenderingAPI.cpp0000644000004100000410000000151613313171755016705 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "GraphicsEngine.h" namespace nux { } ./NuxGraphics/GLShaderParameter.cpp0000644000004100000410000000271413313171755017506 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "NuxCore/NuxCore.h" #include "GLShader.h" #include "GLDeviceObjects.h" #include "GLShaderParameter.h" namespace nux { GLShaderParameter::GLShaderParameter(GLProgramObject *Shader, const char *ParamName, eShaderParameterType ParamType, bool IsOptional, bool IsStatic) : m_ShaderParameterType(ParamType) , m_Name(ParamName) , m_bIsOptional(IsOptional) , m_bIsStatic(IsStatic) , m_ShaderProgram(Shader) , m_ShaderProgram2(0) , m_NextParameter(0) { m_Index = -1; } } ./NuxGraphics/GLResource.h0000644000004100000410000004104213313171755015670 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef GLRESOURCE_H #define GLRESOURCE_H #include "NuxCore/NuxCore.h" #include "NuxCore/Error.h" #include "NuxCore/FilePath.h" #include "NuxCore/Color.h" #include "NuxCore/Rect.h" #include "NuxCore/Point.h" #include "NuxCore/Size.h" #include "BitmapFormats.h" #include "NuxCore/Parsing.h" #include "NuxCore/Object.h" #include "NuxCore/ObjectPtr.h" #include "NuxCore/Math/MathUtility.h" #include "NuxCore/Math/Constants.h" #include "NuxCore/Math/Vector3.h" #include "NuxCore/Math/Vector4.h" #include "NuxCore/Math/Matrix3.h" #include "NuxCore/Math/Matrix4.h" #include "NuxCore/Math/Spline.h" #include "NuxCore/Math/MathFunctions.h" #include "ImageSurface.h" namespace nux { class IOpenGLResource; class BaseTexture; class Texture2D; class TextureRectangle; class TextureCube; class TextureVolume; class TextureFrameAnimation; class BaseMeshBuffer; class NIndexBuffer; class CachedTexture2D; class CachedTextureRectangle; class CachedTextureCube; class CachedTextureVolume; class CachedTextureFrameAnimation; class FontTexture; } #define NUX_ENABLE_CG_SHADERS 0 #if defined(NUX_OS_WINDOWS) #include "GL/glew.h" #include "GL/wglew.h" GLEWContext *glewGetContext(); WGLEWContext *wglewGetContext(); #if (NUX_ENABLE_CG_SHADERS) #include "CG/cg.h" #include "CG/cgGL.h" #pragma comment( lib, "cg.lib" ) #pragma comment( lib, "cgGL.lib" ) #endif #elif defined(NUX_OS_LINUX) #ifdef NUX_OPENGLES_20 #include "NuxGraphics/OpenGLMapping.h" #include "EGL/egl.h" #include "GLES2/gl2.h" #include "GLES2/gl2ext.h" #else #ifndef GLEW_MX #define GLEW_MX #endif #include "GL/glew.h" #include "GL/glxew.h" GLEWContext *glewGetContext(); GLXEWContext *glxewGetContext(); #if (NUX_ENABLE_CG_SHADERS) #include "Cg/cg.h" #include "Cg/cgGL.h" #endif #endif #ifdef USE_X11 // Explicitly include X11 headers as many EGL implementations don't // do it for us. #include #include #endif #endif #include "RunTimeStats.h" #include "NuxGraphicsResources.h" #include "FontTexture.h" #include "GlobalGraphicsInitializer.h" #include "GLError.h" #define CG_FRAGMENT_PROFILE CG_PROFILE_FP30 #define CG_VERTEX_PROFILE CG_PROFILE_VP30 #define NUX_BUFFER_OFFSET(i) ((BYTE *)NULL + (i)) namespace nux { enum { OGL_OK = 0, OGL_ERROR, OGL_ERROR_UNKNOWN, OGL_INVALID_SURFACE_LEVEL, OGL_INVALID_CALL, OGL_INVALID_LOCK, OGL_INVALID_UNLOCK, OGL_INVALID_TEXTURE, OGL_FORCE_DWORD = 0x7fffffff /* force 32-bit size enum */ }; extern const char *OGLDeviceErrorMessages[]; #define OGL_OK 0 #define OGL_CALL(call) \ { \ int Result = call; \ if (Result != OGL_OK) \ {nuxError("OGL Object Error: Error # %d - (%s) ", Result, *OGLDeviceErrorMessages[Result] );} \ } //if(Result!=OGL_OK) {nuxError("OGL Object Error: Error # %d - %s", Result, OGLDeviceErrorMessages[Result]);} #ifndef NUX_OPENGLES_20 enum TEXTURE_FORMAT { TEXTURE_FMT_UNKNOWN = 0, TEXTURE_FMT_ALPHA = GL_ALPHA, TEXTURE_FMT_ALPHA8 = GL_ALPHA8, TEXTURE_FMT_ALPHA16 = GL_ALPHA16, TEXTURE_FMT_LUMINANCE = GL_LUMINANCE, TEXTURE_FMT_LUMINANCE8 = GL_LUMINANCE8, TEXTURE_FMT_LUMINANCE16 = GL_LUMINANCE16, TEXTURE_FMT_LUMINANCE_ALPHA = GL_LUMINANCE_ALPHA, TEXTURE_FMT_LUMINANCE8_ALPHA8 = GL_LUMINANCE8_ALPHA8, TEXTURE_FMT_LUMINANCE16_ALPHA16 = GL_LUMINANCE16_ALPHA16, TEXTURE_FMT_INTENSITY = GL_INTENSITY, TEXTURE_FMT_INTENSITY8 = GL_INTENSITY8, TEXTURE_FMT_INTENSITY16 = GL_INTENSITY16, TEXTURE_FMT_GL_DEPTH_COMPONENT = GL_DEPTH_COMPONENT, TEXTURE_FMT_GL_DEPTH_COMPONENT24 = GL_DEPTH_COMPONENT24, TEXTURE_FMT_RGBA = GL_RGBA, TEXTURE_FMT_RGBA8 = GL_RGBA8, TEXTURE_FMT_RGBA16 = GL_RGBA16, TEXTURE_FMT_RGBA16F_ARB = GL_RGBA16F_ARB, TEXTURE_FMT_RGBA32F_ARB = GL_RGBA32F_ARB, TEXTURE_FMT_RGB = GL_RGB, TEXTURE_FMT_RGB8 = GL_RGB8, TEXTURE_FMT_RGB16 = GL_RGB16, TEXTURE_FMT_RGB16F_ARB = GL_RGB16F_ARB, TEXTURE_FMT_RGB32F_ARB = GL_RGB32F_ARB, TEXTURE_FMT_COMPRESSED_RGB_S3TC_DXT1_EXT = GL_COMPRESSED_RGB_S3TC_DXT1_EXT, TEXTURE_FMT_COMPRESSED_RGBA_S3TC_DXT1_EXT = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, TEXTURE_FMT_COMPRESSED_RGBA_S3TC_DXT3_EXT = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, TEXTURE_FMT_COMPRESSED_RGBA_S3TC_DXT5_EXT = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, TEXTURE_FMT_FORCE_DWORD = 0x7fffffff /* force 32-bit size enum */ }; #else enum TEXTURE_FORMAT { TEXTURE_FMT_UNKNOWN = 0, TEXTURE_FMT_ALPHA = GL_ALPHA, TEXTURE_FMT_LUMINANCE = GL_LUMINANCE, TEXTURE_FMT_LUMINANCE_ALPHA = GL_LUMINANCE_ALPHA, TEXTURE_FMT_GL_DEPTH_COMPONENT = GL_DEPTH_COMPONENT, TEXTURE_FMT_RGBA = GL_RGBA, TEXTURE_FMT_RGB = GL_RGB, TEXTURE_FMT_FORCE_DWORD = 0x7fffffff /* force 32-bit size enum */ }; #endif struct PixelFormatReadInfo { const char *Name; GLenum Format; // format use for glReadPixels GLenum type; // type use for glReadPixels // Format specific internal flags, e.g. whether SRGB is supported with this format DWORD Flags; bool Supported; }; enum eCUBEMAP_FACES { CUBEMAP_FACE_POSITIVE_X = GL_TEXTURE_CUBE_MAP_POSITIVE_X, CUBEMAP_FACE_NEGATIVE_X = GL_TEXTURE_CUBE_MAP_NEGATIVE_X, CUBEMAP_FACE_POSITIVE_Y = GL_TEXTURE_CUBE_MAP_POSITIVE_Y, CUBEMAP_FACE_NEGATIVE_Y = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, CUBEMAP_FACE_POSITIVE_Z = GL_TEXTURE_CUBE_MAP_POSITIVE_Z, CUBEMAP_FACE_NEGATIVE_Z = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, CUBEMAP_FACE_FORCE_DWORD = 0x7fffffff }; enum VBO_USAGE { VBO_USAGE_UNKNOWN = 0, VBO_USAGE_STATIC = GL_STATIC_DRAW, VBO_USAGE_DYNAMIC = GL_DYNAMIC_DRAW, VBO_USAGE_STREAM = GL_STREAM_DRAW, VBO_USAGE_FORCE_DWORD = 0x7fffffff /* force 32-bit size enum */ }; enum INDEX_FORMAT { INDEX_FORMAT_UNKNOWN = 0, INDEX_FORMAT_USHORT = GL_UNSIGNED_SHORT, INDEX_FORMAT_UINT = GL_UNSIGNED_INT, INDEX_FORMAT_FORCE_DWORD = 0x7fffffff /* force 32-bit size enum */ }; // Primitives supported by draw-primitive API typedef enum { PRIMITIVE_TYPE_POINTLIST = GL_POINTS, PRIMITIVE_TYPE_LINELIST = GL_LINES, PRIMITIVE_TYPE_LINESTRIP = GL_LINE_STRIP, PRIMITIVE_TYPE_TRIANGLELIST = GL_TRIANGLES, PRIMITIVE_TYPE_TRIANGLESTRIP = GL_TRIANGLE_STRIP, PRIMITIVE_TYPE_TRIANGLEFAN = GL_TRIANGLE_FAN, #ifndef NUX_OPENGLES_20 PRIMITIVE_TYPE_QUADLIST = GL_QUADS, PRIMITIVE_TYPE_QUADSTRIP = GL_QUAD_STRIP, #endif PRIMITIVE_TYPE_FORCE_DWORD = 0x7fffffff /* force 32-bit size enum */ } PRIMITIVE_TYPE; enum OpenGLResourceType { RTINDEXBUFFER, RTVERTEXBUFFER, RTSURFACE, RTVOLUME, RTBASETEXTURE, RTTEXTURE, RTTEXTURERECTANGLE, RTCUBETEXTURE, RTVOLUMETEXTURE, RTANIMATEDTEXTURE, RTVERTEXDECLARATION, RTQUERY, RTFRAMEBUFFEROBJECT, RT_GLSL_VERTEXSHADER, RT_GLSL_PIXELSHADER, RT_GLSL_GEOMETRYSHADER, RT_GLSL_SHADERPROGRAM, RT_CG_VERTEXSHADER, RT_CG_PIXELSHADER, RT_FORCE_DWORD = 0x7fffffff /* force 32-bit size enum */ }; /* Multi-Sample buffer types */ typedef enum { MULTISAMPLE_TYPE_NONE = 0, MULTISAMPLE_TYPE_NONMASKABLE = 1, MULTISAMPLE_TYPE_2_SAMPLES = 2, MULTISAMPLE_TYPE_3_SAMPLES = 3, MULTISAMPLE_TYPE_4_SAMPLES = 4, MULTISAMPLE_TYPE_5_SAMPLES = 5, MULTISAMPLE_TYPE_6_SAMPLES = 6, MULTISAMPLE_TYPE_7_SAMPLES = 7, MULTISAMPLE_TYPE_8_SAMPLES = 8, MULTISAMPLE_TYPE_9_SAMPLES = 9, MULTISAMPLE_TYPE_10_SAMPLES = 10, MULTISAMPLE_TYPE_11_SAMPLES = 11, MULTISAMPLE_TYPE_12_SAMPLES = 12, MULTISAMPLE_TYPE_13_SAMPLES = 13, MULTISAMPLE_TYPE_14_SAMPLES = 14, MULTISAMPLE_TYPE_15_SAMPLES = 15, MULTISAMPLE_TYPE_16_SAMPLES = 16, MULTISAMPLE_TYPE_FORCE_DWORD = 0x7fffffff /* force 32-bit size enum */ } MULTISAMPLE_TYPE; typedef enum { MEM_POOL_DEFAULT = 0, MEM_POOL_MANAGED = 1, MEM_POOL_SYSTEMMEM = 2, MEM_POOL_SCRATCH = 3, MEM_POOL_FORCE_DWORD = 0x7fffffff /* force 32-bit size enum */ } MEM_POOL; typedef struct { OpenGLResourceType ResourceType; unsigned int Width; unsigned int Height; unsigned int Depth; BitmapFormat PixelFormat; unsigned int RowPitch; unsigned int SlicePitch; unsigned int BitsPerPixel; unsigned int WidthInBlocks; unsigned int HeightInBlocks; unsigned int DepthInBlocks; unsigned int BytesPerBlock; int ExpBias; DWORD Flags; MULTISAMPLE_TYPE MultiSampleType; } TEXTURE_DESC; typedef struct _SURFACE_DESC { BitmapFormat PixelFormat; OpenGLResourceType Type; DWORD Usage; MEM_POOL Pool; MULTISAMPLE_TYPE MultiSampleType; DWORD MultiSampleQuality; unsigned int Width; unsigned int Height; } SURFACE_DESC; typedef struct _VOLUME_DESC { BitmapFormat PixelFormat; OpenGLResourceType Type; DWORD Usage; MEM_POOL Pool; unsigned int Width; unsigned int Height; unsigned int Depth; } VOLUME_DESC; typedef struct _ANIMATEDTEXTURE_DESC { BitmapFormat PixelFormat; OpenGLResourceType Type; DWORD Usage; MEM_POOL Pool; unsigned int Width; unsigned int Height; unsigned int Depth; } ANIMATEDTEXTURE_DESC; typedef struct _VERTEXBUFFER_DESC { VBO_USAGE Usage; unsigned int Size; } VERTEXBUFFER_DESC; typedef struct _INDEXBUFFER_DESC { INDEX_FORMAT Format; VBO_USAGE Usage; unsigned int Size; } INDEXBUFFER_DESC; typedef struct _LOCKED_RECT { int Pitch; void *pBits; } SURFACE_LOCKED_RECT; typedef struct _SURFACE_RECT { long left; //Specifies the x-coordinate of the lower-left corner of the rectangle. long top; //Specifies the y-coordinate of the lower-left corner of the rectangle. long right; //Specifies the x-coordinate of the upper-right corner of the rectangle. long bottom; //Specifies the y-coordinate of the upper-right corner of the rectangle. } SURFACE_RECT; /* Structures for LockBox */ typedef struct _VOLUME_BOX { int Left; int Top; int Right; int Bottom; int Front; int Back; } VOLUME_BOX; typedef struct _VOLUME_LOCKED_BOX { int RowPitch; int SlicePitch; void *pBits; } VOLUME_LOCKED_BOX; typedef enum _ATTRIB_DECL_TYPE { ATTRIB_DECLTYPE_UNKNOWN = 0, ATTRIB_DECLTYPE_FLOAT1, ATTRIB_DECLTYPE_FLOAT2, ATTRIB_DECLTYPE_FLOAT3, ATTRIB_DECLTYPE_FLOAT4, ATTRIB_DECLTYPE_COLOR, ATTRIB_DECLTYPE_UBYTE4, ATTRIB_DECLTYPE_SHORT2, ATTRIB_DECLTYPE_SHORT4, ATTRIB_DECLTYPE_UBYTE4N, ATTRIB_DECLTYPE_SHORT2N, ATTRIB_DECLTYPE_SHORT4N, ATTRIB_DECLTYPE_USHORT2N, ATTRIB_DECLTYPE_USHORT4N, ATTRIB_DECLTYPE_UDEC3, ATTRIB_DECLTYPE_DEC3N, ATTRIB_DECLTYPE_FLOAT16_2, ATTRIB_DECLTYPE_FLOAT16_4, ATTRIB_DECLTYPE_UNUSED, ATTRIB_DECLTYPE_FORCE_DWORD = 0x7fffffff /* force 32-bit size enum */ } ATTRIB_DECL_TYPE; typedef enum _ATTRIB_COMPONENT_TYPE { ATTRIB_CT_UNKNOWN = 0, ATTRIB_CT_BYTE = GL_BYTE, ATTRIB_CT_UNSIGNED_BYTE = GL_UNSIGNED_BYTE, ATTRIB_CT_SHORT = GL_SHORT, ATTRIB_CT_UNSIGNED_SHORT = GL_UNSIGNED_SHORT, ATTRIB_CT_INT = GL_INT, ATTRIB_CT_UNSIGNED_INT = GL_UNSIGNED_INT, ATTRIB_CT_FLOAT = GL_FLOAT, #ifndef NUX_OPENGLES_20 ATTRIB_CT_HALF_FLOAT = GL_HALF_FLOAT_ARB, // ATTRIB_CT_2_BYTES = GL_2_BYTES, // ATTRIB_CT_3_BYTES = GL_3_BYTES, // ATTRIB_CT_4_BYTES = GL_4_BYTES, ATTRIB_CT_DOUBLE = GL_DOUBLE, #endif // Type can be GL_UNSIGNED_BYTE, GL_SHORT, GL_INT, GL_FLOAT, GL_DOUBLE ATTRIB_CT_FORCE_DWORD = 0x7fffffff /* force 32-bit size enum */ } ATTRIB_COMPONENT_TYPE; // Binding Semantics typedef enum { ATTRIB_USAGE_DECL_POSITION = 0, ATTRIB_USAGE_DECL_BLENDWEIGHT = 1, ATTRIB_USAGE_DECL_NORMAL = 2, ATTRIB_USAGE_DECL_COLOR = 3, ATTRIB_USAGE_DECL_COLOR1 = 4, ATTRIB_USAGE_DECL_FOGCOORD = 5, ATTRIB_USAGE_DECL_PSIZE = 6, ATTRIB_USAGE_DECL_BLENDINDICES = 7, ATTRIB_USAGE_DECL_TEXCOORD = 8, ATTRIB_USAGE_DECL_TEXCOORD0 = 8, ATTRIB_USAGE_DECL_TEXCOORD1 = 9, ATTRIB_USAGE_DECL_TEXCOORD2 = 10, ATTRIB_USAGE_DECL_TEXCOORD3 = 11, ATTRIB_USAGE_DECL_TEXCOORD4 = 12, ATTRIB_USAGE_DECL_TEXCOORD5 = 13, ATTRIB_USAGE_DECL_TEXCOORD6 = 14, ATTRIB_USAGE_DECL_TEXCOORD7 = 15, ATTRIB_USAGE_DECL_TANGENT = 14, ATTRIB_USAGE_DECL_BINORMAL = 15, ATTRIB_USAGE_DECL_FORCE_DWORD = 0x7fffffff /* force 32-bit size enum */ } ATTRIB_USAGE_DECL; typedef enum { QUERY_TYPE_VCACHE = 4, QUERY_TYPE_RESOURCEMANAGER = 5, QUERY_TYPE_VERTEXSTATS = 6, QUERY_TYPE_EVENT = 8, QUERY_TYPE_OCCLUSION = 9, QUERY_TYPE_SCREENEXTENT = 10, QUERY_TYPE_FORCE_DWORD = 0x7fffffff /* force 32-bit size enum */ } QUERY_TYPE; // Flags field for Issue #define ISSUE_END (1 << 0) // Tells the runtime to issue the end of a query, changing it's state to "non-signaled". #define ISSUE_BEGIN (1 << 1) // Tells the runtime to issue the beginning of a query. struct VERTEXELEMENT { VERTEXELEMENT() { Stream = 0; Offset = 0; Type = ATTRIB_CT_UNKNOWN; NumComponent = 0; stride_ = 0; } VERTEXELEMENT( int stream, int offset, ATTRIB_COMPONENT_TYPE type, BYTE numcomponents, int stride) { Stream = stream; Offset = offset; Type = type; NumComponent = numcomponents; stride_ = stride; } int Stream; intptr_t Offset; // Type can be GL_UNSIGNED_BYTE, GL_SHORT, GL_INT, GL_FLOAT, GL_DOUBLE ... ATTRIB_COMPONENT_TYPE Type; // This can be 1, 2, 3 or 4; For a position(xyzw), it will be 4. For a texture coordinate(uv) it will be 2. int NumComponent; int stride_; }; #define DECL_END VERTEXELEMENT( \ 0xFF, \ 0, \ ATTRIB_CT_UNKNOWN, \ 0, 0) unsigned int GetVertexElementSize(VERTEXELEMENT vtxelement); #define MAXDECLLENGTH 64 #define MAX_NUM_STREAM 8 void DecomposeTypeDeclaraction(ATTRIB_DECL_TYPE Type, BYTE &NumComponent, ATTRIB_COMPONENT_TYPE &ComponentType); // void AddVertexElement(std::vector& Elements, // WORD Stream, // WORD Offset, // //ubiS16 Stride, // ATTRIB_DECL_TYPE Type, // ATTRIB_USAGE_DECL Usage, // BYTE UsageIndex); GLenum GetGLPrimitiveType(PRIMITIVE_TYPE InPrimitiveType); unsigned int GetGLElementCount(PRIMITIVE_TYPE InPrimitiveType, unsigned int InPrimitiveCount); } #endif // GLRESOURCE_H ./NuxGraphics/NuxGraphicsResources.cpp0000644000004100000410000001455413313171755020347 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "GLResource.h" #include "FontTexture.h" #include "NuxGraphicsResources.h" #include "GLResourceManager.h" namespace nux { NUX_IMPLEMENT_GLOBAL_OBJECT(NuxGraphicsResources); void NuxGraphicsResources::Constructor() { } void NuxGraphicsResources::Destructor() { } void NuxGraphicsResources::InitializeResources() { #ifdef NUX_OS_LINUX m_ResourcePathLocation.AddSearchPath(PKGDATADIR); m_ResourcePathLocation.AddSearchPath(PKGDATADIR"/Fonts"); m_ResourcePathLocation.AddSearchPath(PKGDATADIR"/Meshes"); m_ResourcePathLocation.AddSearchPath(PKGDATADIR"/UITextures"); #ifdef NUX_DEBUG /* For examples */ m_ResourcePathLocation.AddSearchPath("../data"); m_ResourcePathLocation.AddSearchPath("../data/Fonts"); m_ResourcePathLocation.AddSearchPath("../data/Meshes"); m_ResourcePathLocation.AddSearchPath("../data/UITextures"); #endif #else m_ResourcePathLocation.AddSearchPath(""); m_ResourcePathLocation.AddSearchPath("./"); m_ResourcePathLocation.AddSearchPath("../"); m_ResourcePathLocation.AddSearchPath("../../"); m_ResourcePathLocation.AddSearchPath("./Data"); m_ResourcePathLocation.AddSearchPath("../Data"); m_ResourcePathLocation.AddSearchPath("../../Data"); m_ResourcePathLocation.AddSearchPath("../../../Data"); m_ResourcePathLocation.AddSearchPath("./Data/Fonts"); m_ResourcePathLocation.AddSearchPath("../Data/Fonts"); m_ResourcePathLocation.AddSearchPath("../../Data/Fonts"); m_ResourcePathLocation.AddSearchPath("../../../Data/Fonts"); m_ResourcePathLocation.AddSearchPath("./Data/UITextures"); m_ResourcePathLocation.AddSearchPath("../Data/UITextures"); m_ResourcePathLocation.AddSearchPath("../../Data/UITextures"); m_ResourcePathLocation.AddSearchPath("../../../Data/UITextures"); #endif m_ResourcePathLocation.AddSearchPath(m_FontSearchPath); m_ResourcePathLocation.AddSearchPath(m_ShaderSearchPath); m_ResourcePathLocation.AddSearchPath(m_UITextureSearchPath); } #ifdef NUX_OS_WINDOWS std::string NuxGraphicsResources::FindResourceLocation(const char *ResourceFileName, bool ErrorOnFail) { std::string path = m_ResourcePathLocation.GetFile(ResourceFileName); if (path == "" && ErrorOnFail) { nuxCriticalMsg("[NuxGraphicsResources::FindResourceLocation] Failed to locate resource file: %s.", ResourceFileName); return std::string(""); } return path; } std::string NuxGraphicsResources::FindUITextureLocation(const char *ResourceFileName, bool ErrorOnFail) { FilePath searchpath; searchpath.AddSearchPath(m_UITextureSearchPath); std::string path = searchpath.GetFile(ResourceFileName); if ((path == "") && ErrorOnFail) { nuxCriticalMsg("[NuxGraphicsResources::FindResourceLocation] Failed to locate ui texture file: %s.", ResourceFileName); return std::string(""); } return path; } std::string NuxGraphicsResources::FindShaderLocation(const char *ResourceFileName, bool ErrorOnFail) { FilePath searchpath; searchpath.AddSearchPath(m_ShaderSearchPath); std::string path = searchpath.GetFile(ResourceFileName); if ((path == "") && ErrorOnFail) { nuxCriticalMsg("[NuxGraphicsResources::FindResourceLocation] Failed to locate shader file: %s.", ResourceFileName); return std::string(""); } return path; } std::string NuxGraphicsResources::FindFontLocation(const char *ResourceFileName, bool ErrorOnFail) { FilePath searchpath; searchpath.AddSearchPath(m_FontSearchPath); std::string path = searchpath.GetFile(ResourceFileName); if ((path == "") && ErrorOnFail) { nuxCriticalMsg("[NuxGraphicsResources::FindResourceLocation] Failed to locate font file file: %s.", ResourceFileName); return std::string(""); } return path; } #elif defined(NUX_OS_LINUX) std::string NuxGraphicsResources::FindResourceLocation(const char *ResourceFileName, bool ErrorOnFail) { std::string path = m_ResourcePathLocation.GetFile(ResourceFileName); if (path == "" && ErrorOnFail) { nuxCriticalMsg("[NuxGraphicsResources::FindResourceLocation] Failed to locate resource file: %s.", ResourceFileName); return ""; } return path; } std::string NuxGraphicsResources::FindUITextureLocation(const char *ResourceFileName, bool ErrorOnFail) { FilePath searchpath; searchpath.AddSearchPath(m_UITextureSearchPath); std::string path = searchpath.GetFile(ResourceFileName); if ((path == "") && ErrorOnFail) { nuxCriticalMsg("[NuxGraphicsResources::FindResourceLocation] Failed to locate ui texture file: %s.", ResourceFileName); return std::string(""); } return path; } std::string NuxGraphicsResources::FindShaderLocation(const char *ResourceFileName, bool ErrorOnFail) { FilePath searchpath; searchpath.AddSearchPath(m_ShaderSearchPath); std::string path = searchpath.GetFile(ResourceFileName); if ((path == "") && ErrorOnFail) { nuxCriticalMsg("[NuxGraphicsResources::FindResourceLocation] Failed to locate shader file: %s.", ResourceFileName); return std::string(""); } return path; } std::string NuxGraphicsResources::FindFontLocation(const char *ResourceFileName, bool ErrorOnFail) { FilePath searchpath; searchpath.AddSearchPath(m_FontSearchPath); std::string path = searchpath.GetFile(ResourceFileName); if ((path == "") && ErrorOnFail) { nuxCriticalMsg("[NuxGraphicsResources::FindResourceLocation] Failed to locate font file file: %s.", ResourceFileName); return std::string(""); } return path; } #endif } ./NuxGraphics/GLWindowManager.cpp0000644000004100000410000001454113313171755017202 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "NuxCore/NuxCore.h" #include "GLWindowManager.h" namespace nux { #if defined(NUX_OS_WINDOWS) const char *WINDOW_CLASS_NAME = "InalogicWindowClass"; HINSTANCE gInstance = 0; #endif DisplayAccessController *DisplayAccessController::m_pInstance = 0; DisplayAccessController::DisplayAccessController() { #if defined(NUX_OS_WINDOWS) // Register Windows Class // Get hInstance of current application. if (gInstance == 0) hInstance = GetModuleHandle(NULL); else hInstance = gInstance; WinClass.cbSize = sizeof(WNDCLASSEX); // CS_CLASSDC Specifies that one device context is shared between all windows created with this class. // CS_DBLCLKS This is needed if you want to be able to detect double mouse clicks made on the window. // CS_HREDRAW The window is redrawn if there is a change in the window's width or if the window is moved horizontally. // CS_NOCLOSE Disables the close option on the window menu. // CS_OWNDC A unique device context is created for each window created. This is the opposite to CS_CLASSDC. // CS_PARENTDC This sets the clipping rectangle of the child window to that of the parent window. This allows the child window to be able to draw on the parent window. // CS_VREDRAW The window is redrawn if there is a change in the window's height or if the window is moved vertically. WinClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS; // Redraw On Size, And Own DC For Window. WinClass.lpfnWndProc = (WNDPROC) WndProcManager; // WndProc Handles Messages WinClass.cbClsExtra = 0; // No Extra Window Data WinClass.cbWndExtra = 0; // No Extra Window Data WinClass.hInstance = hInstance; // Set The Instance WinClass.hIcon = LoadIcon(hInstance, "IDI_INALOGIC"); //LoadIcon(NULL, IDI_WINLOGO); // Load The Default Icon WinClass.hCursor = LoadCursor(NULL, IDC_ARROW); // Class cursor: Load The Arrow Pointer WinClass.hbrBackground = NULL; //(HBRUSH)GetStockObject(BLACK_BRUSH); // No Background Required For GL WinClass.lpszMenuName = NULL; // We Don't Want A Menu WinClass.lpszClassName = WINDOW_CLASS_NAME; //gClassName; // Set The Class Name WinClass.hIconSm = LoadIcon(hInstance, "IDI_INALOGIC"); if (!RegisterClassEx(&WinClass)) // Attempt To Register The Window Class { nuxCriticalMsg("[DisplayAccessController::~DisplayAccessController] Failed to register window class name: %s.", WINDOW_CLASS_NAME); } #endif } DisplayAccessController::~DisplayAccessController() { #if defined(NUX_OS_WINDOWS) if (!UnregisterClass(WINDOW_CLASS_NAME, hInstance)) // Are We Able To Unregister Class { nuxDebugMsg("[DisplayAccessController::~DisplayAccessController] Failed to unregister window class name: %s.", WINDOW_CLASS_NAME); hInstance = NULL; // Set hInstance To NULL } #endif } DisplayAccessController &DisplayAccessController::Instance() { if (m_pInstance == 0) { m_pInstance = new DisplayAccessController(); } return *m_pInstance; } GraphicsDisplay *DisplayAccessController::CreateGLWindow(const char *WindowTitle, unsigned int WindowWidth, unsigned int WindowHeight, WindowStyle Style, GraphicsDisplay *GLWindow, bool fullscreen_flag, bool create_rendering_data) { if (GetGraphicsDisplay()) { // A GlWindow already exist for this thread. nuxAssertMsg(0, "Only one GLWindow per thread is allowed"); return 0; } GraphicsDisplay *glwindow = new GraphicsDisplay(); glwindow->CreateOpenGLWindow(WindowTitle, WindowWidth, WindowHeight, Style, GLWindow, fullscreen_flag, create_rendering_data); return glwindow; } #if defined(NUX_OS_WINDOWS) GraphicsDisplay *DisplayAccessController::CreateFromForeignWindow(HWND WindowHandle, HDC WindowDCHandle, HGLRC OpenGLRenderingContext) { if (GetGraphicsDisplay()) { // A GlWindow already exist for this thread. nuxAssertMsg(0, "Only one GLWindow per thread is allowed"); return 0; } GraphicsDisplay *glwindow = new GraphicsDisplay(); glwindow->CreateFromOpenGLWindow(WindowHandle, WindowDCHandle, OpenGLRenderingContext); return glwindow; } #elif defined(USE_X11) # ifdef NUX_OPENGLES_20 GraphicsDisplay *DisplayAccessController::CreateFromForeignWindow(Display *X11Display, Window X11Window, EGLContext OpenGLContext) # else GraphicsDisplay *DisplayAccessController::CreateFromForeignWindow(Display *X11Display, Window X11Window, GLXContext OpenGLContext) # endif { if (GetGraphicsDisplay()) { // A GlWindow already exist for this thread. nuxAssertMsg(0, "Only one GLWindow per thread is allowed"); return 0; } GraphicsDisplay *glwindow = new GraphicsDisplay(); glwindow->CreateFromOpenGLWindow(X11Display, X11Window, OpenGLContext); return glwindow; } #endif } // namespace nux #ifndef NUX_OPENGLES_20 GLEWContext *glewGetContext() { return nux::GetGraphicsDisplay()->GetGLEWContext(); } #endif #if defined(NUX_OS_WINDOWS) WGLEWContext *wglewGetContext() { return nux::GetGraphicsDisplay()->GetWGLEWContext(); } #elif defined(NUX_OS_LINUX) && !defined(NUX_OPENGLES_20) GLXEWContext *glxewGetContext() { return nux::GetGraphicsDisplay()->GetGLXEWContext(); } #endif ./NuxGraphics/GraphicsDisplayX11.cpp0000755000004100000410000025252013313171755017601 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "GLResource.h" #include "GpuDevice.h" #include "GLDeviceObjects.h" #include "GLResourceManager.h" #include "GLTextureResourceManager.h" #include "GLVertexResourceManager.h" #include "GraphicsEngine.h" #include "GLWindowManager.h" #include "Events.h" #include "GraphicsDisplay.h" #include #include namespace nux { Time GraphicsDisplay::double_click_time_delay = 400; // milliseconds namespace atom { namespace { Atom XdndPosition = 0; Atom XdndEnter = 0; Atom XdndStatus = 0; Atom XdndLeave = 0; Atom XdndDrop = 0; Atom XdndAware = 0; Atom XdndFinished = 0; Atom XdndSelection = 0; Atom XdndTypeList = 0; Atom XdndActionMove = 0; Atom XdndActionCopy = 0; Atom XdndActionPrivate = 0; Atom XdndActionLink = 0; Atom XdndActionAsk = 0; Atom WM_DELETE_WINDOW = 0; Atom _NET_WM_STATE_STICKY = 0; Atom _NET_WM_STATE_SKIP_TASKBAR = 0; Atom _NET_WM_STATE_SKIP_PAGER = 0; Atom _NET_WM_STATE_ABOVE = 0; Atom _NET_WM_STATE = 0; Atom _NET_WM_WINDOW_TYPE = 0; Atom _NET_WM_WINDOW_TYPE_UTILITY = 0; Atom _NET_WM_WINDOW_TYPE_DND = 0; void initialize(Display *dpy) { XdndPosition = XInternAtom(dpy, "XdndPosition", False); XdndEnter = XInternAtom(dpy, "XdndEnter", False); XdndStatus = XInternAtom(dpy, "XdndStatus", False); XdndLeave = XInternAtom(dpy, "XdndLeave", False); XdndDrop = XInternAtom(dpy, "XdndDrop", False); XdndAware = XInternAtom(dpy, "XdndAware", False); XdndFinished = XInternAtom(dpy, "XdndFinished", False); XdndSelection = XInternAtom(dpy, "XdndSelection", False); XdndTypeList = XInternAtom(dpy, "XdndTypeList", False); XdndActionMove = XInternAtom(dpy, "XdndActionMove", False); XdndActionCopy = XInternAtom(dpy, "XdndActionCopy", False); XdndActionPrivate = XInternAtom(dpy, "XdndActionPrivate", False); XdndActionLink = XInternAtom(dpy, "XdndActionLink", False); XdndActionAsk = XInternAtom(dpy, "XdndActionAsk", False); WM_DELETE_WINDOW = XInternAtom(dpy, "WM_DELETE_WINDOW", False); _NET_WM_STATE_STICKY = XInternAtom(dpy, "_NET_WM_STATE_STICKY", False); _NET_WM_STATE_SKIP_TASKBAR = XInternAtom(dpy, "_NET_WM_STATE_SKIP_TASKBAR", False); _NET_WM_STATE_SKIP_PAGER = XInternAtom(dpy, "_NET_WM_STATE_SKIP_PAGER", False); _NET_WM_STATE_ABOVE = XInternAtom(dpy, "_NET_WM_STATE_ABOVE", False); _NET_WM_STATE = XInternAtom(dpy, "_NET_WM_STATE", False); _NET_WM_WINDOW_TYPE = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); _NET_WM_WINDOW_TYPE_UTILITY = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_UTILITY", False); _NET_WM_WINDOW_TYPE_DND = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DND", False); } } } GraphicsDisplay::GraphicsDisplay() : m_X11Display(NULL) , m_X11Screen(0) , m_X11Window(0) , m_X11VisualInfo(NULL) , m_current_xic(NULL) , parent_window_(0) , m_GLCtx(NULL) #ifndef NUX_OPENGLES_20 , glx_window_(0) #endif , m_NumVideoModes(0) , m_X11VideoModes(0) , m_BorderPixel(0) , _x11_major(0) , _x11_minor(0) , _glx_major(0) , _glx_minor(0) , _has_glx_13(false) , m_X11RepeatKey(true) , viewport_size_(Size(0,0)) , window_size_(Size(0,0)) , m_WindowPosition(Point(0,0)) , fullscreen_(false) , screen_bit_depth_(32) , gfx_interface_created_(false) , m_CreatedFromForeignWindow(false) , last_click_time_(0) , double_click_counter_(0) , m_pEvent(NULL) , _last_dnd_position(Point(0, 0)) //DND , m_PauseGraphicsRendering(false) , m_FrameTime(0) , m_DeviceFactory(0) , m_GraphicsContext(0) , m_Style(WINDOWSTYLE_NORMAL) , _drag_display(NULL) , _drag_window(0) , _drag_source(0) , _drag_drop_timestamp(0) , _dnd_source_data(NULL) , _dnd_source_window(0) , _global_pointer_grab_data(0) , _global_pointer_grab_active(false) , _global_pointer_grab_callback(0) , _global_keyboard_grab_data(0) , _global_keyboard_grab_active(false) , _global_keyboard_grab_callback(0) , _dnd_is_drag_source(false) , _dnd_source_target_accepts_drop(false) , _dnd_source_grab_active(false) , _dnd_source_drop_sent(false) { inlSetThreadLocalStorage(_TLS_GraphicsDisplay, this); m_X11LastEvent.type = -1; m_pEvent = new Event(); _dnd_source_funcs.get_drag_image = 0; _dnd_source_funcs.get_drag_types = 0; _dnd_source_funcs.get_data_for_type = 0; _dnd_source_funcs.drag_finished = 0; } GraphicsDisplay::~GraphicsDisplay() { NUX_SAFE_DELETE( m_GraphicsContext ); NUX_SAFE_DELETE( m_DeviceFactory ); if (m_CreatedFromForeignWindow == false) { DestroyOpenGLWindow(); } NUX_SAFE_DELETE( m_pEvent ); inlSetThreadLocalStorage(_TLS_GraphicsDisplay, 0); XFree(m_X11VideoModes); XFree(m_X11VisualInfo); } std::string GraphicsDisplay::FindResourceLocation(const char *ResourceFileName, bool ErrorOnFail) { std::string path = m_ResourcePathLocation.GetFile(ResourceFileName); if (path == "" && ErrorOnFail) { nuxCriticalMsg("[GraphicsDisplay::FindResourceLocation] Failed to locate resource file: %s.", ResourceFileName); return ""; } return path; } std::string GraphicsDisplay::FindUITextureLocation(const char *ResourceFileName, bool ErrorOnFail) { FilePath searchpath; searchpath.AddSearchPath(m_UITextureSearchPath); std::string path = searchpath.GetFile(ResourceFileName); if ((path == "") && ErrorOnFail) { nuxCriticalMsg("[GraphicsDisplay::FindResourceLocation] Failed to locate ui texture file: %s.", ResourceFileName); return std::string(""); } return path; } std::string GraphicsDisplay::FindShaderLocation(const char *ResourceFileName, bool ErrorOnFail) { FilePath searchpath; searchpath.AddSearchPath(m_ShaderSearchPath); std::string path = searchpath.GetFile(ResourceFileName); if ((path == "") && ErrorOnFail) { nuxCriticalMsg("[GraphicsDisplay::FindResourceLocation] Failed to locate shader file: %s.", ResourceFileName); return std::string(""); } return path; } std::string GraphicsDisplay::FindFontLocation(const char *ResourceFileName, bool ErrorOnFail) { FilePath searchpath; searchpath.AddSearchPath(m_FontSearchPath); std::string path = searchpath.GetFile(ResourceFileName); if ((path == "") && ErrorOnFail) { nuxCriticalMsg("[GraphicsDisplay::FindResourceLocation] Failed to locate font file file: %s.", ResourceFileName); return std::string(""); } return path; } bool GraphicsDisplay::IsGfxInterfaceCreated() { return gfx_interface_created_; } #ifndef NUX_OPENGLES_20 static Bool WaitForNotify( Display * /* dpy */, XEvent *event, XPointer arg ) { return(event->type == MapNotify) && (event->xmap.window == (Window) arg); } #endif // TODO: change windowWidth, windowHeight, to window_size; static NCriticalSection CreateOpenGLWindow_CriticalSection; bool GraphicsDisplay::CreateOpenGLWindow(const char* window_title, unsigned int WindowWidth, unsigned int WindowHeight, WindowStyle /* Style */, const GraphicsDisplay * /* Parent */, bool fullscreen_flag, bool /* create_rendering_data */) { int xinerama_event, xinerama_error; int xinerama_major, xinerama_minor; NScopeLock Scope(&CreateOpenGLWindow_CriticalSection); window_title_ = window_title; gfx_interface_created_ = false; // FIXME : put at the end Size new_size(WindowWidth, WindowHeight); viewport_size_ = new_size; window_size_ = new_size; // end of fixme fullscreen_ = fullscreen_flag; // Set The Global Fullscreen Flag // Open The display. m_X11Display = XOpenDisplay(0); if (m_X11Display == 0) { nuxDebugMsg("[GraphicsDisplay::CreateOpenGLWindow] XOpenDisplay has failed. The window cannot be created."); return false; } m_X11Screen = DefaultScreen(m_X11Display); XF86VidModeQueryVersion(m_X11Display, &_x11_major, &_x11_minor); XineramaQueryVersion(m_X11Display, &xinerama_major, &xinerama_minor); XineramaQueryExtension(m_X11Display, &xinerama_event, &xinerama_error); atom::initialize(m_X11Display); XF86VidModeGetAllModeLines(m_X11Display, m_X11Screen, &m_NumVideoModes, &m_X11VideoModes); m_X11OriginalVideoMode = *m_X11VideoModes[0]; int best_mode = -1; if (fullscreen_) // Attempt Fullscreen Mode? { // check if resolution is supported bool mode_supported = false; for (int mode = 0 ; mode < m_NumVideoModes; ++mode) { if ((m_X11VideoModes[mode]->hdisplay == viewport_size_.width ) && (m_X11VideoModes[mode]->vdisplay == viewport_size_.height )) { mode_supported = true; best_mode = mode; break; } } if (mode_supported == false) { fullscreen_ = false; } } #ifndef NUX_OPENGLES_20 // Check support for GLX int dummy0, dummy1; if (!glXQueryExtension(m_X11Display, &dummy0, &dummy1)) { nuxCriticalMsg("[GraphicsDisplay::CreateOpenGLWindow] GLX is not supported."); return false; } // Check GLX version glXQueryVersion(m_X11Display, &_glx_major, &_glx_minor); // FBConfigs support added in GLX version 1.3 if (((_glx_major == 1) && (_glx_minor < 3)) || (_glx_major < 1)) { _has_glx_13 = false; } else { _has_glx_13 = true; } _has_glx_13 = false; // force old way. this is temporary... if (_has_glx_13 == false) { // Find an OpenGL capable visual. static int g_DoubleBufferVisual[] = { GLX_RGBA, GLX_DOUBLEBUFFER, GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8, GLX_ALPHA_SIZE, 8, GLX_DEPTH_SIZE, 24, GLX_STENCIL_SIZE, 8, None }; XFree(m_X11VisualInfo); m_X11VisualInfo = glXChooseVisual(m_X11Display, m_X11Screen, g_DoubleBufferVisual); if (m_X11VisualInfo == NULL) { nuxDebugMsg("[GraphicsDisplay::CreateOpenGLWindow] Cannot get appropriate visual."); return false; } // Create OpenGL Context. if (m_GLCtx) glXDestroyContext(m_X11Display, m_GLCtx); m_GLCtx = glXCreateContext(m_X11Display, m_X11VisualInfo, 0, GL_TRUE); m_X11Colormap = XCreateColormap(m_X11Display, RootWindow(m_X11Display, m_X11VisualInfo->screen), m_X11VisualInfo->visual, AllocNone); } else { int DoubleBufferAttributes[] = { //GLX_X_RENDERABLE, True, GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR, GLX_DOUBLEBUFFER, True, GLX_RED_SIZE, 8, /* the maximum number of bits per component */ GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8, GLX_ALPHA_SIZE, 8, GLX_DEPTH_SIZE, 24, GLX_STENCIL_SIZE, 8, None }; GLXFBConfig *fbconfigs = NULL; int fbcount; #define GET_PROC(proc_type, proc_name, check) \ do \ { \ proc_name = (proc_type) glXGetProcAddress((const GLubyte *) #proc_name); \ } while (0) /* initialize GLX 1.3 function pointers */ GET_PROC(PFNGLXGETFBCONFIGSPROC, glXGetFBConfigs, false); GET_PROC(PFNGLXGETFBCONFIGATTRIBPROC, glXGetFBConfigAttrib, false); GET_PROC(PFNGLXGETVISUALFROMFBCONFIGPROC, glXGetVisualFromFBConfig, false); GET_PROC(PFNGLXCREATEWINDOWPROC, glXCreateWindow, false); GET_PROC(PFNGLXDESTROYWINDOWPROC, glXDestroyWindow, false); GET_PROC(PFNGLXCREATEPIXMAPPROC, glXCreatePixmap, false); GET_PROC(PFNGLXDESTROYPIXMAPPROC, glXDestroyPixmap, false); GET_PROC(PFNGLXCREATEPBUFFERPROC, glXCreatePbuffer, false); GET_PROC(PFNGLXDESTROYPBUFFERPROC, glXDestroyPbuffer, false); GET_PROC(PFNGLXCREATENEWCONTEXTPROC, glXCreateNewContext, false); GET_PROC(PFNGLXMAKECONTEXTCURRENTPROC, glXMakeContextCurrent, false); GET_PROC(PFNGLXCHOOSEFBCONFIGPROC, glXChooseFBConfig, false); /* GLX_SGIX_pbuffer */ GET_PROC(PFNGLXCREATEGLXPBUFFERSGIXPROC, glXCreateGLXPbufferSGIX, false); GET_PROC(PFNGLXDESTROYGLXPBUFFERSGIXPROC, glXDestroyGLXPbufferSGIX, false); #undef GET_PROC // Request a double buffer configuration fbconfigs = glXChooseFBConfig(m_X11Display, DefaultScreen(m_X11Display), DoubleBufferAttributes, &fbcount); if (fbconfigs == NULL) { nuxCriticalMsg("[GraphicsDisplay::CreateOpenGLWindow] glXChooseFBConfig cannot get a supported configuration."); return false; } // Select best multi-sample config. if ((_glx_major >= 1) && (_glx_minor >= 4)) { int best_fbc = -1, worst_fbc = -1, best_num_samp = -1, worst_num_samp = 999; for (int i = 0; i < fbcount; i++) { XVisualInfo *vi = glXGetVisualFromFBConfig(m_X11Display, fbconfigs[i]); if (vi) { int sample_buf, samples; glXGetFBConfigAttrib(m_X11Display, fbconfigs[i], GLX_SAMPLE_BUFFERS, &sample_buf); glXGetFBConfigAttrib(m_X11Display, fbconfigs[i], GLX_SAMPLES , &samples); //nuxDebugMsg("Matching fbconfig %d, visual ID 0x%2x: SAMPLE_BUFFERS = %d SAMPLES = %d\n", i, vi->visualid, sample_buf, samples); if (((best_fbc < 0) || sample_buf) && (samples > best_num_samp)) { best_fbc = i; best_num_samp = samples; } if ((worst_fbc < 0) || (!sample_buf) || (samples < worst_num_samp)) { worst_fbc = i; worst_num_samp = samples; } } XFree(vi); } nuxAssertMsg(best_fbc >= 0, "[GraphicsDisplay::CreateOpenGLWindow] Invalid frame buffer config."); _fb_config = fbconfigs[best_fbc]; } else { // Choose the first one _fb_config = fbconfigs[0]; } XFree(fbconfigs); XFree(m_X11VisualInfo); m_X11VisualInfo = glXGetVisualFromFBConfig(m_X11Display, _fb_config); m_X11Colormap = XCreateColormap(m_X11Display, RootWindow(m_X11Display, m_X11VisualInfo->screen), m_X11VisualInfo->visual, AllocNone); } #else EGLDisplay dpy = eglGetDisplay((EGLNativeDisplayType)m_X11Display); if (dpy == EGL_NO_DISPLAY) { nuxDebugMsg("[GraphicsDisplay::CreateOpenGLWindow] Cannot get EGL display."); return false; } EGLint major, minor; if (!eglInitialize(dpy, &major, &minor)) { nuxDebugMsg("[GraphicsDisplay::CreateOpenGLWindow] Cannot initialize EGL."); return false; } eglBindAPI(EGL_OPENGL_ES_API); const EGLint config_attribs[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RED_SIZE, 1, EGL_GREEN_SIZE, 1, EGL_BLUE_SIZE, 1, EGL_ALPHA_SIZE, 1, EGL_DEPTH_SIZE, 1, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_CONFIG_CAVEAT, EGL_NONE, EGL_NONE, }; EGLConfig configs[1024]; EGLint count; if (!eglChooseConfig(dpy, config_attribs, configs, 1024, &count)) { nuxDebugMsg("[GraphicsDisplay::CreateOpenGLWindow] Cannot get EGL config."); return false; } EGLConfig config = configs[0]; EGLint visualid = 0; if (!eglGetConfigAttrib(dpy, config, EGL_NATIVE_VISUAL_ID, &visualid)) { nuxDebugMsg("[GraphicsDisplay::CreateOpenGLWindow] Cannot get native visual ID from EGL config."); return false; } XVisualInfo visual_info; memset(&visual_info, 0, sizeof(visual_info)); visual_info.visualid = visualid; XFree(m_X11VisualInfo); m_X11VisualInfo = XGetVisualInfo(m_X11Display, VisualIDMask, &visual_info, &count); if (!m_X11VisualInfo) { nuxCriticalMsg("[GraphicsDisplay::CreateOpenGLWindow] Cannot get appropriate visual."); return false; } m_X11Colormap = XCreateColormap(m_X11Display, RootWindow(m_X11Display, m_X11VisualInfo->screen), m_X11VisualInfo->visual, AllocNone); #endif m_X11Attr.background_pixmap = 0; m_X11Attr.border_pixel = 0; m_X11Attr.colormap = m_X11Colormap; m_X11Attr.override_redirect = fullscreen_; m_X11Attr.event_mask = // Mouse /*Button1MotionMask | Button2MotionMask | Button3MotionMask | Button4MotionMask | Button5MotionMask | ButtonMotionMask |*/ ButtonPressMask | ButtonReleaseMask | // Mouse motion //-OwnerGrabButtonMask | //PointerMotionHintMask | PointerMotionMask | // Keyboard //--KeymapStateMask | KeyPressMask | KeyReleaseMask | // Window enter/exit LeaveWindowMask | EnterWindowMask | // Exposure Focus ExposureMask | FocusChangeMask | // Structure notify //--ResizeRedirectMask | StructureNotifyMask;// | //--SubstructureNotifyMask | //--SubstructureRedirectMask | // Visibility //--VisibilityChangeMask | // Property //--PropertyChangeMask | // Colormap //--ColormapChangeMask | // No event //--NoEventMask; if (fullscreen_) { XF86VidModeSwitchToMode(m_X11Display, m_X11Screen, m_X11VideoModes[best_mode]); XF86VidModeSetViewPort(m_X11Display, m_X11Screen, 0, 0); //Width = m_X11VideoModes[best_mode]->hdisplay; //Height = m_X11VideoModes[best_mode]->vdisplay; XFree(m_X11VideoModes); /* create a fullscreen window */ m_X11Window = XCreateWindow(m_X11Display, RootWindow(m_X11Display, m_X11VisualInfo->screen), 0, 0, // X, Y window_size_.width, window_size_.height, 0, // Border m_X11VisualInfo->depth, // Depth InputOutput, // Class m_X11VisualInfo->visual, // Visual CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect, &m_X11Attr); XWarpPointer(m_X11Display, None, m_X11Window, 0, 0, 0, 0, 0, 0); //XMapRaised(m_X11Display, m_X11Window); XGrabKeyboard(m_X11Display, m_X11Window, True, GrabModeAsync, GrabModeAsync, CurrentTime); XGrabPointer(m_X11Display, m_X11Window, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, m_X11Window, None, CurrentTime); } else { m_X11Window = XCreateWindow(m_X11Display, RootWindow(m_X11Display, m_X11VisualInfo->screen), 0, 0, window_size_.width, window_size_.height, 0, m_X11VisualInfo->depth, InputOutput, m_X11VisualInfo->visual, CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect, &m_X11Attr); /* only set window title and handle wm_delete_events if in windowed mode */ m_WMDeleteWindow = atom::WM_DELETE_WINDOW; XSetWMProtocols(m_X11Display, m_X11Window, &m_WMDeleteWindow, 1); XSetStandardProperties(m_X11Display, m_X11Window, window_title_.c_str(), window_title_.c_str(), None, NULL, 0, NULL); //XMapRaised(m_X11Display, m_X11Window); } #ifndef NUX_OPENGLES_20 if (_has_glx_13) { XFree(m_X11VisualInfo); m_X11VisualInfo = 0; /* Create a GLX context for OpenGL rendering */ if (m_GLCtx) glXDestroyContext(m_X11Display, m_GLCtx); m_GLCtx = glXCreateNewContext(m_X11Display, _fb_config, GLX_RGBA_TYPE, NULL, True); if (m_GLCtx == 0) { nuxDebugMsg("[GraphicsDisplay::CreateOpenGLWindow] m_GLCtx is null"); } /* Create a GLX window to associate the frame buffer configuration ** with the created X window */ glx_window_ = glXCreateWindow(m_X11Display, _fb_config, m_X11Window, NULL); // Map the window to the screen, and wait for it to appear */ XMapWindow(m_X11Display, m_X11Window); XEvent event; XIfEvent(m_X11Display, &event, WaitForNotify, (XPointer) m_X11Window); /* Bind the GLX context to the Window */ glXMakeContextCurrent(m_X11Display, glx_window_, glx_window_, m_GLCtx); } #else m_GLSurface = eglCreateWindowSurface(dpy, config, (EGLNativeWindowType)m_X11Window, 0); if (!m_GLSurface) { nuxCriticalMsg("[GraphicsDisplay::CreateOpenGLWindow] Failed to create surface."); return false; } const EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; m_GLCtx = eglCreateContext(dpy, config, EGL_NO_CONTEXT, context_attribs); if (m_GLCtx == EGL_NO_CONTEXT) { nuxCriticalMsg("[GraphicsDisplay::CreateOpenGLWindow] Failed to create EGL context."); return false; } #endif MakeGLContextCurrent(); gfx_interface_created_ = true; m_DeviceFactory = new GpuDevice(viewport_size_.width, viewport_size_.height, BITFMT_R8G8B8A8, m_X11Display, m_X11Window, _has_glx_13, _fb_config, m_GLCtx, 1, 0, false); if (m_DeviceFactory->GetGpuInfo().Support_EXT_Framebuffer_Object()) m_DeviceFactory->GetFrameBufferObject()->SetupFrameBufferObject(); m_GraphicsContext = new GraphicsEngine(*this); //EnableVSyncSwapControl(); //DisableVSyncSwapControl(); glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); SwapBuffer(); InitGlobalGrabWindow(); return TRUE; } #ifdef NUX_OPENGLES_20 bool GraphicsDisplay::CreateFromOpenGLWindow(Display *X11Display, Window X11Window, EGLContext OpenGLContext) #else bool GraphicsDisplay::CreateFromOpenGLWindow(Display *X11Display, Window X11Window, GLXContext OpenGLContext) #endif { // Do not make the opengl context current // Do not swap the framebuffer // Do not clear the depth or color buffer // Do not enable/disbale VSync m_X11Display = X11Display; m_X11Window = X11Window; m_GLCtx = OpenGLContext; m_X11Screen = DefaultScreen(m_X11Display); atom::initialize(m_X11Display); Window root_return; int x_return, y_return; unsigned int width_return, height_return; unsigned int border_width_return; unsigned int depth_return; XGetGeometry(X11Display, X11Window, &root_return, &x_return, &y_return, &width_return, &height_return, &border_width_return, &depth_return); window_size_ = Size(width_return, height_return); m_WindowPosition = Point(x_return, y_return); viewport_size_ = Size(width_return, height_return); gfx_interface_created_ = true; // m_DeviceFactory = new GpuDevice(viewport_size_.GetWidth(), viewport_size_.GetHeight(), BITFMT_R8G8B8A8); m_DeviceFactory = new GpuDevice(viewport_size_.width, viewport_size_.height, BITFMT_R8G8B8A8, m_X11Display, m_X11Window, false, _fb_config, m_GLCtx, 1, 0, false); if (m_DeviceFactory->GetGpuInfo().Support_EXT_Framebuffer_Object()) m_DeviceFactory->GetFrameBufferObject()->SetupFrameBufferObject(); m_GraphicsContext = new GraphicsEngine(*this); InitGlobalGrabWindow(); m_CreatedFromForeignWindow = true; return true; } GraphicsEngine* GraphicsDisplay::GetGraphicsEngine() const { return m_GraphicsContext; } GpuDevice* GraphicsDisplay::GetGpuDevice() const { return m_DeviceFactory; } void GraphicsDisplay::SetCurrentXIC(XIC xic) { m_current_xic = xic; } int GraphicsDisplay::GetGlXMajor() const { return _glx_major; } int GraphicsDisplay::GetGlXMinor() const { return _glx_minor; } bool GraphicsDisplay::HasFrameBufferSupport() { return m_DeviceFactory->GetGpuInfo().Support_EXT_Framebuffer_Object(); } // TODO(thumper): Size const& GraphicsDisplay::GetWindowSize(); void GraphicsDisplay::GetWindowSize(int &w, int &h) { w = window_size_.width; h = window_size_.height; } void GraphicsDisplay::GetDesktopSize(int &w, int &h) { Window root; int x, y; unsigned int width, height, depth, border_width; bool ret = XGetGeometry(m_X11Display, RootWindow(m_X11Display, m_X11Screen), &root, &x, &y, &width, &height, &border_width, &depth); if (ret == false) { nuxAssert("[GetDesktopSize] Failed to get the desktop size"); w = 0; h = 0; } } void GraphicsDisplay::SetWindowSize(int width, int height) { nuxDebugMsg("[GraphicsDisplay::SetWindowSize] Setting window size to %dx%d", width, height); // Resize window client area XResizeWindow(m_X11Display, m_X11Window, width, height); XFlush(m_X11Display); } void GraphicsDisplay::SetWindowPosition(int x, int y) { nuxDebugMsg("[GraphicsDisplay::SetWindowPosition] Setting window position to %dx%d", x, y); // Resize window client area XMoveWindow(m_X11Display, m_X11Window, x, y); XFlush(m_X11Display); } int GraphicsDisplay::GetWindowWidth() { return window_size_.width; } int GraphicsDisplay::GetWindowHeight() { return window_size_.height; } void GraphicsDisplay::SetViewPort(int x, int y, int width, int height) { if (IsGfxInterfaceCreated()) { //do not rely on viewport_size_: glViewport can be called directly viewport_size_ = Size(width, height); m_GraphicsContext->SetViewport(x, y, width, height); m_GraphicsContext->SetScissor(0, 0, width, height); } } void GraphicsDisplay::ResetWindowSize() { Window root_return; int x_return, y_return; unsigned int width_return, height_return; unsigned int border_width_return; unsigned int depth_return; XGetGeometry(m_X11Display, m_X11Window, &root_return, &x_return, &y_return, &width_return, &height_return, &border_width_return, &depth_return); window_size_ = Size(width_return, height_return); m_WindowPosition = Point(x_return, y_return); } Point GraphicsDisplay::GetMouseScreenCoord() { Window root_return; Window child_return; int root_x_return; int root_y_return; int win_x_return; int win_y_return; unsigned int mask_return; XQueryPointer(m_X11Display, RootWindow(m_X11Display, m_X11Screen), &root_return, &child_return, &root_x_return, &root_y_return, &win_x_return, &win_y_return, &mask_return); XFlush(m_X11Display); return Point(root_x_return, root_y_return); } Point GraphicsDisplay::GetMouseWindowCoord() { Window root_return; Window child_return; int root_x_return; int root_y_return; int win_x_return; int win_y_return; unsigned int mask_return; XQueryPointer(m_X11Display, RootWindow(m_X11Display, m_X11Screen), &root_return, &child_return, &root_x_return, &root_y_return, &win_x_return, &win_y_return, &mask_return); XFlush(m_X11Display); return Point(win_x_return, win_y_return); } Point GraphicsDisplay::GetWindowCoord() { XWindowAttributes attrib; int status = XGetWindowAttributes(m_X11Display, m_X11Window, &attrib); if (status == 0) { nuxAssert("[GraphicsDisplay::GetWindowCoord] Failed to get the window attributes."); return Point(0, 0); } return Point(attrib.x, attrib.y); } Rect GraphicsDisplay::GetWindowGeometry() { return Rect(m_WindowPosition.x, m_WindowPosition.y, window_size_.width, window_size_.height); } Rect GraphicsDisplay::GetNCWindowGeometry() { return Rect(m_WindowPosition.x, m_WindowPosition.y, window_size_.width, window_size_.height); } void GraphicsDisplay::MakeGLContextCurrent() { #ifndef NUX_OPENGLES_20 if (_has_glx_13) { nuxDebugMsg("Has glx 1.3"); if (!glXMakeContextCurrent(m_X11Display, glx_window_, glx_window_, m_GLCtx)) { nuxDebugMsg("Destroy"); DestroyOpenGLWindow(); } } else if (!glXMakeCurrent(m_X11Display, m_X11Window, m_GLCtx)) { DestroyOpenGLWindow(); } #else EGLDisplay dpy = eglGetDisplay((EGLNativeDisplayType)m_X11Display); if (!eglMakeCurrent(dpy, m_GLSurface, m_GLSurface, m_GLCtx)) { DestroyOpenGLWindow(); } #endif } void GraphicsDisplay::SwapBuffer(bool glswap) { // There are a lot of mouse motion events coming from X11. The system processes one event at a time and sleeps // if necessary to cap the frame rate to 60 frames per seconds. But while the thread sleeping, there are accumulated // motion events waiting to be processed. This creates an increasing backlog of motion events. It translate into a slow // motion of elements that moves in response to the mouse. // Solution: if the the current event is a motion event, changes are, it is followed many more motion events. // In this case, don't sleep the thread... Swap the framebuffer to see the result of the current single motion event. // It maybe worth investigating how to properly balance event processing and drawing in order to keep the // frame rate and the responsiveness at acceptable levels. // As a consequence, when the mouse is moving, the frame rate goes beyond 60fps. /*bool bsleep = true; if (XPending(m_X11Display) > 0) { XEvent xevent; XPeekEvent(m_X11Display, &xevent); if (xevent.type == MotionNotify) { //nuxDebugMsg("[GraphicsDisplay::SwapBuffer]: MotionNotify event."); bsleep = false; } }*/ if (IsPauseThreadGraphicsRendering()) return; if (glswap) { #ifndef NUX_OPENGLES_20 if (_has_glx_13) glXSwapBuffers(m_X11Display, glx_window_); else glXSwapBuffers(m_X11Display, m_X11Window); #else eglSwapBuffers(eglGetDisplay((EGLNativeDisplayType)m_X11Display), m_GLSurface); #endif } m_FrameTime = m_Timer.PassedMilliseconds(); } void GraphicsDisplay::DestroyOpenGLWindow() { if (gfx_interface_created_ == true) { if (m_GLCtx == 0) { nuxDebugMsg("[GraphicsDisplay::DestroyOpenGLWindow] m_GLCtx is null"); } if (m_GLCtx) { #ifndef NUX_OPENGLES_20 // Release the current context if (_has_glx_13) { if (!glXMakeContextCurrent(m_X11Display, None, None, NULL)) { nuxAssert("[GraphicsDisplay::DestroyOpenGLWindow] glXMakeContextCurrent failed."); } } else { if (!glXMakeCurrent(m_X11Display, None, NULL)) { nuxAssert("[GraphicsDisplay::DestroyOpenGLWindow] glXMakeCurrent failed."); } } glXDestroyContext(m_X11Display, m_GLCtx); if (_has_glx_13) { glXDestroyWindow(m_X11Display, glx_window_); } #else EGLDisplay dpy = eglGetDisplay((EGLNativeDisplayType)m_X11Display); if (!eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)) { nuxAssert("[GraphicsDisplay::DestroyOpenGLWindow] eglMakeCurrent failed."); } eglDestroyContext(dpy, m_GLCtx); eglDestroySurface(dpy, m_GLSurface); eglTerminate(dpy); eglReleaseThread(); #endif m_GLCtx = NULL; } /* switch back to original desktop resolution if we were in fs */ if (fullscreen_) { XF86VidModeSwitchToMode(m_X11Display, m_X11Screen, &m_X11OriginalVideoMode); XF86VidModeSetViewPort(m_X11Display, m_X11Screen, 0, 0); } XDestroyWindow(m_X11Display, m_X11Window); XFreeColormap(m_X11Display, m_X11Colormap); XCloseDisplay(m_X11Display); } gfx_interface_created_ = false; } int GraphicsDisplay::MouseMove(XEvent xevent, Event *m_pEvent) { // Erase mouse event and mouse doubleclick events. Keep the mouse states. unsigned int _mouse_state = m_pEvent->mouse_state & 0x0F000000; m_pEvent->type = NUX_MOUSE_MOVE; if (xevent.type == MotionNotify) { _mouse_state |= (xevent.xmotion.state & Button1Mask) ? NUX_STATE_BUTTON1_DOWN : 0; _mouse_state |= (xevent.xmotion.state & Button2Mask) ? NUX_STATE_BUTTON2_DOWN : 0; _mouse_state |= (xevent.xmotion.state & Button3Mask) ? NUX_STATE_BUTTON3_DOWN : 0; } else if (xevent.type == LeaveNotify || xevent.type == EnterNotify) { _mouse_state |= (xevent.xcrossing.state & Button1Mask) ? NUX_STATE_BUTTON1_DOWN : 0; _mouse_state |= (xevent.xcrossing.state & Button2Mask) ? NUX_STATE_BUTTON2_DOWN : 0; _mouse_state |= (xevent.xcrossing.state & Button3Mask) ? NUX_STATE_BUTTON3_DOWN : 0; } m_pEvent->mouse_state = _mouse_state; return 0; } int GraphicsDisplay::MousePress(XEvent xevent, Event *m_pEvent) { // Erase mouse event and mouse double-click events. Keep the mouse states. ulong _mouse_state = m_pEvent->mouse_state & 0x0F000000; bool double_click = false; Time current_time = xevent.xbutton.time; if ((double_click_counter_ == 1) && (current_time - last_click_time_ < double_click_time_delay)) { double_click = true; double_click_counter_ = 0; } else { _mouse_state |= NUX_STATE_FIRST_EVENT; double_click_counter_ = 1; } // State of the button before the event _mouse_state |= (xevent.xbutton.state & Button1Mask) ? NUX_STATE_BUTTON1_DOWN : 0; _mouse_state |= (xevent.xbutton.state & Button2Mask) ? NUX_STATE_BUTTON2_DOWN : 0; _mouse_state |= (xevent.xbutton.state & Button3Mask) ? NUX_STATE_BUTTON3_DOWN : 0; if (xevent.xbutton.type == ButtonPress) { if (xevent.xbutton.button == Button1) { if (double_click) m_pEvent->type = NUX_MOUSE_DOUBLECLICK; else m_pEvent->type = NUX_MOUSE_PRESSED; _mouse_state |= NUX_EVENT_BUTTON1_DOWN; _mouse_state |= NUX_STATE_BUTTON1_DOWN; } if (xevent.xbutton.button == Button2) { if (double_click) m_pEvent->type = NUX_MOUSE_DOUBLECLICK; else m_pEvent->type = NUX_MOUSE_PRESSED; _mouse_state |= NUX_EVENT_BUTTON2_DOWN; _mouse_state |= NUX_STATE_BUTTON2_DOWN; } if (xevent.xbutton.button == Button3) { if (double_click) m_pEvent->type = NUX_MOUSE_DOUBLECLICK; else m_pEvent->type = NUX_MOUSE_PRESSED; _mouse_state |= NUX_EVENT_BUTTON3_DOWN; _mouse_state |= NUX_STATE_BUTTON3_DOWN; } if (xevent.xbutton.button == Button4) { _mouse_state |= NUX_EVENT_MOUSEWHEEL; m_pEvent->type = NUX_MOUSE_WHEEL; m_pEvent->wheel_delta = NUX_MOUSEWHEEL_DELTA; return 1; } if (xevent.xbutton.button == Button5) { _mouse_state |= NUX_EVENT_MOUSEWHEEL; m_pEvent->type = NUX_MOUSE_WHEEL; m_pEvent->wheel_delta = -NUX_MOUSEWHEEL_DELTA; return 1; } if (xevent.xbutton.button == 6) { _mouse_state |= NUX_EVENT_MOUSEWHEEL; m_pEvent->type = NUX_MOUSE_WHEEL; m_pEvent->wheel_delta = (NUX_MOUSEWHEEL_DELTA ^ 2); return 1; } if (xevent.xbutton.button == 7) { _mouse_state |= NUX_EVENT_MOUSEWHEEL; m_pEvent->type = NUX_MOUSE_WHEEL; m_pEvent->wheel_delta = -(NUX_MOUSEWHEEL_DELTA ^ 2); return 1; } } m_pEvent->mouse_state = _mouse_state; return 0; } int GraphicsDisplay::MouseRelease(XEvent xevent, Event *m_pEvent) { // Erase mouse event and mouse double-click events. Keep the mouse states. ulong _mouse_state = m_pEvent->mouse_state & 0x0F000000; // State of the button before the event _mouse_state |= (xevent.xbutton.state & Button1Mask) ? NUX_STATE_BUTTON1_DOWN : 0; _mouse_state |= (xevent.xbutton.state & Button2Mask) ? NUX_STATE_BUTTON2_DOWN : 0; _mouse_state |= (xevent.xbutton.state & Button3Mask) ? NUX_STATE_BUTTON3_DOWN : 0; if (double_click_counter_ == 1) { _mouse_state |= NUX_STATE_FIRST_EVENT; } if (xevent.xbutton.type == ButtonRelease) { if (xevent.xbutton.button == Button1) { m_pEvent->type = NUX_MOUSE_RELEASED; _mouse_state |= NUX_EVENT_BUTTON1_UP; _mouse_state &= ~NUX_STATE_BUTTON1_DOWN; } if (xevent.xbutton.button == Button2) { m_pEvent->type = NUX_MOUSE_RELEASED; _mouse_state |= NUX_EVENT_BUTTON2_UP; _mouse_state &= ~NUX_STATE_BUTTON2_DOWN; } if (xevent.xbutton.button == Button3) { m_pEvent->type = NUX_MOUSE_RELEASED; _mouse_state |= NUX_EVENT_BUTTON3_UP; _mouse_state &= ~NUX_STATE_BUTTON3_DOWN; } } m_pEvent->mouse_state = _mouse_state; last_click_time_ = xevent.xbutton.time; return 0; } unsigned int GetModifierKeyState(unsigned int modifier_key_state) { unsigned int state = 0; // For CapsLock, we don't want to know if the key is pressed Down or Up. // We really want to know the state of the the CapsLock: on(keyboard light is on) or off? if (modifier_key_state & LockMask) { state |= KEY_MODIFIER_CAPS_LOCK; } if (modifier_key_state & ControlMask) { state |= KEY_MODIFIER_CTRL; } if (modifier_key_state & ShiftMask) { state |= KEY_MODIFIER_SHIFT; } if (modifier_key_state & Mod1Mask) { state |= KEY_MODIFIER_ALT; } if (modifier_key_state & Mod2Mask) { state |= KEY_MODIFIER_NUMLOCK; } // todo(jaytaoko): find out which key enable mod3mask // if (modifier_key_state & Mod3Mask) // { // } if (modifier_key_state & Mod4Mask) { state |= KEY_MODIFIER_SUPER; } // todo(jaytaoko): find out which key enable mod5mask // if (modifier_key_state & Mod5Mask) // { // } return state; } bool GraphicsDisplay::GetSystemEvent(Event *evt) { m_pEvent->Reset(); // Erase mouse event and mouse doubleclick states. Keep the mouse states. m_pEvent->mouse_state &= 0x0F000000; bool got_event; // Process event matching this window XEvent xevent; if (XPending(m_X11Display)) { bool bProcessEvent = true; XNextEvent(m_X11Display, &xevent); if (XFilterEvent(&xevent, None) == True) { return true; } if (!_event_filters.empty()) { for (auto filter : _event_filters) { bool result = filter.filter(xevent, filter.data); if (result) { memcpy(evt, m_pEvent, sizeof(Event)); return true; } } } // Detect auto repeat keys. X11 sends a combination of KeyRelease/KeyPress(at the same time) when a key auto repeats. // Here, we make sure we process only the keyRelease when the key is effectively released. if ((xevent.type == KeyPress) || (xevent.type == KeyRelease)) { if (xevent.xkey.keycode < 256) { // Detect if a key is repeated char Keys[32]; // The XQueryKeymap function returns a bit vector for the logical state of the keyboard, where each bit set // to 1 indicates that the corresponding key is currently pressed down. The vector is represented as 32 bytes. // Byte N(from 0) contains the bits for keys 8N to 8N + 7 with the least significant bit in the byte representing // key 8N. // Note that the logical state of a device(as seen by client applications) may lag the physical state if device // event processing is frozen. XQueryKeymap(m_X11Display, Keys); if (Keys[xevent.xkey.keycode >> 3] & (1 << (xevent.xkey.keycode % 8))) { // KeyRelease event + KeyDown = discard repeated event if (xevent.type == KeyRelease) { m_X11LastEvent = xevent; bProcessEvent = false; } // KeyPress event + key repeat disabled + matching KeyRelease event = discard repeated event if ((xevent.type == KeyPress) && (!m_X11RepeatKey) && (m_X11LastEvent.xkey.keycode == xevent.xkey.keycode) && (m_X11LastEvent.xkey.time == xevent.xkey.time)) { bProcessEvent = false;; } } } } if (xevent.type == MotionNotify) { while (XCheckTypedEvent(m_X11Display, MotionNotify, &xevent)); } if (bProcessEvent) ProcessXEvent(xevent, false); memcpy(evt, m_pEvent, sizeof(Event)); got_event = true; } else { memcpy(evt, m_pEvent, sizeof(Event)); got_event = false; } return got_event; } #if defined(NUX_OS_LINUX) void GraphicsDisplay::InjectXEvent(Event *evt, XEvent xevent) { m_pEvent->Reset(); // Erase mouse event and mouse doubleclick states. Keep the mouse states. m_pEvent->mouse_state &= 0x0F000000; // We could do some checks here to make sure the xevent is really what it pretends to be. ProcessXEvent(xevent, false); memcpy(evt, m_pEvent, sizeof(Event)); } void GraphicsDisplay::AddEventFilter(EventFilterArg arg) { _event_filters.push_back(arg); } void GraphicsDisplay::RemoveEventFilter(void *owner) { std::list::iterator it; for (it = _event_filters.begin(); it != _event_filters.end(); ++it) { if ((*it).data == owner) { _event_filters.erase(it); break; } } } #endif void GraphicsDisplay::ProcessForeignX11Event(XEvent *xevent, Event *nux_event) { m_pEvent->Reset(); // Erase mouse event and mouse doubleclick states. Keep the mouse states. m_pEvent->mouse_state &= 0x0F000000; // Process event matching this window if (true /*(NUX_REINTERPRET_CAST(XAnyEvent*, xevent))->window == m_X11Window*/) { bool bProcessEvent = true; // Detect auto repeat keys. X11 sends a combination of KeyRelease/KeyPress(at the same time) when a key auto repeats. // Here, we make sure we process only the keyRelease when the key is effectively released. if ((xevent->type == KeyPress) || (xevent->type == KeyRelease)) { if (xevent->xkey.keycode < 256) { // Detect if a key is repeated char Keys[32]; // The XQueryKeymap function returns a bit vector for the logical state of the keyboard, where each bit set // to 1 indicates that the corresponding key is currently pressed down. The vector is represented as 32 bytes. // Byte N(from 0) contains the bits for keys 8N to 8N + 7 with the least significant bit in the byte representing // key 8N. // Note that the logical state of a device(as seen by client applications) may lag the physical state if device // event processing is frozen. XQueryKeymap(xevent->xany.display, Keys); if (Keys[xevent->xkey.keycode >> 3] & (1 << (xevent->xkey.keycode % 8))) { // KeyRelease event + KeyDown = discard repeated event if (xevent->type == KeyRelease) { m_X11LastEvent = *xevent; bProcessEvent = false; } // KeyPress event + key repeat disabled + matching KeyRelease event = discard repeated event if ((xevent->type == KeyPress) && (!m_X11RepeatKey) && (m_X11LastEvent.xkey.keycode == xevent->xkey.keycode) && (m_X11LastEvent.xkey.time == xevent->xkey.time)) { bProcessEvent = false;; } } } } if (xevent->type == MotionNotify) { while (XCheckTypedEvent(m_X11Display, MotionNotify, xevent)); } if (bProcessEvent) ProcessXEvent(*xevent, true); memcpy(nux_event, m_pEvent, sizeof(Event)); } else { memcpy(nux_event, m_pEvent, sizeof(Event)); } } Event &GraphicsDisplay::GetCurrentEvent() { return *m_pEvent; } bool GraphicsDisplay::HasXPendingEvent() const { return XPending(m_X11Display); } void GraphicsDisplay::RecalcXYPosition(int x_root, int y_root, int &x_recalc, int &y_recalc) { int main_window_x = m_WindowPosition.x; int main_window_y = m_WindowPosition.y; x_recalc = x_root - main_window_x; y_recalc = y_root - main_window_y; } void GraphicsDisplay::RecalcXYPosition(Window TheMainWindow, XEvent xevent, int &x_recalc, int &y_recalc) { x_recalc = y_recalc = 0; int main_window_x = m_WindowPosition.x; int main_window_y = m_WindowPosition.y; bool same = (TheMainWindow == xevent.xany.window); switch(xevent.type) { case ButtonPress: case ButtonRelease: { if (same) { x_recalc = xevent.xbutton.x; y_recalc = xevent.xbutton.y; } else { x_recalc = xevent.xbutton.x_root - main_window_x; y_recalc = xevent.xbutton.y_root - main_window_y; } break; } case MotionNotify: { if (same) { x_recalc = xevent.xmotion.x; y_recalc = xevent.xmotion.y; } else { x_recalc = xevent.xmotion.x_root - main_window_x; y_recalc = xevent.xmotion.y_root - main_window_y; } break; } case LeaveNotify: case EnterNotify: { if (same) { x_recalc = xevent.xcrossing.x; y_recalc = xevent.xcrossing.y; } else { x_recalc = xevent.xcrossing.x_root - main_window_x; y_recalc = xevent.xcrossing.y_root - main_window_y; } break; } } } void GetDefaultSizeLookupString(XEvent event, Event* nux_event) { nux_event->dtext = new char[NUX_EVENT_TEXT_BUFFER_SIZE]; int num_char_stored = XLookupString(&event.xkey, nux_event->dtext, NUX_EVENT_TEXT_BUFFER_SIZE, (KeySym*)&nux_event->x11_keysym, nullptr); nux_event->dtext[num_char_stored] = 0; } void GraphicsDisplay::ProcessXEvent(XEvent xevent, bool foreign) { int x_recalc = 0; int y_recalc = 0; RecalcXYPosition(m_X11Window, xevent, x_recalc, y_recalc); bool local_from_server = !foreign; foreign = foreign || xevent.xany.window != m_X11Window; m_pEvent->type = NUX_NO_EVENT; m_pEvent->x11_window = xevent.xany.window; switch(xevent.type) { case DestroyNotify: { if (foreign) break; m_pEvent->type = NUX_DESTROY_WINDOW; //nuxDebugMsg("[GraphicsDisplay::ProcessXEvents]: DestroyNotify event."); break; } case Expose: { if (foreign) break; m_pEvent->type = NUX_WINDOW_DIRTY; //nuxDebugMsg("[GraphicsDisplay::ProcessXEvents]: Expose event."); break; } case ConfigureNotify: { if (foreign) break; m_pEvent->type = NUX_SIZE_CONFIGURATION; m_pEvent->width = xevent.xconfigure.width; m_pEvent->height = xevent.xconfigure.height; window_size_ = Size(xevent.xconfigure.width, xevent.xconfigure.height); int x, y; Window child_return; XTranslateCoordinates(m_X11Display, m_X11Window, RootWindow(m_X11Display, 0), 0, 0, &x, &y, &child_return); m_WindowPosition = Point(x, y); //nuxDebugMsg("[GraphicsDisplay::ProcessXEvents]: ConfigureNotify event. %d %d", x, y); break; } case FocusIn: { if (!local_from_server) break; m_pEvent->type = NUX_WINDOW_ENTER_FOCUS; m_pEvent->mouse_state = 0; m_pEvent->dx = 0; m_pEvent->dy = 0; m_pEvent->virtual_code = 0; //nuxDebugMsg("[GraphicsDisplay::ProcessXEvents]: FocusIn event."); break; } case FocusOut: { if (!local_from_server) break; m_pEvent->type = NUX_WINDOW_EXIT_FOCUS; m_pEvent->mouse_state = 0; m_pEvent->dx = 0; m_pEvent->dy = 0; m_pEvent->virtual_code = 0; //nuxDebugMsg("[GraphicsDisplay::ProcessXEvents]: FocusOut event."); break; } case KeyPress: { //nuxDebugMsg("[GraphicsDisplay::ProcessXEvents]: KeyPress event."); KeyCode keycode = xevent.xkey.keycode; KeySym keysym = NoSymbol; keysym = XkbKeycodeToKeysym(xevent.xany.display, keycode, 0, 0); m_pEvent->key_modifiers = GetModifierKeyState(xevent.xkey.state); m_pEvent->key_repeat_count = 0; m_pEvent->x11_keysym = keysym; m_pEvent->x11_keycode = xevent.xkey.keycode; m_pEvent->type = NUX_KEYDOWN; m_pEvent->x11_timestamp = xevent.xkey.time; m_pEvent->x11_key_state = xevent.xkey.state; Memset(m_pEvent->text, 0, NUX_EVENT_TEXT_BUFFER_SIZE); bool skip = false; if ((keysym == NUX_VK_BACKSPACE) || (keysym == NUX_VK_DELETE) || (keysym == NUX_VK_ESCAPE)) { //temporary fix for TextEntry widget: filter some keys skip = true; } if (!skip) { int num_char_stored = 0; if (m_current_xic) { delete[] m_pEvent->dtext; m_pEvent->dtext = nullptr; Status status; num_char_stored = XmbLookupString(m_current_xic, &xevent.xkey, nullptr, 0, (KeySym*) &m_pEvent->x11_keysym, &status); if (status == XLookupKeySym) { GetDefaultSizeLookupString(xevent, m_pEvent); } else if (num_char_stored > 0) { int buf_len = num_char_stored + 1; m_pEvent->dtext = new char[buf_len]; num_char_stored = XmbLookupString(m_current_xic, &xevent.xkey, m_pEvent->dtext, buf_len, (KeySym*) &m_pEvent->x11_keysym, nullptr); m_pEvent->dtext[num_char_stored] = 0; } } else { GetDefaultSizeLookupString(xevent, m_pEvent); } } if (m_pEvent->dtext == nullptr) { m_pEvent->dtext = new char[NUX_EVENT_TEXT_BUFFER_SIZE]; m_pEvent->dtext[0] = 0; } break; } case KeyRelease: { //nuxDebugMsg("[GraphicsDisplay::ProcessXEvents]: KeyRelease event."); KeyCode keycode = xevent.xkey.keycode; KeySym keysym = NoSymbol; keysym = XkbKeycodeToKeysym(xevent.xany.display, keycode, 0, 0); m_pEvent->key_modifiers = GetModifierKeyState(xevent.xkey.state); m_pEvent->key_repeat_count = 0; m_pEvent->x11_keysym = keysym; m_pEvent->x11_keycode = xevent.xkey.keycode; m_pEvent->type = NUX_KEYUP; m_pEvent->x11_timestamp = xevent.xkey.time; m_pEvent->x11_key_state = xevent.xkey.state; break; } case ButtonPress: { if (_dnd_is_drag_source) { HandleDndDragSourceEvent(xevent); break; } m_pEvent->x = x_recalc; m_pEvent->y = y_recalc; m_pEvent->x_root = 0; m_pEvent->y_root = 0; m_pEvent->key_modifiers = GetModifierKeyState(xevent.xkey.state); m_pEvent->x11_timestamp = xevent.xbutton.time; MousePress(xevent, m_pEvent); //nuxDebugMsg("[GraphicsDisplay::ProcessXEvents]: ButtonPress event."); break; } case ButtonRelease: { if (_dnd_is_drag_source) { HandleDndDragSourceEvent(xevent); // fall through on purpose } m_pEvent->x = x_recalc; m_pEvent->y = y_recalc; m_pEvent->x_root = 0; m_pEvent->y_root = 0; m_pEvent->key_modifiers = GetModifierKeyState(xevent.xkey.state); m_pEvent->x11_timestamp = xevent.xbutton.time; MouseRelease(xevent, m_pEvent); //nuxDebugMsg("[GraphicsDisplay::ProcessXEvents]: ButtonRelease event."); break; } case MotionNotify: { if (_dnd_is_drag_source) { HandleDndDragSourceEvent(xevent); break; } m_pEvent->x = x_recalc; m_pEvent->y = y_recalc; m_pEvent->x_root = 0; m_pEvent->y_root = 0; m_pEvent->key_modifiers = GetModifierKeyState(xevent.xkey.state); m_pEvent->x11_timestamp = xevent.xmotion.time; MouseMove(xevent, m_pEvent); //nuxDebugMsg("[GraphicsDisplay::ProcessXEvents]: MotionNotify event."); break; } // Note: there is no WM_MOUSEENTER. WM_MOUSEENTER is equivalent to WM_MOUSEMOVE after a WM_MOUSELEAVE. case LeaveNotify: { if (xevent.xcrossing.mode != NotifyNormal || !local_from_server) break; m_pEvent->x = -1; m_pEvent->y = -1; m_pEvent->x_root = 0; m_pEvent->y_root = 0; m_pEvent->key_modifiers = GetModifierKeyState(xevent.xkey.state); m_pEvent->x11_timestamp = xevent.xcrossing.time; m_pEvent->type = NUX_WINDOW_MOUSELEAVE; //nuxDebugMsg("[GraphicsDisplay::ProcessXEvents]: LeaveNotify event."); break; } case EnterNotify: { if (xevent.xcrossing.mode != NotifyNormal || !local_from_server) break; m_pEvent->x = x_recalc; m_pEvent->y = y_recalc; m_pEvent->x_root = 0; m_pEvent->y_root = 0; m_pEvent->key_modifiers = GetModifierKeyState(xevent.xkey.state); m_pEvent->x11_timestamp = xevent.xcrossing.time; MouseMove(xevent, m_pEvent); //nuxDebugMsg("[GraphicsDisplay::ProcessXEvents]: EnterNotify event."); break; } case SelectionRequest: { if (xevent.xselectionrequest.selection == atom::XdndSelection) HandleDndSelectionRequest(xevent); break; } case MapNotify: { if (xevent.xmap.window == _dnd_source_window) { DrawDndSourceWindow(); } else { //nuxDebugMsg("[GraphicsDisplay::ProcessXEvents]: MapNotify event."); m_pEvent->type = NUX_WINDOW_MAP; } break; } case UnmapNotify: { //nuxDebugMsg("[GraphicsDisplay::ProcessXEvents]: UnmapNotify event."); m_pEvent->type = NUX_WINDOW_UNMAP; break; } case ClientMessage: { //if(foreign) // break; if ((xevent.xclient.format == 32) && ((xevent.xclient.data.l[0]) == static_cast (m_WMDeleteWindow))) { m_pEvent->type = NUX_TERMINATE_APP; //nuxDebugMsg("[GraphicsDisplay::ProcessXEvents]: ClientMessage event: Close Application."); } if (xevent.xclient.message_type == atom::XdndPosition) { HandleXDndPosition(xevent, m_pEvent); } else if (xevent.xclient.message_type == atom::XdndEnter) { HandleXDndEnter(xevent); m_pEvent->type = NUX_DND_ENTER_WINDOW; } else if (xevent.xclient.message_type == atom::XdndStatus) { HandleXDndStatus(xevent); m_pEvent->type = NUX_NO_EVENT; } else if (xevent.xclient.message_type == atom::XdndLeave) { HandleXDndLeave(xevent); m_pEvent->type = NUX_DND_LEAVE_WINDOW; } else if (xevent.xclient.message_type == atom::XdndDrop) { HandleXDndDrop(xevent, m_pEvent); } else if (xevent.xclient.message_type == atom::XdndFinished) { HandleXDndFinished(xevent); m_pEvent->type = NUX_NO_EVENT; } break; } } } void GraphicsDisplay::HandleDndSelectionRequest(XEvent xevent) { XEvent result; if (!_dnd_source_funcs.get_data_for_type) return; result.xselection.type = SelectionNotify; result.xselection.display = xevent.xany.display; result.xselection.requestor = xevent.xselectionrequest.requestor; result.xselection.selection = xevent.xselectionrequest.selection; result.xselection.target = xevent.xselectionrequest.target; result.xselection.property = xevent.xselectionrequest.property; result.xselection.time = xevent.xselectionrequest.time; int format, size; char *type = XGetAtomName(xevent.xany.display, xevent.xselectionrequest.target); const unsigned char *data = (const unsigned char *) (*(_dnd_source_funcs.get_data_for_type)) (type, &size, &format, _dnd_source_data); XFree(type); XChangeProperty(xevent.xany.display, xevent.xselectionrequest.requestor, xevent.xselectionrequest.property, xevent.xselectionrequest.target, format, PropModeReplace, data, size); XSendEvent(xevent.xany.display, xevent.xselectionrequest.requestor, False, 0, &result); } gboolean GraphicsDisplay::OnDragEndTimeout(gpointer data) { static_cast (data)->EndDndDrag(DNDACTION_NONE); return false; } void GraphicsDisplay::HandleDndDragSourceEvent(XEvent xevent) { if (_dnd_source_drop_sent) return; switch(xevent.type) { case ButtonPress: break; case ButtonRelease: if (!_dnd_source_target_window || !_dnd_source_target_accepts_drop) { SetDndSourceTargetWindow(None); EndDndDrag(DNDACTION_NONE); } else { SendDndSourceDrop(_dnd_source_target_window, xevent.xbutton.time); _dnd_source_drop_sent = true; UngrabPointer(this); _dnd_source_grab_active = false; g_timeout_add(1000, &GraphicsDisplay::OnDragEndTimeout, this); } break; case MotionNotify: Window target = GetDndTargetWindowForPos(xevent.xmotion.x_root, xevent.xmotion.y_root); if (_dnd_source_window) { Window rw; int x, y; unsigned int w, h, b, d; XGetGeometry(GetX11Display(), _dnd_source_window, &rw, &x, &y, &w, &h, &b, &d); XMoveWindow(GetX11Display(), _dnd_source_window, xevent.xmotion.x_root - (w / 2), xevent.xmotion.y_root - (h / 2)); } if (target != _dnd_source_target_window) SetDndSourceTargetWindow(target); if (_dnd_source_target_window) SendDndSourcePosition(_dnd_source_target_window, xevent.xmotion.x_root, xevent.xmotion.y_root, xevent.xmotion.time); break; } } void GraphicsDisplay::SendDndSourceDrop(Window target, Time time) { XClientMessageEvent drop_message; drop_message.window = target; drop_message.format = 32; drop_message.type = ClientMessage; drop_message.message_type = atom::XdndDrop; drop_message.data.l[0] = _dnd_source_window; drop_message.data.l[1] = 0; drop_message.data.l[2] = time; XSendEvent(GetX11Display(), target, False, NoEventMask, (XEvent *) &drop_message); } void GraphicsDisplay::SendDndSourcePosition(Window target, int x, int y, Time time) { XClientMessageEvent position_message; position_message.window = target; position_message.format = 32; position_message.type = ClientMessage; position_message.message_type = atom::XdndPosition; position_message.data.l[0] = _dnd_source_window; position_message.data.l[1] = 0; position_message.data.l[2] = (x << 16) + y; position_message.data.l[3] = time; position_message.data.l[4] = atom::XdndActionCopy; //fixme XSendEvent(GetX11Display(), target, False, NoEventMask, (XEvent *) &position_message); } void GraphicsDisplay::SendDndSourceEnter(Window target) { XClientMessageEvent enter_message; enter_message.window = target; enter_message.format = 32; enter_message.type = ClientMessage; enter_message.message_type = atom::XdndEnter; enter_message.data.l[0] = _dnd_source_window; enter_message.data.l[1] = (((unsigned long) xdnd_version) << 24) + 1; // mark that we have set the atom list enter_message.data.l[2] = None; // fixme, these should contain the first 3 atoms enter_message.data.l[3] = None; enter_message.data.l[4] = None; XSendEvent(GetX11Display(), target, False, NoEventMask, (XEvent *) &enter_message); } void GraphicsDisplay::SendDndSourceLeave(Window target) { XClientMessageEvent leave_message; leave_message.window = target; leave_message.format = 32; leave_message.type = ClientMessage; leave_message.message_type = atom::XdndLeave; leave_message.data.l[0] = _dnd_source_window; leave_message.data.l[1] = 0; // flags XSendEvent(GetX11Display(), target, False, NoEventMask, (XEvent *) &leave_message); } void GraphicsDisplay::SetDndSourceTargetWindow(Window target) { if (target == _dnd_source_target_window || !_dnd_source_grab_active) return; if (_dnd_source_target_window) SendDndSourceLeave(_dnd_source_target_window); if (target) SendDndSourceEnter(target); _dnd_source_target_accepts_drop = false; _dnd_source_target_window = target; } // This function hilariously inefficient Window GraphicsDisplay::GetDndTargetWindowForPos(int pos_x, int pos_y) { Window result = 0; Window root_window = DefaultRootWindow(GetX11Display()); int cur_x, cur_y; XTranslateCoordinates(GetX11Display(), root_window, root_window, pos_x, pos_y, &cur_x, &cur_y, &result); if (!result) return result; Window src = root_window; while (true) { // translate into result space Window child; int new_x, new_y; XTranslateCoordinates(GetX11Display(), src, result, cur_x, cur_y, &new_x, &new_y, &child); cur_x = new_x; cur_y = new_y; // Check if our current window is XdndAware Atom type = 0; int format; unsigned long n, a; unsigned char *data = 0; if (XGetWindowProperty(GetX11Display(), result, atom::XdndAware, 0, 1, False, XA_ATOM, &type, &format, &n, &a, &data) == Success) { if (data) { long dnd_version = 0; dnd_version = ((Atom *)data)[0]; if (dnd_version < 5) result = 0; // dont have v5? go away until I implement this :) XFree(data); break; // result is the winner } } // Find child window if any and ignore translation XTranslateCoordinates(GetX11Display(), result, result, cur_x, cur_y, &new_x, &new_y, &child); // there is no child window, stop if (!child) { result = 0; break; } src = result; result = child; } return result; } void GraphicsDisplay::EndDndDrag(DndAction action) { Display *display = GetX11Display(); if (_dnd_source_funcs.drag_finished) (*(_dnd_source_funcs.drag_finished)) (action, _dnd_source_data); _dnd_is_drag_source = false; if (_dnd_source_window) XDestroyWindow(display, _dnd_source_window); _dnd_source_window = 0; GrabDndSelection(display, None, CurrentTime); UngrabPointer(this); _dnd_source_grab_active = false; _dnd_source_funcs.get_drag_image = 0; _dnd_source_funcs.get_drag_types = 0; _dnd_source_funcs.get_data_for_type = 0; _dnd_source_funcs.drag_finished = 0; _dnd_source_data = 0; } void GraphicsDisplay::DrawDndSourceWindow() { if (!_dnd_source_funcs.get_drag_image || !_dnd_source_data || !_dnd_source_window) return; Display *display = GetX11Display(); NBitmapData *data = (*(_dnd_source_funcs.get_drag_image)) (_dnd_source_data); XImage *image; image = XGetImage(display, _dnd_source_window, 0, 0, data->GetWidth(), data->GetHeight(), AllPlanes, ZPixmap); GC gc = XCreateGC(display, _dnd_source_window, 0, NULL); BitmapFormat format = data->GetFormat(); /* draw some shit */ if (data->IsTextureData()) { ImageSurface surface = data->GetSurface(0); int x, y; for (y = 0; y < data->GetHeight(); y++) { for (x = 0; x < data->GetWidth(); x++) { long pixel = (long) surface.Read(x, y); long a; if (format == BITFMT_R8G8B8) a = 255; else a = ((pixel >> 24) & 0xff); long r = (((pixel >> 16) & 0xff) * a) / 255; long g = (((pixel >> 8) & 0xff) * a) / 255; long b = (((pixel >> 0) & 0xff) * a) / 255; long result_pixel = (a << 24) | (b << 16) | (g << 8) | (r << 0); XPutPixel(image, x, y, result_pixel); } } } /* upload */ XPutImage(display, _dnd_source_window, gc, image, 0, 0, 0, 0, data->GetWidth(), data->GetHeight()); XDestroyImage(image); } void GraphicsDisplay::StartDndDrag(const DndSourceFuncs &funcs, void *user_data) { Display *display = GetX11Display(); if (!display || !GrabPointer(NULL, this, true)) { if (funcs.drag_finished) (*(funcs.drag_finished)) (DNDACTION_NONE, user_data); return; } _dnd_source_funcs = funcs; _dnd_source_data = user_data; _dnd_source_grab_active = true; _dnd_source_drop_sent = false; int width = 100, height = 100; if (_dnd_source_funcs.get_drag_image) { NBitmapData *data = (*(_dnd_source_funcs.get_drag_image)) (_dnd_source_data); width = data->GetWidth(); height = data->GetHeight(); delete data; } Window root = DefaultRootWindow(display); XVisualInfo vinfo; if (!XMatchVisualInfo(display, XDefaultScreen(display), 32, TrueColor, &vinfo)) { printf("Could not match visual info\n"); EndDndDrag(DNDACTION_NONE); return; } XSetWindowAttributes attribs; attribs.override_redirect = true; attribs.background_pixel = 0; attribs.border_pixel = 0; attribs.colormap = XCreateColormap(display, root, vinfo.visual, AllocNone); unsigned long attrib_mask = CWOverrideRedirect | CWBackPixel | CWBorderPixel | CWColormap; // make a window which will serve two purposes: // First this window will be used to display feedback to the user // Second this window will grab and own the XdndSelection Selection _dnd_source_window = XCreateWindow(display, root, -1000, -1000, width, height, 0, vinfo.depth, InputOutput, vinfo.visual, attrib_mask, &attribs); XSelectInput(display, _dnd_source_window, StructureNotifyMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | PointerMotionMask); XMapRaised(display, _dnd_source_window); Atom atom_type[1]; atom_type[0] = atom::_NET_WM_WINDOW_TYPE_DND; XChangeProperty(display, _dnd_source_window, atom::_NET_WM_WINDOW_TYPE, XA_ATOM, 32, PropModeReplace, (unsigned char*) atom_type, 1); Atom data[32]; int i = 0; data[i++] = atom::_NET_WM_STATE_STICKY; data[i++] = atom::_NET_WM_STATE_SKIP_TASKBAR; data[i++] = atom::_NET_WM_STATE_SKIP_PAGER; data[i++] = atom::_NET_WM_STATE_ABOVE; XChangeProperty(display, _dnd_source_window, atom::_NET_WM_STATE, XA_ATOM, 32, PropModeReplace, (unsigned char *) data, i); Region region = XCreateRegion(); if (region) { XShapeCombineRegion(display, _dnd_source_window, ShapeInput, 0, 0, region, ShapeSet); XDestroyRegion(region); } XFlush(display); _dnd_is_drag_source = true; _dnd_source_target_window = 0; std::list types = _dnd_source_funcs.get_drag_types(_dnd_source_data); std::list::iterator it; Atom type_atoms[types.size()]; i = 0; for (it = types.begin(); it != types.end(); ++it) { type_atoms[i] = XInternAtom(display, *it, false); i++; } XChangeProperty(display, _dnd_source_window, atom::XdndTypeList, XA_ATOM, 32, PropModeReplace, (unsigned char *)type_atoms, i); GrabDndSelection(display, _dnd_source_window, CurrentTime); } bool GraphicsDisplay::GrabDndSelection(Display *display, Window window, Time time) { XSetSelectionOwner(GetX11Display(), atom::XdndSelection, window, time); Window owner = XGetSelectionOwner(display, atom::XdndSelection); return owner == window; } void GraphicsDisplay::SendDndStatus(bool accept, DndAction action, Rect region) { if (!_drag_window || !_drag_display || !_drag_source) return; Atom a; switch(action) { case DNDACTION_MOVE: a = atom::XdndActionMove; break; case DNDACTION_COPY: a = atom::XdndActionCopy; break; case DNDACTION_PRIVATE: a = atom::XdndActionPrivate; break; case DNDACTION_LINK: a = atom::XdndActionLink; break; case DNDACTION_ASK: a = atom::XdndActionAsk; break; default: a = None; break; } SendXDndStatus(_drag_display, _drag_window, _drag_source, accept, a, region); } void GraphicsDisplay::SendDndFinished(bool accepted, DndAction performed_action) { if (!_drag_window || !_drag_display || !_drag_source) return; Atom a; switch(performed_action) { case DNDACTION_MOVE: a = atom::XdndActionMove; break; case DNDACTION_COPY: a = atom::XdndActionCopy; break; case DNDACTION_PRIVATE: a = atom::XdndActionPrivate; break; case DNDACTION_LINK: a = atom::XdndActionLink; break; case DNDACTION_ASK: a = atom::XdndActionAsk; break; default: a = None; break; } SendXDndFinished(_drag_display, _drag_window, _drag_source, accepted, a); } std::list GraphicsDisplay::GetDndMimeTypes() { std::list result; if (!_drag_display) return result; Atom a; int i; for (i = 0; i <= _xdnd_max_type; i++) { a = _xdnd_types[i]; if (!a) break; char *name = XGetAtomName(_drag_display, a); result.push_back(g_strdup(name)); XFree(name); } return result; } char * GraphicsDisplay::GetDndData(char *property) { if (!_drag_display) return NULL; if (_dnd_is_drag_source) { int size, format; return g_strdup((*(_dnd_source_funcs.get_data_for_type)) (property, &size, &format, _dnd_source_data)); } else { Atom a = XInternAtom(_drag_display, property, false); return GetXDndData(_drag_display, _drag_window, a, _drag_drop_timestamp); } } void GraphicsDisplay::SendXDndStatus(Display *display, Window source, Window target, bool accept, Atom action, Rect box) { XClientMessageEvent response; response.window = target; response.format = 32; response.type = ClientMessage; response.message_type = atom::XdndStatus; response.data.l[0] = source; response.data.l[1] = 0; // flags response.data.l[2] = (box.x << 16) | box.y; // x, y response.data.l[3] = (box.width << 16) | box.height; // w, h if (accept) { response.data.l[4] = action; response.data.l[1] |= 1 << 0; } else { response.data.l[4] = None; } XSendEvent(display, target, False, NoEventMask, (XEvent *) &response); } void GraphicsDisplay::HandleXDndPosition(XEvent event, Event* nux_event) { const unsigned long *l = (const unsigned long *)event.xclient.data.l; int x = (l[2] & 0xffff0000) >> 16; int y = l[2] & 0x0000ffff; int x_recalc = 0; int y_recalc = 0; RecalcXYPosition(x, y, x_recalc, y_recalc); nux_event->type = NUX_DND_MOVE; nux_event->x = x_recalc; nux_event->y = y_recalc; // Store the last DND position; _last_dnd_position = Point(x_recalc, y_recalc); } void GraphicsDisplay::HandleXDndEnter(XEvent event) { const long *l = event.xclient.data.l; int version = (int)(((unsigned long)(l[1])) >> 24); if (version > xdnd_version) return; _drag_source = l[0]; _drag_window = event.xany.window; _drag_display = event.xany.display; int j = 0; if (l[1] & 1) { unsigned char *retval = 0; unsigned long n, a; int f; Atom type = None; XGetWindowProperty(_drag_display, _drag_source, atom::XdndTypeList, 0, _xdnd_max_type, False, XA_ATOM, &type, &f, &n, &a, &retval); if (retval) { Atom *data = (Atom *)retval; for (; j < _xdnd_max_type && j < (int)n; j++) _xdnd_types[j] = data[j]; XFree((uchar*)data); } } else { // xdnd supports up to 3 types without using XdndTypelist int i; for (i = 2; i < 5; i++) _xdnd_types[j++] = l[i]; } _xdnd_types[j] = 0; } void GraphicsDisplay::HandleXDndStatus(XEvent event) { const unsigned long *l = (const unsigned long *)event.xclient.data.l; // should protect against stray messages if (l[1] & 1) _dnd_source_target_accepts_drop = true; else _dnd_source_target_accepts_drop = false; } void GraphicsDisplay::HandleXDndLeave(XEvent /* event */) { // reset the key things _xdnd_types[0] = 0; _drag_source = 0; _drag_window = 0; _drag_drop_timestamp = 0; } bool GraphicsDisplay::GetXDndSelectionEvent(Display *display, Window target, Atom property, long time, XEvent *result, int attempts) { // request the selection XConvertSelection(display, atom::XdndSelection, property, atom::XdndSelection, target, time); XFlush(display); int i; for (i = 0; i < attempts; i++) { if (XCheckTypedWindowEvent(display, target, SelectionNotify, result)) { return true; } XFlush(display); struct timeval usleep_tv; usleep_tv.tv_sec = 0; usleep_tv.tv_usec = 50000; select(0, 0, 0, 0, &usleep_tv); } return false; } void GraphicsDisplay::SendXDndFinished(Display *display, Window source, Window target, bool result, Atom action) { XClientMessageEvent response; response.window = target; response.format = 32; response.type = ClientMessage; response.message_type = atom::XdndFinished; response.data.l[0] = source; response.data.l[1] = result ? 1 : 0; // flags response.data.l[2] = action; // action XSendEvent(display, target, False, NoEventMask, (XEvent *) &response); } char * GraphicsDisplay::GetXDndData(Display *display, Window requestor, Atom property, long time) { char *result = 0; XEvent xevent; if (GetXDndSelectionEvent(display, requestor, property, time, &xevent, 50)) { unsigned char *buffer = NULL; Atom type; unsigned long bytes_left; // bytes_after unsigned long length; // nitems int format; if (XGetWindowProperty(display, requestor, atom::XdndSelection, 0, 10000, False, AnyPropertyType, &type, &format, &length, &bytes_left, &buffer) == Success) { result = g_strdup((char *) buffer); XFree(buffer); } } return result; } void GraphicsDisplay::HandleXDndDrop(XEvent event, Event *nux_event) { const long *l = event.xclient.data.l; _drag_drop_timestamp = l[2]; nux_event->type = NUX_DND_DROP; // The drop does not provide(x, y) coordinates of the location of the drop. Use the last DND position. nux_event->x = _last_dnd_position.x; nux_event->y = _last_dnd_position.y; nux_event->x11_timestamp = _drag_drop_timestamp; } void GraphicsDisplay::HandleXDndFinished(XEvent event) { const unsigned long *l = (const unsigned long *)event.xclient.data.l; if (l[0] != _dnd_source_target_window) return; bool accepted = l[1] & 1; DndAction result = DNDACTION_NONE; if (accepted) { if (l[2] == atom::XdndActionCopy) result = DNDACTION_COPY; else if (l[2] == atom::XdndActionAsk) result = DNDACTION_ASK; else if (l[2] == atom::XdndActionLink) result = DNDACTION_LINK; else if (l[2] == atom::XdndActionMove) result = DNDACTION_MOVE; else if (l[2] == atom::XdndActionPrivate) result = DNDACTION_PRIVATE; } EndDndDrag(result); } void GraphicsDisplay::InitGlobalGrabWindow() { Display *display = GetX11Display(); XSetWindowAttributes attribs; attribs.override_redirect = True; _global_grab_window = XCreateWindow(display, DefaultRootWindow(display), -100, -100, // X, Y 1, 1, // Width, Height 0, // Border 0, // Depth InputOnly, // Class CopyFromParent, // Visual CWOverrideRedirect, &attribs); XSelectInput(display, _global_grab_window, StructureNotifyMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | PointerMotionMask); XMapRaised(display, _global_grab_window); Atom atom_type[1]; atom_type[0] = atom::_NET_WM_WINDOW_TYPE_UTILITY; XChangeProperty(display, _global_grab_window, atom::_NET_WM_WINDOW_TYPE, XA_ATOM, 32, PropModeReplace, (unsigned char*) atom_type, 1); Atom data[32]; int i = 0; data[i++] = atom::_NET_WM_STATE_STICKY; data[i++] = atom::_NET_WM_STATE_SKIP_TASKBAR; data[i++] = atom::_NET_WM_STATE_SKIP_PAGER; data[i++] = atom::_NET_WM_STATE_ABOVE; XChangeProperty(display, _global_grab_window, atom::_NET_WM_STATE, XA_ATOM, 32, PropModeReplace, (unsigned char *) data, i); } bool GraphicsDisplay::GrabPointer(GrabReleaseCallback callback, void *data, bool replace_existing) { if (_global_pointer_grab_active) { if (!replace_existing || _dnd_source_grab_active) // prevent grabbing over DND grabs return false; if (_global_pointer_grab_callback) (*_global_pointer_grab_callback) (true, _global_pointer_grab_data); } if (!_global_pointer_grab_active) { int result = XGrabPointer(GetX11Display(), _global_grab_window, True, ButtonPressMask | ButtonReleaseMask | PointerMotionMask | ButtonMotionMask , GrabModeAsync, GrabModeAsync, None, None, CurrentTime); if (result == GrabSuccess) _global_pointer_grab_active = true; } if (_global_pointer_grab_active) { _global_pointer_grab_callback = callback; _global_pointer_grab_data = data; } return _global_pointer_grab_active; } bool GraphicsDisplay::UngrabPointer(void *data) { if (data != _global_pointer_grab_data || !_global_pointer_grab_active) return false; _global_pointer_grab_active = false; XUngrabPointer(GetX11Display(), CurrentTime); if (_global_pointer_grab_callback) (*_global_pointer_grab_callback) (false, data); _global_pointer_grab_data = 0; _global_pointer_grab_callback = 0; return true; } bool GraphicsDisplay::PointerIsGrabbed() { return _global_pointer_grab_active; } bool GraphicsDisplay::GrabKeyboard(GrabReleaseCallback callback, void *data, bool replace_existing) { if (_global_keyboard_grab_active) { if (!replace_existing) return false; // fail case if (_global_keyboard_grab_callback) (*_global_keyboard_grab_callback) (true, _global_keyboard_grab_data); } if (!_global_keyboard_grab_active) { int result = XGrabKeyboard(GetX11Display(), _global_grab_window, True, GrabModeAsync, GrabModeAsync, CurrentTime); if (result == GrabSuccess) _global_keyboard_grab_active = true; } if (_global_keyboard_grab_active) { _global_keyboard_grab_callback = callback; _global_keyboard_grab_data = data; } return _global_keyboard_grab_active; } bool GraphicsDisplay::UngrabKeyboard(void *data) { if (data != _global_keyboard_grab_data || !_global_keyboard_grab_active) return false; _global_keyboard_grab_active = false; XUngrabKeyboard(GetX11Display(), CurrentTime); if (_global_keyboard_grab_callback) (*_global_keyboard_grab_callback) (false, data); _global_keyboard_grab_data = 0; _global_keyboard_grab_callback = 0; return true; } bool GraphicsDisplay::KeyboardIsGrabbed() { return _global_keyboard_grab_active; } void GraphicsDisplay::ShowWindow() { XMapRaised(m_X11Display, m_X11Window); } void GraphicsDisplay::HideWindow() { XUnmapWindow(m_X11Display, m_X11Window); } bool GraphicsDisplay::IsWindowVisible() { XWindowAttributes window_attributes_return; XGetWindowAttributes(m_X11Display, m_X11Window, &window_attributes_return); if (window_attributes_return.map_state == IsViewable) { return true; } return false; } void GraphicsDisplay::EnterMaximizeWindow() { } void GraphicsDisplay::ExitMaximizeWindow() { } void GraphicsDisplay::SetWindowTitle(const char *Title) { window_title_ = Title; XStoreName(m_X11Display, m_X11Window, window_title_.c_str()); } bool GraphicsDisplay::HasVSyncSwapControl() const { return GetGpuDevice()->GetGpuInfo().Support_EXT_Swap_Control(); } void GraphicsDisplay::EnableVSyncSwapControl() { #ifndef NUX_OPENGLES_20 if (GetGpuDevice()->GetGpuInfo().Support_EXT_Swap_Control()) { GLXDrawable drawable = glXGetCurrentDrawable(); glXSwapIntervalEXT(m_X11Display, drawable, 1); } #endif } void GraphicsDisplay::DisableVSyncSwapControl() { #ifndef NUX_OPENGLES_20 if (GetGpuDevice()->GetGpuInfo().Support_EXT_Swap_Control()) { GLXDrawable drawable = glXGetCurrentDrawable(); if (drawable != None) { glXSwapIntervalEXT(m_X11Display, drawable, 0); } } #endif } float GraphicsDisplay::GetFrameTime() const { return m_FrameTime; } void GraphicsDisplay::ResetFrameTime() { m_Timer.Reset(); } void GraphicsDisplay::PauseThreadGraphicsRendering() { m_PauseGraphicsRendering = true; MakeGLContextCurrent(); } bool GraphicsDisplay::IsPauseThreadGraphicsRendering() const { return m_PauseGraphicsRendering; } } ./NuxGraphics/IOpenGLCubeTexture.cpp0000644000004100000410000001104313313171755017624 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "GLDeviceObjects.h" #include "IOpenGLCubeTexture.h" namespace nux { NUX_IMPLEMENT_OBJECT_TYPE(IOpenGLCubeTexture); IOpenGLCubeTexture::IOpenGLCubeTexture( unsigned int EdgeLength , int Levels , BitmapFormat PixelFormat) : IOpenGLBaseTexture(RTCUBETEXTURE, EdgeLength, EdgeLength, 1, Levels, PixelFormat) { CHECKGL(glGenTextures(1, &_OpenGLID)); CHECKGL(glBindTexture(GL_TEXTURE_CUBE_MAP, _OpenGLID)); for (unsigned int face = CUBEMAP_FACE_POSITIVE_X; face < CUBEMAP_FACE_NEGATIVE_Z + 1; face++) { std::vector *array = new std::vector(); _SurfaceArray[ (eCUBEMAP_FACES) face] = array; //array = (*(_SurfaceArray.find((eCUBEMAP_FACES)face))).second; for (int l = 0; l < Levels; l++) { IOpenGLSurface *surface = new IOpenGLSurface(this, _OpenGLID, GL_TEXTURE_CUBE_MAP, face, l); surface->InitializeLevel(); array->push_back( surface ); //IOpenGLSurface* surface = new(array) IOpenGLSurface(this, GL_TEXTURE_CUBE_MAP, face, l) ; } } CHECKGL(glBindTexture(GL_TEXTURE_CUBE_MAP, _OpenGLID)); SetFiltering(GL_NEAREST, GL_NEAREST); SetWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); SetRenderStates(); GRunTimeStats.Register(this); } IOpenGLCubeTexture::~IOpenGLCubeTexture() { for (unsigned int face = CUBEMAP_FACE_POSITIVE_X; face < CUBEMAP_FACE_NEGATIVE_Z + 1; face++) { std::vector *array = (_SurfaceArray.find((eCUBEMAP_FACES) face))->second; for (int l = 0; l < _NumMipLevel; l++) { ((*array) [l])->UnReference(); } array->clear(); delete array; } _SurfaceArray.clear(); CHECKGL(glDeleteTextures(1, &_OpenGLID)); _OpenGLID = 0; GRunTimeStats.UnRegister(this); } int IOpenGLCubeTexture::GetCubeMapSurface( eCUBEMAP_FACES FaceType, int Level, IOpenGLSurface **ppCubeMapSurface ) { if (Level < _NumMipLevel) { std::vector *array = (* (_SurfaceArray.find(FaceType))).second; *ppCubeMapSurface = (*array) [Level]; //(*ppCubeMapSurface)->AddRef(); } else { return OGL_INVALID_SURFACE_LEVEL; } return 1; } int IOpenGLCubeTexture::CubeLockRect( eCUBEMAP_FACES FaceType, int Level, SURFACE_LOCKED_RECT *pLockedRect, const SURFACE_RECT *pRect) { nuxAssertMsg(pLockedRect, "[IOpenGLCubeTexture::LockRect] Invalid parameter 'pLockedRect'."); nuxAssertMsg(Level >= 0, "[IOpenGLCubeTexture::LockRect] Invalid mipmap level."); nuxAssertMsg(Level < _NumMipLevel, "[IOpenGLCubeTexture::LockRect] Invalid mipmap level."); if (Level < _NumMipLevel) { std::vector *array = (* (_SurfaceArray.find(FaceType))).second; IOpenGLSurface *pCubeSurfaceLevel = (*array) [Level]; return pCubeSurfaceLevel->LockRect(pLockedRect, pRect); } else { pLockedRect->pBits = 0; pLockedRect->Pitch = 0; return OGL_INVALID_SURFACE_LEVEL; } return OGL_OK; } int IOpenGLCubeTexture::CubeUnlockRect( eCUBEMAP_FACES FaceType, int Level ) { nuxAssertMsg(Level >= 0, "[IOpenGLCubeTexture::LockRect] Invalid mipmap level."); nuxAssertMsg(Level < _NumMipLevel, "[IOpenGLCubeTexture::LockRect] Invalid mipmap level."); if (Level < _NumMipLevel) { std::vector *array = (* (_SurfaceArray.find(FaceType))).second; IOpenGLSurface *pCubeSurfaceLevel = (*array) [Level]; return pCubeSurfaceLevel->UnlockRect(); } else { return OGL_INVALID_SURFACE_LEVEL; } return OGL_OK; } unsigned int IOpenGLCubeTexture::EnableGammaCorrection(bool /* b */) { nuxAssert(_OpenGLID); return OGL_OK; } } ./NuxGraphics/GLError.h0000644000004100000410000000362413313171755015176 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef GLERROR_H #define GLERROR_H // WARNING: Never call glGetError between glBegin and glEnd. // WARNING: Never use CHECKGL between glBegin() and glEnd(). #ifdef NUX_DEBUG #define CHECKGL(GLcall ) \ { \ GLcall; \ if (1) \ nux::CheckGLError( ANSI_TO_TCHAR(#GLcall), __FILE__, __LINE__ ); \ } #define CHECKGL_MSG( msg ) \ { \ if (1) \ nux::CheckGLError( ANSI_TO_TCHAR(#msg), __FILE__, __LINE__ ); \ } #else #define CHECKGL(GLcall) \ { \ GLcall; \ } #define CHECKGL_MSG( msg ) \ { \ } #endif namespace nux { void CheckGLError(const char *GLcall, const char *file, int line); } #endif // GLERROR_H ./NuxGraphics/GLTextureResourceManager.h0000644000004100000410000004247013313171755020552 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef GLTEXTURERESOURCEMANAGER_H #define GLTEXTURERESOURCEMANAGER_H #include "GLResourceManager.h" #include "IOpenGLBaseTexture.h" #include namespace nux { class NTextureData; class BaseTexture; class CachedBaseTexture; /*! * Create and load a 2D texture filled with RGBA pixels loaded from the image * file pointed by filename. The loading uses the GdkPixbuf library which * implies that the supported formats depend on the GdkPixbuf loaders * installed on the client system. * * @max_size Specifies the maximal required size for the image to be loaded, * if the width or height exceeds that value, the image is scaled down * respecting the aspect ratio. A value of -1 means that no maximal value is * required. * @premultiply Specifies if the R, G and B color channels must be * premultiplied by the alpha channel before being uploaded to the texture. * Note that if there's no alpha channel, the argument is ignored. * @return The resulting texture. */ BaseTexture* CreateTexture2DFromFile(const char* filename, int max_size, bool premultiply); /*! * Create and load a 2D texture filled with RGBA pixels loaded from the * GdkPixbuf pointed by pixbuf. * * @premultiply Specifies if the R, G and B color channels must be * premultiplied by the alpha channel before being uploaded to the texture. * Note that if there's no alpha channel, the argument is ignored. * @return The resulting texture. */ BaseTexture* CreateTexture2DFromPixbuf(GdkPixbuf* pixbuf, bool premultiply); // FIXME(loicm) Should be deprecated. BaseTexture* CreateTextureFromPixbuf(GdkPixbuf* pixbuf); BaseTexture* CreateTextureFromFile(const char* TextureFilename); BaseTexture* CreateTextureFromBitmapData(const NBitmapData* BitmapData); BaseTexture* LoadTextureFromFile(const std::string& filename); //! Abstract base class for textures. class BaseTexture: public ResourceData { NUX_DECLARE_OBJECT_TYPE(BaseTexture, ResourceData); BaseTexture(NUX_FILE_LINE_PROTO); virtual ~BaseTexture(); /*! Update the texture with the provided Bitmap data. In doing so, if the texture as been cached in the resource manager, then the the DeviceTexture inside the CachedTexture will no longer be returned by GetDeviceTexture(). Instead a new device texture will be returned. @BitmapData Pointer to the bitmap data. @UpdateAndCacheResource If true, then the texture is cached immediately. If false, the texture will be cached the first time GetDeviceTexture() or GetCachedTexture() is called. @return True if there was no error during the update. */ virtual bool Update(const NBitmapData* BitmapData, bool UpdateAndCacheResource = true) = 0; /*! Update the texture with the provided filename. In doing so, if the texture as been cached in the resource manager, then the the DeviceTexture inside the CachedTexture will no longer be returned by GetDeviceTexture(). Instead a new device texture will be returned. @BitmapData Pointer to the bitmap data. @UpdateAndCacheResource If true, then the texture is cached immediately. If false, the texture will be cached the first time GetDeviceTexture() or GetCachedTexture() is called. @return True if there was no error during the update. */ virtual bool Update(const char* filename, bool UpdateAndCacheResource = true) = 0; virtual void GetData(void* Buffer, int MipIndex, int StrideY, int face = 0) = 0; /*! @return The texture width. */ virtual int GetWidth() const = 0; /*! @return The texture height. */ virtual int GetHeight() const = 0; /*! @return The texture depth. Return 1 for Texture2D, TextureCube, TextureRenctangle. TextureVolume and TextureFrameAnimation have a depth equal or greater than 1. For TextureFrameAnimation the depth represents the number of frames. */ virtual int GetDepth() const { return 1; } /*! @return True if the width and height of the texture are powers of two. */ virtual bool IsPowerOfTwo() const = 0; /*! @return The texture data format. */ virtual BitmapFormat GetFormat() const = 0; /*! @return The number of mip maps in the texture. */ virtual int GetNumMipLevel() const = 0; /*! @return True if the texture storage contains valid bitmap data. */ virtual bool IsNull() const = 0; virtual BaseTexture* Clone() const = 0; /*! Cache the texture if it hasn't been been already and return the device texture. \sa IOpenGLBaseTexture; @return The device texture. */ ObjectPtr GetDeviceTexture(); /*! Cache the texture if it hasn't been been already and return the cached texture. \sa CachedBaseTexture; @return The cached texture. */ ObjectPtr GetCachedTexture(); }; //! General Texture /*! The class of texture that cover power-of-two and non-power-of-two dimensions. */ class Texture2D: public BaseTexture { NUX_DECLARE_OBJECT_TYPE(Texture2D, BaseTexture); public: Texture2D(NUX_FILE_LINE_PROTO); // TODO: Why can we create a texture without a texture? Texture2D(const NTextureData& Image, NUX_FILE_LINE_PROTO); ~Texture2D(); /*! Update the hardware resources associated to this with the provided texture data. @param BitmapData The texture data to update into the hardware resource. @param UpdateAndCacheResource if True, then the texture data is loaded into this object, and the caching into hardware data is done right away. If false, the caching is done latter by calling GetGraphicsDisplay()->GetGraphicsEngine()->CacheResource(this); @return True is there was not error. */ virtual bool Update(const NBitmapData* BitmapData, bool UpdateAndCacheResource = true); /*! Update the hardware resources associated to this object with the data associated to the file name. @param Filename File name of texture data to update into the hardware resource. @param UpdateAndCacheResource if True, then the texture data is loaded into this object, and the caching into hardware data is done right away. If false, the caching is done latter by calling GetGraphicsDisplay()->GetGraphicsEngine()->CacheResource(this); @return True is there was not error. */ virtual bool Update(const char* Filename, bool UpdateAndCacheResource = true); /*! @return True if the texture storage contains valid bitmap data. */ virtual bool IsNull() const { return _image.IsNull(); } void GetData(void* Buffer, int MipIndex, int StrideY, int face = 0); /*! @return The number of mip maps in the texture. */ int GetNumMipLevel() const { return _image.GetNumMipmap(); } /*! @return The texture width. */ int GetWidth() const { return _image.GetWidth(); } /*! @return The texture height. */ int GetHeight() const { return _image.GetHeight(); } /*! @return The texture data format. */ BitmapFormat GetFormat() const { return _image.GetFormat(); } /*! @return True if the width and height of the texture are powers of two. */ bool IsPowerOfTwo() const { return IsPowerOf2(_image.GetWidth()) && IsPowerOf2(_image.GetHeight()); } virtual Texture2D* Clone() const; private: NTextureData _image; //!< Storage for the texture data }; class TextureRectangle: public BaseTexture { NUX_DECLARE_OBJECT_TYPE(TextureRectangle, BaseTexture); public: TextureRectangle(NUX_FILE_LINE_PROTO); // TODO: Why can we create a texture without a texture? TextureRectangle(const NTextureData& Image, NUX_FILE_LINE_PROTO); ~TextureRectangle(); virtual bool Update(const NBitmapData* BitmapData, bool UpdateAndCacheResource = true); virtual bool Update(const char* filename, bool UpdateAndCacheResource = true); /*! @return True if the texture storage contains valid bitmap data. */ virtual bool IsNull() const { return _image.IsNull(); } void GetData(void* Buffer, int MipIndex, int StrideY, int face = 0); /*! @return The number of mip maps in the texture. */ int GetNumMipLevel() const { return _image.GetNumMipmap(); } /*! @return The texture width. */ int GetWidth() const { return _image.GetWidth(); } /*! @return The texture height. */ int GetHeight() const { return _image.GetHeight(); } /*! @return The texture data format. */ BitmapFormat GetFormat() const { return _image.GetFormat(); } /*! @return True if the width and height of the texture are powers of two. */ bool IsPowerOfTwo() const { return IsPowerOf2(_image.GetWidth()) && IsPowerOf2(_image.GetHeight()); } virtual TextureRectangle* Clone() const; private: NTextureData _image; }; class TextureCube: public BaseTexture { NUX_DECLARE_OBJECT_TYPE(TextureCube, BaseTexture); public: TextureCube(NUX_FILE_LINE_PROTO); // TODO: why can we have a texture without a texture? TextureCube(const NCubemapData& Image); ~TextureCube(); virtual bool Update(const NBitmapData* BitmapData, bool UpdateAndCacheResource = true); virtual bool Update(const char* filename, bool UpdateAndCacheResource = true); /*! @return True if the texture storage contains valid bitmap data. */ virtual bool IsNull() const { return _image.IsNull(); } void GetData(void* Buffer, int MipIndex, int StrideY, int face = 0); /*! @return The number of mip maps in the texture. */ int GetNumMipLevel() const { return _image.GetNumMipmap(); } /*! @return The texture width. */ int GetWidth() const { return _image.GetWidth(); } /*! @return The texture height. */ int GetHeight() const { return _image.GetHeight(); } /*! @return The texture data format. */ BitmapFormat GetFormat() const { return _image.GetFormat(); } /*! @return True if the width and height of the texture are powers of two. */ bool IsPowerOfTwo() const { return IsPowerOf2(_image.GetWidth()) && IsPowerOf2(_image.GetHeight()); } virtual TextureCube* Clone() const; private: NCubemapData _image; }; class TextureVolume: public BaseTexture { NUX_DECLARE_OBJECT_TYPE(TextureVolume, BaseTexture); public: TextureVolume(NUX_FILE_LINE_PROTO); // TODO: why can we have a texture without a texture? TextureVolume(const NVolumeData& Image); ~TextureVolume(); virtual bool Update(const NBitmapData* BitmapData, bool UpdateAndCacheResource = true); virtual bool Update(const char* filename, bool UpdateAndCacheResource = true); /*! @return True if the texture storage contains valid bitmap data. */ virtual bool IsNull() const { return _image.IsNull(); } void GetData(void* Buffer, int MipIndex, int StrideY, int slice = 0); /*! @return The number of mip maps in the texture. */ int GetNumMipLevel() const { return _image.GetNumMipmap(); } /*! @return The texture width. */ int GetWidth() const { return _image.GetWidth(); } /*! @return The texture height. */ int GetHeight() const { return _image.GetHeight(); } /*! @return The texture depth. For TextureFrameAnimation the depth represents the number of frames. */ int GetDepth() const { return _image.GetDepth(); } /*! @return The texture data format. */ BitmapFormat GetFormat() const { return _image.GetFormat(); } /*! @return True if the width and height of the texture are powers of two. */ bool IsPowerOfTwo() const { return IsPowerOf2(_image.GetWidth()) && IsPowerOf2(_image.GetHeight()); } virtual TextureVolume* Clone() const; private: NVolumeData _image; }; class TextureFrameAnimation: public BaseTexture { NUX_DECLARE_OBJECT_TYPE(TextureFrameAnimation, BaseTexture); public: TextureFrameAnimation(NUX_FILE_LINE_PROTO); // TODO: why can we have a texture without a texture? TextureFrameAnimation(const NAnimatedTextureData& Image); ~TextureFrameAnimation(); virtual bool Update(const NBitmapData* BitmapData, bool UpdateAndCacheResource = true); virtual bool Update(const char* filename, bool UpdateAndCacheResource = true); /*! @return True if the texture storage contains valid bitmap data. */ virtual bool IsNull() const { return _image.IsNull(); } void GetData(void* Buffer, int MipIndex, int StrideY, int slice = 0); int GetFrameTime(int Frame); /*! @return The number of mip maps in the texture. */ int GetNumMipLevel() const { return _image.GetNumMipmap(); } /*! @return The texture width. */ int GetWidth() const { return _image.GetWidth(); } /*! @return The texture height. */ int GetHeight() const { return _image.GetHeight(); } /*! @return The number of animation frames in the texture. */ int GetDepth() const { return _image.GetDepth(); } /*! @return The texture data format. */ BitmapFormat GetFormat() const { return _image.GetFormat(); } /*! @return true if the width and heigth of the texture are powers of two. */ bool IsPowerOfTwo() const { return IsPowerOf2(_image.GetWidth()) && IsPowerOf2(_image.GetHeight()); } virtual TextureFrameAnimation* Clone() const; private: NAnimatedTextureData _image; }; class CachedBaseTexture: public CachedResourceData { NUX_DECLARE_OBJECT_TYPE(CachedBaseTexture, CachedResourceData); public: ObjectPtr < IOpenGLBaseTexture > m_Texture; CachedBaseTexture(NResourceSet* ResourceManager); ~CachedBaseTexture(); virtual void LoadMipLevel(BaseTexture* SourceTexture, int MipLevel) = 0; virtual bool UpdateResource(ResourceData* Resource); bool RecreateTexture(BaseTexture* Source); virtual void UpdateTexture(BaseTexture* Source) = 0; unsigned int SourceWidth; unsigned int SourceHeight; unsigned int SourceDepth; BitmapFormat SourceFormat; }; class CachedTexture2D: public CachedBaseTexture { NUX_DECLARE_OBJECT_TYPE(CachedTexture2D, CachedBaseTexture); public: CachedTexture2D(NResourceSet* ResourceManager, Texture2D* SourceTexture); ~CachedTexture2D(); virtual void UpdateTexture(BaseTexture* Source); virtual void LoadMipLevel(BaseTexture* SourceTexture, int MipLevel); }; class CachedTextureRectangle: public CachedBaseTexture { NUX_DECLARE_OBJECT_TYPE(CachedTextureRectangle, CachedBaseTexture); public: CachedTextureRectangle(NResourceSet* ResourceManager, TextureRectangle* SourceTexture); ~CachedTextureRectangle(); virtual void UpdateTexture(BaseTexture* Source); virtual void LoadMipLevel(BaseTexture* SourceTexture, int MipLevel); }; class CachedTextureCube: public CachedBaseTexture { NUX_DECLARE_OBJECT_TYPE(CachedTextureCube, CachedBaseTexture); public: CachedTextureCube(NResourceSet* ResourceManager, TextureCube* SourceTexture); ~CachedTextureCube(); virtual void UpdateTexture(BaseTexture* Source); virtual void LoadMipLevel(BaseTexture* SourceTexture, int MipLevel); }; class CachedTextureVolume: public CachedBaseTexture { NUX_DECLARE_OBJECT_TYPE(CachedTextureVolume, CachedBaseTexture); public: CachedTextureVolume(NResourceSet* ResourceManager, TextureVolume* SourceTexture); ~CachedTextureVolume(); virtual void UpdateTexture(BaseTexture* Source); virtual void LoadMipLevel(BaseTexture* SourceTexture, int MipLevel); }; class CachedTextureFrameAnimation: public CachedBaseTexture { NUX_DECLARE_OBJECT_TYPE(CachedTextureFrameAnimation, CachedBaseTexture); public: CachedTextureFrameAnimation(NResourceSet* ResourceManager, TextureFrameAnimation* SourceTexture); ~CachedTextureFrameAnimation(); virtual void UpdateTexture(BaseTexture* Source); virtual void LoadMipLevel(BaseTexture* SourceTexture, int MipLevel); }; } #endif // GLTEXTURERESOURCEMANAGER_H ./NuxGraphics/FontRenderer.cpp0000644000004100000410000006736213313171755016623 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "GLResource.h" #include "IOpenGLResource.h" #include "GLResourceManager.h" #include "IOpenGLBaseTexture.h" #include "GpuDevice.h" #include "GLTextureResourceManager.h" #include "GraphicsEngine.h" #include "FontRenderer.h" namespace nux { namespace { const int CURSOR_OFFSET = 0; static int CURSOR_SIZE = 2; // On NVidia system: // - declare the vertex attribute name before any other attribute. // - Give the vertex attribute a name that comes before any other attribute name. For instance prefix the vertex attribute name with "_". std::string gFontVtxShader(" \n\ attribute vec4 _Position; \n\ attribute vec4 iOffset; \n\ attribute vec4 iScale; \n\ attribute vec4 iTexUV; \n\ uniform mat4 ViewProjectionMatrix; \n\ varying vec4 oTexCoord0; \n\ void main() \n\ { \n\ oTexCoord0 = iTexUV; \n\ vec4 myvertex = _Position * iScale + iOffset; \n\ gl_Position = ViewProjectionMatrix * myvertex; \n\ }"); std::string gFontFragShader(" \n\ #extension GL_ARB_texture_rectangle : enable \n\ #ifdef GL_ES \n\ precision mediump float; \n\ #endif \n\ uniform vec4 TextColor; \n\ varying vec4 oTexCoord0; \n\ #ifdef SAMPLERTEX2D \n\ uniform sampler2D FontTexture; \n\ vec4 SampleTexture(sampler2D TexObject, vec4 TexCoord) \n\ { \n\ return texture2D(TexObject, TexCoord.st); \n\ } \n\ #elif defined SAMPLERTEX2DRECT \n\ uniform sampler2DRect FontTexture; \n\ vec4 SampleTexture(sampler2DRect TexObject, vec4 TexCoord) \n\ { \n\ return texture2DRect(TexObject, TexCoord.st); \n\ } \n\ #endif \n\ void main() \n\ { \n\ vec4 diffuse = SampleTexture(FontTexture, oTexCoord0); \n\ gl_FragColor = vec4(TextColor.x, TextColor.y, TextColor.z, diffuse.w); \n\ }"); std::string FontAsmVtx("!!ARBvp1.0 \n\ ATTRIB iScale = vertex.attrib[9]; \n\ ATTRIB iOffset = vertex.attrib[10]; \n\ OUTPUT oPos = result.position; \n\ OUTPUT oTexCoord0 = result.texcoord[0]; \n\ # Transform the vertex to clip coordinates. \n\ TEMP temp; \n\ MAD temp, vertex.position, iScale, iOffset; \n\ DP4 oPos.x, state.matrix.mvp.row[0], temp; \n\ DP4 oPos.y, state.matrix.mvp.row[1], temp; \n\ DP4 oPos.z, state.matrix.mvp.row[2], temp; \n\ DP4 oPos.w, state.matrix.mvp.row[3], temp; \n\ MOV oTexCoord0, vertex.attrib[8]; \n\ END"); std::string FontAsmFrg("!!ARBfp1.0 \n\ PARAM color = program.local[0]; \n\ TEMP temp; \n\ TEMP tex0; \n\ TEX tex0, fragment.texcoord[0], texture[0], 2D; \n\ MOV temp, color; \n\ MUL temp.w, color, tex0; \n\ MOV result.color, temp; \n\ END"); std::string FontAsmFrgRect("!!ARBfp1.0 \n\ PARAM color = program.local[0]; \n\ TEMP temp; \n\ TEMP tex0; \n\ TEX tex0, fragment.texcoord[0], texture[0], RECT; \n\ MOV temp, color; \n\ MUL temp.w, color, tex0; \n\ MOV result.color, temp; \n\ END"); } // anon namespace FontRenderer::FontRenderer(GraphicsEngine &graphics_engine) : _graphics_engine(graphics_engine) { if (_graphics_engine.UsingGLSLCodePath()) { _pixel_shader_prog = GetGraphicsDisplay()->GetGpuDevice()->CreatePixelShader(); _vertex_shader_prog = GetGraphicsDisplay()->GetGpuDevice()->CreateVertexShader(); _shader_prog = GetGraphicsDisplay()->GetGpuDevice()->CreateShaderProgram(); _vertex_shader_prog->SetShaderCode(gFontVtxShader.c_str()); #ifndef NUX_OPENGLES_20 _pixel_shader_prog->SetShaderCode(gFontFragShader.c_str(), "#define SAMPLERTEX2DRECT"); #else _pixel_shader_prog->SetShaderCode(gFontFragShader.c_str(), "#define SAMPLERTEX2D"); #endif _shader_prog->ClearShaderObjects(); _shader_prog->AddShaderObject(_vertex_shader_prog); _shader_prog->AddShaderObject(_pixel_shader_prog); //CHECKGL(glBindAttribLocation(_shader_prog->GetOpenGLID(), 0, "_Position")); _shader_prog->Link(); } #ifndef NUX_OPENGLES_20 else { _asm_shader_prog = GetGraphicsDisplay()->GetGpuDevice()->CreateAsmShaderProgram(); _asm_shader_prog->LoadVertexShader(FontAsmVtx.c_str()); _asm_shader_prog->LoadPixelShader(FontAsmFrg.c_str()); _asm_shader_prog->Link(); _asm_font_texture_rect_prog = GetGraphicsDisplay()->GetGpuDevice()->CreateAsmShaderProgram(); _asm_font_texture_rect_prog->LoadVertexShader(FontAsmVtx.c_str()); _asm_font_texture_rect_prog->LoadPixelShader(FontAsmFrgRect.c_str()); _asm_font_texture_rect_prog->Link(); } #endif } FontRenderer::~FontRenderer() { } void FontRenderer::PositionString(ObjectPtr const& Font, std::string const& str, PageBBox const& pageBBox, StringBBox& strBBox, TextAlignment alignment, int NumCharacter) { int xmin = pageBBox.xmin + pageBBox.x_margin; int xmax = pageBBox.xmax - pageBBox.x_margin; int ymin = pageBBox.ymin + pageBBox.y_margin; int ymax = pageBBox.ymax - pageBBox.y_margin; int NumChar = 0; int str_len = str.size(); if (NumCharacter == 0) NumChar = str_len; else NumChar = std::min(str_len, NumCharacter); strBBox.width = Font->GetStringWidth(str, NumChar); strBBox.height = Font->GetLineHeight(); int x = 0; int y = 0; switch(alignment) { case eAlignTextCenter: if (strBBox.width > xmax - xmin) x = xmin; // the text is larger than the box: default to eAlignTextLeft for x. else x = xmin + ((float) (xmax - xmin) - (float) (strBBox.width)) / 2.0f; y = ymin + ((float) (ymax - ymin) - (float) (strBBox.height)) / 2.0f; break; case eAlignTextRight: x = xmin + ((float) (xmax - xmin) - (float) (strBBox.width)); y = ymin + ((float) (ymax - ymin) - (float) (strBBox.height)) / 2.0f; break; case eAlignTextLeft: default: x = xmin; y = ymin + ((float) (ymax - ymin) - (float) (strBBox.height)) / 2.0f; break; } strBBox.x = x; strBBox.y = y; } int FontRenderer::RenderColorText(ObjectPtr const& Font, int x, int y, std::string const& Str, Color const& color, bool WriteAlphaChannel, int NumCharacter) { return RenderText(Font, x, y, Str, color, WriteAlphaChannel, 0, NumCharacter); } int FontRenderer::RenderColorTextLineStatic(ObjectPtr const& Font, PageBBox const& pageSize, std::string const& Str, Color const& color, bool WriteAlphaChannel, TextAlignment alignment) { StringBBox stringBBox; _graphics_engine.PushClippingRectangle(Rect(pageSize.xmin, pageSize.ymin, pageSize.xmax - pageSize.xmin, pageSize.ymax - pageSize.ymin)); PositionString(Font, Str, pageSize, stringBBox, alignment); int off = RenderText(Font, stringBBox.x, stringBBox.y, Str, color, WriteAlphaChannel, 0, Str.size()); _graphics_engine.PopClippingRectangle(); return off; } int FontRenderer::RenderColorTextLineEdit(ObjectPtr const& Font, PageBBox const& pageSize, std::string const& Str, Color const& TextColor, bool WriteAlphaChannel, Color const& SelectedTextColor, Color const& SelectedTextBackgroundColor, Color const& TextBlinkColor, Color const& CursorColor, bool ShowCursor, unsigned int CursorPosition, int offset, int selection_start, int selection_end) { StringBBox stringBBox; Color selection_color(0xFF888888); // TODO: sanity checking on selection_start and end std::string substring = Str.substr(selection_start, selection_end - selection_start); unsigned int substring_width = Font->GetStringWidth(substring); int substring_pos = Font->GetStringWidth(Str, selection_start); _graphics_engine.PushClippingRectangle(Rect(pageSize.xmin, pageSize.ymin, pageSize.xmax - pageSize.xmin, pageSize.ymax - pageSize.ymin)); if (substring_width > 0) _graphics_engine.QRP_Color(pageSize.xmin + offset + substring_pos, pageSize.ymin, substring_width, pageSize.ymax - pageSize.ymin, SelectedTextBackgroundColor); _graphics_engine.PopClippingRectangle(); // TODO: double check this, pushing exactly sthe same rect as above _graphics_engine.PushClippingRectangle(Rect(pageSize.xmin, pageSize.ymin, pageSize.xmax - pageSize.xmin, pageSize.ymax - pageSize.ymin)); PositionString(Font, Str, pageSize, stringBBox, eAlignTextLeft); // Part before selected text int off = RenderText(Font, stringBBox.x + offset, stringBBox.y, Str, TextColor, WriteAlphaChannel, 0, selection_start); // Selection part off = RenderText(Font, stringBBox.x + offset, stringBBox.y, Str, SelectedTextColor, WriteAlphaChannel, selection_start, selection_end - selection_start); // Part after selected text off = RenderText(Font, stringBBox.x + offset, stringBBox.y, Str, TextColor, WriteAlphaChannel, selection_end, Str.size() - selection_end); _graphics_engine.PopClippingRectangle(); if (ShowCursor) { // Render Cursor std::string temp = Str.substr(0, CursorPosition); int w = Font->GetStringWidth(temp); int x = pageSize.xmin + w + offset + CURSOR_OFFSET; x = (x >= pageSize.xmax) ? pageSize.xmax - 1 : x; _graphics_engine.PushClippingRectangle(Rect(x, pageSize.ymin, CURSOR_SIZE, pageSize.ymax - pageSize.ymin)); _graphics_engine.QRP_Color(x, pageSize.ymin, CURSOR_SIZE, pageSize.ymax - pageSize.ymin, CursorColor); RenderText(Font, stringBBox.x + offset, stringBBox.y, Str, TextBlinkColor, WriteAlphaChannel, CursorPosition, 1); _graphics_engine.PopClippingRectangle(); } return off; } int FontRenderer::RenderText(ObjectPtr const& Font, int x, int y, std::string const& str, Color const& color, bool WriteAlphaChannel, int StartCharacter, int NumCharacters) { // !WARNING This call works if all the glyph of the font are in a single texture. int StrLength = str.size(); if (StrLength <= 0) return 0; nuxAssertMsg(NumCharacters >= 0, "[FontRenderer::RenderText] Incorrect value for NumCharacters."); nuxAssertMsg(StartCharacter >= 0, "[FontRenderer::RenderText] Incorrect value for StartCharacter."); nuxAssertMsg(StartCharacter <= StrLength, "[FontRenderer::RenderText] Incorrect value for StartCharacter."); int NumCharToDraw = std::min(StrLength - StartCharacter, NumCharacters); if (NumCharToDraw <= 0) return 0; CHECKGL(glDisable(GL_CULL_FACE)); int CurX = x; int CurY = y; _graphics_engine.GetRenderStates().SetBlend(TRUE, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); _graphics_engine.GetRenderStates().SetColorMask(TRUE, TRUE, TRUE, WriteAlphaChannel); // Do not write the alpha of characters GLshort *Index = new GLshort[StrLength*6]; Vector4 *Position = new Vector4[StrLength*4]; Vector4 *UV = new Vector4[StrLength*4]; Vector4 *Offset = new Vector4[StrLength*4]; Vector4 *Scale = new Vector4[StrLength*4]; ObjectPtr glTexture = _graphics_engine.ResourceCache.GetCachedResource(Font->TextureArray[0]); float tex_width = (float) glTexture->m_Texture->GetWidth(); float tex_height = (float) glTexture->m_Texture->GetHeight(); for (int i = 0; i < StrLength; ++i) { unsigned char c = static_cast (str[i]); unsigned int CharX = Font->m_Charset.Chars[c /*Str[i]*/].x; unsigned int CharY = Font->m_Charset.Chars[c /*Str[i]*/].y; unsigned int Width = Font->m_Charset.Chars[c /*Str[i]*/].Width; unsigned int Height = Font->m_Charset.Chars[c /*Str[i]*/].Height; //int OffsetX = Font->m_Charset.Chars[c /*Str[i]*/].XOffset; //int OffsetY = Font->m_Charset.Chars[c /*Str[i]*/].YOffset; int abcA = Font->m_Charset.Chars[c /*Str[i]*/].abcA; int abcB = Font->m_Charset.Chars[c /*Str[i]*/].abcB; int abcC = Font->m_Charset.Chars[c /*Str[i]*/].abcC; //int page = Font->m_Charset.Chars[c /*Str[i]*/].page; if ((i >= StartCharacter) && (i < StartCharacter + NumCharToDraw)) { int II = i - StartCharacter; Position[II*4 + 0].x = 0; // x Position[II*4 + 0].y = 0; // y Position[II*4 + 0].z = 0; // z Position[II*4 + 0].w = 1.0f; // w Position[II*4 + 1].x = 1.0f; // x Position[II*4 + 1].y = 0; // y Position[II*4 + 1].z = 0; // z Position[II*4 + 1].w = 1; // w Position[II*4 + 2].x = 1.0f; // x Position[II*4 + 2].y = 1.0f; // y Position[II*4 + 2].z = 0; // z Position[II*4 + 2].w = 1; // w Position[II*4 + 3].x = 0; // x Position[II*4 + 3].y = 1.0f; // y Position[II*4 + 3].z = 0; // z Position[II*4 + 3].w = 1; // w for (int j = 0; j < 4; j++) { Offset[II*4 + j].x = CurX + abcA; Offset[II*4 + j].y = CurY; Offset[II*4 + j].z = 0.0f; Offset[II*4 + j].w = 0.0f; Scale[II*4 + j].x = Width; Scale[II*4 + j].y = Height; Scale[II*4 + j].z = 1.0f; Scale[II*4 + j].w = 1.0f; } if (glTexture->m_Texture->Type().IsDerivedFromType(IOpenGLRectangleTexture::StaticObjectType)) { //upper left UV[II*4 + 0].x = CharX; UV[II*4 + 0].y = CharY; UV[II*4 + 0].z = 0.0f; UV[II*4 + 0].w = 0.0f; //upper right UV[II*4 + 1].x = (CharX + Width); UV[II*4 + 1].y = CharY; UV[II*4 + 1].z = 0.0f; UV[II*4 + 1].w = 0.0f; //lower right UV[II*4 + 2].x = (CharX + Width); UV[II*4 + 2].y = (CharY + Height); UV[II*4 + 2].z = 0.0f; UV[II*4 + 2].w = 0.0f; //lower left UV[II*4 + 3].x = CharX; UV[II*4 + 3].y = (CharY + Height); UV[II*4 + 3].z = 0.0f; UV[II*4 + 3].w = 0.0f; } else { //upper left UV[II*4 + 0].x = CharX / tex_width; UV[II*4 + 0].y = CharY / tex_height; UV[II*4 + 0].z = 0.0f; UV[II*4 + 0].w = 0.0f; //upper right UV[II*4 + 1].x = (CharX + Width) / tex_width; UV[II*4 + 1].y = CharY / tex_height; UV[II*4 + 1].z = 0.0f; UV[II*4 + 1].w = 0.0f; //lower right UV[II*4 + 2].x = (CharX + Width) / tex_width; UV[II*4 + 2].y = (CharY + Height) / tex_height; UV[II*4 + 2].z = 0.0f; UV[II*4 + 2].w = 0.0f; //lower left UV[II*4 + 3].x = CharX / tex_width; UV[II*4 + 3].y = (CharY + Height) / tex_height; UV[II*4 + 3].z = 0.0f; UV[II*4 + 3].w = 0.0f; } } // Set up element array indices Index[i*6 + 0] = i*4; Index[i*6 + 1] = i*4 + 2; Index[i*6 + 2] = i*4 + 3; Index[i*6 + 3] = i*4; Index[i*6 + 4] = i*4 + 1; Index[i*6 + 5] = i*4 + 2; CurX += abcA + abcB + abcC; } CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); int in_attrib_position = 0; int in_attrib_tex_uv = 0; int in_attrib_scale = 0; int in_attrib_offset = 0; #ifndef NUX_OPENGLES_20 ObjectPtr shader_program; #endif if (_graphics_engine.UsingGLSLCodePath()) { _shader_prog->Begin(); int ViewProjectionMatrix = _shader_prog->GetUniformLocationARB("ViewProjectionMatrix"); Matrix4 mat = _graphics_engine.GetOpenGLModelViewProjectionMatrix(); _shader_prog->SetUniformLocMatrix4fv(ViewProjectionMatrix, 1, false, (float *) &mat); in_attrib_position = _shader_prog->GetAttributeLocation("_Position"); in_attrib_tex_uv = _shader_prog->GetAttributeLocation("iTexUV"); in_attrib_scale = _shader_prog->GetAttributeLocation("iScale"); in_attrib_offset = _shader_prog->GetAttributeLocation("iOffset"); int FontTexture = _shader_prog->GetUniformLocationARB("FontTexture"); int TextColor = _shader_prog->GetUniformLocationARB("TextColor"); _graphics_engine.SetTexture(GL_TEXTURE0, glTexture->m_Texture); if (FontTexture != -1) { CHECKGL(glUniform1iARB(FontTexture, 0)); } if (TextColor != -1) { CHECKGL(glUniform4fARB(TextColor, color.red, color.green, color.blue, color.alpha)); } } #ifndef NUX_OPENGLES_20 else { shader_program = _asm_shader_prog; if (glTexture->m_Texture->Type().IsDerivedFromType(IOpenGLRectangleTexture::StaticObjectType)) { shader_program = _asm_font_texture_rect_prog; } shader_program->Begin(); CHECKGL(glMatrixMode(GL_MODELVIEW)); CHECKGL(glLoadIdentity()); Matrix4 model_view_matrix = _graphics_engine.GetModelViewMatrix(); model_view_matrix.Transpose(); CHECKGL(glLoadMatrixf((float *) model_view_matrix.m)); CHECKGL(glMatrixMode(GL_PROJECTION)); CHECKGL(glLoadIdentity()); Matrix4 projection_matrix = GetGraphicsDisplay()->GetGraphicsEngine()->GetProjectionMatrix(); projection_matrix.Transpose(); CHECKGL(glLoadMatrixf((float *) projection_matrix.m)); in_attrib_position = VTXATTRIB_POSITION; in_attrib_tex_uv = VTXATTRIB_TEXCOORD0; in_attrib_scale = VTXATTRIB_TEXCOORD1; in_attrib_offset = VTXATTRIB_TEXCOORD2; CHECKGL(glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, color.red, color.green, color.blue, color.alpha )); _graphics_engine.SetTexture(GL_TEXTURE0, glTexture->m_Texture); } #endif if (in_attrib_offset != -1) { CHECKGL(glEnableVertexAttribArrayARB(in_attrib_offset)); CHECKGL(glVertexAttribPointerARB(in_attrib_offset, 4, GL_FLOAT, GL_FALSE, 16, Offset)); } if (in_attrib_position != -1) { CHECKGL(glEnableVertexAttribArrayARB(in_attrib_position)); CHECKGL(glVertexAttribPointerARB(in_attrib_position, 4, GL_FLOAT, GL_FALSE, 16, Position)); } if (in_attrib_scale != -1) { CHECKGL(glEnableVertexAttribArrayARB(in_attrib_scale)); CHECKGL(glVertexAttribPointerARB(in_attrib_scale, 4, GL_FLOAT, GL_FALSE, 16, Scale)); } if (in_attrib_tex_uv != -1) { CHECKGL(glEnableVertexAttribArrayARB(in_attrib_tex_uv)); CHECKGL(glVertexAttribPointerARB(in_attrib_tex_uv, 4, GL_FLOAT, GL_FALSE, 16, UV)); } if (NumCharToDraw > 0) CHECKGL(glDrawElements( GL_TRIANGLES, NumCharToDraw * 6, GL_UNSIGNED_SHORT, Index )); if (in_attrib_position != -1) CHECKGL(glDisableVertexAttribArrayARB(in_attrib_position)); if (in_attrib_offset != -1) CHECKGL(glDisableVertexAttribArrayARB(in_attrib_offset)); if (in_attrib_scale != -1) CHECKGL(glDisableVertexAttribArrayARB(in_attrib_scale)); if (in_attrib_tex_uv != -1) CHECKGL(glDisableVertexAttribArrayARB(in_attrib_tex_uv)); if (_graphics_engine.UsingGLSLCodePath()) { _shader_prog->End(); } else { #ifndef NUX_OPENGLES_20 shader_program->End(); #endif } _graphics_engine.GetRenderStates().SetColorMask(TRUE, TRUE, TRUE, TRUE); _graphics_engine.GetRenderStates().SetBlend(FALSE); CurX -= x + CURSOR_OFFSET; delete [] Index; delete [] Position; delete [] UV; delete [] Scale; delete [] Offset; return CurX; // number of pixel to offset before writing the next string. } int FontRenderer::RenderTextToBuffer(float *VertexBuffer, int VBSize, ObjectPtr const& Font, Rect const& geo, std::string const& str, Color const& color, TextAlignment alignment, int NumCharacter) { nuxAssertMsg(NumCharacter >= 0, "[FontRenderer::RenderTextToBuffer] Number of char to draw must be positive."); int NumCharToDraw = 0; if (NumCharacter == 0) NumCharToDraw = str.size(); else NumCharToDraw = Min((int) str.size(), NumCharacter); nuxAssertMsg(3 * NumCharToDraw * 16 <= VBSize, "[FontRenderer::RenderTextToBuffer] VertexBuffer not large enough."); if (3 * NumCharToDraw * 16 > VBSize) return 0; StringBBox stringBBox; PageBBox pageBox; pageBox.xmin = geo.x; pageBox.xmax = geo.x + geo.GetWidth(); pageBox.ymin = geo.y; pageBox.ymax = geo.y + geo.GetHeight(); pageBox.x_margin = 0; pageBox.y_margin = 0; PositionString(Font, str, pageBox, stringBBox, alignment); int CurX = stringBBox.x; int CurY = stringBBox.y; Vector4 *Position = (Vector4 *) VertexBuffer; for (int i = 0; i < NumCharToDraw; ++i) { unsigned char c = static_cast (str[i]); unsigned int CharX = Font->m_Charset.Chars[c /*Str[i]*/].x; unsigned int CharY = Font->m_Charset.Chars[c /*Str[i]*/].y; unsigned int Width = Font->m_Charset.Chars[c /*Str[i]*/].Width; unsigned int Height = Font->m_Charset.Chars[c /*Str[i]*/].Height; //int OffsetX = Font->m_Charset.Chars[c /*Str[i]*/].XOffset; //int OffsetY = Font->m_Charset.Chars[c /*Str[i]*/].YOffset; int abcA = Font->m_Charset.Chars[c /*Str[i]*/].abcA; int abcB = Font->m_Charset.Chars[c /*Str[i]*/].abcB; int abcC = Font->m_Charset.Chars[c /*Str[i]*/].abcC; //int page = Font->m_Charset.Chars[c /*Str[i]*/].page; // Position upper left // Scale Offset Position[i*12 + 0].x = 0.0f * Width + (CurX + abcA); // x Position[i*12 + 0].y = 0.0f * Height + (CurY); // y Position[i*12 + 0].z = 0.0f * 1.0f + 0.0f; // z Position[i*12 + 0].w = 1.0f * 1.0f + 0.0f; // w // texture coord Position[i*12 + 1].x = CharX; Position[i*12 + 1].y = CharY; Position[i*12 + 1].z = 0.0f; Position[i*12 + 1].w = 1.0f; // color Position[i*12 + 2].x = color.red; Position[i*12 + 2].y = color.green; Position[i*12 + 2].z = color.blue; Position[i*12 + 2].w = color.alpha; // Position lower left Position[i*12 + 9].x = 0.0f * Width + (CurX + abcA); // x Position[i*12 + 9].y = 1.0f * Height + (CurY); // y Position[i*12 + 9].z = 0.0f * 1.0f + 0.0f; // z Position[i*12 + 9].w = 1.0f * 1.0f + 0.0f; // w // texture coord Position[i*12 + 10].x = CharX; Position[i*12 + 10].y = CharY + Height; Position[i*12 + 10].z = 0.0f; Position[i*12 + 10].w = 1.0f; // color Position[i*12 + 11].x = color.red; Position[i*12 + 11].y = color.green; Position[i*12 + 11].z = color.blue; Position[i*12 + 11].w = color.alpha; // Position lower right Position[i*12 + 6].x = 1.0f * Width + (CurX + abcA); // x Position[i*12 + 6].y = 1.0f * Height + (CurY); // y Position[i*12 + 6].z = 0.0f * 1.0f + 0.0f; // z Position[i*12 + 6].w = 1.0f * 1.0f + 0.0f; // w // texture coord Position[i*12 + 7].x = CharX + Width; Position[i*12 + 7].y = CharY + Height; Position[i*12 + 7].z = 0.0f; Position[i*12 + 7].w = 1.0f; // color Position[i*12 + 8].x = color.red; Position[i*12 + 8].y = color.green; Position[i*12 + 8].z = color.blue; Position[i*12 + 8].w = color.alpha; // Position upper right Position[i*12 + 3].x = 1.0f * Width + (CurX + abcA); // x Position[i*12 + 3].y = 0.0f * Height + (CurY); // y Position[i*12 + 3].z = 0.0f * 1.0f + 0.0f; // z Position[i*12 + 3].w = 1.0f * 1.0f + 0.0f; // w // texture coord Position[i*12 + 4].x = CharX + Width; Position[i*12 + 4].y = CharY; Position[i*12 + 4].z = 0.0f; Position[i*12 + 4].w = 1.0f; // color Position[i*12 + 5].x = color.red; Position[i*12 + 5].y = color.green; Position[i*12 + 5].z = color.blue; Position[i*12 + 5].w = color.alpha; CurX += abcA + abcB + abcC; } CurX -= stringBBox.x + CURSOR_OFFSET; return NumCharToDraw; } } ./NuxGraphics/CairoGraphics.cpp0000644000004100000410000004300513313171755016730 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "NuxCore/NuxCore.h" #include "NuxCore/Rect.h" #include "BitmapFormats.h" #include "CairoGraphics.h" namespace nux { CairoGraphics::CairoGraphics(cairo_format_t format, int width, int height) : m_surface_format(format) , _width(0) , _height(0) , _zoom(1.0f) , _opacity(1.0f) { nuxAssert(width >= 0); nuxAssert(height >= 0); _width = width; _height = height; if (_width <= 0) _width = 1; if (_height <= 0) _height = 1; _cairo_surface = cairo_image_surface_create(m_surface_format, _width, _height); _cr = cairo_create(_cairo_surface); if (cairo_status(_cr) == CAIRO_STATUS_NO_MEMORY) { // If memory cannot be allocated, a special cairo_t object will be returned // on which cairo_status() returns CAIRO_STATUS_NO_MEMORY. // You can use this object normally, but no drawing will be done. nuxAssertMsg(0, "[CairoGraphics::GetContext] Cairo context error."); } } CairoGraphics::~CairoGraphics() { if (_cr) { cairo_destroy(_cr); } cairo_surface_destroy(_cairo_surface); } cairo_t *CairoGraphics::GetContext() { cairo_t *cr = cairo_create(_cairo_surface); if (cairo_status(cr) == CAIRO_STATUS_NO_MEMORY) { // If memory cannot be allocated, a special cairo_t object will be returned // on which cairo_status() returns CAIRO_STATUS_NO_MEMORY. // You can use this object normally, but no drawing will be done. nuxAssertMsg(0, "[CairoGraphics::GetContext] Cairo context error."); } return cr; } cairo_t *CairoGraphics::GetInternalContext() { return _cr; } cairo_surface_t* CairoGraphics::GetSurface() { return _cairo_surface; } NBitmapData *CairoGraphics::GetBitmap() { if ((_width <= 0) || (_height <= 0)) { nuxDebugMsg("[CairoGraphics::GetBitmap] Invalid surface."); } NUX_RETURN_VALUE_IF_NULL(_width, 0); NUX_RETURN_VALUE_IF_NULL(_height, 0); cairo_surface_flush(_cairo_surface); BitmapFormat bitmap_format = BITFMT_UNKNOWN; if (m_surface_format == CAIRO_FORMAT_ARGB32) { // Each pixel is a 32-bit quantity, with alpha in the upper 8 bits, // then red, then green, then blue. The 32-bit quantities are stored native-endian. // Pre-multiplied alpha is used. (That is, 50% transparent red is 0x80800000, not 0x80ff0000.) bitmap_format = BITFMT_B8G8R8A8; } if (m_surface_format == CAIRO_FORMAT_RGB24) { // Each pixel is a 32-bit quantity, with the upper 8 bits unused. // Red, Green, and Blue are stored in the remaining 24 bits in that order. bitmap_format = BITFMT_B8G8R8A8; } if (m_surface_format == CAIRO_FORMAT_A8) { // Each pixel is a 8-bit quantity holding an alpha value. bitmap_format = BITFMT_A8; } if (m_surface_format == CAIRO_FORMAT_A1) bitmap_format = BITFMT_A8; NTextureData *bitmap_data = new NTextureData(bitmap_format, _width, _height, 1); unsigned char *ptr = cairo_image_surface_get_data(_cairo_surface); int stride = cairo_image_surface_get_stride(_cairo_surface); if (ptr == NULL || stride == 0) { // _cairo_surface is not a valid surface nuxError("[CairoGraphics::GetBitmap] Invalid surface"); return bitmap_data; // just returns because we will segfault otherwise } unsigned char* dest_u8 = bitmap_data->GetSurface(0).GetPtrRawData(); const int pitch = bitmap_data->GetSurface(0).GetPitch(); if (m_surface_format == CAIRO_FORMAT_A1) { std::vector temp(pitch); for (int j = 0; j < _height; ++j) { for (int i = 0; i < _width; ++i) { // Get the byte int a = ptr[j * stride + i/8]; // Get the position in the byte int b = (i - 8 * (i / 8)); // Shift the byte and get the last bit int c = (a >> b) & 0x1; // If the last bit is set, put 1, otherwise put 0 temp[i] = c ? 0xFF : 0x0; } Memcpy(dest_u8 + j * pitch, temp.data(), _width); } } else { for (int j = 0; j < _height; ++j) { Memcpy(dest_u8 + j * pitch, (const void *) (&ptr[j * stride]), _width * GPixelFormats[bitmap_format].NumComponents); } } return bitmap_data; } int CairoGraphics::GetWidth() const { return _width; } int CairoGraphics::GetHeight() const { return _height; } bool CairoGraphics::PushState() { nuxAssert(_cr); _opacity_stack.push(_opacity); cairo_save(_cr); return true; } bool CairoGraphics::PopState() { nuxAssert(_cr); if (_opacity_stack.empty()) { return false; } _opacity = _opacity_stack.top(); _opacity_stack.pop(); cairo_restore(_cr); return true; } bool CairoGraphics::ClearCanvas() { // Clear the surface. nuxAssert(_cr); cairo_operator_t op = cairo_get_operator(_cr); cairo_set_operator(_cr, CAIRO_OPERATOR_CLEAR); cairo_paint(_cr); cairo_set_operator(_cr, op); // Set the clip region to an infinitely large shape containing the target. cairo_reset_clip(_cr); _opacity = 1.0f; _opacity_stack = std::stack(); cairo_restore(_cr); cairo_save(_cr); return true; } bool CairoGraphics::ClearRect(double x, double y, double w, double h) { nuxAssert(_cr); cairo_rectangle(_cr, x, y, w, h); cairo_operator_t op = cairo_get_operator(_cr); cairo_set_operator(_cr, CAIRO_OPERATOR_CLEAR); cairo_fill(_cr); cairo_set_operator(_cr, op); return true; } bool CairoGraphics::DrawLine(double x0, double y0, double x1, double y1, double width, const Color &c) { nuxAssert(_cr); if (width < 0.0) { return false; } cairo_set_line_width(_cr, width); cairo_set_source_rgba(_cr, c.red, c.green, c.blue, _opacity); cairo_move_to(_cr, x0, y0); cairo_line_to(_cr, x1, y1); cairo_stroke(_cr); return true; } void CairoGraphics::TranslateCoordinates(double tx, double ty) { nuxAssert(_cr); cairo_translate(_cr, tx, ty); } bool CairoGraphics::DrawFilledRect(double x, double y, double w, double h, const Color &c) { nuxAssert(_cr); if (w <= 0.0 || h <= 0.0) { return false; } cairo_set_source_rgba(_cr, c.red, c.green, c.blue, _opacity); cairo_rectangle(_cr, x, y, w, h); cairo_fill(_cr); return true; } bool CairoGraphics::DrawCanvas(double x, double y, CairoGraphics *cg) { if (cg == 0) return false; cairo_surface_t *s = cg->GetSurface(); double src_zoom = cg->_zoom; double inv_zoom = 1.0 / src_zoom; cairo_save(_cr); IntersectRectClipRegion(x, y, cg->GetWidth(), cg->GetHeight()); cairo_scale(_cr, inv_zoom, inv_zoom); cairo_set_source_surface(_cr, s, x * src_zoom, y * src_zoom); cairo_pattern_set_extend(cairo_get_source(_cr), CAIRO_EXTEND_PAD); cairo_paint_with_alpha(_cr, _opacity); cairo_restore(_cr); return true; } static inline double _align(double val) { double fract = val - (int) val; if (fract != 0.5f) return(double) ((int) val + 0.5f); else return val; } bool CairoGraphics::DrawRoundedRectangle(cairo_t* cr, double aspect, double x, double y, double cornerRadius, double width, double height, bool align) { double radius = cornerRadius / aspect; if (align) { // top-left, right of the corner cairo_move_to(cr, _align(x + radius), _align(y)); // top-right, left of the corner cairo_line_to(cr, _align(x + width - radius), _align(y)); // top-right, below the corner cairo_arc(cr, _align(x + width - radius), _align(y + radius), radius, -90.0f * G_PI / 180.0f, 0.0f * G_PI / 180.0f); // bottom-right, above the corner cairo_line_to(cr, _align(x + width), _align(y + height - radius)); // bottom-right, left of the corner cairo_arc(cr, _align(x + width - radius), _align(y + height - radius), radius, 0.0f * G_PI / 180.0f, 90.0f * G_PI / 180.0f); // bottom-left, right of the corner cairo_line_to(cr, _align(x + radius), _align(y + height)); // bottom-left, above the corner cairo_arc(cr, _align(x + radius), _align(y + height - radius), radius, 90.0f * G_PI / 180.0f, 180.0f * G_PI / 180.0f); // top-left, right of the corner cairo_arc(cr, _align(x + radius), _align(y + radius), radius, 180.0f * G_PI / 180.0f, 270.0f * G_PI / 180.0f); } else { // top-left, right of the corner cairo_move_to(cr, x + radius, y); // top-right, left of the corner cairo_line_to(cr, x + width - radius, y); // top-right, below the corner cairo_arc(cr, x + width - radius, y + radius, radius, -90.0f * G_PI / 180.0f, 0.0f * G_PI / 180.0f); // bottom-right, above the corner cairo_line_to(cr, x + width, y + height - radius); // bottom-right, left of the corner cairo_arc(cr, x + width - radius, y + height - radius, radius, 0.0f * G_PI / 180.0f, 90.0f * G_PI / 180.0f); // bottom-left, right of the corner cairo_line_to(cr, x + radius, y + height); // bottom-left, above the corner cairo_arc(cr, x + radius, y + height - radius, radius, 90.0f * G_PI / 180.0f, 180.0f * G_PI / 180.0f); // top-left, right of the corner cairo_arc(cr, x + radius, y + radius, radius, 180.0f * G_PI / 180.0f, 270.0f * G_PI / 180.0f); } return true; } static inline void _blurinner(guchar* pixel, gint* zR, gint* zG, gint* zB, gint* zA, gint alpha, gint aprec, gint zprec) { gint R; gint G; gint B; guchar A; R = *pixel; G = *(pixel + 1); B = *(pixel + 2); A = *(pixel + 3); *zR += (alpha * ((R << zprec) - *zR)) >> aprec; *zG += (alpha * ((G << zprec) - *zG)) >> aprec; *zB += (alpha * ((B << zprec) - *zB)) >> aprec; *zA += (alpha * ((A << zprec) - *zA)) >> aprec; *pixel = *zR >> zprec; *(pixel + 1) = *zG >> zprec; *(pixel + 2) = *zB >> zprec; *(pixel + 3) = *zA >> zprec; } static inline void _blurrow(guchar* pixels, gint width, gint /* height */, // TODO: This seems very strange. Why is height not used as it is in _blurcol() ? gint channels, gint line, gint alpha, gint aprec, gint zprec) { gint zR; gint zG; gint zB; gint zA; gint index; guchar* scanline; scanline = &(pixels[line * width * channels]); zR = *scanline << zprec; zG = *(scanline + 1) << zprec; zB = *(scanline + 2) << zprec; zA = *(scanline + 3) << zprec; for (index = 0; index < width; index ++) _blurinner(&scanline[index * channels], &zR, &zG, &zB, &zA, alpha, aprec, zprec); for (index = width - 2; index >= 0; index--) _blurinner(&scanline[index * channels], &zR, &zG, &zB, &zA, alpha, aprec, zprec); } static inline void _blurcol(guchar* pixels, gint width, gint height, gint channels, gint x, gint alpha, gint aprec, gint zprec) { gint zR; gint zG; gint zB; gint zA; gint index; guchar* ptr; ptr = pixels; ptr += x * channels; zR = *((guchar*) ptr ) << zprec; zG = *((guchar*) ptr + 1) << zprec; zB = *((guchar*) ptr + 2) << zprec; zA = *((guchar*) ptr + 3) << zprec; for (index = width; index < (height - 1) * width; index += width) _blurinner((guchar*) &ptr[index * channels], &zR, &zG, &zB, &zA, alpha, aprec, zprec); for (index = (height - 2) * width; index >= 0; index -= width) _blurinner((guchar*) &ptr[index * channels], &zR, &zG, &zB, &zA, alpha, aprec, zprec); } // // pixels image-data // width image-width // height image-height // channels image-channels // // in-place blur of image 'img' with kernel of approximate radius 'radius' // // blurs with two sided exponential impulse response // // aprec = precision of alpha parameter in fixed-point format 0.aprec // // zprec = precision of state parameters zR,zG,zB and zA in fp format 8.zprec // void _expblur(guchar* pixels, gint width, gint height, gint channels, gint radius, gint aprec, gint zprec) { gint alpha; gint row = 0; gint col = 0; if (radius < 1) return; // calculate the alpha such that 90% of // the kernel is within the radius. // (Kernel extends to infinity) alpha = (gint) ((1 << aprec) * (1.0f - expf(-2.3f / (radius + 1.f)))); for (; row < height; row++) _blurrow(pixels, width, height, channels, row, alpha, aprec, zprec); for (; col < width; col++) _blurcol(pixels, width, height, channels, col, alpha, aprec, zprec); return; } // if called like BlurSurface(radius) or BlurSurface(radius, NULL) it will // try to blur the image-surface of the internal cairo-context bool CairoGraphics::BlurSurface(unsigned int radius, cairo_surface_t* surf) { cairo_surface_t* surface; guchar* pixels; guint width; guint height; cairo_format_t format; if (surf) surface = surf; else surface = cairo_get_target(_cr); // don't do anything if we're not dealing with an image-surface if (cairo_surface_get_type(surface) != CAIRO_SURFACE_TYPE_IMAGE) return false; // before we mess with the surface execute any pending drawing cairo_surface_flush(surface); pixels = cairo_image_surface_get_data(surface); width = cairo_image_surface_get_width(surface); height = cairo_image_surface_get_height(surface); format = cairo_image_surface_get_format(surface); switch(format) { case CAIRO_FORMAT_ARGB32: _expblur(pixels, width, height, 4, radius, 16, 7); break; case CAIRO_FORMAT_RGB24: _expblur(pixels, width, height, 3, radius, 16, 7); break; case CAIRO_FORMAT_A8: _expblur(pixels, width, height, 1, radius, 16, 7); break; default : // do nothing break; } // inform cairo we altered the surfaces contents cairo_surface_mark_dirty(surface); return true; } bool CairoGraphics::IntersectRectClipRegion(double x, double y, double w, double h) { if (w <= 0.0 || h <= 0.0) { return false; } cairo_antialias_t pre = cairo_get_antialias(_cr); cairo_set_antialias(_cr, CAIRO_ANTIALIAS_NONE); cairo_rectangle(_cr, x, y, w, h); cairo_clip(_cr); cairo_set_antialias(_cr, pre); return true; } bool CairoGraphics::IntersectGeneralClipRegion(std::list ®ion) { bool do_clip = false; cairo_antialias_t pre = cairo_get_antialias(_cr); cairo_set_antialias(_cr, CAIRO_ANTIALIAS_NONE); std::list::iterator it; for (it = region.begin(); it != region.end(); ++it) { Rect rect = (*it); if (!rect.IsNull()) { cairo_rectangle(_cr, rect.x, rect.y, rect.width, rect.height); do_clip = true; } } if (do_clip) { cairo_clip(_cr); } cairo_set_antialias(_cr, pre); return true; } } ./NuxGraphics/RenderingPipeGLSL.h0000644000004100000410000000000013313171755017060 0ustar www-datawww-data./NuxGraphics/GLTextureStates.cpp0000644000004100000410000003026413313171755017264 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "GLResource.h" #include "GLTextureStates.h" namespace nux { const struct TextureStateLookUpTable { TextureStateLookUpTable() { // setup render state map #define UL_MAP(state__, default_value__, checked__) \ default_texture_state[GFXTS_##state__].iValue = default_value__; \ default_texture_state[GFXTS_##state__].Checked = checked__; #define UL_MAP_FLOAT(state__, default_value__, checked__) \ default_texture_state[GFXTS_##state__].fValue = default_value__; \ default_texture_state[GFXTS_##state__].Checked = checked__; UL_MAP(ADDRESSU , GL_REPEAT , 1); UL_MAP(ADDRESSV , GL_REPEAT , 1); UL_MAP(ADDRESSW , GL_REPEAT , 1); UL_MAP(MINFILTER , GL_NEAREST , 1); UL_MAP(MAGFILTER , GL_NEAREST , 1); UL_MAP(MIPFILTER , GL_NEAREST , 1); UL_MAP(MIP_BASE_LEVEL , 0 , 1); UL_MAP(MIP_MAX_LEVEL , 1000 , 1); UL_MAP_FLOAT(MIN_LOD , -1000 , 1); UL_MAP_FLOAT(MAX_LOD , +1000 , 1); UL_MAP(BORDERCOLOR , 0x0 , 1); #undef UL_MAP #undef UL_MAP_FLOAT }; TextureStateMap default_texture_state[GFXTS_MAX_TEXTURESTATES]; } s_TextureStateLUT; GLTextureStates::GLTextureStates(GLuint Type) { SetType(Type); Memcpy(&m_TextureStateChanges, &s_TextureStateLUT.default_texture_state, sizeof(m_TextureStateChanges)); } GLTextureStates::~GLTextureStates() { } void GLTextureStates::SetType(GLuint Type) { #ifndef NUX_OPENGLES_20 nuxAssertMsg( (Type == GL_TEXTURE_1D) || (Type == GL_TEXTURE_2D) || (Type == GL_TEXTURE_RECTANGLE_ARB) || (Type == GL_TEXTURE_3D) || (Type == GL_TEXTURE_CUBE_MAP_ARB), "Error[GLTextureStates::GLTextureStates]: Invalid texture type."); #else nuxAssertMsg( (Type == GL_TEXTURE_2D), "Error[GLTextureStates::GLTextureStates]: Invalid texture type."); #endif m_Type = Type; } void GLTextureStates::ResetDefault() { } void GLTextureStates::ResetStateChangeToDefault() { } void GLTextureStates::SetRenderStates() { HW_SetFiltering(); HW_SetWrap(); HW_SetLOD(); HW_SetMipLevel(); } #define SET_TS_VALUE(a, b) if (a.iValue != b){(a).iValue = (b); (a).Dirty = true;} #define TS_VALUE(a, b) (a).iValue #define SET_TS_VALUE_FLOAT(a, b) if (a.fValue != b){(a).fValue = (b); (a).Dirty = true;} #define TS_VALUE_FLOAT(a, b) (a).fValue void GLTextureStates::HW_SetFiltering() { if (m_TextureStateChanges[GFXTS_MINFILTER].Dirty || m_TextureStateChanges[GFXTS_MAGFILTER].Dirty) { CHECKGL(glTexParameteri(m_Type, GL_TEXTURE_MIN_FILTER, m_TextureStateChanges[GFXTS_MINFILTER].iValue )); CHECKGL(glTexParameteri(m_Type, GL_TEXTURE_MAG_FILTER, m_TextureStateChanges[GFXTS_MAGFILTER].iValue)); m_TextureStateChanges[GFXTS_MINFILTER].Dirty = false; m_TextureStateChanges[GFXTS_MAGFILTER].Dirty = false; } } void GLTextureStates::HW_SetWrap() { if (m_TextureStateChanges[GFXTS_ADDRESSU].Dirty || m_TextureStateChanges[GFXTS_ADDRESSV].Dirty || m_TextureStateChanges[GFXTS_ADDRESSW].Dirty) { CHECKGL(glTexParameteri(m_Type, GL_TEXTURE_WRAP_S, m_TextureStateChanges[GFXTS_ADDRESSU].iValue)); CHECKGL(glTexParameteri(m_Type, GL_TEXTURE_WRAP_T, m_TextureStateChanges[GFXTS_ADDRESSV].iValue)); #ifndef NUX_OPENGLES_20 CHECKGL(glTexParameteri(m_Type, GL_TEXTURE_WRAP_R, m_TextureStateChanges[GFXTS_ADDRESSW].iValue)); #endif m_TextureStateChanges[GFXTS_ADDRESSU].Dirty = false; m_TextureStateChanges[GFXTS_ADDRESSV].Dirty = false; m_TextureStateChanges[GFXTS_ADDRESSW].Dirty = false; } } void GLTextureStates::HW_SetLOD() { #ifndef NUX_OPENGLES_20 if (m_Type == GL_TEXTURE_RECTANGLE_ARB) { // No support for mip LOP on rectangle texture. // ATI seems to not generate and Error. // Nvidia generates an error m_TextureStateChanges[GFXTS_MIN_LOD].Dirty = false; m_TextureStateChanges[GFXTS_MAX_LOD].Dirty = false; return; } if (m_TextureStateChanges[GFXTS_MIN_LOD].Dirty || m_TextureStateChanges[GFXTS_MAX_LOD].Dirty) { CHECKGL(glTexParameteri(m_Type, GL_TEXTURE_MIN_LOD, m_TextureStateChanges[GFXTS_MIN_LOD].fValue)); CHECKGL(glTexParameteri(m_Type, GL_TEXTURE_MAX_LOD, m_TextureStateChanges[GFXTS_MAX_LOD].fValue)); m_TextureStateChanges[GFXTS_MIN_LOD].Dirty = false; m_TextureStateChanges[GFXTS_MAX_LOD].Dirty = false; } #endif } void GLTextureStates::HW_SetMipLevel() { #ifndef NUX_OPENGLES_20 if (m_TextureStateChanges[GFXTS_MIN_LOD].Dirty || m_TextureStateChanges[GFXTS_MAX_LOD].Dirty) { CHECKGL(glTexParameteri(m_Type, GL_TEXTURE_MIN_LOD, m_TextureStateChanges[GFXTS_MIN_LOD].fValue)); CHECKGL(glTexParameteri(m_Type, GL_TEXTURE_MAX_LOD, m_TextureStateChanges[GFXTS_MAX_LOD].fValue)); m_TextureStateChanges[GFXTS_MIN_LOD].Dirty = false; m_TextureStateChanges[GFXTS_MAX_LOD].Dirty = false; } #endif } void GLTextureStates::HW_SetBorderColor() { } void GLTextureStates::SetFiltering( unsigned int MinFilter, unsigned int MagFilter /*,unsigned int MIP*/) { nuxAssertMsg( (MinFilter == GL_LINEAR) || (MinFilter == GL_NEAREST) || (MinFilter == GL_NEAREST_MIPMAP_NEAREST) || (MinFilter == GL_LINEAR_MIPMAP_NEAREST) || (MinFilter == GL_NEAREST_MIPMAP_LINEAR) || (MinFilter == GL_LINEAR_MIPMAP_LINEAR), "Error[GLTextureStates::SetFiltering]: Invalid MinFilter state"); nuxAssertMsg( (MagFilter == GL_LINEAR) || (MagFilter == GL_NEAREST), "Error[GLTextureStates::SetFiltering]: Invalid MagFilter state"); // nuxAssertMsg( // (MIP == GL_LINEAR) || // (MIP == GL_NEAREST), // "Error[GLTextureStates::SetFiltering]: Invalid Mipmap Filter State"); #ifndef NUX_OPENGLES_20 if (m_Type == GL_TEXTURE_RECTANGLE_ARB) { if ((MinFilter != GL_NEAREST) && (MinFilter != GL_LINEAR)) { nuxError("[GLTextureStates::SetFiltering] Incorrect MinFilter for rectangle texture."); SET_TS_VALUE(m_TextureStateChanges[GFXTS_MINFILTER], GL_LINEAR); } else { SET_TS_VALUE(m_TextureStateChanges[GFXTS_MINFILTER], MinFilter); } if ((MagFilter != GL_NEAREST) && (MagFilter != GL_LINEAR)) { nuxError("[GLTextureStates::SetFiltering] Incorrect MagFilter for rectangle texture."); SET_TS_VALUE(m_TextureStateChanges[GFXTS_MAGFILTER], GL_LINEAR); } else { SET_TS_VALUE(m_TextureStateChanges[GFXTS_MAGFILTER], MagFilter); } } else { SET_TS_VALUE(m_TextureStateChanges[GFXTS_MINFILTER], MinFilter); SET_TS_VALUE(m_TextureStateChanges[GFXTS_MAGFILTER], MagFilter); } #else SET_TS_VALUE(m_TextureStateChanges[GFXTS_MINFILTER], MinFilter); SET_TS_VALUE(m_TextureStateChanges[GFXTS_MAGFILTER], MagFilter); #endif //SET_TS_VALUE(m_TextureStateChanges[GFXTS_MIPFILTER], MIP); } void GLTextureStates::SetWrap( unsigned int U, unsigned int V, unsigned int W) { #ifndef NUX_OPENGLES_20 nuxAssertMsg( (U == GL_CLAMP) || (U == GL_CLAMP_TO_EDGE) || (U == GL_CLAMP_TO_BORDER) || (U == GL_MIRRORED_REPEAT) || (U == GL_MIRROR_CLAMP_EXT) || (U == GL_MIRROR_CLAMP_TO_EDGE_EXT) || (U == GL_MIRROR_CLAMP_TO_BORDER_EXT) || (U == GL_REPEAT), "Error[GLTextureStates::SetWrap]: Invalid U Wrap State"); nuxAssertMsg( (V == GL_CLAMP) || (V == GL_CLAMP_TO_EDGE) || (V == GL_CLAMP_TO_BORDER) || (V == GL_MIRRORED_REPEAT) || (V == GL_MIRROR_CLAMP_EXT) || (V == GL_MIRROR_CLAMP_TO_EDGE_EXT) || (V == GL_MIRROR_CLAMP_TO_BORDER_EXT) || (V == GL_REPEAT), "Error[GLTextureStates::SetWrap]: Invalid V Wrap State"); nuxAssertMsg( (W == GL_CLAMP) || (W == GL_CLAMP_TO_EDGE) || (W == GL_CLAMP_TO_BORDER) || (W == GL_MIRRORED_REPEAT) || (W == GL_MIRROR_CLAMP_EXT) || (W == GL_MIRROR_CLAMP_TO_EDGE_EXT) || (W == GL_MIRROR_CLAMP_TO_BORDER_EXT) || (W == GL_REPEAT), "Error[GLTextureStates::SetWrap]: Invalid W Wrap State"); if (m_Type == GL_TEXTURE_RECTANGLE_ARB) { if ((U != GL_CLAMP) && (U != GL_CLAMP_TO_BORDER) && (U != GL_CLAMP_TO_EDGE)) { nuxError("[GLTextureStates::SetFiltering] Incorrect warp for rectangle texture."); SET_TS_VALUE(m_TextureStateChanges[GFXTS_ADDRESSU], GL_CLAMP_TO_EDGE); } else { SET_TS_VALUE(m_TextureStateChanges[GFXTS_ADDRESSU], U); } if ((V != GL_CLAMP) && (V != GL_CLAMP_TO_BORDER) && (V != GL_CLAMP_TO_EDGE)) { nuxError("[GLTextureStates::SetFiltering] Incorrect warp for rectangle texture."); SET_TS_VALUE(m_TextureStateChanges[GFXTS_ADDRESSV], GL_CLAMP_TO_EDGE); } else { SET_TS_VALUE(m_TextureStateChanges[GFXTS_ADDRESSV], V); } if ((W != GL_CLAMP) && (W != GL_CLAMP_TO_BORDER) && (W != GL_CLAMP_TO_EDGE)) { nuxError("[GLTextureStates::SetFiltering] Incorrect warp for rectangle texture."); SET_TS_VALUE(m_TextureStateChanges[GFXTS_ADDRESSW], GL_CLAMP_TO_EDGE); } else { SET_TS_VALUE(m_TextureStateChanges[GFXTS_ADDRESSW], W); } } else { SET_TS_VALUE(m_TextureStateChanges[GFXTS_ADDRESSU], U); SET_TS_VALUE(m_TextureStateChanges[GFXTS_ADDRESSV], V); SET_TS_VALUE(m_TextureStateChanges[GFXTS_ADDRESSW], W); } #else nuxAssertMsg( (U == GL_CLAMP) || (U == GL_CLAMP_TO_EDGE) || (U == GL_CLAMP_TO_BORDER) || (U == GL_MIRRORED_REPEAT) || (U == GL_REPEAT), "Error[GLTextureStates::SetWrap]: Invalid U Wrap State"); nuxAssertMsg( (V == GL_CLAMP) || (V == GL_CLAMP_TO_EDGE) || (V == GL_CLAMP_TO_BORDER) || (V == GL_MIRRORED_REPEAT) || (V == GL_REPEAT), "Error[GLTextureStates::SetWrap]: Invalid V Wrap State"); SET_TS_VALUE(m_TextureStateChanges[GFXTS_ADDRESSU], U); SET_TS_VALUE(m_TextureStateChanges[GFXTS_ADDRESSV], V); #endif } void GLTextureStates::SetLOD(float MinLod, float MaxLod) { SET_TS_VALUE_FLOAT(m_TextureStateChanges[GFXTS_MIN_LOD], MinLod); SET_TS_VALUE_FLOAT(m_TextureStateChanges[GFXTS_MAX_LOD], MaxLod); } void GLTextureStates::SetMipLevel( unsigned int MinMip, unsigned int MaxMip) { SET_TS_VALUE(m_TextureStateChanges[GFXTS_MIP_BASE_LEVEL], MinMip); SET_TS_VALUE(m_TextureStateChanges[GFXTS_MIP_MAX_LEVEL], MaxMip); } void GLTextureStates::SetBorderColor( float R, float G, float B, float A) { unsigned int r, g, b, a; r = 255 * Clamp(R, 0.0f, 1.0f); g = 255 * Clamp(G, 0.0f, 1.0f); b = 255 * Clamp(B, 0.0f, 1.0f); a = 255 * Clamp(A, 0.0f, 1.0f); unsigned int color = (unsigned int) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)); SET_TS_VALUE(m_TextureStateChanges[GFXTS_BORDERCOLOR], color); } #undef SET_TS_VALUE #undef TS_VALUE #undef SET_TS_VALUE_FLOAT #undef TS_VALUE_FLOAT } ./NuxGraphics/Makefile.am0000644000004100000410000001112313313171755015536 0ustar www-datawww-dataCLEANFILES = DISTCLEANFILES = EXTRA_DIST = GraphicsDisplayWin.cpp \ GraphicsDisplayWin.h lib_LTLIBRARIES = \ libnux-graphics-@NUX_API_VERSION@.la libnux_graphics_@NUX_API_VERSION@_la_CPPFLAGS= \ -I$(srcdir) \ -I$(top_srcdir) \ -DPREFIX=\""$(prefix)"\" \ -DLIBDIR=\""$(libdir)"\" \ -DDATADIR=\""$(datadir)"\" \ -DPKGDATADIR=\""$(pkgdatadir)/@NUX_API_VERSION@"\" \ -DG_LOG_DOMAIN=\"NuxGraphics\" \ $(GCC_FLAGS) \ $(NUX_GRAPHICS_CFLAGS) \ $(MAINTAINER_CFLAGS) \ $(GEIS_CFLAGS) \ $(COVERAGE_CFLAGS) libnux_graphics_@NUX_API_VERSION@_la_LIBADD = \ $(top_builddir)/NuxCore/libnux-core-@NUX_API_VERSION@.la \ $(NUX_GRAPHICS_LIBS) \ $(GEIS_LIBS) libnux_graphics_@NUX_API_VERSION@_la_LDFLAGS = \ $(NUX_LT_LDFLAGS) \ $(COVERAGE_LDFLAGS) source_h = \ BitmapFormats.h \ CairoGraphics.h \ Events.h \ FontTexture.h \ FontRenderer.h \ GdkGraphics.h \ Gfx_Interface.h \ GLDeviceFrameBufferObject.h \ GLDeviceObjects.h \ GLError.h \ GlobalGraphicsInitializer.h \ GLPBuffer.h \ GLRenderStates.h \ GLResource.h \ GLResourceManager.h \ GLShader.h \ GLShaderParameter.h \ GLSh_ColorPicker.h \ GLSh_DrawFunction.h \ GLSh_Fill.h \ GLTemplatePrimitiveBuffer.h \ GLTextureResourceManager.h \ GLTextureStates.h \ GLThread.h \ GLTimer.h \ GLVertexResourceManager.h \ GLWindowManager.h \ GpuDevice.h \ GraphicsDisplay.h \ GraphicsEngine.h \ MeshData.h \ MeshFileLoader-OBJ.h \ ImageSurface.h \ IOpenGLAnimatedTexture.h \ IOpenGLBaseTexture.h \ IOpenGLCubeTexture.h \ IOpenGLFrameBufferObject.h \ IOpenGLGLSLShader.h \ IOpenGLIndexBuffer.h \ IOpenGLPixelBufferOject.h \ IOpenGLQuery.h \ IOpenGLRectangleTexture.h \ IOpenGLResource.h \ IOpenGLSurface.h \ IOpenGLTexture2D.h \ IOpenGLVertexBuffer.h \ IOpenGLVertexDeclaration.h \ IOpenGLVolume.h \ IOpenGLVolumeTexture.h \ NuxGraphics.h \ NuxGraphicsObject.h \ NuxGraphicsResources.h \ OpenGLDefinitions.h \ OpenGLMapping.h \ RenderingPipe.h \ RenderingPipeGLSL.h \ RenderingPipeTextureBlendShaderSource.h \ RunTimeStats.h if USE_X11 source_h += \ GraphicsDisplayX11.h \ VirtualKeyCodesX11.h \ XInputWindow.h endif if !NUX_OPENGLES_20 source_h += \ IOpenGLAsmShader.h \ RenderingPipeAsm.h endif if HAVE_GEIS source_h += \ GestureEvent.h endif source_cpp = \ BitmapFormats.cpp \ CairoGraphics.cpp \ Events.cpp \ FontRenderer.cpp \ FontTexture.cpp \ GdkGraphics.cpp \ GLDeviceFrameBufferObject.cpp \ GLDeviceObjects.cpp \ GLError.cpp \ GlobalGraphicsInitializer.cpp \ GLPBuffer.cpp \ GLRenderStates.cpp \ GLResource.cpp \ GLResourceManager.cpp \ GLShader.cpp \ GLShaderParameter.cpp \ GLSh_ColorPicker.cpp \ GLSh_DrawFunction.cpp \ GLSh_Fill.cpp \ GLTemplatePrimitiveBuffer.cpp \ GLTextureResourceManager.cpp \ GLTextureStates.cpp \ GLTimer.cpp \ GLVertexResourceManager.cpp \ GLWindowManager.cpp \ GpuDevice.cpp \ GpuDeviceShader.cpp \ GpuDeviceTexture.cpp \ GpuDeviceVertex.cpp \ GraphicsEngine.cpp \ MeshData.cpp \ MeshFileLoader-OBJ.cpp \ ImageSurface.cpp \ IOpenGLAnimatedTexture.cpp \ IOpenGLBaseTexture.cpp \ IOpenGLCubeTexture.cpp \ IOpenGLFrameBufferObject.cpp \ IOpenGLGLSLShader.cpp \ IOpenGLIndexBuffer.cpp \ IOpenGLPixelBufferOject.cpp \ IOpenGLQuery.cpp \ IOpenGLRectangleTexture.cpp \ IOpenGLSurface.cpp \ IOpenGLTexture2D.cpp \ IOpenGLVertexBuffer.cpp \ IOpenGLVertexDeclaration.cpp \ IOpenGLVolume.cpp \ IOpenGLVolumeTexture.cpp \ NuxGraphics.cpp \ NuxGraphicsObject.cpp \ NuxGraphicsResources.cpp \ RenderingPipe.cpp \ RenderingPipeGLSL.cpp \ RenderingPipeTextureBlend.cpp \ GLRenderingAPI.cpp \ RunTimeStats.cpp if USE_X11 source_cpp += \ GraphicsDisplayX11.cpp \ XInputWindow.cpp endif if !NUX_OPENGLES_20 source_cpp += \ IOpenGLAsmShader.cpp \ RenderingPipeAsm.cpp endif if HAVE_GEIS source_cpp += \ GestureEvent.cpp endif libnux_graphics_@NUX_API_VERSION@_la_SOURCES = \ $(source_cpp) \ $(source_h) nux_graphicsdir = $(includedir)/Nux-@NUX_API_VERSION@/NuxGraphics nux_graphics_HEADERS = \ $(source_h) nux-graphics-@NUX_API_VERSION@.pc: nux-graphics.pc $(AM_V_GEN) cp -f nux-graphics.pc nux-graphics-@NUX_API_VERSION@.pc pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = nux-graphics-@NUX_API_VERSION@.pc unused_src = \ FreetypeFont.cpp \ FreetypeFont.h \ GdiImageLoader.cpp \ GdiImageLoader.h \ GfxEventsX11.h \ IOpenGLCgShader.cpp \ IOpenGLCgShader.h \ Readme.txt \ VirtualKeyCodes.h CLEANFILES += nux-graphics-@NUX_API_VERSION@.pc DISTCLEANFILES += nux-graphics.pc EXTRA_DIST += nux-graphics.pc.in ${unused_src} ./NuxGraphics/CairoGraphics.h0000644000004100000410000001056513313171755016402 0ustar www-datawww-data/* * Copyright 2010, 2011 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef CAIROGRAPHICS_H #define CAIROGRAPHICS_H #ifdef NUX_ARCH_ARM #include "cairo.h" #else #include "cairo/cairo.h" #endif #include "BitmapFormats.h" #include "ImageSurface.h" #include namespace nux { class CairoFontOptions { public: CairoFontOptions() : font_options_(::cairo_font_options_create()) {} ~CairoFontOptions() { ::cairo_font_options_destroy(font_options_); } operator cairo_font_options_t*() { return font_options_; } private: cairo_font_options_t* font_options_; }; //! A cairo graphics container /*! CairoGraphics encapsulates a cairo surface and context. */ class CairoGraphics { public: CairoGraphics(cairo_format_t format, int width, int height); ~CairoGraphics(); //! Return a cairo context to the encapsulated surface. /*! Return the cairo context of this object. Call cairo_destroy to destroy the context when you are done with it. @return A cairo context. */ cairo_t *GetContext(); //! Return an internal cairo context to the encapsulated surface. Should not be destroyed. /*! Return the cairo context of this object. This cairo context should not be destroyed with cairo_destroy. @return A cairo context. */ cairo_t *GetInternalContext(); cairo_surface_t* GetSurface(); //! Create a NBitmapData pointer to a 2D texture data. /*! The returned data must be destroyed with delete. @return A pointer to a 2D texture data. */ NBitmapData *GetBitmap(); int GetWidth() const; int GetHeight() const; bool PushState(); bool PopState(); bool ClearCanvas(); bool ClearRect(double x, double y, double w, double h); bool DrawLine(double x0, double y0, double x1, double y1, double width, const Color &c); void TranslateCoordinates(double dx, double dy); bool DrawFilledRect(double x, double y, double w, double h, const Color &c); bool DrawCanvas(double x, double y, CairoGraphics *cg); bool DrawRoundedRectangle(cairo_t* cr, double aspect, double x, double y, double cornerRadius, double width, double height, bool align = false); bool BlurSurface(unsigned int radius, cairo_surface_t* surf = NULL); bool IntersectRectClipRegion(double x, double y, double w, double h); bool IntersectGeneralClipRegion(std::list ®ion); /** * Enum used to specify horizontal alignment. */ enum Alignment { ALIGN_LEFT, ALIGN_CENTER, ALIGN_RIGHT, ALIGN_JUSTIFY }; /** * Enum used to specify vertical alignment. */ enum VAlignment { VALIGN_TOP, VALIGN_MIDDLE, VALIGN_BOTTOM }; /** * Enum used to specify trimming type. */ enum Trimming { TRIMMING_NONE, TRIMMING_CHARACTER, TRIMMING_WORD, TRIMMING_CHARACTER_ELLIPSIS, TRIMMING_WORD_ELLIPSIS, TRIMMING_PATH_ELLIPSIS }; /** * Enum used to specify text flags. */ enum TextFlag { TEXT_FLAGS_NONE = 0, TEXT_FLAGS_UNDERLINE = 1, TEXT_FLAGS_STRIKEOUT = 2, TEXT_FLAGS_WORDWRAP = 4 }; private: //! Cairo surface format cairo_format_t m_surface_format; //! Cairo surface cairo_surface_t *_cairo_surface; cairo_t * _cr; int _width; //!< Surface width. int _height; //!< Surface height. double _zoom; float _opacity; std::stack _opacity_stack; }; } #endif // CAIROGRAPHICS_H ./NuxGraphics/GfxEventsX11.h0000644000004100000410000003052713313171755016067 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef GFXEVENTSX11_H #define GFXEVENTSX11_H #include "GLResource.h" #include "VirtualKeyCodesX11.h" //--------------------------------------------------------------key_code_e // Keyboard codes. There's also a restricted set of codes that are most // probably supported on different platforms. Any platform dependent codes // should be converted into these ones. There're only those codes are // defined that cannot be represented as printable ASCII-characters. // All printable ASCII-set can be used in a regilar C/C++ manner: // ' ', 'A', '0' '+' and so on. // Since the class is used for creating very simple demo-applications // we don't need very rich possibilities here, just basic ones. // Actually the numeric key codes are taken from the SDL library, so, // the implementation of the SDL support does not require any mapping. //enum eKeyCode //{ // // ASCII set. Should be supported everywhere // key_backspace = 8, // key_tab = 9, // key_clear = 12, // key_return = 13, // key_shift = 16, // key_control = 17, // key_pause = 19, // key_escape = 27, // // key_space = 32, // // // Keypad // key_delete = 127, // key_kp0 = 256, // key_kp1 = 257, // key_kp2 = 258, // key_kp3 = 259, // key_kp4 = 260, // key_kp5 = 261, // key_kp6 = 262, // key_kp7 = 263, // key_kp8 = 264, // key_kp9 = 265, // key_kp_period = 266, // key_kp_divide = 267, // key_kp_multiply = 268, // key_kp_minus = 269, // key_kp_plus = 270, // key_kp_enter = 271, // key_kp_equals = 272, // // // Arrow-keys and stuff // key_up = 273, // key_down = 274, // key_right = 275, // key_left = 276, // key_insert = 277, // key_home = 278, // key_end = 279, // key_page_up = 280, // key_page_down = 281, // // // Functional keys. You'd better avoid using // // f11...f15 in your applications if you want // // the applications to be portable // key_f1 = 282, // key_f2 = 283, // key_f3 = 284, // key_f4 = 285, // key_f5 = 286, // key_f6 = 287, // key_f7 = 288, // key_f8 = 289, // key_f9 = 290, // key_f10 = 291, // key_f11 = 292, // key_f12 = 293, // key_f13 = 294, // key_f14 = 295, // key_f15 = 296, // // // The possibility of using these keys is // // very restricted. Actually it's guaranteed // // only in win32_api and win32_sdl implementations // key_numlock = 300, // key_capslock = 301, // key_scrollock = 302, // // // Phew! // end_of_key_codes //}; namespace nux { const long I_ExposureMask = (1L << 15); const long I_StructureNotifyMask = (1L << 17); const long I_SubstructureNotifyMask = (1L << 19); #define NUX_BackSpace NUX_VK_BACK #define NUX_Tab NUX_VK_TAB #define NUX_Clear NUX_VK_CLEAR #define NUX_Enter NUX_VK_ENTER #define NUX_Shift_L NUX_VK_SHIFT #define NUX_Control_L NUX_VK_CONTROL #define NUX_Alt_L NUX_VK_MENU #define NUX_Pause NUX_VK_PAUSE #define NUX_Caps_Lock NUX_VK_CAPITAL #define NUX_Escape NUX_VK_ESCAPE #define NUX_SpaceBar NUX_VK_SPACE #define NUX_Page_Up NUX_VK_PAGE_UP #define NUX_Page_Down NUX_VK_PAGE_DOWN #define NUX_End NUX_VK_END #define NUX_Home NUX_VK_HOME #define NUX_Left NUX_VK_LEFT #define NUX_Up NUX_VK_UP #define NUX_Right NUX_VK_RIGHT #define NUX_Down NUX_VK_DOWN #define NUX_Print NUX_VK_SNAPSHOT #define NUX_Insert NUX_VK_INSERT #define NUX_Delete NUX_VK_DELETE #define NUX_LWin NUX_VK_LWIN #define NUX_RWin NUX_VK_RWIN #define NUX_APPS NUX_VK_APPS #define NUX_Multiply NUX_VK_MULTIPLY #define NUX_Add NUX_VK_ADD #define NUX_Subtract NUX_VK_SUBTRACT #define NUX_Decimal NUX_VK_DECIMAL #define NUX_Divide NUX_VK_DIVIDE #define NUX_Numlock NUX_VK_NUMLOCK #define NUX_Scroll NUX_VK_SCROLL #define NUX_KP_ENTER (0xff00 | NUX_VK_ENTER) #define NUX_EXT_Shift_R (0xff00 | NUX_VK_SHIFT) #define NUX_EXT_Control_R (0xff00 | NUX_VK_CONTROL) #define NUX_EXT_Alt_R (0xff00 | NUX_VK_MENU) #define NUX_KP_PAGE_UP (0xff00 | NUX_VK_PAGE_UP) #define NUX_KP_PAGE_DOWN (0xff00 | NUX_VK_PAGE_DOWN) #define NUX_KP_END (0xff00 | NUX_VK_END) #define NUX_KP_HOME (0xff00 | NUX_VK_HOME) #define NUX_KP_LEFT (0xff00 | NUX_VK_LEFT) #define NUX_KP_UP (0xff00 | NUX_VK_UP) #define NUX_KP_RIGHT (0xff00 | NUX_VK_RIGHT) #define NUX_KP_DOWN (0xff00 | NUX_VK_DOWN) #define NUX_KP_INSERT (0xff00 | NUX_VK_INSERT) #define NUX_KP_DELETE (0xff00 | NUX_VK_DELETE) #define NUX_F1 NUX_VK_F1 #define NUX_F2 NUX_VK_F2 #define NUX_F3 NUX_VK_F3 #define NUX_F4 NUX_VK_F4 #define NUX_F5 NUX_VK_F5 #define NUX_F6 NUX_VK_F6 #define NUX_F7 NUX_VK_F7 #define NUX_F8 NUX_VK_F8 #define NUX_F9 NUX_VK_F9 #define NUX_F10 NUX_VK_F10 #define NUX_F11 NUX_VK_F11 #define NUX_F12 NUX_VK_F12 #define NUX_F13 NUX_VK_F13 #define NUX_F14 NUX_VK_F14 #define NUX_F15 NUX_VK_F15 #define NUX_F16 NUX_VK_F16 #define NUX_F17 NUX_VK_F17 #define NUX_F18 NUX_VK_F18 #define NUX_F19 NUX_VK_F19 #define NUX_F20 NUX_VK_F20 #define NUX_F21 NUX_VK_F21 #define NUX_F22 NUX_VK_F22 #define NUX_F23 NUX_VK_F23 #define NUX_F24 NUX_VK_F24 #define NUX_LEFT_MOUSE 1 #define NUX_MIDDLE_MOUSE 2 #define NUX_RIGHT_MOUSE 3 // Key States. Set in e_key_modifiers. #define NUX_STATE_SHIFT 0x00010000 #define NUX_STATE_CAPS_LOCK 0x00020000 #define NUX_STATE_CTRL 0x00040000 #define NUX_STATE_ALT 0x00080000 #define NUX_STATE_NUMLOCK 0x00100000 // most X servers do this? #define NUX_STATE_META 0x00400000 // correct for XFree86 #define NUX_STATE_SCROLLLOCK 0x00800000 // correct for XFree86 // These flags describe the mouse button responsible for the mouse event. // They are valid only for the current frame. // Go in e_mouse_state. #define NUX_EVENT_BUTTON1_UP 0x00001000 #define NUX_EVENT_BUTTON2_UP 0x00002000 #define NUX_EVENT_BUTTON3_UP 0x00004000 #define NUX_EVENT_BUTTON1_DOWN 0x00010000 #define NUX_EVENT_BUTTON2_DOWN 0x00020000 #define NUX_EVENT_BUTTON3_DOWN 0x00040000 #define NUX_EVENT_BUTTON1 0x00010000 #define NUX_EVENT_BUTTON2 0x00020000 #define NUX_EVENT_BUTTON3 0x00040000 #define NUX_EVENT_MOUSEWHEEL 0x00080000 // These flags describe the state of the mouse buttons. // They persist over several frame until the mouse buttons change state. // Go in e_mouse_state. #define NUX_STATE_BUTTON1_DOWN 0x01000000 #define NUX_STATE_BUTTON2_DOWN 0x02000000 #define NUX_STATE_BUTTON3_DOWN 0x04000000 // These flags are set if the event is a double click. // They are valid only for the current frame. // Go in e_mouse_state. #define NUX_EVENT_BUTTON1_DBLCLICK 0x10000000 #define NUX_EVENT_BUTTON2_DBLCLICK 0x20000000 #define NUX_EVENT_BUTTON3_DBLCLICK 0x40000000 #define eLEFT_BUTTON NUX_EVENT_BUTTON1 #define eMIDDLE_BUTTON NUX_EVENT_BUTTON2 #define eRIGHT_BUTTON NUX_EVENT_BUTTON3 #define eLEFT_BUTTON_DOWN NUX_STATE_BUTTON1_DOWN #define eMIDDLE_BUTTON_DOWN NUX_STATE_BUTTON2_DOWN #define eRIGHT_BUTTON_DOWN NUX_STATE_BUTTON3_DOWN #define NUX_WIN32_MOUSEWHEEL_DELTA 120 // 120 correspond to one notch of the mouse wheel typedef unsigned char uchar; typedef unsigned long ulong; struct EventToNameStruct { int event; const TCHAR *EventName; }; enum { // events NUX_NO_EVENT = 0, NUX_MOUSE_PRESSED, NUX_MOUSE_RELEASED, NUX_KEYDOWN, NUX_KEYUP, NUX_MOUSE_MOVE, NUX_SIZE_CONFIGURATION, NUX_WINDOW_CONFIGURATION, NUX_WINDOW_ENTER_FOCUS, NUX_WINDOW_EXIT_FOCUS, NUX_WINDOW_DIRTY, NUX_WINDOW_MOUSELEAVE, NUX_MOUSEWHEEL, NUX_DESTROY_WINDOW, NUX_TERMINATE_APP }; typedef struct IEvent { int width, height; unsigned int ascii_code; int virtual_code; bool IsLeftMouseDown; bool IsRightMouseDown; bool IsMiddleMouseDown; int e_x, e_y, e_x_root, e_y_root, e_dx, e_dy, e_clicks, e_is_click, e_keysym; int e_wheeldelta; unsigned long e_key_modifiers; // key modifiers unsigned short e_key_repeat_count; // number of time a key is repeated; unsigned long e_mouse_state; char *e_text; int e_length; unsigned long e_event; IEvent() { IsLeftMouseDown = false; IsRightMouseDown = false; IsMiddleMouseDown = false; e_text = (char *) ""; for (int i = 0; i < NUX_MAX_VK; i++) { VirtualKeycodeState[i] = 0; } ascii_code = 0; virtual_code = 0; e_key_modifiers = 0; e_key_repeat_count = 0; e_mouse_state = 0; e_x = 0; e_y = 0; e_x_root = 0; e_y_root = 0; e_dx = 0; e_dy = 0; e_clicks = 0; e_is_click = 0; e_keysym = 0; e_wheeldelta = 0; //Application = 0; } int event_x() const { return e_x; } int event_y() const { return e_y; } int event_x_root() const { return e_x_root; } int event_y_root() const { return e_y_root; } int event_dx() const { return e_dx; } int event_dy() const { return e_dy; } void get_mouse (int &, int &); unsigned long event_key_state() const { return e_key_modifiers; } unsigned long event_mouse_state() const { return e_mouse_state; } //! Return virtual key code of the key that has triggered the last event. /*! Return virtual key code of the key that has triggered the last event. @return the virtual key code. */ unsigned long event_keysym() const { return e_keysym; } unsigned short event_key_auto_repeat_count() const { return e_key_repeat_count; } bool event_is_key_auto_repeat() const { if (e_key_repeat_count > 1) return true; return false; } const char *event_text() const { return e_text; } // Because an event is save in e_event instead of calling immediately the handling function, // we must clear the previous event each time before we test for new event in Gfx_OpenGLImpl::get_event. void Reset() { e_event = NUX_NO_EVENT; e_text = (char *) ""; e_keysym = 0; e_key_repeat_count = 0; e_wheeldelta = 0; } unsigned long VirtualKeycodeState[NUX_MAX_VK]; //! Return the state of the Virtual key /*! Return the state of the Virtual key. @param VirtualKey virtual key code. @return 1 if the key is pressed, 0 if the key is released. */ unsigned long GetVirtualKeyState (unsigned long VirtualKey) const { if (VirtualKey >= NUX_MAX_VK) return 0; if (VirtualKey <= 0) return 0; return VirtualKeycodeState[VirtualKey]; } //void* Application; } IEvent; } #endif // GFXEVENTSX11_H ./NuxGraphics/GLDeviceFrameBufferObject.cpp0000644000004100000410000003010713313171755021067 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "GLResource.h" #include "GpuDevice.h" #include "GLDeviceObjects.h" #include "GLResourceManager.h" #include "GLTextureResourceManager.h" #include "GLVertexResourceManager.h" #include "GLDeviceFrameBufferObject.h" #include "GLTemplatePrimitiveBuffer.h" #include "GraphicsEngine.h" namespace nux { GLenum AttachmentBuffer[] = { GL_COLOR_ATTACHMENT0_EXT #ifndef NUX_OPENGLES_20 // GLES 2.0 only supports one color attachment , GL_COLOR_ATTACHMENT1_EXT , GL_COLOR_ATTACHMENT2_EXT , GL_COLOR_ATTACHMENT3_EXT #endif }; ////////////////////////////////////////////////////////////////////////// // GLFramebufferObject ////////////////////////////////////////////////////////////////////////// GLFramebufferObject::GLFramebufferObject() : m_fboId(0) , m_savedFboId(0) { m_fboId = _GenerateFboId(); // Bind this FBO so that it actually gets created now _GuardedBind(); _GuardedUnbind(); } GLFramebufferObject::~GLFramebufferObject() { CHECKGL(glDeleteFramebuffersEXT(1, (const GLuint *) &m_fboId)); } void GLFramebufferObject::Bind() { #ifdef NUX_OPENGLES_20 GLenum binding = GL_FRAMEBUFFER; #else GLenum binding = GL_DRAW_FRAMEBUFFER_EXT; #endif CHECKGL(glBindFramebufferEXT(binding, m_fboId)); } void GLFramebufferObject::Disable() { #ifdef NUX_OPENGLES_20 GLenum binding = GL_FRAMEBUFFER; #else GLenum binding = GL_DRAW_FRAMEBUFFER_EXT; #endif CHECKGL(glBindFramebufferEXT(binding, 0)); } void GLFramebufferObject::AttachTexture( GLenum attachment, GLenum texType, GLuint texId, int mipLevel, int zSlice) { _GuardedBind(); if ( GetAttachedId(attachment) != texId ) { _FramebufferTextureND( attachment, texType, texId, mipLevel, zSlice ); } else { // nuxError("GLFramebufferObject::AttachTexture PERFORMANCE WARNING:\n // \tRedundant bind of texture(id = %d).\n"), texId); } _GuardedUnbind(); } void GLFramebufferObject::AttachTextures( int numTextures, GLenum texTarget[], GLuint texId[], GLenum attachment[], int mipLevel[], int zSlice[] ) { for (int i = 0; i < numTextures; ++i) { AttachTexture( texTarget[i], texId[i], attachment ? attachment[i] : (GL_COLOR_ATTACHMENT0_EXT + i), mipLevel ? mipLevel[i] : 0, zSlice ? zSlice[i] : 0 ); } } void GLFramebufferObject::AttachRenderBuffer( GLenum attachment, GLuint buffId ) { _GuardedBind(); if ( GetAttachedId(attachment) != buffId ) { CHECKGL(glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, attachment, GL_RENDERBUFFER_EXT, buffId)); } else { // nuxError(TEXT("GLFramebufferObject::AttachRenderBuffer PERFORMANCE WARNING:\n // \tRedundant bind of GLRenderbuffer(id = %d).\n"), buffId); } _GuardedUnbind(); } void GLFramebufferObject::Unattach( GLenum attachment ) { _GuardedBind(); GLenum type = GetAttachedType(attachment); switch(type) { case GL_NONE: break; case GL_RENDERBUFFER_EXT: AttachRenderBuffer( attachment, 0 ); break; case GL_TEXTURE: AttachTexture( attachment, GL_TEXTURE_2D, 0 ); break; default: std::cout << "GLFramebufferObject::unbind_attachment ERROR: Unknown attached resource type\n"; } _GuardedUnbind(); } GLint GLFramebufferObject::GetMaxColorAttachments() { #ifndef NUX_OPENGLES_20 GLint maxAttach = 0; CHECKGL(glGetIntegerv( GL_MAX_COLOR_ATTACHMENTS_EXT, &maxAttach )); return maxAttach; #else return 1; #endif } GLuint GLFramebufferObject::_GenerateFboId() { GLuint id = 0; CHECKGL(glGenFramebuffersEXT(1, &id)); return id; } void GLFramebufferObject::_GuardedBind() { #ifndef NUX_OPENGLES_20 // Only binds if m_fboId is different than the currently bound FBO CHECKGL(glGetIntegerv( GL_DRAW_FRAMEBUFFER_BINDING_EXT, &m_savedFboId )); if (m_fboId != m_savedFboId) { CHECKGL(glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_fboId)); } #else // Only binds if m_fboId is different than the currently bound FBO CHECKGL(glGetIntegerv( GL_FRAMEBUFFER_BINDING_EXT, &m_savedFboId )); if (m_fboId != m_savedFboId) { CHECKGL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fboId)); } #endif } void GLFramebufferObject::_GuardedUnbind() { #ifdef NUX_OPENGLES_20 GLenum binding = GL_FRAMEBUFFER; #else GLenum binding = GL_DRAW_FRAMEBUFFER_EXT; #endif // Returns FBO binding to the previously enabled FBO if (m_savedFboId != m_fboId) { CHECKGL(glBindFramebufferEXT(binding, (GLuint) m_savedFboId)); } } void GLFramebufferObject::_FramebufferTextureND( GLenum attachment, GLenum texType, GLuint texId, int mipLevel, int zSlice ) { if (texType == GL_TEXTURE_2D) { // Default is GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_ARB, or cube faces CHECKGL(glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, attachment, texType, texId, mipLevel )); } #ifndef NUX_OPENGLES_20 else if (texType == GL_TEXTURE_1D) { CHECKGL(glFramebufferTexture1DEXT( GL_FRAMEBUFFER_EXT, attachment, GL_TEXTURE_1D, texId, mipLevel )); } else if (texType == GL_TEXTURE_3D) { CHECKGL(glFramebufferTexture3DEXT( GL_FRAMEBUFFER_EXT, attachment, GL_TEXTURE_3D, texId, mipLevel, zSlice )); } #endif } bool GLFramebufferObject::IsValid() { _GuardedBind(); bool isOK = false; GLenum status; status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); CHECKGL_MSG(glCheckFramebufferStatusEXT); switch(status) { case GL_FRAMEBUFFER_COMPLETE_EXT: // Everything's OK isOK = true; break; case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: nuxError("[GLFramebufferObject::IsValid] GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT"); isOK = false; break; case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: nuxError("[GLFramebufferObject::IsValid] GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT"); isOK = false; break; // See issue(87) of http://www.opengl.org/registry/specs/EXT/framebuffer_object.txt // case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT: // nuxError("[GLFramebufferObject::IsValid] GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT"); // isOK = false; // break; case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: nuxError("[GLFramebufferObject::IsValid] GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT"); isOK = false; break; #ifndef NUX_OPENGLES_20 case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: nuxError("[GLFramebufferObject::IsValid] GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT"); isOK = false; break; case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: nuxError("[GLFramebufferObject::IsValid] GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT"); isOK = false; break; case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: nuxError("[GLFramebufferObject::IsValid] GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT"); isOK = false; break; #endif // case GL_FRAMEBUFFER_STATUS_ERROR_EXT: // nuxError("[GLFramebufferObject::IsValid] GL_FRAMEBUFFER_STATUS_ERROR_EXT"); // isOK = false; // break; case GL_FRAMEBUFFER_UNSUPPORTED_EXT: nuxError("[GLFramebufferObject::IsValid] GL_FRAMEBUFFER_UNSUPPORTED_EXT"); isOK = false; break; default: nuxError("[GLFramebufferObject::IsValid] Unknown ERROR"); isOK = false; } _GuardedUnbind(); return isOK; } /// Accessors GLenum GLFramebufferObject::GetAttachedType( GLenum attachment ) { // Returns GL_RENDERBUFFER_EXT or GL_TEXTURE _GuardedBind(); GLint type = 0; CHECKGL(glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER_EXT, attachment, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT, &type)); _GuardedUnbind(); return GLenum(type); } GLuint GLFramebufferObject::GetAttachedId( GLenum attachment ) { _GuardedBind(); GLint id = 0; CHECKGL(glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER_EXT, attachment, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT, &id)); _GuardedUnbind(); return GLuint(id); } GLint GLFramebufferObject::GetAttachedMipLevel( GLenum attachment ) { _GuardedBind(); GLint level = 0; CHECKGL(glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER_EXT, attachment, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT, &level)); _GuardedUnbind(); return level; } GLint GLFramebufferObject::GetAttachedCubeFace( GLenum attachment ) { _GuardedBind(); GLint level = 0; #ifndef NUX_OPENGLES_20 CHECKGL(glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER_EXT, attachment, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT, &level)); #endif _GuardedUnbind(); return level; } GLint GLFramebufferObject::GetAttachedZSlice( GLenum attachment ) { _GuardedBind(); GLint slice = 0; #ifndef NUX_OPENGLES_20 CHECKGL(glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER_EXT, attachment, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT, &slice)); #endif _GuardedUnbind(); return slice; } ////////////////////////////////////////////////////////////////////////// // GLRenderbuffer ////////////////////////////////////////////////////////////////////////// GLRenderbuffer::GLRenderbuffer() : m_bufId(0) { m_bufId = _CreateBufferId(); } GLRenderbuffer::GLRenderbuffer(GLenum internalFormat, int width, int height) : m_bufId(_CreateBufferId()) { Set(internalFormat, width, height); } GLRenderbuffer::~GLRenderbuffer() { CHECKGL(glDeleteRenderbuffersEXT(1, &m_bufId)); } void GLRenderbuffer::Bind() { CHECKGL(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_bufId)); } void GLRenderbuffer::Unbind() { CHECKGL(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0)); } void GLRenderbuffer::Set(GLenum internalFormat, int width, int height) { int maxSize = GLRenderbuffer::GetMaxSize(); if (width > maxSize || height > maxSize ) { std::cout << "GLRenderbuffer::GLRenderbuffer() ERROR: Size too big width=" << width << "height=" << height << "\n"; return; } // Guarded bind GLint savedId = 0; CHECKGL(glGetIntegerv( GL_RENDERBUFFER_BINDING_EXT, &savedId )); if (savedId != (GLint) m_bufId) { Bind(); } // Allocate memory for renderBuffer CHECKGL(glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, internalFormat, width, height )); // Guarded unbind if (savedId != (GLint) m_bufId) { Unbind(); } } GLuint GLRenderbuffer::GetId() const { return m_bufId; } GLint GLRenderbuffer::GetMaxSize() { GLint maxAttach = 0; CHECKGL(glGetIntegerv( GL_MAX_RENDERBUFFER_SIZE_EXT, &maxAttach )); return maxAttach; } GLuint GLRenderbuffer::_CreateBufferId() { GLuint id = 0; CHECKGL(glGenRenderbuffersEXT(1, &id)); return id; } } ./NuxGraphics/NuxGraphics.cpp0000644000004100000410000000277613313171755016457 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "GLResource.h" #include "FontTexture.h" #include "NuxGraphics.h" #include "GLResourceManager.h" #if defined(NUX_OS_WINDOWS) #include "GraphicsDisplay.h" #elif defined(NUX_OS_LINUX) #include "GraphicsDisplay.h" #endif namespace nux { void NuxGraphicsInitialize() { inlRegisterThreadLocalIndex(1, _TLS_GraphicsDisplay, NULL); #if defined(NUX_OS_WINDOWS) #endif #if defined(NUX_OS_LINUX) && G_ENCODE_VERSION (GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION) <= GLIB_VERSION_2_34 // Necessary in order to use gdk g_type_init(); #endif GNuxGraphicsResources.InitializeResources(); } GraphicsDisplay* GetGraphicsDisplay() { return(GraphicsDisplay *) inlGetThreadLocalStorage(_TLS_GraphicsDisplay); } } ./NuxGraphics/NuxGraphics.h0000644000004100000410000000242013313171755016106 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef NUXGRAPHICS_H #define NUXGRAPHICS_H namespace nux { class GraphicsDisplay; class GpuDevice; class GraphicsEngine; GraphicsDisplay* GetGraphicsDisplay(); #define NUX_FINDRESOURCELOCATION(a) GNuxGraphicsResources.FindResourceLocation(a, false) #define NUX_FIND_RESOURCE_LOCATION_NOFAIL(a) GNuxGraphicsResources.FindResourceLocation(a, true) inlDeclareThreadLocalStorage(GraphicsDisplay *, 1, _TLS_GraphicsDisplay); void NuxGraphicsInitialize(); } #endif // NUXGRAPHICS_H ./NuxGraphics/MeshFileLoader-OBJ.h0000644000004100000410000000025113313171755017106 0ustar www-datawww-data#ifndef MESHFILELOADER_H #define MESHFILELOADER_H namespace nux { class MeshData; MeshData* LoadMeshFile_OBJ(const char* filename); } #endif // MESHFILELOADER_H ./NuxGraphics/GpuDevice.cpp0000755000004100000410000011675013313171755016100 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "GLResource.h" #include "NuxGraphics.h" #include "GpuDevice.h" #include "GLDeviceObjects.h" #include "GLResourceManager.h" #include "GLTextureResourceManager.h" #include "GLVertexResourceManager.h" #include "GLDeviceFrameBufferObject.h" #include "GLTemplatePrimitiveBuffer.h" #include "GraphicsEngine.h" #include #include #include #include #include namespace nux { #if (NUX_ENABLE_CG_SHADERS) extern void cgErrorCallback(void); #endif typedef struct { int major; int minor; } OpenGLVersion; static OpenGLVersion OpenGLVersionTable [] = { {1, 0}, {1, 1}, {1, 2}, {1, 3}, {1, 4}, {2, 0}, {2, 1}, {3, 0}, {3, 1}, {3, 2}, {3, 3}, {4, 0}, {4, 1}, {0, 0} }; extern PixelFormatInfo GPixelFormats[]; static void InitTextureFormats() { #ifndef NUX_OPENGLES_20 GPixelFormats[ BITFMT_UNKNOWN ].PlatformFormat = GL_NONE; // Not supported for rendering. // Data in PC system memory: R(LSB) G B A(MSB) ---> GL Format:GL_RGBA - GL Type:GL_UNSIGNED_INT_8_8_8_8_REV GPixelFormats[BITFMT_R8G8B8A8].PlatformFormat = GL_RGBA8; GPixelFormats[BITFMT_R8G8B8A8].Format = GL_RGBA; GPixelFormats[BITFMT_R8G8B8A8].type = GL_UNSIGNED_INT_8_8_8_8_REV; // Data in PC system memory: A(LSB) B G R(MSB) ---> GL Format:GL_RGBA - GL Type:GL_UNSIGNED_INT_8_8_8_8 GPixelFormats[BITFMT_A8B8G8R8].PlatformFormat = GL_RGBA8; GPixelFormats[BITFMT_A8B8G8R8].Format = GL_RGBA; GPixelFormats[BITFMT_A8B8G8R8].type = GL_UNSIGNED_INT_8_8_8_8; // Data in PC system memory: B(LSB) G R A(MSB) ---> GL Format:GL_BGRA - GL Type:GL_UNSIGNED_INT_8_8_8_8_REV GPixelFormats[BITFMT_B8G8R8A8].PlatformFormat = GL_RGBA8; GPixelFormats[BITFMT_B8G8R8A8].Format = GL_BGRA; GPixelFormats[BITFMT_B8G8R8A8].type = GL_UNSIGNED_INT_8_8_8_8_REV; // Data in PC system memory: A(LSB) R G B(MSB) ---> GL Format:GL_BGRA - GL Type:GL_UNSIGNED_INT_8_8_8_8 GPixelFormats[BITFMT_A8R8G8B8].PlatformFormat = GL_RGBA8; GPixelFormats[BITFMT_A8R8G8B8].Format = GL_BGRA; GPixelFormats[BITFMT_A8R8G8B8].type = GL_UNSIGNED_INT_8_8_8_8; // Data in PC system memory: R(LSB) G B(MSB) ---> GL Format:GL_RGB - GL Type:GL_UNSIGNED GPixelFormats[BITFMT_R8G8B8].PlatformFormat = GL_RGB8; GPixelFormats[BITFMT_R8G8B8].Format = GL_RGB; GPixelFormats[BITFMT_R8G8B8].type = GL_UNSIGNED_BYTE; GPixelFormats[BITFMT_B8G8R8].PlatformFormat = GL_RGB8; GPixelFormats[BITFMT_B8G8R8].Format = GL_BGR; GPixelFormats[BITFMT_B8G8R8].type = GL_UNSIGNED_BYTE; GPixelFormats[BITFMT_R5G6B5].PlatformFormat = GL_RGB5; GPixelFormats[BITFMT_R5G6B5].Format = GL_RGB; GPixelFormats[BITFMT_R5G6B5].type = GL_UNSIGNED_SHORT_5_6_5; GPixelFormats[BITFMT_RGBA16F].PlatformFormat = GL_RGBA16F_ARB; GPixelFormats[BITFMT_RGBA16F].Format = GL_RGBA; GPixelFormats[BITFMT_RGBA16F].type = GL_HALF_FLOAT_ARB; GPixelFormats[BITFMT_RGB32F].PlatformFormat = GL_RGB; GPixelFormats[BITFMT_RGB32F].Format = GL_RGB; GPixelFormats[BITFMT_RGB32F].type = GL_FLOAT; GPixelFormats[BITFMT_RGBA32F].PlatformFormat = GL_RGBA32F_ARB; GPixelFormats[BITFMT_RGBA32F].Format = GL_RGBA; GPixelFormats[BITFMT_RGBA32F].type = GL_FLOAT; // Note: Using GL_DEPTH_COMPONENT24 or GL_DEPTH_COMPONENT for PlatformFormat generate error GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT. GPixelFormats[BITFMT_D24S8].PlatformFormat = GL_DEPTH24_STENCIL8_EXT; GPixelFormats[BITFMT_D24S8].Format = GL_DEPTH_STENCIL_EXT; // or GL_DEPTH_STENCIL_NV; GPixelFormats[BITFMT_D24S8].type = GL_UNSIGNED_INT_24_8_EXT; // or GL_UNSIGNED_INT_24_8_NV; GPixelFormats[BITFMT_DXT1].PlatformFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; GPixelFormats[BITFMT_DXT2].PlatformFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; GPixelFormats[BITFMT_DXT3].PlatformFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; GPixelFormats[BITFMT_DXT4].PlatformFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; GPixelFormats[BITFMT_DXT5].PlatformFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; GPixelFormats[BITFMT_R10G10B10A2].PlatformFormat = GL_RGB10_A2; GPixelFormats[BITFMT_R10G10B10A2].Format = GL_RGBA; GPixelFormats[BITFMT_R10G10B10A2].type = GL_UNSIGNED_INT_10_10_10_2; GPixelFormats[BITFMT_A2B10G10R10].PlatformFormat = GL_RGB10_A2; GPixelFormats[BITFMT_A2B10G10R10].Format = GL_RGBA; GPixelFormats[BITFMT_A2B10G10R10].type = GL_UNSIGNED_INT_2_10_10_10_REV; GPixelFormats[BITFMT_B10G10R10A2].PlatformFormat = GL_RGB10_A2; GPixelFormats[BITFMT_B10G10R10A2].Format = GL_BGRA; GPixelFormats[BITFMT_B10G10R10A2].type = GL_UNSIGNED_INT_10_10_10_2; GPixelFormats[BITFMT_A2R10G10B10].PlatformFormat = GL_RGB10_A2; GPixelFormats[BITFMT_A2R10G10B10].Format = GL_BGRA; GPixelFormats[BITFMT_A2R10G10B10].type = GL_UNSIGNED_INT_2_10_10_10_REV; GPixelFormats[BITFMT_A8].PlatformFormat = GL_RGBA8; GPixelFormats[BITFMT_A8].Format = GL_LUMINANCE; GPixelFormats[BITFMT_A8].type = GL_UNSIGNED_BYTE; #else GPixelFormats[ BITFMT_UNKNOWN ].PlatformFormat = GL_NONE; // Not supported for rendering. // Data in PC system memory: R(LSB) G B A(MSB) ---> GL Format:GL_RGBA - GL Type:GL_UNSIGNED_INT_8_8_8_8_REV GPixelFormats[BITFMT_R8G8B8A8].PlatformFormat = GL_RGBA; GPixelFormats[BITFMT_R8G8B8A8].Format = GL_RGBA; GPixelFormats[BITFMT_R8G8B8A8].type = GL_UNSIGNED_BYTE; // Data in PC system memory: B(LSB) G R A(MSB) ---> GL Format:GL_BGRA - GL Type:GL_UNSIGNED_INT_8_8_8_8_REV GPixelFormats[BITFMT_B8G8R8A8].PlatformFormat = GL_BGRA_EXT; GPixelFormats[BITFMT_B8G8R8A8].Format = GL_BGRA_EXT; GPixelFormats[BITFMT_B8G8R8A8].type = GL_UNSIGNED_BYTE; // Data in PC system memory: R(LSB) G B(MSB) ---> GL Format:GL_RGB - GL Type:GL_UNSIGNED GPixelFormats[BITFMT_R8G8B8].PlatformFormat = GL_RGB; GPixelFormats[BITFMT_R8G8B8].Format = GL_RGB; GPixelFormats[BITFMT_R8G8B8].type = GL_UNSIGNED_BYTE; GPixelFormats[BITFMT_R5G6B5].PlatformFormat = GL_RGB; GPixelFormats[BITFMT_R5G6B5].Format = GL_RGB; GPixelFormats[BITFMT_R5G6B5].type = GL_UNSIGNED_SHORT_5_6_5; // Note: Using GL_DEPTH_COMPONENT24 or GL_DEPTH_COMPONENT for PlatformFormat generate error GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT. GPixelFormats[BITFMT_D24S8].PlatformFormat = GL_DEPTH_STENCIL_OES; GPixelFormats[BITFMT_D24S8].Format = GL_DEPTH_STENCIL_OES; GPixelFormats[BITFMT_D24S8].type = GL_UNSIGNED_INT_24_8_OES; GPixelFormats[BITFMT_A8].PlatformFormat = GL_ALPHA; GPixelFormats[BITFMT_A8].Format = GL_ALPHA; GPixelFormats[BITFMT_A8].type = GL_UNSIGNED_BYTE; #endif } STREAMSOURCE GpuDevice::_StreamSource[MAX_NUM_STREAM]; GpuInfo::GpuInfo() : _support_opengl_version_11(false) , _support_opengl_version_12(false) , _support_opengl_version_13(false) , _support_opengl_version_14(false) , _support_opengl_version_15(false) , _support_opengl_version_20(false) , _support_opengl_version_21(false) , _support_opengl_version_30(false) , _support_opengl_version_31(false) , _support_opengl_version_32(false) , _support_opengl_version_33(false) , _support_opengl_version_40(false) , _support_opengl_version_41(false) , _opengl_max_texture_size(0) , _opengl_max_texture_units(0) , _opengl_max_texture_coords(0) , _opengl_max_texture_image_units(0) , _opengl_max_fb_attachment(0) , _opengl_max_vertex_attributes(0) , _support_ext_swap_control(false) , _support_arb_vertex_program(false) , _support_arb_fragment_program(false) , _support_arb_shader_objects(false) , _support_arb_vertex_shader(false) , _support_arb_fragment_shader(false) , _support_arb_vertex_buffer_object(false) , _support_arb_texture_non_power_of_two(false) , _support_ext_framebuffer_object(false) , _support_ext_draw_range_elements(false) , _support_ext_stencil_two_side(false) , _support_ext_texture_rectangle(false) , _support_arb_texture_rectangle(false) , _support_nv_texture_rectangle(false) , _support_arb_pixel_buffer_object(false) , _support_ext_blend_equation_separate(false) , _support_depth_buffer(false) #ifndef NUX_OPENGLES_20 , _support_ext_texture_srgb(false) , _support_ext_texture_srgb_decode(false) , _support_ext_framebuffer_srgb(false) , _support_arb_framebuffer_srgb(false) #endif { } void GpuInfo::Setup() { #ifndef NUX_OPENGLES_20 _support_opengl_version_11 = GLEW_VERSION_1_1; _support_opengl_version_12 = GLEW_VERSION_1_2; _support_opengl_version_13 = GLEW_VERSION_1_3; _support_opengl_version_14 = GLEW_VERSION_1_4; _support_opengl_version_15 = GLEW_VERSION_1_5; _support_opengl_version_20 = GLEW_VERSION_2_0; _support_opengl_version_21 = GLEW_VERSION_2_1; _support_opengl_version_30 = GLEW_VERSION_3_0; _support_opengl_version_31 = GLEW_VERSION_3_1; _support_opengl_version_32 = GLEW_VERSION_3_2; // _support_opengl_version_33 = GLEW_VERSION_3_3; // _support_opengl_version_40 = GLEW_VERSION_4_0; // _support_opengl_version_41 = GLEW_VERSION_4_1; // See: http://developer.nvidia.com/object/General_FAQ.html // The value of GL_MAX_TEXTURE_UNITS is 4 for GeForce FX and GeForce 6 Series GPUs. Why is that, since those GPUs have 16 texture units? CHECKGL(glGetIntegerv(GL_MAX_TEXTURE_SIZE, &_opengl_max_texture_size)); CHECKGL(glGetIntegerv(GL_MAX_TEXTURE_UNITS, &_opengl_max_texture_units)); CHECKGL(glGetIntegerv(GL_MAX_TEXTURE_COORDS, &_opengl_max_texture_coords)); CHECKGL(glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &_opengl_max_texture_image_units)); CHECKGL(glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &_opengl_max_vertex_attributes)); CHECKGL(glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, &_opengl_max_fb_attachment)); _support_depth_buffer = true; #else // By opengl es 2.0 standard, GL_MAX_TEXTURE_SIZE should return a minimum of 64. CHECKGL(glGetIntegerv(GL_MAX_TEXTURE_SIZE, &_opengl_max_texture_size)); // GL_MAX_TEXTURE_UNITS is not supported under opengl es 2.0. // GL_MAX_TEXTURE_IMAGE_UNITS is supported under opengl es 2.0. CHECKGL(glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &_opengl_max_texture_image_units)); // GL_MAX_COLOR_ATTACHMENTS_EXT is not supported under opengl es 2.0. _opengl_max_fb_attachment = 1; if (glGetString(GL_OES_depth_texture)) { _support_depth_buffer = true; } #endif #if defined(NUX_OS_WINDOWS) _support_ext_swap_control = WGLEW_EXT_swap_control; #elif defined(NUX_OS_LINUX) && !defined(NUX_OPENGLES_20) _support_ext_swap_control = GLXEW_SGI_swap_control; #endif #ifndef NUX_OPENGLES_20 _support_arb_vertex_program = GLEW_ARB_vertex_program; _support_arb_fragment_program = GLEW_ARB_fragment_program; _support_ext_framebuffer_object = GLEW_EXT_framebuffer_object; _support_arb_shader_objects = GLEW_ARB_shader_objects; _support_arb_vertex_shader = GLEW_ARB_vertex_shader; _support_arb_fragment_shader = GLEW_ARB_fragment_shader; _support_arb_vertex_buffer_object = GLEW_ARB_vertex_buffer_object; _support_arb_texture_non_power_of_two = GLEW_ARB_texture_non_power_of_two; _support_ext_draw_range_elements = GLEW_EXT_draw_range_elements; _support_ext_stencil_two_side = GLEW_EXT_stencil_two_side; _support_ext_texture_rectangle = GLEW_EXT_texture_rectangle; _support_arb_texture_rectangle = GLEW_ARB_texture_rectangle; _support_nv_texture_rectangle = GLEW_NV_texture_rectangle; _support_arb_pixel_buffer_object = GLEW_ARB_pixel_buffer_object; _support_ext_blend_equation_separate = GLEW_EXT_blend_equation_separate; _support_ext_texture_srgb = GLEW_EXT_texture_sRGB; _support_ext_texture_srgb_decode = false; //GLEW_EXT_texture_sRGB_decode; _support_ext_framebuffer_srgb = GLEW_EXT_framebuffer_sRGB; _support_arb_framebuffer_srgb = GLEW_ARB_framebuffer_sRGB; #else _support_arb_vertex_program = false; _support_arb_fragment_program = false; _support_arb_shader_objects = true; _support_arb_vertex_shader = true; _support_arb_fragment_shader = true; _support_arb_vertex_buffer_object = true; _support_arb_texture_non_power_of_two = true; _support_ext_framebuffer_object = true; _support_ext_draw_range_elements = false; _support_ext_stencil_two_side = false; _support_ext_texture_rectangle = false; _support_arb_texture_rectangle = false; _support_nv_texture_rectangle = false; _support_arb_pixel_buffer_object = false; _support_ext_blend_equation_separate = true; #endif } #if defined(NUX_OS_WINDOWS) GpuDevice::GpuDevice(unsigned int DeviceWidth, unsigned int DeviceHeight, BitmapFormat DeviceFormat, HDC device_context, HGLRC &opengl_rendering_context, int req_opengl_major, int req_opengl_minor, bool opengl_es_20) #elif defined(USE_X11) # ifdef NUX_OPENGLES_20 GpuDevice::GpuDevice(unsigned int DeviceWidth, unsigned int DeviceHeight, BitmapFormat DeviceFormat, Display *display, Window window, bool has_glx_13_support, EGLConfig fb_config, EGLContext &opengl_rendering_context, int req_opengl_major, int req_opengl_minor, bool opengl_es_20) # else GpuDevice::GpuDevice(unsigned int /* DeviceWidth */, unsigned int /* DeviceHeight */, BitmapFormat /* DeviceFormat */, Display *display, Window window, bool has_glx_13_support, GLXFBConfig fb_config, GLXContext &opengl_rendering_context, int req_opengl_major, int req_opengl_minor, bool opengl_es_20) # endif #elif defined(NO_X11) GpuDevice::GpuDevice(unsigned int DeviceWidth, unsigned int DeviceHeight, BitmapFormat DeviceFormat, EGLDisplay display, EGLConfig fb_config, EGLContext &opengl_rendering_context, int req_opengl_major, int req_opengl_minor) #endif : opengl_major_(0) , opengl_minor_(0) , use_pixel_buffer_object_(false) , pixel_store_alignment_(4) , gpu_render_states_(NULL) , gpu_info_(NULL) { gpu_brand_ = GPU_VENDOR_UNKNOWN; #ifndef NUX_OPENGLES_20 // OpenGL extension initialization GLenum Glew_Ok = 0; Glew_Ok = Glew_Ok + (1 - 1); // Suppress compiler warning about set but not used variable. #ifdef GLEW_MX Glew_Ok = glewContextInit(glewGetContext()); nuxAssertMsg(Glew_Ok == GLEW_OK, "[GpuDevice::GpuDevice] GL Extensions failed to initialize."); #if defined(NUX_OS_WINDOWS) Glew_Ok = wglewContextInit(wglewGetContext()); #elif defined(NUX_OS_LINUX) Glew_Ok = glxewContextInit(glxewGetContext()); #elif defined(NUX_OS_MACOSX) Glew_Ok = glxewContextInit(glxewGetContext()); #endif nuxAssertMsg(Glew_Ok == GLEW_OK, "[GpuDevice::GpuDevice] OpenGL Extensions failed to initialize."); #else glewInit(); #endif #endif #ifndef NUX_OPENGLES_20 _openGL_version_string = ANSI_TO_TCHAR(NUX_REINTERPRET_CAST(const char *, glGetString(GL_VERSION))); CHECKGL_MSG(glGetString(GL_VERSION)); if (0) { // We need OpenGL minor and major version. Before OpenGL 3.0, the version number was reported as a string of format // "major.minor". That string has to be parsed to extract the major and minor version numbers. This is not really safe as // we have no guaranty that the version string is has we think it is. Some drivers report a version string like "xx.xx.xx". // Begin string parsing to extract the major and minor version numbers. std::string opengl_major; std::string opengl_minor; std::string split = "."; size_t pos = 0; pos = _openGL_version_string.find(split, pos); if (pos != tstring::npos) { size_t split_string_size = split.length(); opengl_major = _openGL_version_string.substr(0, pos); opengl_minor = _openGL_version_string.substr(pos + split_string_size, _openGL_version_string.length() - (pos + split_string_size) ); } int major_length = opengl_major.length(); opengl_major_ = 0; int digit_position = 1; while (major_length && (opengl_major.c_str()[major_length-1] >= '0') && (opengl_major.c_str()[major_length-1] <= '9')) { opengl_major_ += (opengl_major.c_str()[major_length-1] - '0') * digit_position; digit_position *= 10; --major_length; } int minor_length = opengl_minor.length(); opengl_minor_ = 0; digit_position = 0; while (minor_length && (opengl_minor.c_str()[digit_position] >= '0') && (opengl_minor.c_str()[digit_position] <= '9')) { opengl_minor_ += opengl_minor_ * 10 + (opengl_minor.c_str()[digit_position] - '0'); ++digit_position; --minor_length; } // End string parsing if (opengl_major_ >= 3) { CHECKGL(glGetIntegerv(GL_MAJOR_VERSION, &opengl_major_)); CHECKGL(glGetIntegerv(GL_MINOR_VERSION, &opengl_minor_)); } } else { std::vector versions; boost::split(versions, _openGL_version_string, boost::algorithm::is_any_of(".")); opengl_major_ = std::stoi(versions[0]); opengl_minor_ = std::stoi(versions[1]); if (opengl_major_ >= 3) { CHECKGL(glGetIntegerv(GL_MAJOR_VERSION, &opengl_major_)); CHECKGL(glGetIntegerv(GL_MINOR_VERSION, &opengl_minor_)); } } #else opengl_major_ = 2; opengl_minor_ = 0; #endif #if defined(NUX_OS_WINDOWS) bool opengl_es_context_created = false; if (((opengl_major_ >= 3) && (req_opengl_major >= 3)) || (opengl_major_ >= 3) || opengl_es_20) #elif defined(USE_X11) // Should this be GLES check? //bool opengl_es_context_created = false; if (has_glx_13_support && (((opengl_major_ >= 3) && (req_opengl_major >= 3)) || ((opengl_major_ >= 3) && opengl_es_20))) #elif defined(NO_X11) if (((opengl_major_ >= 3) && (req_opengl_major >= 3)) || (opengl_major_ >= 3)) #endif { // Create a new Opengl Rendering Context bool requested_profile_is_supported = false; int index = 0; for (index = 0; OpenGLVersionTable [index].major != 0; index++) { if ((OpenGLVersionTable[index].major == req_opengl_major) && (OpenGLVersionTable[index].minor == req_opengl_minor)) { if (opengl_major_ == 1) { if ((req_opengl_major == 1) && (req_opengl_minor >= 0) && (req_opengl_minor <= 5)) requested_profile_is_supported = true; } else if (opengl_major_ == 2) { if ((req_opengl_major == 2) && (req_opengl_minor >= 0) && (req_opengl_minor <= 1)) requested_profile_is_supported = true; } else if (opengl_major_ == 3) { if ((req_opengl_major == 3) && (req_opengl_minor >= 0) && (req_opengl_minor <= 3)) requested_profile_is_supported = true; } else if (opengl_major_ == 4) { if ((req_opengl_major == 4) && (req_opengl_minor >= 0) && (req_opengl_minor <= 1)) requested_profile_is_supported = true; } break; } } #if !defined(NO_X11) if (opengl_es_20) { #if defined(NUX_OS_WINDOWS) int attribs[] = { WGL_CONTEXT_MAJOR_VERSION_ARB, 2, WGL_CONTEXT_MINOR_VERSION_ARB, 0, WGL_CONTEXT_PROFILE_MASK_ARB, //WGL_CONTEXT_ES2_PROFILE_BIT_EXT, 0 }; HGLRC new_opengl_rendering_context = wglCreateContextAttribsARB(device_context,0, attribs); if (new_opengl_rendering_context == 0) { nuxDebugMsg("[GpuDevice::GpuDevice] OpenGL ES 2.0 context creation has failed."); } else { wglMakeCurrent(NULL, NULL); wglDeleteContext(opengl_rendering_context); opengl_rendering_context = new_opengl_rendering_context; wglMakeCurrent(device_context, opengl_rendering_context); opengl_es_context_created = true; } #elif defined(NUX_OS_LINUX) /* int attribs[] = { GLX_CONTEXT_MAJOR_VERSION_ARB, 2, GLX_CONTEXT_MINOR_VERSION_ARB, 0, //GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_ES2_PROFILE_BIT_EXT, 0 }; GLXContext new_opengl_rendering_context = glXCreateContextAttribsARB(display, fb_config, 0, true, attribs); if (new_opengl_rendering_context == 0) { nuxDebugMsg("[GpuDevice::GpuDevice] OpenGL ES 2.0 context creation has failed."); } else { opengl_rendering_context = new_opengl_rendering_context; glXMakeCurrent(display, window, opengl_rendering_context); opengl_es_context_created = true; }*/ #endif } else #endif if (requested_profile_is_supported) { #if defined(NUX_OS_WINDOWS) int profile_mask = 0; int profile_value = 0; int flag_mask = 0; int flag_value = 0; if (((req_opengl_major == 3) && (req_opengl_minor >= 3)) || (req_opengl_major >= 4)) { profile_mask = WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; profile_value = WGL_CONTEXT_PROFILE_MASK_ARB; flag_mask = WGL_CONTEXT_FLAGS_ARB; flag_value = 0; } int attribs[] = { WGL_CONTEXT_MAJOR_VERSION_ARB, req_opengl_major, WGL_CONTEXT_MINOR_VERSION_ARB, req_opengl_minor, profile_mask, profile_value, flag_mask, flag_value, 0 }; HGLRC new_opengl_rendering_context = wglCreateContextAttribsARB(device_context,0, attribs); if (new_opengl_rendering_context == 0) { nuxDebugMsg("[GpuDevice::GpuDevice] OpenGL version %d.%d context creation has failed.", req_opengl_major, req_opengl_minor); } else { wglMakeCurrent(NULL, NULL); wglDeleteContext(opengl_rendering_context); opengl_rendering_context = new_opengl_rendering_context; wglMakeCurrent(device_context, opengl_rendering_context); } #elif defined(NUX_OS_LINUX) && !defined(NUX_OPENGLES_20) int profile_mask = 0; int profile_value = 0; int flag_mask = 0; int flag_value = 0; if (((req_opengl_major == 3) && (req_opengl_minor >= 3)) || (req_opengl_major >= 4)) { profile_mask = GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; profile_value = GLX_CONTEXT_PROFILE_MASK_ARB; flag_mask = GLX_CONTEXT_FLAGS_ARB; flag_value = 0; } int attribs[] = { GLX_CONTEXT_MAJOR_VERSION_ARB, req_opengl_major, GLX_CONTEXT_MINOR_VERSION_ARB, req_opengl_minor, profile_mask, profile_value, flag_mask, flag_value, 0 }; GLXContext new_opengl_rendering_context = glXCreateContextAttribsARB(display, fb_config, 0, true, attribs); if (new_opengl_rendering_context == 0) { nuxDebugMsg("[GpuDevice::GpuDevice] OpenGL version %d.%d context creation has failed.", req_opengl_major, req_opengl_minor); attribs[0] = 1; // major version attribs[1] = 0; // minor version attribs[2] = 0; new_opengl_rendering_context = glXCreateContextAttribsARB(display, fb_config, 0, true, attribs); opengl_rendering_context = new_opengl_rendering_context; glXMakeCurrent(display, window, opengl_rendering_context); } else { opengl_rendering_context = new_opengl_rendering_context; glXMakeCurrent(display, window, opengl_rendering_context); } #endif } else { nuxDebugMsg("[GpuDevice::GpuDevice] Using highest default OpenGL version."); } } _board_vendor_string = ANSI_TO_TCHAR(NUX_REINTERPRET_CAST(const char *, glGetString(GL_VENDOR))); CHECKGL_MSG(glGetString(GL_VENDOR)); _board_renderer_string = ANSI_TO_TCHAR(NUX_REINTERPRET_CAST(const char *, glGetString(GL_RENDERER))); CHECKGL_MSG(glGetString(GL_RENDERER)); _openGL_version_string = ANSI_TO_TCHAR(NUX_REINTERPRET_CAST(const char *, glGetString(GL_VERSION))); CHECKGL_MSG(glGetString(GL_VERSION)); nuxDebugMsg("Gpu Vendor: %s", _board_vendor_string.c_str()); nuxDebugMsg("Gpu Renderer: %s", _board_renderer_string.c_str()); nuxDebugMsg("Gpu OpenGL Version: %s", _openGL_version_string.c_str()); nuxDebugMsg("Gpu OpenGL Major Version: %d", opengl_major_); nuxDebugMsg("Gpu OpenGL Minor Version: %d", opengl_minor_); std::transform(_board_vendor_string.begin(), _board_vendor_string.end(), _board_vendor_string.begin(), ::toupper); if (_board_vendor_string.find("NVIDIA", 0) != tstring::npos) { gpu_brand_ = GPU_BRAND_NVIDIA; } else if (_board_vendor_string.find("ATI", 0) != tstring::npos) { gpu_brand_ = GPU_BRAND_AMD; } else if (_board_vendor_string.find("TUNGSTEN", 0) != tstring::npos) { gpu_brand_ = GPU_BRAND_INTEL; } use_pixel_buffer_object_ = false; gpu_info_ = new GpuInfo(); gpu_info_->Setup(); gpu_render_states_ = new GpuRenderStates(gpu_brand_, gpu_info_); #if defined(NUX_OS_WINDOWS) OGL_EXT_SWAP_CONTROL = WGLEW_EXT_swap_control; #elif defined(NUX_OS_LINUX) && !defined(NUX_OPENGLES_20) OGL_EXT_SWAP_CONTROL = GLXEW_SGI_swap_control; #endif InitTextureFormats(); // See Avoiding 16 Common OpenGL Pitfalls // 7. Watch Your Pixel Store Alignment // http://www.opengl.org/resources/features/KilgardTechniques/oglpitfall/ // We use a pack /unpack alignment to 1 so we don't have any padding at the end of row. CHECKGL(glPixelStorei(GL_UNPACK_ALIGNMENT, pixel_store_alignment_)); CHECKGL(glPixelStorei(GL_PACK_ALIGNMENT, pixel_store_alignment_)); // _DeviceWidth = DeviceWidth; // _DeviceHeight = DeviceHeight; // // _ViewportX = 0; // _ViewportY = 0; // _ViewportWidth = DeviceWidth; // _ViewportHeight = DeviceHeight; for (int i = 0; i < MAX_NUM_STREAM; i++) { _StreamSource[i].ResetStreamSource(); } // Configure NVidia CG #if (NUX_ENABLE_CG_SHADERS) { m_Cgcontext = 0; // Create Cg context and set profile. CHECKGL(cgSetErrorCallback( cgErrorCallback )); m_Cgcontext = cgCreateContext(); nuxAssert(m_Cgcontext); //CHECKGL(cgGLEnableProfile( CG_PROFILE_VP40 )); //CHECKGL(cgGLEnableProfile( CG_PROFILE_FP40 )); CHECKGL(cgGLSetManageTextureParameters( m_Cgcontext, CG_FALSE )); } #endif if (GetGpuInfo().Support_EXT_Framebuffer_Object()) { _FrameBufferObject = CreateFrameBufferObject(); _FrameBufferObject->Deactivate(); } } GpuDevice::~GpuDevice() { NUX_SAFE_DELETE(gpu_info_); NUX_SAFE_DELETE(gpu_render_states_); _FrameBufferObject.Release(); active_framebuffer_object_.Release(); _PixelBufferArray.clear(); for (int i = 0; i < MAX_NUM_STREAM; i++) { _StreamSource[i].ResetStreamSource(); } // NVidia CG #if (NUX_ENABLE_CG_SHADERS) cgDestroyContext(m_Cgcontext); #endif } ObjectPtr GpuDevice::CreateFrameBufferObject() { ObjectPtr result; result.Adopt(new IOpenGLFrameBufferObject(NUX_TRACKER_LOCATION)); return result; } int GpuDevice::GetOpenGLMajorVersion() const { return opengl_major_; } int GpuDevice::GetOpenGLMinorVersion() const { return opengl_minor_; } unsigned int GpuDevice::GetPixelStoreAlignment() const { return pixel_store_alignment_; } bool GpuDevice::UsePixelBufferObjects() const { return use_pixel_buffer_object_; } GpuBrand GpuDevice::GetGPUBrand() const { return gpu_brand_; } GpuRenderStates &GpuDevice::GetRenderStates() { return *gpu_render_states_; } const GpuInfo& GpuDevice::GetGpuInfo() const { return *gpu_info_; } void GpuDevice::ResetRenderStates() { gpu_render_states_->ResetStateChangeToDefault(); } void GpuDevice::VerifyRenderStates() { gpu_render_states_->CheckStateChange(); } void GpuDevice::InvalidateTextureUnit(int TextureUnitIndex) { CHECKGL(glActiveTextureARB(TextureUnitIndex)); CHECKGL(glBindTexture(GL_TEXTURE_2D, 0)); #ifndef NUX_OPENGLES_20 CHECKGL(glBindTexture(GL_TEXTURE_1D, 0)); CHECKGL(glBindTexture(GL_TEXTURE_CUBE_MAP, 0)); CHECKGL(glBindTexture(GL_TEXTURE_3D, 0)); CHECKGL(glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0)); #endif // From lowest priority to highest priority: // GL_TEXTURE_1D, // GL_TEXTURE_2D, // GL_TEXTURE_RECTANGLE_ARB, // GL_TEXTURE_3D, // GL_TEXTURE_CUBE_MAP. #ifndef NUX_OPENGLES_20 CHECKGL(glDisable(GL_TEXTURE_2D)); CHECKGL(glDisable(GL_TEXTURE_1D)); CHECKGL(glDisable(GL_TEXTURE_RECTANGLE_ARB)); CHECKGL(glDisable(GL_TEXTURE_3D)); CHECKGL(glDisable(GL_TEXTURE_CUBE_MAP)); #endif } int GpuDevice::AllocateUnpackPixelBufferIndex(int *index) { unsigned int num = (unsigned int) _PixelBufferArray.size(); for (unsigned int i = 0; i < num; i++) { if (_PixelBufferArray[i].IsReserved == FALSE) { _PixelBufferArray[i].IsReserved = TRUE; *index = i; return OGL_OK; } } // Not enough free pbo PixelBufferObject pbo; pbo.PBO = CreatePixelBufferObject(4, (VBO_USAGE) GL_STATIC_DRAW); pbo.IsReserved = TRUE; _PixelBufferArray.push_back(pbo); *index = (int) _PixelBufferArray.size() - 1; return OGL_OK; } int GpuDevice::FreeUnpackPixelBufferIndex(const int index) { int num = (int) _PixelBufferArray.size(); nuxAssertMsg((index >= 0) && (index < num), "[GpuDevice::FreeUnpackPixelBufferIndex] Trying to Free a pixel buffer index that does not exist."); if ((index < 0) || (index >= num)) { return OGL_ERROR; } _PixelBufferArray[index].IsReserved = false; // // if (0) // // { // // // Can we realloc the memory used by the buffer with much less memory(4x4bytes)??? // // CHECKGL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, OpenGLID)); // // CHECKGL(glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, 4*4, NULL, GL_STREAM_DRAW_ARB)); // // } return OGL_OK; } void *GpuDevice::LockUnpackPixelBufferIndex(const int index, int Size) { #ifndef NUX_OPENGLES_20 BindUnpackPixelBufferIndex(index); CHECKGL(glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, Size, NULL, GL_STREAM_DRAW)); void *pBits = glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY_ARB); CHECKGL_MSG(glMapBufferARB ); CHECKGL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); return pBits; #else return NULL; #endif } void* GpuDevice::LockPackPixelBufferIndex(const int index, int Size) { #ifndef NUX_OPENGLES_20 BindPackPixelBufferIndex(index); CHECKGL(glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, Size, NULL, GL_STREAM_DRAW)); void *pBits = glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_WRITE_ONLY_ARB); CHECKGL_MSG(glMapBufferARB ); CHECKGL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0)); return pBits; #else return NULL; #endif } void GpuDevice::UnlockUnpackPixelBufferIndex(const int index) { #ifndef NUX_OPENGLES_20 BindUnpackPixelBufferIndex(index); CHECKGL(glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB)); CHECKGL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0)); #endif } void GpuDevice::UnlockPackPixelBufferIndex(const int index) { #ifndef NUX_OPENGLES_20 BindPackPixelBufferIndex(index); CHECKGL(glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB)); CHECKGL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0)); #endif } int GpuDevice::BindUnpackPixelBufferIndex(const int index) { int num = (int) _PixelBufferArray.size(); nuxAssertMsg((index >= 0) && (index < num), "[GpuDevice::BindUnpackPixelBufferIndex] Trying to bind an invalid pixel buffer index."); if ((index < 0) || (index >= num)) { return OGL_ERROR; } nuxAssertMsg(_PixelBufferArray[index].IsReserved == true, "[GpuDevice::BindUnpackPixelBufferIndex] Trying to reserved pixel buffer index."); if (_PixelBufferArray[index].IsReserved == false) { return OGL_ERROR; } _PixelBufferArray[index].PBO->BindUnpackPixelBufferObject(); return OGL_OK; } int GpuDevice::BindPackPixelBufferIndex(const int index) { int num = (int) _PixelBufferArray.size(); nuxAssertMsg((index >= 0) && (index < num), "[GpuDevice::BindPackPixelBufferIndex] Trying to bind an invalid pixel buffer index."); if ((index < 0) || (index >= num)) { return OGL_ERROR; } nuxAssertMsg(_PixelBufferArray[index].IsReserved == true, "[GpuDevice::BindPackPixelBufferIndex] Trying to reserved pixel buffer index."); if (_PixelBufferArray[index].IsReserved == false) { return OGL_ERROR; } _PixelBufferArray[index].PBO->BindPackPixelBufferObject(); return OGL_OK; } int GpuDevice::FormatFrameBufferObject(unsigned int Width, unsigned int Height, BitmapFormat PixelFormat) { if (!GetGpuInfo().Support_EXT_Framebuffer_Object()) { nuxDebugMsg("[GpuDevice::FormatFrameBufferObject] No support for OpenGL framebuffer extension."); return 0; } return _FrameBufferObject->FormatFrameBufferObject(Width, Height, PixelFormat); } int GpuDevice::SetColorRenderTargetSurface(unsigned int ColorAttachmentIndex, ObjectPtr pRenderTargetSurface) { if (!GetGpuInfo().Support_EXT_Framebuffer_Object()) { nuxDebugMsg("[GpuDevice::SetColorRenderTargetSurface] No support for OpenGL framebuffer extension."); return 0; } return _FrameBufferObject->SetRenderTarget(ColorAttachmentIndex, pRenderTargetSurface); } int GpuDevice::SetDepthRenderTargetSurface(ObjectPtr pDepthSurface) { if (!GetGpuInfo().Support_EXT_Framebuffer_Object()) { nuxDebugMsg("[GpuDevice::SetDepthRenderTargetSurface] No support for OpenGL framebuffer extension."); return 0; } return _FrameBufferObject->SetDepthSurface(pDepthSurface); } ObjectPtr GpuDevice::GetColorRenderTargetSurface(unsigned int ColorAttachmentIndex) { if (!GetGpuInfo().Support_EXT_Framebuffer_Object()) { nuxDebugMsg("[GpuDevice::GetColorRenderTargetSurface] No support for OpenGL framebuffer extension."); return ObjectPtr (0); } return _FrameBufferObject->GetRenderTarget(ColorAttachmentIndex); } ObjectPtr GpuDevice::GetDepthRenderTargetSurface() { if (!GetGpuInfo().Support_EXT_Framebuffer_Object()) { nuxDebugMsg("[GpuDevice::GetDepthRenderTargetSurface] No support for OpenGL framebuffer extension."); return ObjectPtr (0); } return _FrameBufferObject->GetDepthRenderTarget(); } void GpuDevice::ActivateFrameBuffer() { if (!GetGpuInfo().Support_EXT_Framebuffer_Object()) { nuxDebugMsg("[GpuDevice::ActivateFrameBuffer] No support for OpenGL framebuffer extension."); return; } _FrameBufferObject->Activate(); } void GpuDevice::SetCurrentFrameBufferObject(ObjectPtr fbo) { active_framebuffer_object_ = fbo; } ObjectPtr GpuDevice::GetFrameBufferObject() const { return _FrameBufferObject; } ObjectPtr GpuDevice::GetCurrentFrameBufferObject() { return active_framebuffer_object_; } ObjectPtr GpuDevice::ActiveFboTextureAttachment(int color_attachment_index) { if (active_framebuffer_object_.IsValid()) { return active_framebuffer_object_->TextureAttachment(color_attachment_index); } return ObjectPtr(0); } ObjectPtr GpuDevice::ActiveFboDepthTextureAttachment() { if (active_framebuffer_object_.IsValid()) { return active_framebuffer_object_->DepthTextureAttachment(); } return ObjectPtr(0); } void GpuDevice::DeactivateFrameBuffer() { if (!GetGpuInfo().Support_EXT_Framebuffer_Object()) { nuxDebugMsg("[GpuDevice::DeactivateFrameBuffer] No support for OpenGL framebuffer extension."); return; } #ifdef NUX_OPENGLES_20 GLenum binding = GL_FRAMEBUFFER; #else GLenum binding = GL_DRAW_FRAMEBUFFER_EXT; #endif active_framebuffer_object_.Release(); CHECKGL(glBindFramebufferEXT(binding, 0)); CHECKGL(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0)); } ObjectPtr GpuDevice::CreateSystemCapableDeviceTexture( int Width , int Height , int Levels , BitmapFormat PixelFormat , NUX_FILE_LINE_DECL) { if ((Width <= 0) || (Height <= 0)) { return ObjectPtr(0); } if (GetGpuInfo().Support_ARB_Texture_Non_Power_Of_Two()) { return CreateTexture(Width, Height, Levels, PixelFormat, NUX_FILE_LINE_PARAM); } if (GetGpuInfo().Support_EXT_Texture_Rectangle() || GetGpuInfo().Support_ARB_Texture_Rectangle()) { return CreateRectangleTexture(Width, Height, Levels, PixelFormat, NUX_FILE_LINE_PARAM); } nuxAssertMsg(0, "[NuxGraphicsResources::CreateSystemCapableDeviceTexture] No support for non power of two textures or rectangle textures"); return ObjectPtr(); } BaseTexture* GpuDevice::CreateSystemCapableTexture(NUX_FILE_LINE_DECL) { if (GetGpuInfo().Support_ARB_Texture_Non_Power_Of_Two()) { return new Texture2D(NUX_FILE_LINE_PARAM); // Why are we creating a texture without a texture here? } if (GetGpuInfo().Support_EXT_Texture_Rectangle() || GetGpuInfo().Support_ARB_Texture_Rectangle()) { return new TextureRectangle(NUX_FILE_LINE_PARAM); // Why are we creating a texture without a texture here? } nuxAssertMsg(0, "[NuxGraphicsResources::CreateSystemCapableTexture] No support for non power of two textures or rectangle textures"); return 0; } } ./NuxGraphics/RunTimeStats.cpp0000644000004100000410000001712513313171755016620 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include #include "GLResource.h" #include "IOpenGLResource.h" #include "IOpenGLBaseTexture.h" #include "IOpenGLIndexBuffer.h" #include "IOpenGLVertexBuffer.h" #include "RunTimeStats.h" namespace nux { NUX_IMPLEMENT_GLOBAL_OBJECT(RenderingStats); unsigned int RenderingStats::m_NumTex2D = 0; unsigned int RenderingStats::m_GPUSizeTex2D = 0; unsigned int RenderingStats::m_NumTexRectangle = 0; unsigned int RenderingStats::m_GPUSizeTexRectangle = 0; unsigned int RenderingStats::m_NumTexCube = 0; unsigned int RenderingStats::m_GPUSizeTexCube = 0; unsigned int RenderingStats::m_NumTexVolume = 0; unsigned int RenderingStats::m_GPUSizeTexVolume = 0; unsigned int RenderingStats::m_NumTexAnimated = 0; unsigned int RenderingStats::m_GPUSizeTexAnimated = 0; unsigned int RenderingStats::m_NumPBO = 0; // Counted as Vertex Buffer unsigned int RenderingStats::m_GPUSizePBO = 0; // Counted as Vertex Buffer unsigned int RenderingStats::m_NumQueryObject = 0; unsigned int RenderingStats::m_NumFrameBufferObject = 0; unsigned int RenderingStats::m_NumVertexBuffer = 0; unsigned int RenderingStats::m_GPUSizeVertexBuffer = 0; unsigned int RenderingStats::m_NumIndexBuffer = 0; unsigned int RenderingStats::m_GPUSizeIndexBuffer = 0; unsigned int RenderingStats::m_NumVertexShader = 0; unsigned int RenderingStats::m_NumPixelShader = 0; unsigned int RenderingStats::m_NumShaderProgram = 0; unsigned int RenderingStats::m_TotalGPUSize = 0; void RenderingStats::Constructor() { } void RenderingStats::Destructor() { #ifdef DEBUG if (m_NumIndexBuffer != 0) { std::cerr << "[RenderingStats::Destructor] Some index buffers have not been released."; } if (m_NumTex2D != 0) { std::cerr << "[RenderingStats::Destructor] Some 2D textures have not been released."; for (auto id: _texture_2d_array) { std::cerr << "[RenderingStats::Destructor] Remaining 2D textures: " << id; } } if (m_NumTexRectangle != 0) { std::cerr << "[RenderingStats::Destructor] Some rectangle textures buffers have not been released."; for (auto id: _texture_rect_array) { std::cerr << "[RenderingStats::Destructor] Remaining Rectangle textures: " << id; } } #endif } void RenderingStats::Register(IOpenGLResource *GraphicsObject) { switch(GraphicsObject->GetResourceType()) { case RTINDEXBUFFER: { m_NumIndexBuffer++; m_GPUSizeIndexBuffer += NUX_REINTERPRET_CAST(IOpenGLIndexBuffer *, GraphicsObject)->GetSize(); m_TotalGPUSize += m_GPUSizeIndexBuffer; break; } case RTVERTEXBUFFER: { m_NumVertexBuffer++; m_GPUSizeVertexBuffer += NUX_REINTERPRET_CAST(IOpenGLVertexBuffer *, GraphicsObject)->GetSize(); m_TotalGPUSize += m_GPUSizeVertexBuffer; break; } case RTTEXTURE: { int id = NUX_STATIC_CAST(IOpenGLBaseTexture *, GraphicsObject)->GetOpenGLID(); if (id) _texture_2d_array.push_back(NUX_STATIC_CAST(IOpenGLBaseTexture *, GraphicsObject)->GetOpenGLID()); m_NumTex2D++; m_GPUSizeTex2D += GetTextureSize(NUX_REINTERPRET_CAST(IOpenGLBaseTexture *, GraphicsObject)); m_TotalGPUSize += m_GPUSizeTex2D; break; } case RTTEXTURERECTANGLE: { int id = NUX_STATIC_CAST(IOpenGLBaseTexture *, GraphicsObject)->GetOpenGLID(); if (id) _texture_rect_array.push_back(NUX_STATIC_CAST(IOpenGLBaseTexture *, GraphicsObject)->GetOpenGLID()); m_NumTexRectangle++; m_GPUSizeTexRectangle += GetTextureSize(NUX_REINTERPRET_CAST(IOpenGLBaseTexture *, GraphicsObject)); m_TotalGPUSize += m_GPUSizeTexRectangle; break; } case RTCUBETEXTURE: { m_NumTexCube++; m_GPUSizeTexCube += GetTextureSize(NUX_STATIC_CAST(IOpenGLBaseTexture *, GraphicsObject)); m_TotalGPUSize += m_GPUSizeTexCube; break; } case RTVOLUMETEXTURE: { m_NumTexVolume++; m_GPUSizeTexVolume += GetTextureSize(NUX_STATIC_CAST(IOpenGLBaseTexture *, GraphicsObject)); m_TotalGPUSize += m_GPUSizeTexVolume; break; } case RTANIMATEDTEXTURE: { // Animated texture size is compted as rectangle textures; m_NumTexAnimated++; break; } case RTQUERY: { m_NumQueryObject++; break; } case RTFRAMEBUFFEROBJECT: { m_NumFrameBufferObject++; break; } default: break; } } void RenderingStats::UnRegister(IOpenGLResource *GraphicsObject) { switch(GraphicsObject->GetResourceType()) { case RTINDEXBUFFER: { m_NumIndexBuffer--; m_GPUSizeIndexBuffer -= NUX_REINTERPRET_CAST(IOpenGLIndexBuffer *, GraphicsObject)->GetSize(); m_TotalGPUSize -= m_GPUSizeIndexBuffer; break; } case RTVERTEXBUFFER: { m_NumVertexBuffer--; m_GPUSizeVertexBuffer -= NUX_REINTERPRET_CAST(IOpenGLVertexBuffer *, GraphicsObject)->GetSize(); m_TotalGPUSize -= m_GPUSizeVertexBuffer; break; } case RTTEXTURE: { int id = NUX_STATIC_CAST(IOpenGLBaseTexture *, GraphicsObject)->GetOpenGLID(); _texture_2d_array.erase(std::remove(_texture_2d_array.begin(), _texture_2d_array.end(), id), _texture_2d_array.end()); m_NumTex2D--; m_GPUSizeTex2D -= GetTextureSize(NUX_REINTERPRET_CAST(IOpenGLBaseTexture *, GraphicsObject)); m_TotalGPUSize -= m_GPUSizeTex2D; break; } case RTTEXTURERECTANGLE: { int id = NUX_STATIC_CAST(IOpenGLBaseTexture *, GraphicsObject)->GetOpenGLID(); _texture_rect_array.erase(std::remove(_texture_rect_array.begin(), _texture_rect_array.end(), id), _texture_rect_array.end()); m_NumTexRectangle--; m_GPUSizeTexRectangle -= GetTextureSize(NUX_REINTERPRET_CAST(IOpenGLBaseTexture *, GraphicsObject)); m_TotalGPUSize -= m_GPUSizeTexRectangle; break; } case RTCUBETEXTURE: { m_NumTexCube--; m_GPUSizeTexCube -= GetTextureSize(NUX_STATIC_CAST(IOpenGLBaseTexture *, GraphicsObject)); m_TotalGPUSize -= m_GPUSizeTexCube; break; } case RTVOLUMETEXTURE: { m_NumTexVolume--; m_GPUSizeTexVolume -= GetTextureSize(NUX_STATIC_CAST(IOpenGLBaseTexture *, GraphicsObject)); m_TotalGPUSize -= m_GPUSizeTexVolume; break; } case RTANIMATEDTEXTURE: { // Animated texture size is compted as rectangle textures; m_NumTexAnimated--; break; } case RTQUERY: { m_NumQueryObject--; break; } case RTFRAMEBUFFEROBJECT: { m_NumFrameBufferObject--; break; } default: break; } } } ./NuxGraphics/IOpenGLAnimatedTexture.cpp0000644000004100000410000000735113313171755020477 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "GLResource.h" #include "GraphicsDisplay.h" #include "GpuDevice.h" #include "GLDeviceObjects.h" #include "IOpenGLAnimatedTexture.h" namespace nux { NUX_IMPLEMENT_OBJECT_TYPE(IOpenGLAnimatedTexture); IOpenGLAnimatedTexture::IOpenGLAnimatedTexture( int Width , int Height , int Depth , BitmapFormat PixelFormat) : IOpenGLBaseTexture(RTANIMATEDTEXTURE, Width, Height, Depth, 1, PixelFormat) , _CurrentFrame(0) { for (int i = 0; i < Depth; i++) { ObjectPtr Texture = GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableDeviceTexture(Width, Height, 1, PixelFormat, NUX_TRACKER_LOCATION); _FrameTextureArray.push_back(Texture); _FrameTimeArray.push_back(41); // 41 ms = 24 frames/second } _OpenGLID = _FrameTextureArray[0]->GetOpenGLID(); SetFiltering(GL_NEAREST, GL_NEAREST); SetWrap(GL_CLAMP, GL_CLAMP, GL_CLAMP); SetRenderStates(); } IOpenGLAnimatedTexture::~IOpenGLAnimatedTexture() { for (int i = 0; i < _Depth; i++) { _FrameTextureArray[i].Release(); } _FrameTextureArray.clear(); _FrameTimeArray.clear(); } ObjectPtr IOpenGLAnimatedTexture::GetSurfaceFrame(int Frame) { nuxAssert(Frame >= 0); nuxAssert(Frame < _Depth); if ((Frame >= 0) && (Frame < _Depth)) { return _FrameTextureArray[Frame]->GetSurfaceLevel(0); } else { nuxAssertMsg(0, "[IOpenGLAnimatedTexture::GetSurfaceFrame] Invalid surface level"); } return ObjectPtr (0); } void IOpenGLAnimatedTexture::GetSurfaceFrame(int Frame, ObjectPtr& surface) { surface = ObjectPtr (0); surface = GetSurfaceFrame(Frame); } int IOpenGLAnimatedTexture::LockRect( int Frame, SURFACE_LOCKED_RECT *pLockedRect, const SURFACE_RECT *pRect) { return _FrameTextureArray[Frame]->LockRect(0, pLockedRect, pRect); } int IOpenGLAnimatedTexture::UnlockRect( int Frame) { return _FrameTextureArray[Frame]->UnlockRect(0); } void IOpenGLAnimatedTexture::PresentFirstFrame() { _CurrentFrame = 0; _OpenGLID = _FrameTextureArray[_CurrentFrame]->GetOpenGLID(); } void IOpenGLAnimatedTexture::PresentNextFrame() { ++_CurrentFrame; if (_CurrentFrame >= _Depth) _CurrentFrame = 0; _OpenGLID = _FrameTextureArray[_CurrentFrame]->GetOpenGLID(); } void IOpenGLAnimatedTexture::PresentLastFrame() { _CurrentFrame = _Depth - 1; _OpenGLID = _FrameTextureArray[_CurrentFrame]->GetOpenGLID(); } void IOpenGLAnimatedTexture::SetFrameTime(int Frame, int time_ms) { nuxAssert(_CurrentFrame < (int) _FrameTimeArray.size()); _FrameTimeArray[Frame] = time_ms; } int IOpenGLAnimatedTexture::GetFrameTime() { nuxAssert(_CurrentFrame < (int) _FrameTimeArray.size()); return _FrameTimeArray[_CurrentFrame]; } unsigned int IOpenGLAnimatedTexture::GetNumFrame() { return _Depth; } } ./NuxGraphics/IOpenGLRectangleTexture.h0000644000004100000410000000640413313171755020324 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef IOPENGLRECTANGLETEXTURE_H #define IOPENGLRECTANGLETEXTURE_H namespace nux { class IOpenGLBaseTexture; class IOpenGLRectangleTexture: public IOpenGLBaseTexture { NUX_DECLARE_OBJECT_TYPE(IOpenGLRectangleTexture, IOpenGLBaseTexture); public: virtual ~IOpenGLRectangleTexture(); void GetSurfaceLevel(int Level, ObjectPtr& surface); ObjectPtr GetSurfaceLevel(int Level); int LockRect( int Level, SURFACE_LOCKED_RECT *pLockedRect, const SURFACE_RECT *pRect); int UnlockRect( int Level ); unsigned int EnableGammaCorrection(bool b); int GetLevelDesc( int Level, SURFACE_DESC *pDesc ) { nuxAssert(Level >= 0); nuxAssert(Level < _NumMipLevel); if ((Level < 0) || (Level > _NumMipLevel)) { pDesc->Width = 0; pDesc->Height = 0; pDesc->PixelFormat = BITFMT_UNKNOWN; pDesc->Type = _ResourceType; } else { pDesc->Width = Max (1, _Width >> Level); pDesc->Height = Max (1, _Height >> Level); pDesc->PixelFormat = _PixelFormat; pDesc->Type = _ResourceType; } return OGL_OK; } //! Return a pointer to a mipmap level data. /*! Return a pointer to a mipmap level data. The data is in the RGBA format.\n Inherited from IOpenGLBaseTexture. @param level The requested texture mipmap level data. @param width Returns the width in pixel of the image data. @param height Returns the height in pixel of the image data. @param stride Returns the row stride of the image data. @return A pointer to RGBA data. The caller must dlete the data by calling delete []. */ unsigned char* GetSurfaceData(int level, int &width, int &height, int &stride); private: // The Dummy boolean is used to create a skeletal frame for the default // render target texture and surface; Only GpuDevice uses it in its constructor. // Do not use it otherwise!!! IOpenGLRectangleTexture( unsigned int Width , unsigned int Height , unsigned int Levels , BitmapFormat PixelFormat, bool Dummy = false, NUX_FILE_LINE_PROTO); // unsigned int _Width; // unsigned int _Height; std::vector< ObjectPtr > _SurfaceArray; friend class GpuDevice; friend class IOpenGLSurface; }; } #endif // IOPENGLRECTANGLETEXTURE_H ./NuxGraphics/GLWindowManager.h0000644000004100000410000000647713313171755016660 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef DISPLAYACCESSCONTROLLER_H #define DISPLAYACCESSCONTROLLER_H #include "NuxCore/NuxCore.h" #if defined(NUX_OS_WINDOWS) #include "GraphicsDisplay.h" #elif defined(NUX_OS_LINUX) #include "GraphicsDisplay.h" #endif namespace nux { class GraphicsDisplay; class GpuDevice; class GraphicsEngine; extern const char *WINDOW_CLASS_NAME; class DisplayAccessController { public: //! Create a graphics window capable of doing OpenGL rendering. /*! @param WindowTitle The title name of the window. @param WindowWidth Window width. @param WindowHeight Window height. @param Style Window style. @param parent The parent window. @param fullscreen_flag True to create a full screen window. @param create_rendering_data If true, then in GraphicsEngine, the system creates the OpenGL shaders and the font textures for the rendering. */ GraphicsDisplay *CreateGLWindow(const char *WindowTitle, unsigned int WindowWidth, unsigned int WindowHeight, WindowStyle Style, GraphicsDisplay *parent, bool fullscreen_flag = false, bool create_rendering_data = true); #if defined(NUX_OS_WINDOWS) HINSTANCE GetInstance() { return hInstance; } #endif #if defined(NUX_OS_WINDOWS) //! Create a GraphicsDisplay from a foreign window and display. GraphicsDisplay *CreateFromForeignWindow(HWND WindowHandle, HDC WindowDCHandle, HGLRC OpenGLRenderingContext); #elif defined(USE_X11) //! Create a GraphicsDisplay from a foreign window and display. # ifdef NUX_OPENGLES_20 GraphicsDisplay *CreateFromForeignWindow(Display *X11Display, Window X11Window, EGLContext OpenGLContext); # else GraphicsDisplay *CreateFromForeignWindow(Display *X11Display, Window X11Window, GLXContext OpenGLContext); # endif #elif defined(NO_X11) GraphicsDisplay *CreateFromForeignWindow(EGLDisplay *disp, EGLContext OpenGLContext); #endif static DisplayAccessController &Instance(); private: static DisplayAccessController *m_pInstance; DisplayAccessController(); DisplayAccessController(const DisplayAccessController &); // Does not make sense for a singleton. This is a self assignment. DisplayAccessController &operator= (const DisplayAccessController &); // Declare operator address-of as private DisplayAccessController *operator &(); ~DisplayAccessController(); #if defined(NUX_OS_WINDOWS) HINSTANCE hInstance; WNDCLASSEX WinClass; #endif }; #define gGLWindowManager nux::DisplayAccessController::Instance() } #endif // DISPLAYACCESSCONTROLLER_H ./NuxGraphics/GLDeviceObjects.cpp0000644000004100000410000001565113313171755017154 0ustar www-datawww-data/* * Copyright 2010 Inalogic Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "GLResource.h" #include "GpuDevice.h" #include "GLDeviceObjects.h" #include "GLResourceManager.h" #include "GLTextureResourceManager.h" #include "GLVertexResourceManager.h" #include "GLDeviceFrameBufferObject.h" #include "GLTemplatePrimitiveBuffer.h" #include "GraphicsEngine.h" namespace nux { extern PixelFormatInfo GPixelFormats[]; //NObjectType IOpenGLResource::StaticObjectType("IOpenGLResource", 0); NUX_IMPLEMENT_OBJECT_TYPE(IOpenGLResource); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* GLSL Built-in vertex attribute(Deprecated in GLSL 1.30) ------------------------------- Built-in vertex attribute name Incompatible aliased vertex attribute index gl_Vertex 0 gl_Normal 2 gl_Color 3 gl_SecondaryColor 4 gl_FogCoord 5 gl_MultiTexCoord0 8 gl_MultiTexCoord1 9 gl_MultiTexCoord2 10 gl_MultiTexCoord3 11 gl_MultiTexCoord4 12 gl_MultiTexCoord5 13 gl_MultiTexCoord6 14 gl_MultiTexCoord7 15 gl_Vertex: - glVertex{234sifd} - glEnableClientState/glDisableClientState(GL_VERTEX_ARRAY); glVertexPointer(...); gl_Normal: - glNormal{3sifd} - glEnableClientState/glDisableClientState(GL_NORMAL_ARRAY); glNormalPointer(...); gl_Color: - glColor{34sifd} - glEnableClientState/glDisableClientState(GL_COLOR_ARRAY); glColorPointer(...); gl_SecondaryColor(requires GL_EXT_secondary_color) - glSecondaryColor3{bsifd}; - glEnableClientState/glDisableClientState(SECONDARY_COLOR_ARRAY_EXT); glSecondaryColorPointerEXT(...); gl_FogCoord(requires GL_EXT_fog_coord) - glFogCoord{fd}; - glEnableClientState/glDisableClientState(FOG_COORDINATE_ARRAY_EXT); glFogCoordPointerEXT(...); gl_MultiTexCoordXXX - glMultiTexCoord{234fd} - glClientActiveTextureARB(GL_TEXTUREXXX_ARB); glEnableClientState/glDisableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(...); GLSL Vertex Shader Special output variables(write) ---------------------------------------------------- gl_Position (must be written to) gl_PointSize (may be written to) gl_ClipVertex (may be written to) GLSL Vertex Shader Built-in varying(write) GLSL Fragment Shader Built-in varying(read) ------------------------------------------- ------------------------------------------- varying vec4 gl_FrontColor; ----> gl_Color varying vec4 gl_BackColor; ----> gl_Color varying vec4 gl_FrontSecondaryColor; ----> gl_SecondaryColor varying vec4 gl_BackSecondaryColor; ----> gl_SecondaryColor varying vec4 gl_TexCoord[]; ----> gl_TexCoord[] varying float gl_FogFragCoord; ----> gl_FogFragCoord GLSL Fragment Built-in variables -------------------------------- vec4 gl_FragCoord (read only) bool gl_FrontFacing (read only) vec2 gl_PointCoord (read only) GLSL Fragment Shader Special output variables --------------------------------------------- vec4 gl_FragColor (may be written to) vec4 gl_FragData[gl_MaxDrawBuffers] (may be written to) float gl_FragDepth (may be written to) vec2 gl_PointCoord (read only) Binding Semantics for Cg programs Binding Semantics for Varying Input/Output Data ----------------------------------------------- Table 23 summarizes the valid binding semantics for varying input parameters in the vp30 profile. One can also use TANGENT and BINORMAL instead of TEXCOORD6 and TEXCOORD7. These binding semantics map to NV_vertex_program2 input attribute parameters. The two sets act as aliases to each other. Table 23 vp30 Varying Input Binding Semantics Binding Semantics Name Corresponding Data POSITION, ATTR0 Input Vertex, Generic Attribute 0 BLENDWEIGHT, ATTR1 Input vertex weight, Generic Attribute 1 NORMAL, ATTR2 Input normal, Generic Attribute 2 COLOR0, DIFFUSE, ATTR3 Input primary color, Generic Attribute 3 COLOR1, SPECULAR, ATTR4 Input secondary color, Generic Attribute 4 TESSFACTOR, FOGCOORD, ATTR5 Input fog coordinate, Generic Attribute 5 PSIZE, ATTR6 Input point size, Generic Attribute 6 BLENDINDICES, ATTR7 Generic Attribute 7 TEXCOORD0-TEXCOORD7, ATTR8-ATTR15 Input texture coordinates(texcoord0-texcoord7), Generic Attributes 815 TANGENT, ATTR14 Generic Attribute 14 BINORMAL, ATTR15 Generic Attribute 15 Table 24 summarizes the valid binding semantics for varying output parameters in the vp30 profile. These binding semantics map to NV_vertex_program2 output registers. The two sets act as aliases to each other. Table 24 vp30 Varying Output Binding Semantics Binding Semantics Name Corresponding Data POSITION, HPOS Output position PSIZE, PSIZ Output point size FOG, FOGC Output fog coordinate COLOR0, COL0 Output primary color COLOR1, COL1 Output secondary color BCOL0 Output backface primary color BCOL1 Output backface secondary color TEXCOORD0-TEXCOORD7, TEX0-TEX7 Output texture coordinates CLP0-CL5 Output Clip distances */ } ./NuxGraphics/GraphicsDisplayWin.h0000755000004100000410000002261513313171755017432 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #ifndef GRAPHICSDISPLAYWIN_H #define GRAPHICSDISPLAYWIN_H #include "Gfx_Interface.h" #include "GLTimer.h" #include "GLDeviceObjects.h" #include "GLRenderStates.h" #include #include #include #include "Wincodec.h" namespace nux { class Event; class MainFBO; class GpuDevice; class GraphicsEngine; class IOpenGLFrameBufferObject; enum WindowStyle { WINDOWSTYLE_NORMAL, WINDOWSTYLE_PANEL, WINDOWSTYLE_DIALOG, WINDOWSTYLE_TOOL, WINDOWSTYLE_NOBORDER, }; #define NUX_THREADMSG (WM_APP+0) #define NUX_THREADMSG_START_RENDERING (WM_APP+1) // Connection established // start at WM_APP #define NUX_THREADMSG_CHILD_WINDOW_TERMINATED (WM_APP+2) // General failure - Wait Connection failed #define NUX_THREADMSG_THREAD_TERMINATED (WM_APP+3) // Set wParam = Thread ID, lParam = 0 // This will become GLWindow class GraphicsDisplay : public GraphicSystem { friend class GraphicsEngine; private: // WIN32 system variables HGLRC opengl_rendering_context_; //!< OpenGL Rendering Context. HDC device_context_; //!< Device Context. HWND wnd_handle_; //!< Window Handle. HWND parent_window_; //!< Parent window Handle. GLuint pixel_format_; //!< Holds The Results After Searching For A Match DWORD window_extended_style_; //!< Window Extended Style DWORD window_style_; //!< Window Style std::string window_title_; static HGLRC sMainGLRC; // Used as the first argument of wglShareLists to make all successive OpenGL context share their objects static HDC sMainDC; // Used as the first argument of wglShareLists to make all successive OpenGL context share their objects ID2D1Factory* d2d_factory_; IDWriteFactory* dw_factory_; IWICImagingFactory* wic_factory_; Size viewport_size_; //!< Viewport size. Size window_size_; //!< Window size. //! Full screen mode. bool fullscreen_; //! Screen bit depth. unsigned int screen_bit_depth_; //! State of the graphics interface. bool gfx_interface_created_; // Device information void GetDisplayInfo(); bool window_minimized_; HCURSOR cursor_; //!< Windows Cursor. static int Win32KeySymToINL(int Keysym); static int Win32VKToNuxKey(int vk); public: //! Last Win32 event. Event event_; // Creation bool IsGfxInterfaceCreated(); //! Create a window with and OpenGL context. /*! @param WindowTitle The window title. @param WindowWidth Initial window width. @param WindowHeight Initial window height. @param Style The window style. @param ParentWindow The parent window. @param fullscreen_flag Full screen flag. */ bool CreateOpenGLWindow( const char *WindowTitle, unsigned int WindowWidth, unsigned int WindowHeight, WindowStyle Style, const GraphicsDisplay *Parent, bool fullscreen_flag = false, bool create_rendering_data = true); //! Create a GLWindow from a window and device context. /*! @param WindowHandle Provided window. @param WindowDCHandle Provided device context. @param OpenGLRenderingContext And OpenGL rendering context. */ bool CreateFromOpenGLWindow(HWND WindowHandle, HDC WindowDCHandle, HGLRC OpenGLRenderingContext); void DestroyOpenGLWindow(); void SetWindowTitle(const char *Title); void SetWindowSize(int width, int height); void SetViewPort(int x, int y, int width, int height); Point GetMouseScreenCoord(); Point GetMouseWindowCoord(); Point GetWindowCoord(); Rect GetWindowGeometry(); Rect GetNCWindowGeometry(); void MakeGLContextCurrent(bool b = true); void SwapBuffer(bool glswap = true); // Event methods /*! Returns true if there was a pending event to be fetched and false otherwise */ bool GetSystemEvent(Event *evt); const Event& GetCurrentEvent() const; bool isWindowMinimized() const { return window_minimized_; } void ShowWindow(); void HideWindow(); bool IsWindowVisible(); void EnterMaximizeWindow(); void ExitMaximizeWindow(); HWND GetWindowHandle() const { return wnd_handle_; } HWND GetParentWindowHandle() const { return parent_window_; } HDC GetWindowHDC() const { return device_context_; } bool IsChildWindow() const { return parent_window_ != 0; } ID2D1Factory* GetDirect2DFactory(); IDWriteFactory* GetDirectWriteFactory(); IWICImagingFactory* GetWICFactory(); // Return true if VSync swap control is available bool HasVSyncSwapControl() const; void EnableVSyncSwapControl(); void DisableVSyncSwapControl(); // m_FrameRate float GetFrameTime() const; void ResetFrameTime(); GraphicsEngine *GetGraphicsEngine() const; GpuDevice *GetGpuDevice() const; // Dialog bool StartOpenFileDialog(FileDialogOption &fdo); bool StartSaveFileDialog(FileDialogOption &fdo); bool StartColorDialog(ColorDialogOption &cdo); void GetWindowSize(int &w, int &h); int GetWindowWidth(); int GetWindowHeight(); //! Get the window size and reset the GraphicsEngine and GpuDevice accordingly. /*! This is a passive way to set the window size through out the NuxGraphics system. This call gets the current window size and sets its accordingly to all sub-system. */ void ResetWindowSize(); bool HasFrameBufferSupport(); void SetWindowCursor(HCURSOR cursor); HCURSOR GetWindowCursor() const; void ProcessForeignWin32Event(HWND hWnd, MSG msg, WPARAM wParam, LPARAM lParam, Event *event); LRESULT ProcessWin32Event(HWND hWnd, unsigned int uMsg, WPARAM wParam, LPARAM lParam); //! Pause graphics rendering. /*! Pause graphics rendering. This function also sets the current openGL context to 0 for this window. This is useful while a child window is being created and is sharing openGL objects with this context. For wglShareLists to work, both OpenGL context must be set to 0 in their respective thread. Send NUX_THREADMSG_START_RENDERING(PostThreadMessage) to this window to reactivate rendering. Never call this function while doing rendering. Call it only when processing events. */ void PauseThreadGraphicsRendering(); bool IsPauseThreadGraphicsRendering() const; // Pointer and keyboard grab API typedef void(*GrabReleaseCallback) (bool replaced, void *user_data); bool GrabPointer (GrabReleaseCallback callback, void *data, bool replace_existing); bool UngrabPointer(void *data); bool PointerIsGrabbed(); bool GrabKeyboard (GrabReleaseCallback callback, void *data, bool replace_existing); bool UngrabKeyboard(void *data); bool KeyboardIsGrabbed(); void * KeyboardGrabData() { return _global_keyboard_grab_data; } void * PointerGrabData() { return _global_pointer_grab_data; } private: void InitGlobalGrabWindow(); bool m_PauseGraphicsRendering; GLTimer m_Timer; float m_FrameTime; GpuDevice *m_DeviceFactory; GraphicsEngine *m_GraphicsContext; WindowStyle m_Style; HWND _global_grab_window; void *_global_pointer_grab_data; bool _global_pointer_grab_active; GrabReleaseCallback _global_pointer_grab_callback; void *_global_keyboard_grab_data; bool _global_keyboard_grab_active; GrabReleaseCallback _global_keyboard_grab_callback; public: ~GraphicsDisplay(); GLEWContext *GetGLEWContext() { return &m_GLEWContext; } WGLEWContext *GetWGLEWContext() { return &m_WGLEWContext; } private: GraphicsDisplay(); GraphicsDisplay(const GraphicsDisplay &); // Does not make sense for a singleton. This is a self assignment. GraphicsDisplay &operator= (const GraphicsDisplay &); GLEWContext m_GLEWContext; WGLEWContext m_WGLEWContext; friend class DisplayAccessController; }; LRESULT CALLBACK WndProcManager(HWND hWnd, // Handle For This Window unsigned int uMsg, // Message For This Window WPARAM wParam, // Additional Message Information LPARAM lParam); // Additional Message Information } #endif //GRAPHICSDISPLAYWIN_H ./NuxGraphics/GLSh_ColorPicker.cpp0000644000004100000410000004511113313171755017303 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Jay Taoko * */ #include "NuxCore/NuxCore.h" #include "NuxCore/Math/Matrix4.h" #include "GLResource.h" #include "GpuDevice.h" #include "GLDeviceObjects.h" #include "GLResourceManager.h" #include "GLTextureResourceManager.h" #include "GLVertexResourceManager.h" #include "GLTemplatePrimitiveBuffer.h" #include "GraphicsEngine.h" #include "GLShaderParameter.h" #include "GLSh_ColorPicker.h" namespace nux { // The GLSL shaders may contain branches. Intel GPU so far fails on these shaders. // Use assembly shaders for Intel GPUs: ARB_fragment_program does not have the required // instruction to implement the HSV to RGB color conversion. const char* VtxShader = " \n\ uniform mat4 ViewProjectionMatrix; \n\ attribute vec4 AVertex; \n\ attribute vec4 VertexColor; \n\ void main() \n\ { \n\ gl_Position = ViewProjectionMatrix * AVertex; \n\ }"; const char* RedFrgShader = " \n\ #ifdef GL_ES \n\ precision mediump float; \n\ #endif \n\ uniform vec4 RectPosition; \n\ uniform vec4 RectDimension; \n\ uniform vec4 Color; \n\ void main(void) \n\ { \n\ float x = (gl_FragCoord.x - RectPosition.x) / RectDimension.x; \n\ float y = (gl_FragCoord.y - RectPosition.y) / RectDimension.y; \n\ gl_FragColor = vec4(Color.r, y, x, 1.0); \n\ }"; const char* GreenFrgShader = " \n\ #ifdef GL_ES \n\ precision mediump float; \n\ #endif \n\ uniform vec4 RectPosition; \n\ uniform vec4 RectDimension; \n\ uniform vec4 Color; \n\ void main(void) \n\ { \n\ float x = (gl_FragCoord.x - RectPosition.x) / RectDimension.x; \n\ float y = (gl_FragCoord.y - RectPosition.y) / RectDimension.y; \n\ gl_FragColor = vec4(y, Color.g, x, 1.0); \n\ }"; const char* BlueFrgShader = " \n\ #ifdef GL_ES \n\ precision mediump float; \n\ #endif \n\ uniform vec4 RectPosition; \n\ uniform vec4 RectDimension; \n\ uniform vec4 Color; \n\ void main(void) \n\ { \n\ float x = (gl_FragCoord.x - RectPosition.x) / RectDimension.x; \n\ float y = (gl_FragCoord.y - RectPosition.y) / RectDimension.y; \n\ gl_FragColor = vec4(x, y, Color.b, 1.0); \n\ }"; const char* HueFrgShader = " \n\ #ifdef GL_ES \n\ precision mediump float; \n\ #endif \n\ vec3 HSV_To_RGB(vec3 HSV); \n\ uniform vec4 RectPosition; \n\ uniform vec4 RectDimension; \n\ uniform vec4 Color; \n\ void main(void) \n\ { \n\ float x = (gl_FragCoord.x - RectPosition.x) / RectDimension.x; \n\ float y = (gl_FragCoord.y - RectPosition.y) / RectDimension.y; \n\ vec3 rgb = HSV_To_RGB(vec3(Color.x, x, y)); \n\ gl_FragColor = vec4(rgb, 1.0); \n\ }"; const char* SaturationFrgShader = " \n\ #ifdef GL_ES \n\ precision mediump float; \n\ #endif \n\ vec3 HSV_To_RGB(vec3 HSV); \n\ uniform vec4 RectPosition; \n\ uniform vec4 RectDimension; \n\ uniform vec4 Color; \n\ void main(void) \n\ { \n\ float x = (gl_FragCoord.x - RectPosition.x) / RectDimension.x; \n\ float y = (gl_FragCoord.y - RectPosition.y) / RectDimension.y; \n\ vec3 rgb = HSV_To_RGB(vec3(x, Color.y, y)); \n\ gl_FragColor = vec4(rgb, 1.0); \n\ }"; const char* ValueFrgShader = " \n\ #ifdef GL_ES \n\ precision mediump float; \n\ #endif \n\ vec3 HSV_To_RGB(vec3 HSV); \n\ uniform vec4 RectPosition; \n\ uniform vec4 RectDimension; \n\ uniform vec4 Color; \n\ void main(void) \n\ { \n\ float x = (gl_FragCoord.x - RectPosition.x) / RectDimension.x; \n\ float y = (gl_FragCoord.y - RectPosition.y) / RectDimension.y; \n\ vec3 rgb = HSV_To_RGB(vec3(x, y, Color.z)); \n\ gl_FragColor = vec4(rgb, 1.0); \n\ }"; const char* HSV_To_RGBFrgShader = " \n\ #ifdef GL_ES \n\ precision mediump float; \n\ #endif \n\ vec3 HSV_To_RGB(vec3 HSV) \n\ { \n\ vec3 RGB = vec3(HSV.z); \n\ if ( HSV.y != 0.0 ) \n\ { \n\ float var_h = HSV.x * 6.0; \n\ float var_i = floor(var_h); // Or ... var_i = floor( var_h ) \n\ float var_1 = HSV.z * (1.0 - HSV.y); \n\ float var_2 = HSV.z * (1.0 - HSV.y * (var_h-var_i)); \n\ float var_3 = HSV.z * (1.0 - HSV.y * (1.0-(var_h-var_i))); \n\ if (var_i == 0.0) { RGB = vec3(HSV.z, var_3, var_1); } \n\ else if (var_i == 1.0) { RGB = vec3(var_2, HSV.z, var_1); } \n\ else if (var_i == 2.0) { RGB = vec3(var_1, HSV.z, var_3); } \n\ else if (var_i == 3.0) { RGB = vec3(var_1, var_2, HSV.z); } \n\ else if (var_i == 4.0) { RGB = vec3(var_3, var_1, HSV.z); } \n\ else { RGB = vec3(HSV.z, var_1, var_2); } \n\ } \n\ return(RGB); \n\ }"; ////////////////////////////////////////////////////////////////////////////// const char* AsmVtxShader = "!!ARBvp1.0 \n\ ATTRIB iPos = vertex.position; \n\ PARAM mvp[4] = {state.matrix.mvp}; \n\ OUTPUT oPos = result.position; \n\ # Transform the vertex to clip coordinates. \n\ DP4 oPos.x, mvp[0], iPos; \n\ DP4 oPos.y, mvp[1], iPos; \n\ DP4 oPos.z, mvp[2], iPos; \n\ DP4 oPos.w, mvp[3], iPos; \n\ END"; const char* AsmRedFrgShader = "!!ARBfp1.0 \n\ PARAM RectPosition = program.local[0]; \n\ PARAM RectDimension = program.local[1]; \n\ PARAM Color = program.local[2]; \n\ TEMP temp0; \n\ TEMP temp1; \n\ SUB temp0.x, fragment.position.x, RectPosition.x; \n\ SUB temp0.y, fragment.position.y, RectPosition.y; \n\ RCP temp1.x, RectDimension.x; \n\ RCP temp1.y, RectDimension.y; \n\ MUL temp0.xy, temp0, temp1; \n\ MOV temp1.x, Color; \n\ MOV temp1.yz, temp0.yyxx; \n\ MOV temp1.w, {1, 1, 1, 1}; \n\ MOV result.color, temp1; \n\ END"; const char* AsmGreenFrgShader = "!!ARBfp1.0 \n\ PARAM RectPosition = program.local[0]; \n\ PARAM RectDimension = program.local[1]; \n\ PARAM Color = program.local[2]; \n\ TEMP temp0; \n\ TEMP temp1; \n\ SUB temp0.x, fragment.position.x, RectPosition.x; \n\ SUB temp0.y, fragment.position.y, RectPosition.y; \n\ RCP temp1.x, RectDimension.x; \n\ RCP temp1.y, RectDimension.y; \n\ MUL temp0.xy, temp0, temp1; \n\ MOV temp1.y, Color; \n\ MOV temp1.xz, temp0.yyxx; \n\ MOV temp1.w, {1, 1, 1, 1}; \n\ MOV result.color, temp1; \n\ END"; const char* AsmBlueFrgShader = "!!ARBfp1.0 \n\ PARAM RectPosition = program.local[0]; \n\ PARAM RectDimension = program.local[1]; \n\ PARAM Color = program.local[2]; \n\ TEMP temp0; \n\ TEMP temp1; \n\ SUB temp0.x, fragment.position.x, RectPosition.x; \n\ SUB temp0.y, fragment.position.y, RectPosition.y; \n\ RCP temp1.x, RectDimension.x; \n\ RCP temp1.y, RectDimension.y; \n\ MUL temp0.xy, temp0, temp1; \n\ MOV temp1.z, Color; \n\ MOV temp1.xy, temp0.xyxx; \n\ MOV temp1.w, {1, 1, 1, 1}; \n\ MOV result.color, temp1; \n\ END"; const char* AsmHueFrgShader = "!!ARBfp1.0 \n\ MOV result.color, {0, 0, 0, 0}; \n\ END"; const char* AsmSaturationFrgShader = "!!ARBfp1.0 \n\ MOV result.color, {0, 0, 0, 0}; \n\ END"; const char* AsmValueFrgShader = "!!ARBfp1.0 \n\ MOV result.color, {0, 0, 0, 0}; \n\ END"; GLSh_ColorPicker::GLSh_ColorPicker(color::Channel color_channel) : _R(1.0) , _G(0.0) , _B(0.0) , _A(1.0) , _ScreenOffsetX(0) , _ScreenOffsetY(0) { const char* FrgShaderCode; #ifdef NUX_ARCH_ARM if (GetGraphicsDisplay()->GetGraphicsEngine()->UsingGLSLCodePath()) #else if (GetGraphicsDisplay()->GetGraphicsEngine()->UsingGLSLCodePath() && (GetGraphicsDisplay()->GetGpuDevice()->GetGPUBrand() != GPU_BRAND_INTEL)) #endif { switch(color_channel) { case color::RED: { FrgShaderCode = RedFrgShader; break; } case color::GREEN: { FrgShaderCode = GreenFrgShader; break; } case color::BLUE: { FrgShaderCode = BlueFrgShader; break; } case color::HUE: { FrgShaderCode = HueFrgShader; break; } case color::SATURATION: { FrgShaderCode = SaturationFrgShader; break; } case color::VALUE: { FrgShaderCode = ValueFrgShader; break; } default: { nuxDebugMsg("[GLSh_ColorPicker::GLSh_ColorPicker] Unknown color channel"); FrgShaderCode = RedFrgShader; break; } } GlobalPixelShader = GetGraphicsDisplay()->GetGpuDevice()->CreatePixelShader(); sprog = GetGraphicsDisplay()->GetGpuDevice()->CreateShaderProgram(); GlobalPixelShader->SetShaderCode(HSV_To_RGBFrgShader); sprog->AddShaderObject(GlobalPixelShader); sprog->LoadVertexShader(VtxShader, NULL); sprog->LoadPixelShader(FrgShaderCode, NULL); sprog->Link(); } else { switch(color_channel) { case color::RED: { FrgShaderCode = AsmRedFrgShader; break; } case color::GREEN: { FrgShaderCode = AsmGreenFrgShader; break; } case color::BLUE: { FrgShaderCode = AsmBlueFrgShader; break; } case color::HUE: { FrgShaderCode = AsmHueFrgShader; break; } case color::SATURATION: { FrgShaderCode = AsmSaturationFrgShader; break; } case color::VALUE: { FrgShaderCode = AsmValueFrgShader; break; } default: { nuxDebugMsg("[GLSh_ColorPicker::GLSh_ColorPicker] Unknown color channel"); FrgShaderCode = RedFrgShader; break; } } #ifndef NUX_OPENGLES_20 m_AsmProg = GetGraphicsDisplay()->GetGpuDevice()->CreateAsmShaderProgram(); m_AsmProg->LoadVertexShader(AsmVtxShader); m_AsmProg->LoadPixelShader(FrgShaderCode); m_AsmProg->Link(); #endif } } GLSh_ColorPicker::~GLSh_ColorPicker() { GlobalPixelShader = ObjectPtr (0); sprog.Release(); #ifndef NUX_OPENGLES_20 m_AsmProg.Release(); #endif } void GLSh_ColorPicker::SetColor(float R, float G, float B, float A) { _R = R; _G = G; _B = B; _A = A; } void GLSh_ColorPicker::SetScreenPositionOffset(float x, float y) { _ScreenOffsetX = x; _ScreenOffsetY = y; } void GLSh_ColorPicker::Render(int x, int y, int z, int width, int height, int /* WindowWidth */, int WindowHeight) { float fx = x, fy = y; float VtxBuffer[] = { fx, fy, 0.0f, 1.0f, fx, fy + height, 0.0f, 1.0f, fx + width, fy + height, 0.0f, 1.0f, fx + width, fy, 0.0f, 1.0f, }; #ifdef NUX_ARCH_ARM if (GetGraphicsDisplay()->GetGraphicsEngine()->UsingGLSLCodePath()) #else if (GetGraphicsDisplay()->GetGraphicsEngine()->UsingGLSLCodePath() && (GetGraphicsDisplay()->GetGpuDevice()->GetGPUBrand() != GPU_BRAND_INTEL)) #endif { CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); sprog->Begin(); int VertexLocation = sprog->GetAttributeLocation("AVertex"); int VPMatrixLocation = sprog->GetUniformLocationARB("ViewProjectionMatrix"); Matrix4 MVPMatrix = GetGraphicsDisplay()->GetGraphicsEngine()->GetOpenGLModelViewProjectionMatrix(); sprog->SetUniformLocMatrix4fv((GLint) VPMatrixLocation, 1, false, (GLfloat *) & (MVPMatrix.m)); int ColorBase = sprog->GetUniformLocationARB("Color"); int RectPosition = sprog->GetUniformLocationARB("RectPosition"); int RectDimension = sprog->GetUniformLocationARB("RectDimension"); if (ColorBase != -1) CHECKGL(glUniform4fARB(ColorBase, _R, _G, _B, _A)); if (RectPosition != -1) CHECKGL(glUniform4fARB(RectPosition, x + _ScreenOffsetX, WindowHeight - y - height - _ScreenOffsetY, z, 0.0f)); if (RectDimension != -1) CHECKGL(glUniform4fARB(RectDimension, width, height, 0.0f, 0.0f)); CHECKGL(glEnableVertexAttribArrayARB(VertexLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexLocation, 4, GL_FLOAT, GL_FALSE, 16, VtxBuffer)); CHECKGL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); CHECKGL(glDisableVertexAttribArrayARB(VertexLocation)); sprog->End(); } #ifndef NUX_OPENGLES_20 else { CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0)); CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); m_AsmProg->Begin(); CHECKGL(glMatrixMode(GL_MODELVIEW)); CHECKGL(glLoadIdentity()); CHECKGL(glLoadMatrixf((FLOAT *) GetGraphicsDisplay()->GetGraphicsEngine()->GetOpenGLModelViewMatrix().m)); CHECKGL(glMatrixMode(GL_PROJECTION)); CHECKGL(glLoadIdentity()); CHECKGL(glLoadMatrixf((FLOAT *) GetGraphicsDisplay()->GetGraphicsEngine()->GetOpenGLProjectionMatrix().m)); int VertexLocation = VTXATTRIB_POSITION; CHECKGL(glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, x + _ScreenOffsetX, WindowHeight - y - height - _ScreenOffsetY, z, 0.0f)); CHECKGL(glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, width, height, 0.0f, 0.0f)); CHECKGL(glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 2, _R, _G, _B, _A)); CHECKGL(glEnableVertexAttribArrayARB(VertexLocation)); CHECKGL(glVertexAttribPointerARB((GLuint) VertexLocation, 4, GL_FLOAT, GL_FALSE, 16, VtxBuffer)); CHECKGL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); CHECKGL(glDisableVertexAttribArrayARB(VertexLocation)); m_AsmProg->End(); } #endif } } ./tests/0000755000004100000410000000000013313171755012413 5ustar www-datawww-data./tests/gtest-nux-geisadapter.cpp0000644000004100000410000001605713313171755017354 0ustar www-datawww-data#include #include #include "geis_mock.h" #include class GeisAdapterTest : public ::testing::Test { public: GeisAdapterTest() { adapter_emitted_init_complete = false; } void AddGestureClass(Geis geis, GeisGestureClass gesture_class) { GeisEvent event = new struct _GeisEvent; event->type = GEIS_EVENT_CLASS_AVAILABLE; event->attributes.AddPointer(GEIS_EVENT_ATTRIBUTE_CLASS, gesture_class); geis->pending_events.push_back(event); } void AddDevice(Geis geis, GeisDevice device) { GeisEvent event = new struct _GeisEvent; event->type = GEIS_EVENT_DEVICE_AVAILABLE; event->attributes.AddPointer(GEIS_EVENT_ATTRIBUTE_DEVICE, device); geis->pending_events.push_back(event); } void FinishInitialization(Geis geis) { GeisEvent event = new struct _GeisEvent; event->type = GEIS_EVENT_INIT_COMPLETE; geis->pending_events.push_back(event); } void StoreNuxGestureEvent(nux::GestureEvent &gesture_event) { gesture_events.push_back(gesture_event); } void MarkInitCompleteAsEmitted() { adapter_emitted_init_complete = true; } std::list gesture_events; bool adapter_emitted_init_complete; }; /* Send a GEIS_EVENT_INIT_COMPLETE and check if GeisAdapter emits init_complete and IsInitComplete() returns a correct value. */ TEST_F(GeisAdapterTest, SignalsInitComplete) { nux::GeisAdapter geis_adapter; Geis geis = geis_adapter.GetGeisInstance(); ASSERT_FALSE(geis_adapter.IsInitComplete()); geis_adapter.init_complete.connect(sigc::mem_fun(this, &GeisAdapterTest::MarkInitCompleteAsEmitted)); FinishInitialization(geis); geis_adapter.ProcessGeisEvents(); ASSERT_TRUE(adapter_emitted_init_complete); ASSERT_TRUE(geis_adapter.IsInitComplete()); } /* First send some necessary initialization events. One to define a multi-touch device, another defining a gesture class and one that tells that the initialization has completed. After that send a well formed GEIS_EVENT_GESTURE_BEGIN and check if GeisAdapter emits a corresponding nux::GestureEvent. */ TEST_F(GeisAdapterTest, EmitsWellFormedNuxGestureEvent) { nux::GeisAdapter geis_adapter; Geis geis = geis_adapter.GetGeisInstance(); struct _GeisGestureClass drag_class; drag_class.id = 12; drag_class.name = GEIS_GESTURE_DRAG; AddGestureClass(geis, &drag_class); struct _GeisDevice device; device.id = 7; device.attributes.AddBoolean(GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH, true); AddDevice(geis, &device); FinishInitialization(geis); struct _GeisFrame frame; frame.id = 321; frame.class_ids.insert(drag_class.id); frame.attributes.AddInteger(GEIS_GESTURE_ATTRIBUTE_DEVICE_ID, device.id); frame.attributes.AddFloat(GEIS_GESTURE_ATTRIBUTE_FOCUS_X, 87.3f); frame.attributes.AddFloat(GEIS_GESTURE_ATTRIBUTE_FOCUS_Y, 123.4f); struct _GeisGroup group; group.vector.push_back(&frame); struct _GeisGroupSet group_set; group_set.vector.push_back(&group); struct _GeisTouch touch; touch.id = 0; touch.attributes.AddFloat(GEIS_TOUCH_ATTRIBUTE_ID, 123); touch.attributes.AddFloat(GEIS_TOUCH_ATTRIBUTE_X, 777.7f); touch.attributes.AddFloat(GEIS_TOUCH_ATTRIBUTE_Y, 888.8f); struct _GeisTouchSet touch_set; touch_set.vector.push_back(&touch); GeisEvent event = new struct _GeisEvent; event->type = GEIS_EVENT_GESTURE_BEGIN; event->attributes.AddPointer(GEIS_EVENT_ATTRIBUTE_GROUPSET, &group_set); event->attributes.AddPointer(GEIS_EVENT_ATTRIBUTE_TOUCHSET, &touch_set); event->attributes.AddBoolean(GEIS_EVENT_ATTRIBUTE_CONSTRUCTION_FINISHED, true); geis->pending_events.push_back(event); geis_adapter.event_ready.connect(sigc::mem_fun(this, &GeisAdapterTest::StoreNuxGestureEvent)); geis_adapter.ProcessGeisEvents(); ASSERT_EQ(1, gesture_events.size()); const nux::GestureEvent &gesture_event = gesture_events.front(); ASSERT_EQ(nux::EVENT_GESTURE_BEGIN, gesture_event.type); ASSERT_EQ(frame.id, gesture_event.GetGestureId()); ASSERT_EQ(device.GetBoolean(GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH), gesture_event.IsDirectTouch()); ASSERT_FLOAT_EQ(frame.GetFloat(GEIS_GESTURE_ATTRIBUTE_FOCUS_X), gesture_event.GetFocus().x); ASSERT_FLOAT_EQ(frame.GetFloat(GEIS_GESTURE_ATTRIBUTE_FOCUS_Y), gesture_event.GetFocus().y); ASSERT_EQ(touch_set.vector.size(), gesture_event.GetTouches().size()); for (size_t i = 0; i < gesture_event.GetTouches().size(); ++i) { ASSERT_FLOAT_EQ(touch_set.vector[i]->GetInteger(GEIS_TOUCH_ATTRIBUTE_ID), gesture_event.GetTouches()[i].id); ASSERT_FLOAT_EQ(touch_set.vector[i]->GetFloat(GEIS_TOUCH_ATTRIBUTE_X), gesture_event.GetTouches()[i].x); ASSERT_FLOAT_EQ(touch_set.vector[i]->GetFloat(GEIS_TOUCH_ATTRIBUTE_Y), gesture_event.GetTouches()[i].y); } } /* Checks that when a Tap Update GeisEvent is received, GeisAdpater generates two events from it: A Tap Begin and a Tap End. */ TEST_F(GeisAdapterTest, SplitTapUpdateIntoTapBeginAndTapEnd) { nux::GeisAdapter geis_adapter; Geis geis = geis_adapter.GetGeisInstance(); struct _GeisGestureClass tap_class; tap_class.id = 12; tap_class.name = GEIS_GESTURE_TAP; AddGestureClass(geis, &tap_class); struct _GeisDevice device; device.id = 7; device.attributes.AddBoolean(GEIS_DEVICE_ATTRIBUTE_DIRECT_TOUCH, true); AddDevice(geis, &device); FinishInitialization(geis); struct _GeisFrame frame; frame.id = 321; frame.class_ids.insert(tap_class.id); frame.attributes.AddInteger(GEIS_GESTURE_ATTRIBUTE_DEVICE_ID, device.id); frame.attributes.AddFloat(GEIS_GESTURE_ATTRIBUTE_FOCUS_X, 87.3f); frame.attributes.AddFloat(GEIS_GESTURE_ATTRIBUTE_FOCUS_Y, 123.4f); struct _GeisGroup group; group.vector.push_back(&frame); struct _GeisGroupSet group_set; group_set.vector.push_back(&group); struct _GeisTouch touch; touch.id = 0; touch.attributes.AddFloat(GEIS_TOUCH_ATTRIBUTE_ID, 123); touch.attributes.AddFloat(GEIS_TOUCH_ATTRIBUTE_X, 777.7f); touch.attributes.AddFloat(GEIS_TOUCH_ATTRIBUTE_Y, 888.8f); struct _GeisTouchSet touch_set; touch_set.vector.push_back(&touch); GeisEvent event = new struct _GeisEvent; event->type = GEIS_EVENT_GESTURE_UPDATE; event->attributes.AddPointer(GEIS_EVENT_ATTRIBUTE_GROUPSET, &group_set); event->attributes.AddPointer(GEIS_EVENT_ATTRIBUTE_TOUCHSET, &touch_set); event->attributes.AddBoolean(GEIS_EVENT_ATTRIBUTE_CONSTRUCTION_FINISHED, false); geis->pending_events.push_back(event); geis_adapter.event_ready.connect(sigc::mem_fun(this, &GeisAdapterTest::StoreNuxGestureEvent)); geis_adapter.ProcessGeisEvents(); ASSERT_EQ(2, gesture_events.size()); ASSERT_EQ(nux::EVENT_GESTURE_BEGIN, gesture_events.front().type); ASSERT_EQ(nux::TAP_GESTURE, gesture_events.front().GetGestureClasses()); ASSERT_TRUE(gesture_events.front().IsConstructionFinished()); ASSERT_EQ(nux::EVENT_GESTURE_END, gesture_events.back().type); ASSERT_EQ(nux::TAP_GESTURE, gesture_events.back().GetGestureClasses()); ASSERT_TRUE(gesture_events.back().IsConstructionFinished()); } ./tests/Helpers.cpp0000644000004100000410000000342613313171755014526 0ustar www-datawww-data// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- /* * Copyright 2011 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Tim Penhey * */ #include "Helpers.h" #include "NuxCore/LoggingWriter.h" #include #include #include #include namespace nux { namespace testing { std::string ReadFile(std::string const& filename) { std::ifstream input(filename.c_str()); if (input.bad()) throw std::runtime_error("bad file"); return std::string((std::istreambuf_iterator(input)), std::istreambuf_iterator()); } void PumpGObjectMainLoop() { GMainContext* context(g_main_context_get_thread_default()); while (g_main_context_pending(context)) { g_main_context_iteration(context, false); } } CaptureLogOutput::CaptureLogOutput() { logging::Writer::Instance().SetOutputStream(sout_); } CaptureLogOutput::~CaptureLogOutput() { logging::Writer::Instance().SetOutputStream(std::cout); } std::string CaptureLogOutput::GetOutput() { std::string result = sout_.str(); sout_.str(""); return result; } } } ./tests/xtest-scrollbar.cpp0000644000004100000410000000776513313171755016266 0ustar www-datawww-data/* * Copyright 2011 Inalogic Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY 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 * version 3 along with this program. If not, see * * * Authored by: Andrea Azzarone * */ #include "Nux/Nux.h" #include "Nux/WindowThread.h" #include "Nux/VLayout.h" #include "Nux/ProgramFramework/ProgramTemplate.h" #include "Nux/ProgramFramework/TestView.h" #include #include #include "nux_automated_test_framework.h" #include "test-scrollview.h" class ScrollBarTest: public ProgramTemplate { public: ScrollBarTest(const char* program_name, int window_width, int window_height, int program_life_span); ~ScrollBarTest(); virtual void UserInterfaceSetup(); nux::VLayout* layout_; TestScrollView* scroll_view_; nux::VLayout* in_layout_; nux::TestView* test_view_; }; ScrollBarTest::ScrollBarTest(const char* program_name, int window_width, int window_height, int program_life_span) : ProgramTemplate(program_name, window_width, window_height, program_life_span) { } ScrollBarTest::~ScrollBarTest() { } void ScrollBarTest::UserInterfaceSetup() { layout_ = new nux::VLayout(NUX_TRACKER_LOCATION); layout_->SetPadding(20, 20); scroll_view_ = new TestScrollView(); layout_->AddView(scroll_view_); in_layout_ = new nux::VLayout(NUX_TRACKER_LOCATION); scroll_view_->SetLayout(in_layout_); test_view_ = new nux::TestView(); test_view_->SetMinimumHeight(1000); in_layout_->AddView(test_view_); static_cast(window_thread_)->SetLayout(layout_); nux::ColorLayer background(nux::Color(0xFF4D4D4D)); static_cast(window_thread_)->SetWindowBackgroundPaintLayer(&background); } ScrollBarTest* scrollbar_test; void TestingThread(nux::NThread* /* thread */, void* user_data) { while (scrollbar_test->ReadyToGo() == false) { nuxDebugMsg("Waiting to start"); nux::SleepForMilliseconds(300); } nux::SleepForMilliseconds(1000); nux::WindowThread* wnd_thread = static_cast(user_data); NuxAutomatedTestFramework test(wnd_thread); test.Startup(); test.TestReportMsg(scrollbar_test->scroll_view_, "TestScrollView created"); scrollbar_test->scroll_view_->ResetEvents(); test.ViewSendMouseMotionToCenter(scrollbar_test->scroll_view_); test.ViewSendMouseClick(scrollbar_test->scroll_view_, 4); nux::SleepForMilliseconds(1000); test.TestReportMsg(scrollbar_test->scroll_view_->registered_scroll_, "Scroll on the center of the scrollview"); scrollbar_test->scroll_view_->ResetEvents(); test.ViewSendMouseMotionToCenter(scrollbar_test->scroll_view_->GetVScrollbar()); test.ViewSendMouseClick(scrollbar_test->scroll_view_->GetVScrollbar(), 4); nux::SleepForMilliseconds(1000); test.TestReportMsg(scrollbar_test->scroll_view_->registered_scroll_, "Scroll on the scrollbar"); if (test.WhenDoneTerminateProgram()) { nux::SleepForMilliseconds(1000); wnd_thread->ExitMainLoop(); } nuxDebugMsg("Exit testing thread"); } int main() { XInitThreads(); scrollbar_test = new ScrollBarTest("Scrollbar Test", 500, 400, 13000); scrollbar_test->Startup(); scrollbar_test->UserInterfaceSetup(); nux::SystemThread* test_thread = nux::CreateSystemThread(scrollbar_test->GetWindowThread(), &TestingThread, scrollbar_test->GetWindowThread()); test_thread->Start(scrollbar_test); scrollbar_test->Run(); delete test_thread; delete scrollbar_test; return 0; } ./tests/gtest-nux-windowthread.cpp0000644000004100000410000005620013313171755017555 0ustar www-datawww-data#ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include #include #include #include #include #include #include #include #include #include #include #include "Nux/Nux.h" #include "Nux/View.h" #include "Nux/HLayout.h" #include "Nux/ProgramFramework/TestView.h" using namespace testing; using ::testing::Invoke; namespace { class MockFdDispatch { public: MOCK_METHOD0(dispatch, void()); MockFdDispatch(int fd) : mFd (fd) { ON_CALL(*this, dispatch()) .WillByDefault(Invoke(this, &MockFdDispatch::ClearStream)); } private: void ClearStream() { char buf[2]; if (read(mFd, reinterpret_cast (buf), 2) == -1) throw std::runtime_error(strerror(errno)); } int mFd; }; class TestWindowThread : public ::testing::Test { public: TestWindowThread() : seconds_to_quit(0) , quit_thread (NULL) { nux::NuxInitialize(0); wnd_thread.reset (nux::CreateNuxWindow("Nux Window", 300, 200, nux::WINDOWSTYLE_NORMAL, NULL, false, TestWindowThread::WindowThreadInit, this)); if (pipe2(quit_pipe_, O_CLOEXEC) == -1) throw std::runtime_error(strerror(errno)); if (pipe2(test_quit_pipe_, O_CLOEXEC) == -1) throw std::runtime_error(strerror(errno)); WatchFdForEventsOnRun(quit_pipe_[0], std::bind(&TestWindowThread::QuitMessage, this)); } ~TestWindowThread() { if (quit_thread) delete quit_thread; close(quit_pipe_[0]); close(quit_pipe_[1]); close(test_quit_pipe_[0]); close(test_quit_pipe_[1]); } protected: std::unique_ptr wnd_thread; unsigned int seconds_to_quit; nux::SystemThread *quit_thread; void WatchFdForEventsOnRun(int fd, const nux::WindowThread::FdWatchCallback &cb) { WatchedFd wfd; wfd.fd = fd; wfd.callback = cb; watched_fds.push_back(wfd); } /* Watchdog threads are really not that great, but ping-ponging between * the window and application threads would over-complicate this test */ void QuitAfter(unsigned int seconds) { seconds_to_quit = seconds; quit_thread = nux::CreateSystemThread(NULL, TestWindowThread::QuitTask, this); quit_thread->Start(NULL); } void WaitForQuit() { struct pollfd pfd; pfd.events = POLLIN; pfd.revents = 0; pfd.fd = test_quit_pipe_[0]; if (poll(&pfd, 1, -1) == -1) throw std::runtime_error(strerror(errno)); /* Something was written to the read end of our pipe, * we can continue now */ } private: typedef struct _WatchedFd { int fd; nux::WindowThread::FdWatchCallback callback; } WatchedFd; static void WindowThreadInit(nux::NThread *, void *data) { TestWindowThread *tw = reinterpret_cast (data); /* Monitor all nominated fd's */ for (std::vector::iterator it = tw->watched_fds.begin(); it != tw->watched_fds.end(); ++it) { tw->wnd_thread->WatchFdForEvents(it->fd, it->callback); } } static void QuitTask(nux::NThread *, void *data) { TestWindowThread *tw = reinterpret_cast (data); nux::SleepForMilliseconds(tw->seconds_to_quit * 1000); const char *buf = "w\0"; if (write(tw->quit_pipe_[1], reinterpret_cast(const_cast(buf)), 2) == -1) throw std::runtime_error(strerror(errno)); } void QuitMessage() { wnd_thread->ExitMainLoop(); /* Send a message indicating that the main loop * exited and we can safely continue */ const char *buf = "w\0"; if (write(test_quit_pipe_[1], reinterpret_cast(const_cast(buf)), 2) == -1) throw std::runtime_error(strerror(errno)); } std::vector watched_fds; int quit_pipe_[2]; int test_quit_pipe_[2]; }; TEST_F(TestWindowThread, Create) { ASSERT_TRUE(wnd_thread != NULL); EXPECT_EQ(wnd_thread->GetWindowTitle(), std::string("Nux Window")); EXPECT_EQ(wnd_thread->IsModalWindow(), false); EXPECT_EQ(wnd_thread->IsComputingLayout(), false); EXPECT_EQ(wnd_thread->IsInsideLayoutCycle(), false); } TEST_F(TestWindowThread, WatchFd) { int pipefd[2]; if (pipe2 (pipefd, O_CLOEXEC) == -1) throw std::runtime_error(strerror(errno)); MockFdDispatch dispatch(pipefd[0]); EXPECT_CALL(dispatch, dispatch()); WatchFdForEventsOnRun(pipefd[0], std::bind(&MockFdDispatch::dispatch, &dispatch)); const char *buf = "w\0"; if (write(pipefd[1], reinterpret_cast (const_cast (buf)), 2) == -1) throw std::runtime_error (strerror(errno)); QuitAfter(3); wnd_thread->Run(NULL); /* We must wait for quit before closing the pipes */ WaitForQuit(); close (pipefd[0]); close (pipefd[1]); } TEST_F(TestWindowThread, MultiWatchFd) { int pipefd[2], pipefd2[2]; if (pipe2 (pipefd, O_CLOEXEC) == -1) throw std::runtime_error(strerror(errno)); if (pipe2 (pipefd2, O_CLOEXEC) == -1) throw std::runtime_error(strerror(errno)); MockFdDispatch dispatch(pipefd[0]), dispatch2(pipefd2[0]); EXPECT_CALL(dispatch, dispatch()); EXPECT_CALL(dispatch2, dispatch()); WatchFdForEventsOnRun(pipefd[0], std::bind(&MockFdDispatch::dispatch, &dispatch)); WatchFdForEventsOnRun(pipefd2[0], std::bind(&MockFdDispatch::dispatch, &dispatch2)); const char *buf = "w\0"; if (write(pipefd[1], reinterpret_cast (const_cast (buf)), 2) == -1) throw std::runtime_error (strerror(errno)); if (write(pipefd2[1], reinterpret_cast (const_cast (buf)), 2) == -1) throw std::runtime_error (strerror(errno)); QuitAfter(3); wnd_thread->Run(NULL); /* We must wait for quit before closing the pipes */ WaitForQuit(); close (pipefd[0]); close (pipefd[1]); close (pipefd2[0]); close (pipefd2[1]); } TEST_F(TestWindowThread, OneFdEvent) { int pipefd[2], pipefd2[2]; if (pipe2 (pipefd, O_CLOEXEC) == -1) throw std::runtime_error(strerror(errno)); if (pipe2 (pipefd2, O_CLOEXEC) == -1) throw std::runtime_error(strerror(errno)); MockFdDispatch dispatch(pipefd[0]), dispatch2(pipefd2[0]); EXPECT_CALL(dispatch, dispatch()); EXPECT_CALL(dispatch2, dispatch()).Times(0); WatchFdForEventsOnRun(pipefd[0], std::bind(&MockFdDispatch::dispatch, &dispatch)); WatchFdForEventsOnRun(pipefd2[0], std::bind(&MockFdDispatch::dispatch, &dispatch2)); const char *buf = "w\0"; if (write(pipefd[1], reinterpret_cast (const_cast (buf)), 2) == -1) throw std::runtime_error (strerror(errno)); QuitAfter(3); wnd_thread->Run(NULL); /* We must wait for quit before closing the pipes */ WaitForQuit(); close (pipefd[0]); close (pipefd[1]); close (pipefd2[0]); close (pipefd2[1]); } class EmbeddedContext : public ::testing::Test { public: EmbeddedContext() : _display(XOpenDisplay(NULL)) , _root(DefaultRootWindow(_display)) , _window(XCreateSimpleWindow(_display, _root, 0, 0, 300, 200, 0, 0, 0)) , _visinfo(NULL) , _context(NULL) { XVisualInfo temp; XWindowAttributes attrib; if(!XGetWindowAttributes(_display, _window, &attrib)) throw std::runtime_error("failed to get window attributes"); temp.visualid = XVisualIDFromVisual(attrib.visual); int nvinfo = 0; _visinfo = XGetVisualInfo(_display, VisualIDMask, &temp, &nvinfo); if (!_visinfo || !nvinfo) throw std::runtime_error("failed to find visual"); #ifndef NUX_OPENGLES_20 GLint value = 0; glXGetConfig(_display, _visinfo, GLX_USE_GL, &value); if (!value) std::runtime_error("available visual is not a gl visual"); _context = glXCreateContext(_display, _visinfo, NULL, true); glXMakeCurrent(_display, _window, _context); #else EGLDisplay eglDisplay = eglGetDisplay((EGLNativeDisplayType)_display); EGLint major, minor; if (!eglInitialize(eglDisplay, &major, &minor)) throw std::runtime_error("eglInitialize failed"); const EGLint config_attribs[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RED_SIZE, 1, EGL_GREEN_SIZE, 1, EGL_BLUE_SIZE, 1, EGL_ALPHA_SIZE, 0, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_CONFIG_CAVEAT, EGL_NONE, EGL_STENCIL_SIZE, 1, EGL_NONE }; const EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; EGLint count, visualid; EGLConfig configs[1024]; if (!eglChooseConfig(eglDisplay, config_attribs, configs, 1024, &count)) throw std::runtime_error("eglChooseConfig failed"); visualid = temp.visualid; EGLConfig config = configs[0]; for (int i = 0; i < count; ++i) { EGLint val; eglGetConfigAttrib(eglDisplay, configs[i], EGL_NATIVE_VISUAL_ID, &val); if (visualid == val) { config = configs[i]; break; } } eglBindAPI(EGL_OPENGL_ES_API); _surface = eglCreateWindowSurface(eglDisplay, config, _window, 0); if (_surface == EGL_NO_SURFACE) throw std::runtime_error("eglCreateWindowSurface failed"); _context = eglCreateContext(eglDisplay, config, EGL_NO_CONTEXT, context_attribs); if (_context == EGL_NO_CONTEXT) throw std::runtime_error("eglCreateContext failed"); if (!eglMakeCurrent(eglDisplay, _surface, _surface, _context)) throw std::runtime_error("eglMakeCurrent failed"); #endif } MOCK_METHOD0(verifyInit, void()); static void nuxInitThreadEntry(nux::NThread *, void *user_data) { EmbeddedContext *context = reinterpret_cast (user_data); context->verifyInit(); } void SetUp () { EXPECT_CALL(*this, verifyInit()); nux::NuxInitialize(0); _window_thread.reset(nux::CreateFromForeignWindow(_window, _context, EmbeddedContext::nuxInitThreadEntry, this)); _window_thread->Run(NULL); while (g_main_context_iteration(g_main_context_default(), false)); } ~EmbeddedContext () { #ifndef NUX_OPENGLES_20 glXDestroyContext(_display, _context); #else EGLDisplay eglDisplay = eglGetDisplay((EGLNativeDisplayType)_display); eglDestroyContext(eglDisplay, _context); eglDestroySurface(eglDisplay, _surface); eglTerminate(eglDisplay); #endif XDestroyWindow (_display, _window); XCloseDisplay (_display); } const std::shared_ptr & WindowThread () const { return _window_thread; } private: Display *_display; Window _root; Window _window; XVisualInfo *_visinfo; #ifndef NUX_OPENGLES_20 GLXContext _context; #else EGLSurface _surface; EGLContext _context; #endif std::shared_ptr _window_thread; }; TEST_F(EmbeddedContext, WindowThreadIsEmbedded) { EXPECT_TRUE(WindowThread()->IsEmbeddedWindow()); } /* There's not a whole lot we can do to test this at the moment * since we can't really mock out the behaviour of GraphicsEngine */ TEST_F(EmbeddedContext, PresentViewInEmbeddedReadiesForPresentation) { nux::ObjectPtr bw(new nux::BaseWindow(TEXT(""))); bw->ShowWindow(true, false); WindowThread()->ForeignFrameEnded(); bw->PresentInEmbeddedModeOnThisFrame(); EXPECT_TRUE(bw->AllowPresentationInEmbeddedMode()); } TEST_F(EmbeddedContext, QueueDrawOnChildInEmbeddedReadiesForPresentation) { nux::ObjectPtr bw(new nux::BaseWindow(TEXT(""))); nux::HLayout* layout = new nux::HLayout(NUX_TRACKER_LOCATION); nux::View* view = new nux::TestView(""); layout->AddView(view, 1); bw->SetLayout(layout); bw->ShowWindow(true, false); /* Draw command is implicitly queued by ShowWindow, remove it */ view->DoneRedraw(); WindowThread()->ForeignFrameEnded(); view->QueueDraw(); EXPECT_TRUE(bw->AllowPresentationInEmbeddedMode()); } TEST_F(EmbeddedContext, DonePresentViewInEmbeddedMode) { nux::ObjectPtr bw(new nux::BaseWindow(TEXT(""))); bw->PresentInEmbeddedModeOnThisFrame(); bw->MarkPresentedInEmbeddedMode(); EXPECT_FALSE(bw->AllowPresentationInEmbeddedMode()); } TEST_F(EmbeddedContext, NoPresentInvisibleOnQueueDraw) { nux::ObjectPtr window(new nux::BaseWindow(TEXT(""))); nux::HLayout* layout = new nux::HLayout(NUX_TRACKER_LOCATION); nux::View* view = new nux::TestView(""); layout->AddView(view, 1); window->SetLayout(layout); window->ShowWindow(false); view->QueueDraw(); EXPECT_FALSE(window->AllowPresentationInEmbeddedMode()); } TEST_F(EmbeddedContext, NoPresentInvisible) { nux::ObjectPtr window(new nux::BaseWindow(TEXT(""))); window->ShowWindow(false); window->PresentInEmbeddedModeOnThisFrame(); EXPECT_FALSE(window->AllowPresentationInEmbeddedMode()); } TEST_F(EmbeddedContext, AllowPresentationSubsequentQueueDraw) { nux::ObjectPtr window(new nux::BaseWindow(TEXT(""))); nux::HLayout* layout = new nux::HLayout(NUX_TRACKER_LOCATION); nux::View* view = new nux::TestView(""); layout->AddView(view, 1); window->SetLayout(layout); /* This will call QueueDraw initially and attempt to add * the window to the presentation list */ window->SetGeometry(nux::Geometry(0, 0, 100, 100)); EXPECT_FALSE(window->AllowPresentationInEmbeddedMode()); /* This will call it again */ window->ShowWindow(true); EXPECT_TRUE(window->AllowPresentationInEmbeddedMode()); } TEST_F(EmbeddedContext, StillProcessDrawIfInvisible) { nux::ObjectPtr window(new nux::BaseWindow(TEXT(""))); nux::HLayout* layout = new nux::HLayout(NUX_TRACKER_LOCATION); nux::View* view = new nux::TestView(""); layout->AddView(view, 1); window->SetLayout(layout); window->ShowWindow(false); view->QueueDraw(); nux::Geometry clip(0, 0, 100, 100); WindowThread()->RenderInterfaceFromForeignCmd(clip); EXPECT_FALSE(view->IsRedrawNeeded()); } class EmbeddedContextWindow : public EmbeddedContext { public: virtual void SetUp() { EmbeddedContext::SetUp(); _base_window = nux::ObjectPtr(new nux::BaseWindow(TEXT(""))); _base_window->ShowWindow(true, false); /* QueueDraw will call PresentInEmbeddedModeOnThisFrame - we * need to unset this state in order to test it properly */ _base_window->MarkPresentedInEmbeddedMode(); _base_window->DoneRedraw(); } virtual nux::ObjectPtr const & Window() { return _base_window; } private: nux::ObjectPtr _base_window; }; class RedrawRequestVerification { public: MOCK_METHOD0(RedrawRequested, void()); }; TEST_F(EmbeddedContextWindow, AllowPresentationRequestsRedraw) { RedrawRequestVerification verification; EXPECT_CALL(verification, RedrawRequested()); WindowThread()->RedrawRequested.connect(sigc::mem_fun (&verification, &RedrawRequestVerification::RedrawRequested)); Window()->PresentInEmbeddedModeOnThisFrame(); } TEST_F(EmbeddedContextWindow, AllowPresentationAddsToPresentationList) { Window()->PresentInEmbeddedModeOnThisFrame(); std::vector present_list(WindowThread()->GetPresentationListGeometries()); ASSERT_EQ(1, present_list.size()); EXPECT_EQ(present_list[0], Window()->GetAbsoluteGeometry()); } TEST_F(EmbeddedContextWindow, AfterCutoffAddsToPresentationListNext) { WindowThread()->ForeignFrameEnded(); WindowThread()->ForeignFrameCutoff(); ASSERT_TRUE(WindowThread()->GetPresentationListGeometries().empty()); Window()->PresentInEmbeddedModeOnThisFrame(); EXPECT_TRUE(WindowThread()->GetPresentationListGeometries().empty()); } TEST_F(EmbeddedContextWindow, MultipleAllowPresentationAddsToPresentationListUnique) { Window()->PresentInEmbeddedModeOnThisFrame(); Window()->PresentInEmbeddedModeOnThisFrame(); std::vector present_list(WindowThread()->GetPresentationListGeometries()); ASSERT_EQ(1, present_list.size()); EXPECT_EQ(present_list[0], Window()->GetAbsoluteGeometry()); } TEST_F(EmbeddedContextWindow, OneSetOfGeometryForRePresentOnUnchangedPosition) { Window()->PresentInEmbeddedModeOnThisFrame(); Window()->MarkPresentedInEmbeddedMode(); Window()->PresentInEmbeddedModeOnThisFrame(); std::vector present_list(WindowThread()->GetPresentationListGeometries()); ASSERT_EQ(1, present_list.size()); EXPECT_EQ(present_list[0], Window()->GetAbsoluteGeometry()); } TEST_F(EmbeddedContextWindow, TwoSetsOfGeometryForRePresentOnChangedPosition) { Window()->PresentInEmbeddedModeOnThisFrame(); Window()->MarkPresentedInEmbeddedMode(); Window()->PresentInEmbeddedModeOnThisFrame(); Window()->SetBaseX(Window()->GetBaseX() + 1); std::vector present_list(WindowThread()->GetPresentationListGeometries()); ASSERT_EQ(2, present_list.size()); EXPECT_EQ(present_list[0], Window()->GetAbsoluteGeometry()); EXPECT_EQ(present_list[1], Window()->LastPresentedGeometryInEmbeddedMode()); } TEST_F(EmbeddedContextWindow, QueueDrawAddsParentToPresentationList) { nux::HLayout* layout = new nux::HLayout(NUX_TRACKER_LOCATION); nux::View* view = new nux::TestView(""); layout->AddView(view, 1); Window()->SetLayout(layout); view->QueueDraw(); std::vector present_list(WindowThread()->GetPresentationListGeometries()); ASSERT_EQ(1, present_list.size()); EXPECT_EQ(present_list[0], Window()->GetAbsoluteGeometry()); } class EmbeddedContextMultiWindow : public EmbeddedContext { public: virtual void SetUp() { EmbeddedContext::SetUp(); } const nux::ObjectPtr & SpawnWindow() { _base_windows.push_back(nux::ObjectPtr(new nux::BaseWindow(TEXT("")))); _base_windows.back()->ShowWindow(true, false); /* QueueDraw will call PresentInEmbeddedModeOnThisFrame - we * need to unset this state in order to test it properly */ _base_windows.back()->MarkPresentedInEmbeddedMode(); return _base_windows.back(); } virtual std::vector > const & Windows() { return _base_windows; } private: std::vector > _base_windows; }; TEST_F(EmbeddedContextMultiWindow, PresentIfIntersectsRectOneWindow) { nux::Geometry geo(0, 0, 100, 100); nux::ObjectPtr window(SpawnWindow()); window->SetGeometry(geo); WindowThread()->PresentWindowsIntersectingGeometryOnThisFrame(geo); EXPECT_TRUE(window->AllowPresentationInEmbeddedMode()); } TEST_F(EmbeddedContextMultiWindow, PresentOnlyOneWindow) { nux::Geometry geo(0, 0, 100, 100); nux::Geometry outside_geo(0, 101, 100, 100); nux::ObjectPtr window(SpawnWindow()); nux::ObjectPtr outside(SpawnWindow()); window->SetGeometry(geo); outside->SetGeometry(outside_geo); /* Call ForeignFrameEnded to clear the presentation list set up * by making windows visible */ WindowThread()->ForeignFrameEnded(); WindowThread()->PresentWindowsIntersectingGeometryOnThisFrame(geo); EXPECT_TRUE(window->AllowPresentationInEmbeddedMode()); EXPECT_FALSE(outside->AllowPresentationInEmbeddedMode()); } TEST_F(EmbeddedContextMultiWindow, PresentBoth) { nux::Geometry geo(0, 0, 100, 101); nux::Geometry other_geo(0, 100, 100, 100); nux::ObjectPtr window(SpawnWindow()); nux::ObjectPtr other(SpawnWindow()); window->SetGeometry(geo); other->SetGeometry(other_geo); WindowThread()->PresentWindowsIntersectingGeometryOnThisFrame(geo); EXPECT_TRUE(window->AllowPresentationInEmbeddedMode()); EXPECT_TRUE(other->AllowPresentationInEmbeddedMode()); } TEST_F(EmbeddedContextMultiWindow, ForeignFrameEndedPresentNone) { nux::Geometry geo(0, 0, 100, 100); nux::ObjectPtr window(SpawnWindow()); window->SetGeometry(geo); WindowThread()->PresentWindowsIntersectingGeometryOnThisFrame(geo); WindowThread()->ForeignFrameEnded(); EXPECT_FALSE(window->AllowPresentationInEmbeddedMode()); EXPECT_TRUE(WindowThread()->GetPresentationListGeometries().empty()); } TEST_F(EmbeddedContextMultiWindow, AddToPresentationListFailsAfterCutoff) { nux::ObjectPtr windowOne(SpawnWindow()); nux::ObjectPtr windowTwo(SpawnWindow()); WindowThread()->ForeignFrameEnded(); ASSERT_TRUE(WindowThread()->GetPresentationListGeometries().empty()); EXPECT_TRUE(WindowThread()->AddToPresentationList(windowOne.GetPointer(), false)); EXPECT_FALSE(WindowThread()->GetPresentationListGeometries().empty()); WindowThread()->ForeignFrameCutoff(); EXPECT_FALSE(WindowThread()->AddToPresentationList(windowTwo.GetPointer(), false)); } TEST_F(EmbeddedContextMultiWindow, NoPresentInEmbeddedOnThisFrameAfterFrameCutoff) { nux::ObjectPtr windowOne(SpawnWindow()); nux::ObjectPtr windowTwo(SpawnWindow()); WindowThread()->ForeignFrameEnded(); windowOne->PresentInEmbeddedModeOnThisFrame(); WindowThread()->ForeignFrameCutoff(); windowTwo->PresentInEmbeddedModeOnThisFrame(); EXPECT_TRUE(windowOne->AllowPresentationInEmbeddedMode()); EXPECT_FALSE(windowTwo->AllowPresentationInEmbeddedMode()); } TEST_F(EmbeddedContextMultiWindow, PresentInEmbeddedOnThisFrameAfterFrameCutoffIfForced) { nux::ObjectPtr windowOne(SpawnWindow()); nux::ObjectPtr windowTwo(SpawnWindow()); WindowThread()->ForeignFrameEnded(); windowOne->PresentInEmbeddedModeOnThisFrame(); WindowThread()->ForeignFrameCutoff(); windowTwo->PresentInEmbeddedModeOnThisFrame(true); EXPECT_TRUE(windowOne->AllowPresentationInEmbeddedMode()); EXPECT_TRUE(windowTwo->AllowPresentationInEmbeddedMode()); } TEST_F(EmbeddedContextMultiWindow, MoveToPresentationListAfterFrameEndedIfCaughtInCutoff) { nux::ObjectPtr windowOne(SpawnWindow()); nux::ObjectPtr windowTwo(SpawnWindow()); WindowThread()->ForeignFrameEnded(); windowOne->PresentInEmbeddedModeOnThisFrame(); WindowThread()->ForeignFrameCutoff(); windowTwo->PresentInEmbeddedModeOnThisFrame(); WindowThread()->ForeignFrameEnded(); EXPECT_FALSE(windowOne->AllowPresentationInEmbeddedMode()); EXPECT_TRUE(windowTwo->AllowPresentationInEmbeddedMode()); } } ./tests/test-canvas.cpp0000644000004100000410000000147613313171755015357 0ustar www-datawww-data/* * Copyright (C) 2011 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as * published by the Free Software Foundation. * * This program 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 this program. If not, see . * * Authored by: Mirco Müller UnReference(); } ./tests/xim-test-commands.txt0000644000004100000410000000262513313171755016532 0ustar www-datawww-data// // Copyright 2010 Inalogic Inc. // // This program is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License version 3, as published // by the Free Software Foundation. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranties of // MERCHANTABILITY, SATISFACTORY QUALITY 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 // version 3 along with this program. If not, see // // // Author by: Brandon Schaefer // 0 is the name of the IM // 1 is any key sequences you need to enter to get the IM // in the correct state while testing // 2 is text that will get inputed to the IM. The input is what you // would normally type to get your desired CJK string // 3 is the expect result that the IM should turn your input into // 4 is when we know the test is over and to close the current IM // This test GCIN with chewing 0 gcin 1 ctrl+space 1 ctrl+alt+[ 2 w91o3g4 1 enter 1 ctrl+space 3 北市 4 halt // This test Fcitx with google pinyin 0 fcitx 1 ctrl+space 2 dianshi ji1 3 耟椒晃 4 halt // This test Hime with anthy 0 hime 1 ctrl+space 1 ctrl+alt+= 2 shisutemu 1 enter 1 ctrl+space 3 しすてむ 4 halt ./tests/geis_mock.cpp0000644000004100000410000002411213313171755015057 0ustar www-datawww-data/* * Copyright 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Daniel d'Andrada * */ #include #include "geis_mock.h" #include #include #include #include //#define DEBUG_PRINT printf("%s mock called!\n", __func__); #define DEBUG_PRINT /******** GeisAttributes helper class *********/ GeisAttr GeisAttributes::GetByName(GeisString name) { for (size_t i = 0; i < vector.size(); ++i) { GeisAttr attr = vector[i].get(); if (attr->name.compare(name) == 0) return attr; } return nullptr; } GeisAttr GeisAttributes::GetByIndex(GeisSize index) { if (vector.size() > index) { return vector[index].get(); } else { return nullptr; } } GeisSize GeisAttributes::Count() { return vector.size(); } void GeisAttributes::AddBoolean(const char *name, GeisBoolean value) { std::unique_ptr attr(new struct _GeisAttr); attr->type = GEIS_ATTR_TYPE_BOOLEAN; attr->name = name; attr->b = value; vector.push_back(std::move(attr)); } void GeisAttributes::AddFloat(const char *name, GeisFloat value) { std::unique_ptr attr(new struct _GeisAttr); attr->type = GEIS_ATTR_TYPE_FLOAT; attr->name = name; attr->f = value; vector.push_back(std::move(attr)); } void GeisAttributes::AddInteger(const char *name, GeisInteger value) { std::unique_ptr attr(new struct _GeisAttr); attr->type = GEIS_ATTR_TYPE_INTEGER; attr->name = name; attr->i = value; vector.push_back(std::move(attr)); } void GeisAttributes::AddPointer(const char *name, void *value) { std::unique_ptr attr(new struct _GeisAttr); attr->type = GEIS_ATTR_TYPE_POINTER; attr->name = name; attr->p = value; vector.push_back(std::move(attr)); } extern "C" { /******* Geis *******/ Geis geis_new(GeisString /* init_arg_name */, ...) { DEBUG_PRINT Geis geis = new struct _Geis; geis->fd = eventfd(0, EFD_NONBLOCK); return geis; } GeisStatus geis_delete(Geis geis) { DEBUG_PRINT close(geis->fd); delete geis; return GEIS_STATUS_SUCCESS; } GeisStatus geis_get_configuration(Geis geis, GeisString configuration_item_name, void *configuration_item_value) { DEBUG_PRINT if (strcmp(configuration_item_name, GEIS_CONFIGURATION_FD) == 0) { int *fd = static_cast(configuration_item_value); *fd = geis->fd; return GEIS_STATUS_SUCCESS; } else { return GEIS_STATUS_NOT_SUPPORTED; } } GeisStatus geis_dispatch_events(Geis /* geis */) { DEBUG_PRINT return GEIS_STATUS_SUCCESS; } GeisStatus geis_next_event(Geis geis, GeisEvent *event) { DEBUG_PRINT if (geis->pending_events.size() > 0) { *event = geis->pending_events.front(); geis->pending_events.pop_front(); if (geis->pending_events.size() > 0) return GEIS_STATUS_CONTINUE; else return GEIS_STATUS_SUCCESS; } else { *event = nullptr; return GEIS_STATUS_EMPTY; } } GeisStatus geis_gesture_accept(Geis /* geis */, GeisGroup /* group */, GeisGestureId /* gesture_id */) { DEBUG_PRINT return GEIS_STATUS_SUCCESS; } GeisStatus geis_gesture_reject(Geis /* geis */, GeisGroup /* group */, GeisGestureId /* gesture_id */) { DEBUG_PRINT return GEIS_STATUS_SUCCESS; } /******* Attr *******/ GeisString geis_attr_name(GeisAttr attr) { DEBUG_PRINT return attr->name.c_str(); } GeisAttrType geis_attr_type(GeisAttr attr) { DEBUG_PRINT return attr->type; } GeisBoolean geis_attr_value_to_boolean(GeisAttr attr) { DEBUG_PRINT return attr->b; } GeisFloat geis_attr_value_to_float(GeisAttr attr) { DEBUG_PRINT return attr->f; } GeisInteger geis_attr_value_to_integer(GeisAttr attr) { DEBUG_PRINT return attr->i; } GeisPointer geis_attr_value_to_pointer(GeisAttr attr) { DEBUG_PRINT return attr->p; } GeisString geis_attr_value_to_string(GeisAttr attr) { DEBUG_PRINT return attr->s.c_str(); } /*********** Event **************/ void geis_event_delete(GeisEvent event) { DEBUG_PRINT delete event; } GeisEventType geis_event_type(GeisEvent event) { DEBUG_PRINT return event->type; } GeisSize geis_event_attr_count(GeisEvent event) { DEBUG_PRINT return event->attributes.Count(); } GeisAttr geis_event_attr(GeisEvent event, GeisSize index) { DEBUG_PRINT return event->attributes.GetByIndex(index); } GeisAttr geis_event_attr_by_name(GeisEvent event, GeisString attr_name) { DEBUG_PRINT return event->attributes.GetByName(attr_name); } /******** Gesture Class ***********/ void geis_gesture_class_ref(GeisGestureClass /* gesture_class */) { DEBUG_PRINT } void geis_gesture_class_unref(GeisGestureClass /* gesture_class */) { DEBUG_PRINT } GeisString geis_gesture_class_name(GeisGestureClass gesture_class) { DEBUG_PRINT return const_cast(gesture_class->name.c_str()); } GeisInteger geis_gesture_class_id(GeisGestureClass gesture_class) { DEBUG_PRINT return gesture_class->id; } GeisSize geis_gesture_class_attr_count(GeisGestureClass gesture_class) { DEBUG_PRINT return gesture_class->attributes.Count(); } GeisAttr geis_gesture_class_attr(GeisGestureClass gesture_class, int index) { DEBUG_PRINT return gesture_class->attributes.GetByIndex(index); } /********* Device ***********/ GeisInteger geis_device_id(GeisDevice device) { DEBUG_PRINT return device->id; } GeisAttr geis_device_attr_by_name(GeisDevice device, GeisString attr_name) { DEBUG_PRINT return device->attributes.GetByName(attr_name); } /********** Group Set **********/ GeisSize geis_groupset_group_count(GeisGroupSet groupset) { DEBUG_PRINT return groupset->vector.size(); } GeisGroup geis_groupset_group(GeisGroupSet groupset, GeisSize index) { DEBUG_PRINT return groupset->vector[index]; } /****** Group ******/ GeisSize geis_group_frame_count(GeisGroup group) { DEBUG_PRINT return group->vector.size(); } GeisFrame geis_group_frame(GeisGroup group, GeisSize index) { DEBUG_PRINT return group->vector[index]; } /***** Touch Set *****/ GeisSize geis_touchset_touch_count(GeisTouchSet touchset) { DEBUG_PRINT return touchset->vector.size(); } GeisTouch geis_touchset_touch(GeisTouchSet touchset, GeisSize index) { DEBUG_PRINT return touchset->vector[index]; } /***** Touch ******/ GeisTouchId geis_touch_id(GeisTouch touch) { DEBUG_PRINT return touch->id; } GeisSize geis_touch_attr_count(GeisTouch touch) { DEBUG_PRINT return touch->attributes.Count(); } GeisAttr geis_touch_attr(GeisTouch touch, GeisSize index) { DEBUG_PRINT return touch->attributes.GetByIndex(index); } GeisAttr geis_touch_attr_by_name(GeisTouch touch, GeisString name) { DEBUG_PRINT return touch->attributes.GetByName(name); } /***** Frame *****/ GeisGestureId geis_frame_id(GeisFrame frame) { DEBUG_PRINT return frame->id; } GeisBoolean geis_frame_is_class(GeisFrame frame, GeisGestureClass gesture_class) { DEBUG_PRINT std::set::iterator it = frame->class_ids.find(gesture_class->id); if (it == frame->class_ids.end()) return GEIS_FALSE; else return GEIS_TRUE; } GeisSize geis_frame_attr_count(GeisFrame frame) { DEBUG_PRINT return frame->attributes.Count(); } GeisAttr geis_frame_attr(GeisFrame frame, GeisSize index) { DEBUG_PRINT return frame->attributes.GetByIndex(index); } GeisAttr geis_frame_attr_by_name(GeisFrame frame, GeisString name) { DEBUG_PRINT return frame->attributes.GetByName(name); } /***** Subscription *****/ GeisSubscription geis_subscription_new(Geis /* geis */, GeisString /* name */, GeisSubscriptionFlags /* flags */) { DEBUG_PRINT return new struct _GeisSubscription; } GeisStatus geis_subscription_delete(GeisSubscription subscription) { DEBUG_PRINT for (auto filter : subscription->filters) { delete filter; } delete subscription; return GEIS_STATUS_SUCCESS; } GeisStatus geis_subscription_activate(GeisSubscription /* subscription */) { DEBUG_PRINT return GEIS_STATUS_SUCCESS; } GeisStatus geis_subscription_deactivate(GeisSubscription /* subscription */) { DEBUG_PRINT return GEIS_STATUS_SUCCESS; } GeisString geis_subscription_name(GeisSubscription subscription) { DEBUG_PRINT return const_cast(subscription->name.c_str()); } GeisInteger geis_subscription_id(GeisSubscription subscription) { DEBUG_PRINT return subscription->id; } GeisStatus geis_subscription_add_filter(GeisSubscription subscription, GeisFilter filter) { DEBUG_PRINT subscription->filters.push_back(filter); return GEIS_STATUS_SUCCESS; } GeisFilter geis_subscription_filter_by_name(GeisSubscription /* sub */, GeisString /* name */) { DEBUG_PRINT return nullptr; } GeisStatus geis_subscription_remove_filter(GeisSubscription subscription, GeisFilter filter) { DEBUG_PRINT std::vector::iterator it = subscription->filters.begin(); while (it != subscription->filters.end()) { if (filter == *it) { subscription->filters.erase(it); return GEIS_STATUS_SUCCESS; } ++it; } return GEIS_STATUS_BAD_ARGUMENT; } } // extern "C" ./tests/nux_automated_test_framework.h0000644000004100000410000001171013313171755020555 0ustar www-datawww-data/* * Copyright 2010 Inalogic Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY 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 * version 3 along with this program. If not, see * * * Authored by: Jay Taoko * */ #include #include #ifndef NUX_AUTOMATED_TEST_FRAMEWORK_H #define NUX_AUTOMATED_TEST_FRAMEWORK_H class NuxAutomatedTestFramework { public: NuxAutomatedTestFramework(nux::WindowThread *window_thread); virtual ~NuxAutomatedTestFramework(); //! Returns true if composition keys are supported by the server bool CompositionKeysSupported(); //! Warn the developer composition keys are not supported void WarnCompositionKeysNotSupported(); //! Initialize the testing framework. void Startup(); //! Simulate a mouse click event on a view. /*! Move the mouse to the middle of the view (if it isn't there already) and perform a click event. */ void ViewSendMouseClick(nux::View *view, int button); //! Simulate a mouse double click event on a view. /*! Move the mouse to the middle of the view (if it isn't there already) and perform a double click event. */ void ViewSendMouseDoubleClick(nux::View *view, int button); //! Simulate a mouse down event on a view. void ViewSendMouseDown(nux::View *view, int button); //! Simulate a mouse up event on a view. void ViewSendMouseUp(nux::View *view, int button); //! Simulate a drag event on a view from (x0, y0) to (x1, y1). void ViewSendMouseDrag(nux::View *view, int button, int x0, int y0, int x1, int y1); //! Simulate mouse motion to (x, y). void ViewSendMouseMotionTo(nux::View *view, int x, int y); //! Simulate mouse motion to the center of a view. void ViewSendMouseMotionToCenter(nux::View *view); //! Simulate mouse motion to the top left corner of a view. void ViewSendMouseMotionToTopLeft(nux::View *view); //! Simulate mouse motion to the top right corner of a view. void ViewSendMouseMotionToTopRight(nux::View *view); //! Simulate mouse motion to the bottom left corner of a view. void ViewSendMouseMotionToBottomLeft(nux::View *view); //! Simulate mouse motion to the bottom right corner of a view. void ViewSendMouseMotionToBottomRight(nux::View *view); //! Simulate a key event. void ViewSendChar(const char c); //! Simulate a succession of key events. void ViewSendString(const std::string &str); //! Simulate a key combo. void ViewSendKeyCombo(KeySym modsym0, KeySym modsym1, KeySym modsym2, const char c); //! Simulate Ctrl+a. void ViewSendCtrlA(); //! Simulate Delete key. void ViewSendDelete(); //! Simulate Backspace key. void ViewSendBackspace(); //! Simulate Escape key. void ViewSendEscape(); //! Simulate Tab key. void ViewSendTab(); //! Simulate Return key. void ViewSendReturn(); //! Simulate Left arrow key. void ViewSendLeft(); //! Simulate Right arrow key. void ViewSendRight(); //! Simulate Up arrow key. void ViewSendUp(); //! Simulate Down arrow key. void ViewSendDown(); //! Simulate composition keys. void ViewSendCompositionKeys(const std::string &str); //! Simulate 1-4 key presses. void ViewSendKeys(const std::string &str); void ViewSendIBusToggle(); //! Put the mouse pointer anywhere on the display. void PutMouseAt(int x, int y); //! Simulate a mouse event. void SendFakeMouseEvent(int mouse_button_index, bool pressed); //! Simulate a key event. void SendFakeKeyEvent(KeySym keysym, KeySym modsym); //! Simulate a mouse motion event. void SendFakeMouseMotionEvent(int x, int y, int ms_delay); /*! Set the test thread to terminae the program when testing is over. */ void SetTerminateProgramWhenDone(bool terminate); /*! Return true if the test thread is allowed to terminate the program after testing is over. */ bool WhenDoneTerminateProgram(); /*! Print a report message to the console. */ void TestReportMsg(bool b, const char* msg); private: void WindowConfigSignal(int x, int y, int width, int height); bool ready_to_start_; Display* display_; nux::WindowThread *window_thread_; int window_x_; int window_y_; int window_width_; int window_height_; bool terminate_when_test_over_; bool composition_keys_supported_; static int mouse_motion_time_span; // in milliseconds static int mouse_click_time_span; // in milliseconds static int minimum_sleep_time; // in milliseconds static int safety_border_inside_view; // in pixels }; #endif // NUX_AUTOMATED_TEST_FRAMEWORK_H ./tests/xtest-vlayout-key-navigation.cpp0000644000004100000410000001401213313171755020710 0ustar www-datawww-data/* * Copyright 2011 Inalogic Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY 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 * version 3 along with this program. If not, see * * * Authored by: Andrea Azzarone * */ #include "Nux/Nux.h" #include "Nux/WindowThread.h" #include "Nux/VLayout.h" #include "Nux/ProgramFramework/ProgramTemplate.h" #include "Nux/ProgramFramework/TestView.h" #include #include #include "nux_automated_test_framework.h" unsigned int const NUM_VIEWS = 5; unsigned int const ID_UNFOCUSABLE_VIEW = 1; // Please don't make this the last/first one :) class VLayoutKeyNavigationTest : public ProgramTemplate { public: VLayoutKeyNavigationTest(const char* program_name, int window_width, int window_height, int program_life_span); ~VLayoutKeyNavigationTest(); virtual void UserInterfaceSetup(); nux::TestView* CreateView(); void AddView(nux::TestView* view); nux::VLayout* vlayout_; nux::TestView* views_[NUM_VIEWS]; }; VLayoutKeyNavigationTest::VLayoutKeyNavigationTest(const char* program_name, int window_width, int window_height, int program_life_span) : ProgramTemplate(program_name, window_width, window_height, program_life_span) { } VLayoutKeyNavigationTest::~VLayoutKeyNavigationTest() { } nux::TestView* VLayoutKeyNavigationTest::CreateView() { nux::TestView* view = new nux::TestView(); return view; } void VLayoutKeyNavigationTest::AddView(nux::TestView* view) { vlayout_->AddView(view, 1); } void VLayoutKeyNavigationTest::UserInterfaceSetup() { vlayout_ = new nux::VLayout(NUX_TRACKER_LOCATION); vlayout_->SetPadding(20, 20); vlayout_->SetSpaceBetweenChildren(10); for (unsigned int i=0; ican_focus_ = false; nux::GetWindowCompositor().SetKeyFocusArea(views_[0]); static_cast(window_thread_)->SetLayout(vlayout_); nux::ColorLayer background(nux::Color(0xFF4D4D4D)); static_cast(window_thread_)->SetWindowBackgroundPaintLayer(&background); } VLayoutKeyNavigationTest* key_navigation_test = NULL; void TestingThread(nux::NThread* /* thread */, void* user_data) { while (key_navigation_test->ReadyToGo() == false) { nuxDebugMsg("Waiting to start"); nux::SleepForMilliseconds(300); } nux::SleepForMilliseconds(1000); nux::WindowThread* wnd_thread = static_cast(user_data); NuxAutomatedTestFramework test(wnd_thread); test.Startup(); // Set the mouse at coordinates (0, 0) (top-left corner) on the display test.PutMouseAt(0, 0); test.TestReportMsg(key_navigation_test->vlayout_, "TestView created"); test.TestReportMsg(key_navigation_test->views_[0]->has_focus_, "Top left tile has key focus"); // Down key for (unsigned int i=0; iviews_[i]->has_focus_, "Down: key focus out"); if ((i + 1) == ID_UNFOCUSABLE_VIEW) { test.TestReportMsg(!key_navigation_test->views_[i+1]->has_focus_, "Down: key focus skipped"); test.TestReportMsg(key_navigation_test->views_[i+2]->has_focus_, "Down: key focus in"); ++i; } else { test.TestReportMsg(key_navigation_test->views_[i+1]->has_focus_, "Down: key focus in"); } } // Another down key, should do nothing test.SendFakeKeyEvent(XK_Down, 0); nux::SleepForMilliseconds(500); test.TestReportMsg(key_navigation_test->views_[NUM_VIEWS-1]->has_focus_, "Down key, last element"); // Up key for (int i=NUM_VIEWS-1; i>0; --i) { test.SendFakeKeyEvent(XK_Up, 0); nux::SleepForMilliseconds(500); test.TestReportMsg(!key_navigation_test->views_[i]->has_focus_, "Up: key focus out"); if ((i - 1) == (int)ID_UNFOCUSABLE_VIEW) { test.TestReportMsg(!key_navigation_test->views_[i-1]->has_focus_, "Up: key focus skipped"); test.TestReportMsg(key_navigation_test->views_[i-2]->has_focus_, "Up: key focus in"); --i; } else { test.TestReportMsg(key_navigation_test->views_[i-1]->has_focus_, "Up: key focus in"); } } // Another up key, should do nothing test.SendFakeKeyEvent(XK_Up, 0); nux::SleepForMilliseconds(500); test.TestReportMsg(key_navigation_test->views_[0]->has_focus_, "Up key, fist element"); // Keft key, should do nothing test.SendFakeKeyEvent(XK_Left, 0); nux::SleepForMilliseconds(500); test.TestReportMsg(key_navigation_test->views_[0]->has_focus_, "Left key"); // Right key, should do nothing test.SendFakeKeyEvent(XK_Right, 0); nux::SleepForMilliseconds(500); test.TestReportMsg(key_navigation_test->views_[0]->has_focus_, "Right key"); if (test.WhenDoneTerminateProgram()) { nux::SleepForMilliseconds(1000); wnd_thread->ExitMainLoop(); } nuxDebugMsg("Exit testing thread"); } int main() { XInitThreads(); key_navigation_test = new VLayoutKeyNavigationTest("Key navigation Test", 500, 400, 8000); key_navigation_test->Startup(); key_navigation_test->UserInterfaceSetup(); nux::SystemThread* test_thread = nux::CreateSystemThread(key_navigation_test->GetWindowThread(), &TestingThread, key_navigation_test->GetWindowThread()); test_thread->Start(key_navigation_test); key_navigation_test->Run(); delete test_thread; delete key_navigation_test; return 0; } ./tests/gtest-nux-area.cpp0000644000004100000410000001106413313171755015765 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License version 3 along with this program. If not, see * * * Authored by: Jay Taoko * Marco Trevisan */ #include #include #include "Nux/Nux.h" #include "Nux/HLayout.h" #include "Nux/StaticText.h" #include "Nux/ProgramFramework/TestView.h" using namespace testing; namespace { struct MockTestView : nux::TestView { MockTestView() : nux::TestView("MockTestView") {} void SetNextObjectToKeyFocusArea(nux::Area* area) { TestView::SetNextObjectToKeyFocusArea(area); } nux::Area* GetNextObjectToKeyFocusArea() { return TestView::GetNextObjectToKeyFocusArea(); } }; struct TestArea : public testing::Test { void SetUp() { nux::NuxInitialize(0); wnd_thread.reset(nux::CreateNuxWindow("Area Test", 300, 200, nux::WINDOWSTYLE_NORMAL, NULL, false, NULL, NULL)); test_view = new MockTestView(); } boost::shared_ptr wnd_thread; nux::ObjectPtr test_view; }; TEST_F(TestArea, TestAreaSize) { EXPECT_EQ(test_view->GetMinimumWidth(), nux::AREA_MIN_WIDTH); EXPECT_EQ(test_view->GetMaximumWidth(), nux::AREA_MAX_WIDTH); EXPECT_EQ(test_view->GetMinimumHeight(), nux::AREA_MIN_HEIGHT); EXPECT_EQ(test_view->GetMaximumHeight(), nux::AREA_MAX_HEIGHT); test_view->SetMinimumWidth(100); EXPECT_EQ(test_view->GetMinimumWidth(), 100); test_view->SetMaximumWidth(1111); EXPECT_EQ(test_view->GetMaximumWidth(), 1111); test_view->SetMinimumHeight(123); EXPECT_EQ(test_view->GetMinimumHeight(), 123); test_view->SetMaximumHeight(1234); EXPECT_EQ(test_view->GetMaximumHeight(), 1234); test_view->SetMaximumSize(4321, 1234); test_view->SetMinimumSize(123, 432); EXPECT_EQ(test_view->GetMinimumWidth(), 123); EXPECT_EQ(test_view->GetMaximumWidth(), 4321); EXPECT_EQ(test_view->GetMinimumHeight(), 432); EXPECT_EQ(test_view->GetMaximumHeight(), 1234); } TEST_F(TestArea, TestAreaGeometry) { static_cast(test_view.GetPointer())->SetGeometry(0, 0, 100, 100); EXPECT_EQ(test_view->GetBaseX(), 0); EXPECT_EQ(test_view->GetBaseX(), 0); EXPECT_EQ(test_view->GetBaseWidth(), 100); EXPECT_EQ(test_view->GetBaseHeight(), 100); } static bool object_destroyed = false; void OnObjectDestroyed(nux::Object* /* object */) { object_destroyed = true; } TEST_F(TestArea, TestUnParentKeyFocus) { nux::TestView* test_view1 = new nux::TestView(""); nux::HLayout* layout = new nux::HLayout(); test_view1->object_destroyed.connect(sigc::ptr_fun(&OnObjectDestroyed)); test_view1->Reference(); layout->AddView(test_view1, 1); wnd_thread->SetLayout(layout); EXPECT_EQ(test_view1->HasKeyFocus(), false); nux::GetWindowThread()->GetWindowCompositor().SetKeyFocusArea(test_view1); EXPECT_EQ(test_view1->HasKeyFocus(), true); layout->RemoveChildObject(test_view1); EXPECT_EQ(test_view1->HasKeyFocus(), false); test_view1->UnReference(); EXPECT_EQ(object_destroyed, true); } TEST_F(TestArea, NextObjectToKeyFocusSetReset) { MockTestView* parent = new MockTestView(); MockTestView* brother = new MockTestView(); MockTestView* child1 = new MockTestView(); MockTestView* child2 = new MockTestView(); MockTestView* child3 = new MockTestView(); parent->SetNextObjectToKeyFocusArea(brother); ASSERT_EQ(parent->GetNextObjectToKeyFocusArea(), brother); child1->SetParentObject(parent); child1->SetNextObjectToKeyFocusArea(child2); ASSERT_EQ(child1->GetNextObjectToKeyFocusArea(), child2); child2->SetParentObject(parent); child2->SetNextObjectToKeyFocusArea(child3); ASSERT_EQ(child2->GetNextObjectToKeyFocusArea(), child3); child3->SetParentObject(parent); ASSERT_EQ(child3->GetNextObjectToKeyFocusArea(), nullptr); child1->UnReference(); EXPECT_EQ(child2->GetNextObjectToKeyFocusArea(), nullptr); EXPECT_EQ(parent->GetNextObjectToKeyFocusArea(), nullptr); parent->UnReference(); } } ./tests/gtest-nux-inputmethodibus.cpp0000644000004100000410000000572213313171755020304 0ustar www-datawww-data/* * Copyright 2012 Inalogic Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY 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 * version 3 along with this program. If not, see * * * Authored by: Marco Trevisan * */ #include #include "Nux/Nux.h" #include "Nux/InputMethodIBus.h" using namespace nux; class MockIBusIMEContext : public IBusIMEContext { public: static std::vector ParseIBusHotkeys(const gchar** keybindings) { return IBusIMEContext::ParseIBusHotkeys(keybindings); } }; namespace { TEST(TestIBusIMEContext, ParseNullHotkeys) { auto hotkeys = MockIBusIMEContext::ParseIBusHotkeys(nullptr); EXPECT_TRUE(hotkeys.empty()); } TEST(TestIBusIMEContext, ParseInvalidHotkeys) { const gchar* invalid_code[] = {"Alt+InvalidCode", nullptr }; auto hotkeys = MockIBusIMEContext::ParseIBusHotkeys(invalid_code); EXPECT_TRUE(hotkeys.empty()); const gchar* missing_key[] = {"Alt+Control", nullptr }; hotkeys = MockIBusIMEContext::ParseIBusHotkeys(missing_key); EXPECT_TRUE(hotkeys.empty()); } TEST(TestIBusIMEContext, ParseHotkeys) { const gchar* keybindings[] = {"Control+space", "Zenkaku_Hankaku", "Alt+Kanji", "Alt+grave", "Hangul", "Alt+Release+Alt_R", "Alt+Control+Release+Shift_L", nullptr}; auto hotkeys = MockIBusIMEContext::ParseIBusHotkeys(keybindings); ASSERT_EQ(hotkeys.size(), 7); auto event = hotkeys[0]; EXPECT_EQ(event.type, NUX_KEYDOWN); EXPECT_EQ(event.key_modifiers, KEY_MODIFIER_CTRL); EXPECT_EQ(event.x11_keysym, XK_space); event = hotkeys[1]; EXPECT_EQ(event.type, NUX_KEYDOWN); EXPECT_EQ(event.key_modifiers, 0); EXPECT_EQ(event.x11_keysym, XK_Zenkaku_Hankaku); event = hotkeys[2]; EXPECT_EQ(event.type, NUX_KEYDOWN); EXPECT_EQ(event.key_modifiers, KEY_MODIFIER_ALT); EXPECT_EQ(event.x11_keysym, XK_Kanji); event = hotkeys[3]; EXPECT_EQ(event.type, NUX_KEYDOWN); EXPECT_EQ(event.key_modifiers, KEY_MODIFIER_ALT); EXPECT_EQ(event.x11_keysym, XK_grave); event = hotkeys[4]; EXPECT_EQ(event.type, NUX_KEYDOWN); EXPECT_EQ(event.key_modifiers, 0); EXPECT_EQ(event.x11_keysym, XK_Hangul); event = hotkeys[5]; EXPECT_EQ(event.type, NUX_KEYUP); EXPECT_EQ(event.key_modifiers, KEY_MODIFIER_ALT); EXPECT_EQ(event.x11_keysym, XK_Alt_R); event = hotkeys[6]; EXPECT_EQ(event.type, NUX_KEYUP); EXPECT_EQ(event.key_modifiers, (KEY_MODIFIER_ALT | KEY_MODIFIER_CTRL)); EXPECT_EQ(event.x11_keysym, XK_Shift_L); } } ./tests/gtest-nux-statictext.cpp0000644000004100000410000000237713313171755017260 0ustar www-datawww-data#include #include #include #include #include #include #include "Nux/Nux.h" #include "Nux/StaticText.h" using namespace testing; namespace { TEST(TestStaticText, TestCreate) { nux::NuxInitialize(0); nux::WindowThread *wnd_thread = nux::CreateNuxWindow("Nux Window", 300, 200, nux::WINDOWSTYLE_NORMAL, NULL, false, NULL, NULL); nux::StaticText *statictext = new nux::StaticText(""); EXPECT_EQ(statictext->GetText(), std::string("")); // Test the default color. Should be white. EXPECT_EQ(statictext->GetTextColor(), nux::color::White); // Test random color. nux::Color random_color = nux::color::RandomColor(); statictext->SetTextColor(random_color); EXPECT_EQ(statictext->GetTextColor(), random_color); // Test default font. Should be "Ubuntu". EXPECT_EQ(statictext->GetFontName(), std::string("Ubuntu")); // Test random font. statictext->SetFontName("Courrier"); EXPECT_EQ(statictext->GetFontName(), std::string("Courrier")); // Test default font point size; EXPECT_EQ(statictext->GetTextPointSize(), 10); statictext->SetTextPointSize(20); EXPECT_EQ(statictext->GetTextPointSize(), 20); statictext->UnReference(); delete wnd_thread; } } ./tests/gtest-nuxcore-color.cpp0000644000004100000410000002472213313171755017051 0ustar www-datawww-data/* * Copyright 2012 Inalogic Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License version 3 along with this program. If not, see * * * Authored by: Jay Taoko * */ #include #include "NuxCore/Color.h" using namespace testing; static const float epsilon = 0.005f; namespace { TEST(TestColor, TestColorConstructor0) { nux::Color c; EXPECT_EQ(c.red, 0.0f); EXPECT_EQ(c.green, 0.0f); EXPECT_EQ(c.blue, 0.0f); EXPECT_EQ(c.alpha, 1.0); EXPECT_EQ(c.IsPremultiplied(), false); } TEST(TestColor, TestColorConstructor1) { // testing float inputs nux::Color c0(0.1f, 0.2f, 0.3f); EXPECT_EQ(c0.red, 0.1f); EXPECT_EQ(c0.green, 0.2f); EXPECT_EQ(c0.blue, 0.3f); EXPECT_EQ(c0.alpha, 1.0f); EXPECT_EQ(c0.IsPremultiplied(), false); // testing float inputs nux::Color c1(0.1f, 0.2f, 0.3f, 0.4f); EXPECT_EQ(c1.red, 0.1f); EXPECT_EQ(c1.green, 0.2f); EXPECT_EQ(c1.blue, 0.3f); EXPECT_EQ(c1.alpha, 0.4f); EXPECT_EQ(c1.IsPremultiplied(), false); // testing double inputs nux::Color c2(0.1, 0.2, 0.3, 0.4); EXPECT_EQ(c2.red, 0.1f); EXPECT_EQ(c2.green, 0.2f); EXPECT_EQ(c2.blue, 0.3f); EXPECT_EQ(c2.alpha, 0.4f); EXPECT_EQ(c2.IsPremultiplied(), false); } TEST(TestColor, TestColorConstructor2) { nux::Color c0(255, 255, 255); EXPECT_EQ(c0.red, 1.0f); EXPECT_EQ(c0.green, 1.0f); EXPECT_EQ(c0.blue, 1.0f); EXPECT_EQ(c0.alpha, 1.0f); EXPECT_EQ(c0.IsPremultiplied(), false); nux::Color c1(10, 128, 192); EXPECT_EQ(c1.red, 10/255.0f); EXPECT_EQ(c1.green, 128/255.0f); EXPECT_EQ(c1.blue, 192/255.0f); EXPECT_EQ(c1.alpha, 1.0f); EXPECT_EQ(c1.IsPremultiplied(), false); } TEST(TestColor, TestColorConstructor3) { nux::Color c0((255<<24)|(255<<16)|(255<<8)|255); EXPECT_EQ(c0.red, 1.0f); EXPECT_EQ(c0.green, 1.0f); EXPECT_EQ(c0.blue, 1.0f); EXPECT_EQ(c0.alpha, 1.0f); EXPECT_EQ(c0.IsPremultiplied(), false); // A R G B nux::Color c1((128<<24)|(192<<16)|(128<<8)|10); EXPECT_EQ(c1.red, 192/255.0f); EXPECT_EQ(c1.green, 128/255.0f); EXPECT_EQ(c1.blue, 10/255.0f); EXPECT_EQ(c1.alpha, 128/255.0f); EXPECT_EQ(c1.IsPremultiplied(), false); } TEST(TestColor, TestColorConstructorHex) { nux::Color c0("#abc"); EXPECT_EQ(c0.red, 0xaa / 255.0f); EXPECT_EQ(c0.green, 0xbb / 255.0f); EXPECT_EQ(c0.blue, 0xcc / 255.0f); EXPECT_EQ(c0.alpha, 1.0f); EXPECT_EQ(c0.IsPremultiplied(), false); nux::Color c1("#abcd"); EXPECT_EQ(c1.red, 0xaa / 255.0f); EXPECT_EQ(c1.green, 0xbb / 255.0f); EXPECT_EQ(c1.blue, 0xcc / 255.0f); EXPECT_EQ(c1.alpha, 0xdd / 255.0f); EXPECT_EQ(c1.IsPremultiplied(), false); nux::Color c2("#aabbcc"); EXPECT_EQ(c2.red, 0xaa / 255.0f); EXPECT_EQ(c2.green, 0xbb / 255.0f); EXPECT_EQ(c2.blue, 0xcc / 255.0f); EXPECT_EQ(c2.alpha, 1.0f); EXPECT_EQ(c2.IsPremultiplied(), false); nux::Color c3("#aabbccdd"); EXPECT_EQ(c3.red, 0xaa / 255.0f); EXPECT_EQ(c3.green, 0xbb / 255.0f); EXPECT_EQ(c3.blue, 0xcc / 255.0f); EXPECT_EQ(c3.alpha, 0xdd / 255.0f); EXPECT_EQ(c3.IsPremultiplied(), false); nux::Color c4("abcdef"); EXPECT_EQ(c4.red, 0xab / 255.0f ); EXPECT_EQ(c4.green, 0xcd / 255.0f); EXPECT_EQ(c4.blue, 0xef / 255.0f); EXPECT_EQ(c4.alpha, 1.0f); EXPECT_EQ(c4.IsPremultiplied(), false); } TEST(TestColor, TestColorConstructorHexInvalid) { nux::Color c0(""); EXPECT_EQ(c0.red, 0.0f); EXPECT_EQ(c0.green, 0.0f); EXPECT_EQ(c0.blue, 0.0f); EXPECT_EQ(c0.alpha, 1.0f); EXPECT_EQ(c0.IsPremultiplied(), false); nux::Color c1("#abcdeG"); EXPECT_EQ(c0.red, 0.0f); EXPECT_EQ(c0.green, 0.0f); EXPECT_EQ(c0.blue, 0.0f); EXPECT_EQ(c0.alpha, 1.0f); EXPECT_EQ(c1.IsPremultiplied(), false); } TEST(TestColor, TestColorPremultiplied0) { nux::Color c0(0.81f, 0.24f, 0.53f, 0.79f); EXPECT_EQ(c0.red, 0.81f); EXPECT_EQ(c0.green, 0.24f); EXPECT_EQ(c0.blue, 0.53f); EXPECT_EQ(c0.alpha, 0.79f); EXPECT_EQ(c0.IsPremultiplied(), false); nux::Color c1 = c0.GetPremultiplied(); EXPECT_EQ(c1.red, 0.81f * 0.79f); EXPECT_EQ(c1.green, 0.24f * 0.79f); EXPECT_EQ(c1.blue, 0.53f * 0.79f); EXPECT_EQ(c1.alpha, 0.79f); EXPECT_EQ(c1.IsPremultiplied(), true); EXPECT_EQ(c0.IsPremultiplied(), false); } TEST(TestColor, TestColorRGBToHSV0) { nux::color::RedGreenBlue rgb(255/255.0f, 128/255.0f, 169/255.0f); nux::color::HueSaturationValue hsv(rgb); EXPECT_NEAR(hsv.hue, 341/360.0f, epsilon); EXPECT_NEAR(hsv.saturation, 50/100.0f, epsilon); EXPECT_NEAR(hsv.value, 100/100.0f, epsilon); } TEST(TestColor, TestColorHSVToRGB0) { nux::color::HueSaturationValue hsv(341/360.0f, 50/100.0f, 100/100.0f); nux::color::RedGreenBlue rgb(hsv); EXPECT_NEAR(rgb.red, 255/255.0f, epsilon); EXPECT_NEAR(rgb.green, 128/255.0f, epsilon); EXPECT_NEAR(rgb.blue, 169/255.0f, epsilon); } TEST(TestColor, TestColorRGBToHSV1) { nux::color::RedGreenBlue rgb(65/255.0f, 28/255.0f, 6/255.0f); nux::color::HueSaturationValue hsv(rgb); EXPECT_NEAR(hsv.hue, 22/360.0f, epsilon); EXPECT_NEAR(hsv.saturation, 91/100.0f, epsilon); EXPECT_NEAR(hsv.value, 25/100.0f, epsilon); } TEST(TestColor, TestColorHSVToRGB1) { nux::color::HueSaturationValue hsv(22/360.0f, 91/100.0f, 25/100.0f); nux::color::RedGreenBlue rgb(hsv); EXPECT_NEAR(rgb.red, 65/255.0f, epsilon); EXPECT_NEAR(rgb.green, 28/255.0f, epsilon); EXPECT_NEAR(rgb.blue, 6/255.0f, epsilon); } TEST(TestColor, TestColorRGBToHSV2) { nux::color::RedGreenBlue rgb(90/255.0f, 65/255.0f, 158/255.0f); nux::color::HueSaturationValue hsv(rgb); EXPECT_NEAR(hsv.hue, 256/360.0f, epsilon); EXPECT_NEAR(hsv.saturation, 59/100.0f, epsilon); EXPECT_NEAR(hsv.value, 62/100.0f, epsilon); } TEST(TestColor, TestColorHSVToRGB2) { nux::color::HueSaturationValue hsv(256/360.0f, 59/100.0f, 62/100.0f); nux::color::RedGreenBlue rgb(hsv); EXPECT_NEAR(rgb.red, 90/255.0f, epsilon); EXPECT_NEAR(rgb.green, 65/255.0f, epsilon); EXPECT_NEAR(rgb.blue, 158/255.0f, epsilon); } TEST(TestColor, TestColorRGBToHLS0) { nux::color::RedGreenBlue rgb(127/255.0f, 0/255.0f, 255/255.0f); nux::color::HueLightnessSaturation hls(rgb); EXPECT_NEAR(hls.hue, 270/360.0f, epsilon); EXPECT_NEAR(hls.lightness, 50/100.0f, epsilon); EXPECT_NEAR(hls.saturation, 100/100.0f, epsilon); } TEST(TestColor, TestColorHLSToRGB0) { nux::color::HueLightnessSaturation hls(270/360.0f, 50/100.0f, 100/100.0f); nux::color::RedGreenBlue rgb(hls); EXPECT_NEAR(rgb.red, 127/255.0f, epsilon); EXPECT_NEAR(rgb.green, 0/255.0f, epsilon); EXPECT_NEAR(rgb.blue, 255/255.0f, epsilon); } TEST(TestColor, TestColorRGBToHLS1) { nux::color::RedGreenBlue rgb(50/255.0f, 84/255.0f, 13/255.0f); nux::color::HueLightnessSaturation hls(rgb); EXPECT_NEAR(hls.hue, 89/360.0f, epsilon); EXPECT_NEAR(hls.lightness, 19/100.0f, epsilon); EXPECT_NEAR(hls.saturation, 73/100.0f, epsilon); } TEST(TestColor, TestColorHLSToRGB1) { nux::color::HueLightnessSaturation hls(89/360.0f, 19/100.0f, 73/100.0f); nux::color::RedGreenBlue rgb(hls); EXPECT_NEAR(rgb.red, 50/255.0f, epsilon); EXPECT_NEAR(rgb.green, 84/255.0f, epsilon); EXPECT_NEAR(rgb.blue, 13/255.0f, epsilon); } TEST(TestColor, TestColorRGBToHLS2) { nux::color::RedGreenBlue rgb(201/255.0f, 200/255.0f, 239/255.0f); nux::color::HueLightnessSaturation hls(rgb); EXPECT_NEAR(hls.hue, 242/360.0f, epsilon); EXPECT_NEAR(hls.lightness, 86/100.0f, epsilon); EXPECT_NEAR(hls.saturation, 55/100.0f, epsilon); } TEST(TestColor, TestColorHLSToRGB2) { nux::color::HueLightnessSaturation hls(242/360.0f, 86/100.0f, 55/100.0f); nux::color::RedGreenBlue rgb(hls); EXPECT_NEAR(rgb.red, 201/255.0f, epsilon); EXPECT_NEAR(rgb.green, 200/255.0f, epsilon); EXPECT_NEAR(rgb.blue, 239/255.0f, epsilon); } TEST(TestColor, TestSubtraction) { nux::Color start = nux::Color(1.0f, 0.0f, 0.0f); nux::Color finish = nux::Color(0.0f, 0.5f, 0.0f); nux::Color difference = finish - start; EXPECT_THAT(difference.red, FloatEq(-1)); EXPECT_THAT(difference.green, FloatEq(0.5)); EXPECT_THAT(difference.blue, FloatEq(0)); EXPECT_THAT(difference.alpha, FloatEq(0)); } TEST(TestColor, TestColorToRGB) { nux::Color color = nux::Color(0.3f, 0.8f, 0.1f, 0.5f); nux::color::RedGreenBlue rgb = color; EXPECT_EQ(rgb.red, color.red); EXPECT_EQ(rgb.green, color.green); EXPECT_EQ(rgb.blue, color.blue); } TEST(TestColor, TestRandomColor) { float rmin = 1.0f; float rmax = 0.0f; float gmin = 1.0f; float gmax = 0.0f; float bmin = 1.0f; float bmax = 0.0f; for (int i = 0; i < 100; ++i) { nux::Color c = nux::color::RandomColor(); EXPECT_EQ(1.0f, c.alpha); rmin = std::min(rmin, c.red); rmax = std::max(rmax, c.red); gmin = std::min(gmin, c.green); gmax = std::max(gmax, c.green); bmin = std::min(bmin, c.blue); bmax = std::max(bmax, c.blue); } // Ultra unlikely that we create 100 identical values in a row. // The universe will end long before this happens. EXPECT_NE(rmin, rmax); EXPECT_NE(gmin, gmax); EXPECT_NE(bmin, bmax); // Values must have changed from the initial settings EXPECT_NE(1.0f, rmin); EXPECT_NE(0.0f, rmax); EXPECT_NE(1.0f, gmin); EXPECT_NE(0.0f, gmax); EXPECT_NE(1.0f, bmin); EXPECT_NE(0.0f, bmax); } } ./tests/xtest-text-entry.cpp0000644000004100000410000003462313313171755016417 0ustar www-datawww-data/* * Copyright 2010 Inalogic Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY 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 * version 3 along with this program. If not, see * * * Authored by: Jay Taoko * */ #include "Nux/Nux.h" #include "Nux/WindowThread.h" #include "Nux/VLayout.h" #include "Nux/TextEntry.h" #include "Nux/InputMethodIBus.h" #include "Nux/ProgramFramework/ProgramTemplate.h" #include "Nux/ProgramFramework/TestView.h" #include #include #include "nux_automated_test_framework.h" namespace { std::string RESET_KEY_FOCUS_AREA_MSG = "r"; std::string KEY_FOCUS_AREA_RESET_MSG = "d"; } class TextTextEntry: public ProgramTemplate { public: TextTextEntry(const char* program_name, int window_width, int window_height, int program_life_span); ~TextTextEntry(); virtual void UserInterfaceSetup(); void TextEntryClick(nux::TextEntry* text_entry); void OnActivated(); void OnCursorMoved(int); void ResetEvents(); void SendResetKeyFocusAreaMessageToProgram(); nux::TextEntry* text_entry_; bool clicked_; bool activated_; bool cursor_moved_; private: /* Handled inside the TextEntry WindowThread */ void HandleProgramMessage(const std::string &); }; TextTextEntry::TextTextEntry(const char* program_name, int window_width, int window_height, int program_life_span) : ProgramTemplate(program_name, window_width, window_height, program_life_span) , clicked_(false) , activated_(false) , cursor_moved_(false) { ResetEvents(); text_entry_ = NULL; } TextTextEntry::~TextTextEntry() { } void TextTextEntry::ResetEvents() { clicked_ = false; activated_ = false; cursor_moved_ = false; } void TextTextEntry::SendResetKeyFocusAreaMessageToProgram() { SendMessageToProgram(RESET_KEY_FOCUS_AREA_MSG); WaitForMessageFromProgram(KEY_FOCUS_AREA_RESET_MSG); } void TextTextEntry::HandleProgramMessage(const std::string &m) { if (m == RESET_KEY_FOCUS_AREA_MSG) { GetWindowThread()->GetWindowCompositor().SetKeyFocusArea(NULL); GetWindowThread()->GetWindowCompositor().SetKeyFocusArea(text_entry_); SendMessageToTest(KEY_FOCUS_AREA_RESET_MSG); } } void TextTextEntry::TextEntryClick(nux::TextEntry* text_entry) { if (text_entry_ == text_entry) { clicked_ = true; } } void TextTextEntry::OnActivated() { activated_ = true; } void TextTextEntry::OnCursorMoved(int /* position */) { cursor_moved_ = true; } void TextTextEntry::UserInterfaceSetup() { nux::VLayout* main_layout = new nux::VLayout(NUX_TRACKER_LOCATION); text_entry_ = new nux::TextEntry("", NUX_TRACKER_LOCATION); text_entry_->activated.connect(sigc::mem_fun(this, &TextTextEntry::OnActivated)); text_entry_->cursor_moved.connect(sigc::mem_fun(this, &TextTextEntry::OnCursorMoved)); text_entry_->SetFontSize(76); main_layout->AddView(text_entry_, 0, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL); main_layout->SetSpaceBetweenChildren(10); main_layout->SetContentDistribution(nux::MAJOR_POSITION_CENTER); static_cast(window_thread_)->SetLayout(main_layout); nux::ColorLayer background(nux::Color(0xFF4D4D4D)); static_cast(window_thread_)->SetWindowBackgroundPaintLayer(&background); } bool SetEngineActive (IBusBus* bus_, std::string engine) { GList* engines = ibus_bus_list_active_engines(bus_); if (!engines) return false; GList* start = engines; bool found = false; gboolean global_flag = ibus_bus_get_use_global_engine(bus_); // Iterates through the active engines do { IBusEngineDesc *engine_desc = IBUS_ENGINE_DESC (engines->data); // Found Engine, make it active! if (engine == ibus_engine_desc_get_name(engine_desc)) { found = true; // Set ibus to use global engines if (!global_flag) ibus_config_set_value(ibus_bus_get_config(bus_), "general", "use_global_engine", g_variant_new_boolean(true)); // Set and activate the engine ibus_bus_set_global_engine(bus_, engine.c_str()); } } while ((engines = g_list_next(engines)) != NULL); // Restores the global setting back to what it was ibus_config_set_value(ibus_bus_get_config(bus_), "general", "use_global_engine", g_variant_new_boolean(global_flag)); g_list_free(start); return found; } TextTextEntry* test_textentry = NULL; void TestingThread(nux::NThread* /* thread */, void* user_data) { while (test_textentry->ReadyToGo() == false) { nuxDebugMsg("Waiting to start"); nux::SleepForMilliseconds(300); } nux::SleepForMilliseconds(1300); nux::WindowThread* wnd_thread = static_cast(user_data); NuxAutomatedTestFramework test(wnd_thread); test.Startup(); test.TestReportMsg(test_textentry->text_entry_, "TextEntry created"); test_textentry->ResetEvents(); test.ViewSendMouseMotionToCenter(test_textentry->text_entry_); test.ViewSendMouseClick(0, 1); // Type "Nux" // The cursor is at the end of the line // Unset/Set the focus on the text entry // Move the cursor { test.ViewSendString("Nux"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "Nux", "Typed \"Nux\""); test_textentry->SendResetKeyFocusAreaMessageToProgram(); test_textentry->ResetEvents(); test.ViewSendLeft(); nux::SleepForMilliseconds(500); test.TestReportMsg(test_textentry->cursor_moved_, "Cursor moved."); test.ViewSendCtrlA(); test.ViewSendDelete(); } // Type "Nux" // The cursor is at the end of the line // Unset/Set the focus on the text entry // Press enter { test.ViewSendString("Nux"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "Nux", "Typed \"Nux\""); test_textentry->SendResetKeyFocusAreaMessageToProgram(); test_textentry->ResetEvents(); test.ViewSendReturn(); nux::SleepForMilliseconds(500); test.TestReportMsg(test_textentry->activated_, "Activated."); test.ViewSendCtrlA(); test.ViewSendDelete(); } // Type "Nux" // The cursor is at the end of the line // Simulate CTRL+A to select the entire text // Simulate DELETE key to delete the text { test.ViewSendString("Nux"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "Nux", "Typed \"Nux\""); test.ViewSendCtrlA(); nux::SleepForMilliseconds(500); test.TestReportMsg(test_textentry->text_entry_->GetTextSelection() == "Nux", "Selection is \"Nux\""); test.ViewSendDelete(); nux::SleepForMilliseconds(500); test.TestReportMsg(test_textentry->text_entry_->GetText() == "", "TextEntry is empty"); } // Type "0123456789" // The cursor is at the end of the line // Simulate BACKSPACE key until the text is enpty { test.ViewSendString("Ubuntu"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "Ubuntu", "Typed \"Ubuntu\""); test.ViewSendBackspace(); nux::SleepForMilliseconds(500); test.TestReportMsg(test_textentry->text_entry_->GetText() == "Ubunt", "Text is \"Ubunt\""); test.ViewSendBackspace(); nux::SleepForMilliseconds(500); test.TestReportMsg(test_textentry->text_entry_->GetText() == "Ubun", "Text is \"Ubun\""); test.ViewSendBackspace(); nux::SleepForMilliseconds(500); test.TestReportMsg(test_textentry->text_entry_->GetText() == "Ubu", "Text is \"Ubu\""); test.ViewSendBackspace(); nux::SleepForMilliseconds(500); test.TestReportMsg(test_textentry->text_entry_->GetText() == "Ub", "Text is \"Ub\""); test.ViewSendBackspace(); nux::SleepForMilliseconds(500); test.TestReportMsg(test_textentry->text_entry_->GetText() == "U", "Text is \"U\""); test.ViewSendBackspace(); nux::SleepForMilliseconds(500); test.TestReportMsg(test_textentry->text_entry_->GetText() == "", "TextEntry is empty"); } // Type "0123456789" // Move cursor to start of line // Simulate DELETE key until the text is 6789 // Simulate CTRL+A to select the entire text // Simulate DELETE key to delete the text { test.ViewSendString("0123456789"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "0123456789", "Typed \"0123456789\""); test_textentry->text_entry_->MoveCursorToLineStart(); test.ViewSendDelete(); nux::SleepForMilliseconds(500); test.TestReportMsg(test_textentry->text_entry_->GetText() == "123456789", "Text is \"123456789\""); test.ViewSendDelete(); nux::SleepForMilliseconds(500); test.TestReportMsg(test_textentry->text_entry_->GetText() == "23456789", "Text is \"23456789\""); test.ViewSendDelete(); nux::SleepForMilliseconds(500); test.TestReportMsg(test_textentry->text_entry_->GetText() == "3456789", "Text is \"3456789\""); test.ViewSendDelete(); nux::SleepForMilliseconds(500); test.TestReportMsg(test_textentry->text_entry_->GetText() == "456789", "Text is \"456789\""); test.ViewSendDelete(); nux::SleepForMilliseconds(500); test.TestReportMsg(test_textentry->text_entry_->GetText() == "56789", "Text is \"56789\""); test.ViewSendDelete(); nux::SleepForMilliseconds(500); test.TestReportMsg(test_textentry->text_entry_->GetText() == "6789", "Text \"6789\""); test.ViewSendCtrlA(); nux::SleepForMilliseconds(500); test.TestReportMsg(test_textentry->text_entry_->GetTextSelection() == "6789", "Selection is \"6789\""); test.ViewSendDelete(); nux::SleepForMilliseconds(500); test.TestReportMsg(test_textentry->text_entry_->GetText() == "", "TextEntry is empty"); } // Send invalid keys { test.ViewSendKeyCombo(XK_Control_L, 0, 0, 'r'); test.TestReportMsg(test_textentry->text_entry_->GetText() == "", "Invalid key: TextEntry is empty"); nux::SleepForMilliseconds(500); test.ViewSendKeyCombo(XK_Control_L, 0, 0, 'w'); test.TestReportMsg(test_textentry->text_entry_->GetText() == "", "Invalid key: TextEntry is empty"); nux::SleepForMilliseconds(500); test.ViewSendKeyCombo(XK_Control_L, 0, 0, 'g'); test.TestReportMsg(test_textentry->text_entry_->GetText() == "", "Invalid key: TextEntry is empty"); nux::SleepForMilliseconds(500); test.ViewSendKeyCombo(XK_Control_L, 0, 0, 'h'); test.TestReportMsg(test_textentry->text_entry_->GetText() == "", "Invalid key: TextEntry is empty"); nux::SleepForMilliseconds(500); nux::SleepForMilliseconds(500); test.ViewSendCtrlA(); test.ViewSendDelete(); } // Toggle IBus // Type "qwerty" // Simulate key '1' to select the first IM option { // CTRL+Space to initiate iBus //test.ViewSendIBusToggle(); IBusBus* bus_; ibus_init(); bus_ = ibus_bus_new(); bool active = false; // Test for ibus-pinyin if (bus_ && SetEngineActive(bus_,"pinyin")) { // Type random stuff { test.ViewSendString("ninhao"); nux::SleepForMilliseconds(500); test.TestReportMsg(test_textentry->text_entry_->GetText() == "", "TextEntry is only Preedit"); test.ViewSendChar('1'); nux::SleepForMilliseconds(500); test.TestReportMsg(test_textentry->text_entry_->GetText() == "您好", "TextEntry is \"您好\""); test.ViewSendCtrlA(); nux::SleepForMilliseconds(500); test.ViewSendDelete(); nux::SleepForMilliseconds(500); } // Testing Cursor in the preedit window { test.ViewSendString("ming"); nux::SleepForMilliseconds(500); test.TestReportMsg(test_textentry->text_entry_->GetText() == "", "TextEntry is only Preedit"); test.ViewSendLeft(); nux::SleepForMilliseconds(500); test.ViewSendDelete(); nux::SleepForMilliseconds(500); test.ViewSendChar('1'); nux::SleepForMilliseconds(500); test.TestReportMsg(test_textentry->text_entry_->GetText() == "民", "TextEntry is \"民\""); test.ViewSendCtrlA(); nux::SleepForMilliseconds(500); test.ViewSendDelete(); nux::SleepForMilliseconds(500); } active = true; } // Test for ibus-hangul if (bus_ && SetEngineActive(bus_,"hangul")) { // Test for the the space in ibus-hangul working correctlly { test.ViewSendString("asd abc "); nux::SleepForMilliseconds(500); test.TestReportMsg(test_textentry->text_entry_->GetText() == "ㅁㄴㅇ 뮻 ", "TextEntry is \"ㅁㄴㅇ 뮻 \""); test.ViewSendCtrlA(); nux::SleepForMilliseconds(500); test.ViewSendDelete(); nux::SleepForMilliseconds(500); } active = true; } // Checking for ibus-anthy - Japanese if (bus_ && SetEngineActive(bus_,"anthy")) { { test.ViewSendString("shisutemu "); nux::SleepForMilliseconds(500); test.TestReportMsg(test_textentry->text_entry_->GetText() == "", "TextEntry is only Preedit"); // Ctrl + J commits for ibus-anthy test.ViewSendKeyCombo(XK_Control_L, 0, 0, 'j'); nux::SleepForMilliseconds(500); test.TestReportMsg(test_textentry->text_entry_->GetText() == "システム", "TextEntry is \"システム\""); test.ViewSendCtrlA(); nux::SleepForMilliseconds(500); test.ViewSendDelete(); nux::SleepForMilliseconds(500); } active = true; } g_object_unref (bus_); // CTRL+Space to deactivate iBus if (active) test.ViewSendIBusToggle(); } if (test.WhenDoneTerminateProgram()) { wnd_thread->ExitMainLoop(); } nuxDebugMsg("Exit testing thread"); } int main() { XInitThreads(); test_textentry = new TextTextEntry("Text Entry", 600, 200, 40000); test_textentry->Startup(); test_textentry->UserInterfaceSetup(); nux::SystemThread* test_thread = nux::CreateSystemThread(NULL, &TestingThread, test_textentry->GetWindowThread()); test_thread->Start(test_textentry); test_textentry->Run(); delete test_thread; delete test_textentry; return 0; } ./tests/gtest-nux-utils.h0000644000004100000410000000235513313171755015665 0ustar www-datawww-data#ifndef TEST_UTILS_H #define TEST_UTILS_H #include #include namespace { class Utils { public: static void WaitUntil(bool& success, unsigned int max_wait = 10) { bool timeout_reached = false; guint32 timeout_id = ScheduleTimeout(&timeout_reached, max_wait * 1000); while (!success && !timeout_reached) g_main_context_iteration(g_main_context_get_thread_default(), TRUE); if (success) g_source_remove(timeout_id); EXPECT_TRUE(success); } static guint32 ScheduleTimeout(bool* timeout_reached, unsigned int timeout_duration = 10) { return g_timeout_add(timeout_duration, TimeoutCallback, timeout_reached); } static void WaitForTimeout(unsigned int timeout_duration = 10) { WaitForTimeoutMSec(timeout_duration * 1000); } static void WaitForTimeoutMSec(unsigned int timeout_duration = 10) { bool timeout_reached = false; guint32 timeout_id = ScheduleTimeout(&timeout_reached, timeout_duration); while (!timeout_reached) g_main_context_iteration(g_main_context_get_thread_default(), TRUE); g_source_remove(timeout_id); } private: static gboolean TimeoutCallback(gpointer data) { *(bool*)data = true; return FALSE; }; }; } #endif ./tests/xtest-hlayout-key-navigation.cpp0000644000004100000410000001404313313171755020676 0ustar www-datawww-data/* * Copyright 2011 Inalogic Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY 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 * version 3 along with this program. If not, see * * * Authored by: Andrea Azzarone * */ #include "Nux/Nux.h" #include "Nux/WindowThread.h" #include "Nux/HLayout.h" #include "Nux/ProgramFramework/ProgramTemplate.h" #include "Nux/ProgramFramework/TestView.h" #include #include #include "nux_automated_test_framework.h" unsigned int const NUM_VIEWS = 5; unsigned int const ID_UNFOCUSABLE_VIEW = 2; // Please don't make this the last/first one :) class HLayoutKeyNavigationTest : public ProgramTemplate { public: HLayoutKeyNavigationTest(const char* program_name, int window_width, int window_height, int program_life_span); ~HLayoutKeyNavigationTest(); virtual void UserInterfaceSetup(); nux::TestView* CreateView(); void AddView(nux::TestView* view); nux::HLayout* hlayout_; nux::TestView* views_[NUM_VIEWS]; }; HLayoutKeyNavigationTest::HLayoutKeyNavigationTest(const char* program_name, int window_width, int window_height, int program_life_span) : ProgramTemplate(program_name, window_width, window_height, program_life_span) { } HLayoutKeyNavigationTest::~HLayoutKeyNavigationTest() { } nux::TestView* HLayoutKeyNavigationTest::CreateView() { nux::TestView* view = new nux::TestView(); return view; } void HLayoutKeyNavigationTest::AddView(nux::TestView* view) { hlayout_->AddView(view, 1); } void HLayoutKeyNavigationTest::UserInterfaceSetup() { hlayout_ = new nux::HLayout(NUX_TRACKER_LOCATION); hlayout_->SetPadding(20, 20); hlayout_->SetSpaceBetweenChildren(10); for (unsigned int i=0; ican_focus_ = false; nux::GetWindowCompositor().SetKeyFocusArea(views_[0]); static_cast(window_thread_)->SetLayout(hlayout_); nux::ColorLayer background(nux::Color(0xFF4D4D4D)); static_cast(window_thread_)->SetWindowBackgroundPaintLayer(&background); } HLayoutKeyNavigationTest* key_navigation_test = NULL; void TestingThread(nux::NThread* /* thread */, void* user_data) { while (key_navigation_test->ReadyToGo() == false) { nuxDebugMsg("Waiting to start"); nux::SleepForMilliseconds(300); } nux::SleepForMilliseconds(1000); nux::WindowThread* wnd_thread = static_cast(user_data); NuxAutomatedTestFramework test(wnd_thread); test.Startup(); // Set the mouse at coordinates (0, 0) (top-left corner) on the display test.PutMouseAt(0, 0); test.TestReportMsg(key_navigation_test->hlayout_, "TestView created"); test.TestReportMsg(key_navigation_test->views_[0]->has_focus_, "Top left tile has key focus"); // Right key for (unsigned int i=0; iviews_[i]->has_focus_, "Right: key focus out"); if ((i+1) == ID_UNFOCUSABLE_VIEW) { test.TestReportMsg(!key_navigation_test->views_[i+1]->has_focus_, "Right: key focus skipped"); test.TestReportMsg(key_navigation_test->views_[i+2]->has_focus_, "Right: key focus in"); ++i; } else { test.TestReportMsg(key_navigation_test->views_[i+1]->has_focus_, "Right: key focus in"); } } // Another right key, should do nothing test.SendFakeKeyEvent(XK_Right, 0); nux::SleepForMilliseconds(500); test.TestReportMsg(key_navigation_test->views_[NUM_VIEWS-1]->has_focus_, "Rigth key, last element"); // Left key for (unsigned int i=NUM_VIEWS-1; i>0; --i) { test.SendFakeKeyEvent(XK_Left, 0); nux::SleepForMilliseconds(500); test.TestReportMsg(!key_navigation_test->views_[i]->has_focus_, "Left: key focus out"); if ((i-1) == ID_UNFOCUSABLE_VIEW) { test.TestReportMsg(!key_navigation_test->views_[i-1]->has_focus_, "Left: key focus skipped"); test.TestReportMsg(key_navigation_test->views_[i-2]->has_focus_, "Left: key focus in"); --i; } else { test.TestReportMsg(key_navigation_test->views_[i-1]->has_focus_, "Left: key focus in"); } } // Another Left key, should do nothing test.SendFakeKeyEvent(XK_Left, 0); nux::SleepForMilliseconds(500); test.TestReportMsg(key_navigation_test->views_[0]->has_focus_, "Left key, fist element"); // Up key, should do nothing test.SendFakeKeyEvent(XK_Up, 0); nux::SleepForMilliseconds(500); test.TestReportMsg(key_navigation_test->views_[0]->has_focus_, "Up key"); // Down key, should do nothing test.SendFakeKeyEvent(XK_Down, 0); nux::SleepForMilliseconds(500); test.TestReportMsg(key_navigation_test->views_[0]->has_focus_, "Down key"); if (test.WhenDoneTerminateProgram()) { nux::SleepForMilliseconds(1000); wnd_thread->ExitMainLoop(); } nuxDebugMsg("Exit testing thread"); } int main() { XInitThreads(); key_navigation_test = new HLayoutKeyNavigationTest("Key navigation Test", 500, 400, 8000); key_navigation_test->Startup(); key_navigation_test->UserInterfaceSetup(); nux::SystemThread* test_thread = nux::CreateSystemThread(key_navigation_test->GetWindowThread(), &TestingThread, key_navigation_test->GetWindowThread()); test_thread->Start(key_navigation_test); key_navigation_test->Run(); delete test_thread; delete key_navigation_test; return 0; } ./tests/gtest-nux-axisdecelerationanimation.cpp0000644000004100000410000000534713313171755022307 0ustar www-datawww-data/* * Copyright (C) 2012 - Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Daniel d'Andrada */ #include #include using namespace nux; TEST(AxisDecelerationAnimation, ComesToAHalt) { AxisDecelerationAnimation animation; float min_pos = 0.0f; float max_pos = 100.0f; float start_pos = 10.0f; animation.SetMinimumPosition(min_pos); animation.SetMaximumPosition(max_pos); animation.SetStartPosition(start_pos); animation.SetStartVelocity(100.0f); animation.SetOvershootBoundsEnabled(false); animation.Start(); float last_pos = start_pos; float last_movement = 0.0f; for (int i = 0; i < 1000 && animation.IsActive(); ++i) { animation.Update(16); /* Check that it's moving along the velocity direction */ ASSERT_TRUE(animation.GetPosition() > last_pos); float movement = animation.GetPosition() - last_pos; if (i > 0) { /* Check that it's decelerating */ ASSERT_TRUE(movement - last_movement); } last_pos = animation.GetPosition(); last_movement = movement; } /* Check that it came to a halt */ ASSERT_FALSE(animation.IsActive()); } TEST(AxisDecelerationAnimation, StopAtBounds) { AxisDecelerationAnimation animation; float min_pos = 0.0f; float max_pos = 100.0f; float start_pos = 50.0f; animation.SetMinimumPosition(min_pos); animation.SetMaximumPosition(max_pos); /* test different velocities on both directions */ std::vector velocities; for (int i = 1; i <= 100; ++i) { velocities.push_back(i); } for (int i = -1; i >= -100; --i) { velocities.push_back(i); } for (size_t i = 0; i < velocities.size(); ++i) { animation.SetStartPosition(start_pos); animation.SetStartVelocity(velocities[i]); animation.Start(); for (int j = 0; j < 1000 && animation.IsActive(); ++j) { animation.Update(16); } ASSERT_FALSE(animation.IsActive()); ASSERT_LE(animation.GetPosition(), max_pos); ASSERT_GE(animation.GetPosition(), min_pos); } } ./tests/gtest-nux-cairo-wrapper.cpp0000644000004100000410000001137213313171755017632 0ustar www-datawww-data/* * Copyright (C) 2011 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as * published by the Free Software Foundation. * * This program 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 this program. If not, see . * * Authored by: Mirco Müller #include #include "Nux/CairoWrapper.h" #include #include #include typedef void (*TestFunc)(void); nux::TimerFunctor* g_timer = NULL; nux::TimerHandle g_handler = NULL; void callback_one (nux::Geometry const& geom, cairo_t* cr) { if (cairo_status (cr) != CAIRO_STATUS_SUCCESS) return; cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); cairo_paint (cr); cairo_set_operator (cr, CAIRO_OPERATOR_OVER); cairo_scale (cr, 1.0, 1.0); cairo_set_source_rgba (cr, 1.0, 0.5, 0.25, 1.0); cairo_rectangle (cr, 5.0, 5.0, (double) geom.width - 10.0, (double) geom.height - 10.0); cairo_fill (cr); } void callback_two (nux::Geometry const& geom, cairo_t* cr) { if (cairo_status (cr) != CAIRO_STATUS_SUCCESS) return; cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); cairo_paint (cr); cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); cairo_scale (cr, 1.0, 1.0); cairo_set_source_rgba (cr, 0.25, 0.5, 1.0, 1.0); cairo_rectangle (cr, 2.0, 2.0, (double) geom.width - 4.0, (double) geom.height - 4.0); cairo_fill (cr); } void terminate (void* data) { nux::WindowThread* thread = NUX_STATIC_CAST (nux::WindowThread*, data); thread->ExitMainLoop(); } void init (nux::NThread* /* thread */, void* data) { TestFunc func = (TestFunc) data; (func) (); g_timer = new nux::TimerFunctor (); g_timer->tick.connect (sigc::ptr_fun (&terminate)); g_handler = nux::GetTimer().AddOneShotTimer (100, g_timer, nux::GetWindowThread ()); } void run_test (TestFunc func) { nux::WindowThread* wt = NULL; wt = nux::CreateGUIThread (TEXT ("Canvas Test"), 400, 400, 0, &init, (void*) func); wt->Run (NULL); delete wt; delete g_timer; g_timer = NULL; } void test_construction () { nux::Geometry geom_one = {0, 0, 100, 100}; nux::Geometry geom_two = {0, 0, 200, 200}; nux::CairoWrapper wrapper (geom_one, sigc::ptr_fun (callback_one)); EXPECT_FALSE (wrapper.Invalidate (geom_one)); EXPECT_TRUE (wrapper.Invalidate (geom_two)); } void test_invalidate () { nux::Geometry geom_one = {0, 0, 100, 100}; nux::Geometry geom_two = {0, 0, 150, 75}; nux::CairoWrapper wrapper (geom_one, sigc::ptr_fun (callback_one)); EXPECT_FALSE (wrapper.Invalidate (geom_one)); EXPECT_TRUE (wrapper.Invalidate (geom_two)); } void test_get_cairo_surface () { nux::Geometry geom = {0, 0, 100, 100}; nux::CairoWrapper wrapper (geom, sigc::ptr_fun (callback_one)); cairo_surface_t* surf = wrapper.GetCairoSurface (); EXPECT_FALSE (surf == NULL); } void test_get_cairo_context () { nux::Geometry geom = {0, 0, 100, 100}; nux::CairoWrapper wrapper (geom, sigc::ptr_fun (callback_one)); EXPECT_TRUE (wrapper.GetCairoContext ()); } void test_dump_to_file () { nux::Geometry geom = {0, 0, 100, 100}; nux::CairoWrapper wrapper (geom, sigc::ptr_fun (callback_one)); EXPECT_TRUE (wrapper.DumpToFile ("/tmp/dump.png")); } void test_get_texture () { nux::Geometry geom = {0, 0, 100, 100}; nux::CairoWrapper wrapper (geom, sigc::ptr_fun (callback_one)); EXPECT_TRUE (wrapper.GetTexture ()); } void test_get_bitmap () { nux::Geometry geom = {0, 0, 100, 100}; nux::CairoWrapper wrapper (geom, sigc::ptr_fun (callback_one)); EXPECT_TRUE (wrapper.GetBitmap ()); } namespace { TEST (DISABLED_TestCairoWrapper, TestConstruction) { run_test (test_construction); } TEST (DISABLED_TestCairoWrapper, TestInvalidate) { run_test (test_invalidate); } TEST (DISABLED_TestCairoWrapper, TestGetCairoSurface) { run_test (test_get_cairo_surface); } TEST (DISABLED_TestCairoWrapper, TestGetCairoContext) { run_test (test_get_cairo_context); } TEST (DISABLED_TestCairoWrapper, TestDumpToFile) { run_test (test_dump_to_file); } TEST (DISABLED_TestCairoWrapper, TestGetTexture) { run_test (test_get_texture); } TEST (DISABLED_TestCairoWrapper, TestGetBitmap) { run_test (test_get_bitmap); } } ./tests/dummy-xorg-test-runner.sh0000755000004100000410000000405613313171755017353 0ustar www-datawww-data#!/bin/bash # Copyright (C) 2013 Canonical Ltd # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License version 3 as # published by the Free Software Foundation. # # This program 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 this program. If not, see . # # Authored by: Marco Trevisan MAX_WAIT=10 binary=$(which $1) if [ -z "$binary" ]; then if [ -z "$1" ]; then echo "Empty command submitted" elif [ ! -x "$1" ]; then echo "The provided $1 is not executable" fi exit 1 fi logfile=$(mktemp -t dummy.Xorg.log.XXXXXXXX) conffile=$(mktemp -t dummy.Xorg.conf.XXXXXXXX) cat << 'END_DUMMY_XORG_CONF' > $conffile Section "Monitor" Identifier "Dummy Monitor" EndSection Section "Device" Identifier "Dummy Card" Driver "dummy" EndSection Section "Screen" DefaultDepth 24 Identifier "Dummy Screen" Device "Dummy Card" Monitor "Dummy Monitor" EndSection END_DUMMY_XORG_CONF function do_cleanup() { if [ -n "$x_pid" ] && (kill -0 $x_pid &> /dev/null); then kill $x_pid; fi rm $conffile rm $logfile* } trap "do_cleanup; exit 1" SIGHUP SIGINT SIGSEGV SIGTERM dpy=$((RANDOM+1)) export DISPLAY=:`for id in $(seq $dpy $((dpy+50))); do test -e /tmp/.X$id-lock || { echo $id; exit 0; }; done; exit 1` Xorg $DISPLAY -config $conffile -logfile $logfile &> /dev/null & x_pid=$! start_time=$(date +%s) while [ ! -e /tmp/.X${DISPLAY:1}-lock ] && [ $(($(date +%s) - start_time)) -le $MAX_WAIT ]; do sleep 0.1 done if [ $(($(date +%s) - start_time)) -gt $MAX_WAIT ]; then echo "The X server was not able to run in time" if [ -s $logfile ]; then echo "Xorg Log:" cat $logfile fi do_cleanup exit 1 fi shift $binary $@ ret_val=$? do_cleanup exit $ret_val ./tests/gtest-nux-gesturebroker.cpp0000644000004100000410000001251313313171755017740 0ustar www-datawww-data/* * Copyright (C) 2012 - Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Daniel d'Andrada */ #include #include "Nux/GestureBroker.h" #include "FakeGestureEvent.h" using namespace nux; namespace { class SimpleTarget : public nux::GestureTarget { public: SimpleTarget(int id) : id(id) {} virtual ~SimpleTarget() {} virtual GestureDeliveryRequest GestureEvent(const nux::GestureEvent &/* event */) { return GestureDeliveryRequest::NONE; } void Die() { died.emit(*this); } int id; }; class SimpleGestureBroker : public nux::GestureBroker { public: virtual ~SimpleGestureBroker() {} std::vector targets_to_be_found; private: std::vector virtual FindGestureTargets(const nux::GestureEvent &/* event */) { return targets_to_be_found; } }; } class GestureBrokerTest : public ::testing::Test { public: GestureBrokerTest() { } SimpleGestureBroker gesture_broker; nux::FakeGestureEvent fake_event; }; TEST_F(GestureBrokerTest, RejectGestureIfTargetBecomesUnavailable) { std::shared_ptr target (new SimpleTarget (0)); nux::TouchPoint touch (0, 1.0f, 1.0f); gesture_broker.targets_to_be_found.push_back (target); g_gesture_acceptance[0] = 0; fake_event.type = nux::EVENT_GESTURE_BEGIN; fake_event.gesture_id = 0; fake_event.gesture_classes = nux::TOUCH_GESTURE; fake_event.timestamp = 0; fake_event.touches.clear(); fake_event.touches.push_back(touch); fake_event.is_construction_finished = false; gesture_broker.ProcessGestureBegin(fake_event.ToGestureEvent()); ASSERT_EQ (0, g_gesture_acceptance[0]); /* This target is now unavailable */ target->Die(); /* Reject the gesture */ EXPECT_EQ (-1, g_gesture_acceptance[0]); } /* Let's simulate a situation where a user lays 4 fingers over a trackpad. 5 different gesture candidates will be generated out of this physical action. if touch ids are 0,1,2 and 3, the following gestures will be generated: {0,1,2}, {0,1,3}, {0,2,3}, {1,2,3} and {0,1,2,3} The gesture canditates with the most fingers must prevail and the others must be rejected. */ TEST_F(GestureBrokerTest, GestureWithMostTouchesTakesPrecedence) { nux::TouchPoint all_touches[4]; all_touches[0].id = 0; all_touches[0].x = all_touches[0].y = 1.0f; all_touches[1].id = 1; all_touches[1].x = all_touches[0].y = 2.0f; all_touches[2].id = 2; all_touches[2].x = all_touches[0].y = 3.0f; all_touches[3].id = 3; all_touches[3].x = all_touches[0].y = 4.0f; gesture_broker.targets_to_be_found.push_back( ShPtGestureTarget(new SimpleTarget(0))); for (int i = 0; i < 5; ++i) g_gesture_acceptance[i] = 0; // begin gesture 0 with touches {0,1,2} fake_event.type = nux::EVENT_GESTURE_BEGIN; fake_event.gesture_id = 0; fake_event.gesture_classes = nux::TOUCH_GESTURE; fake_event.timestamp = 0; fake_event.touches.clear(); fake_event.touches.push_back(all_touches[0]); fake_event.touches.push_back(all_touches[1]); fake_event.touches.push_back(all_touches[2]); fake_event.is_construction_finished = false; gesture_broker.ProcessGestureBegin(fake_event.ToGestureEvent()); // begin gesture 1 with touches {0,1,3} fake_event.gesture_id = 1; fake_event.touches.clear(); fake_event.touches.push_back(all_touches[0]); fake_event.touches.push_back(all_touches[1]); fake_event.touches.push_back(all_touches[3]); gesture_broker.ProcessGestureBegin(fake_event.ToGestureEvent()); // begin gesture 2 with touches {0,2,3} fake_event.gesture_id = 2; fake_event.touches.clear(); fake_event.touches.push_back(all_touches[0]); fake_event.touches.push_back(all_touches[2]); fake_event.touches.push_back(all_touches[3]); gesture_broker.ProcessGestureBegin(fake_event.ToGestureEvent()); // begin gesture 3 with touches {1,2,3} fake_event.gesture_id = 3; fake_event.touches.clear(); fake_event.touches.push_back(all_touches[1]); fake_event.touches.push_back(all_touches[2]); fake_event.touches.push_back(all_touches[3]); gesture_broker.ProcessGestureBegin(fake_event.ToGestureEvent()); // begin gesture 4 with touches {0,1,2,3} fake_event.gesture_id = 4; fake_event.touches.clear(); fake_event.touches.push_back(all_touches[0]); fake_event.touches.push_back(all_touches[1]); fake_event.touches.push_back(all_touches[2]); fake_event.touches.push_back(all_touches[3]); gesture_broker.ProcessGestureBegin(fake_event.ToGestureEvent()); ASSERT_EQ(-1, g_gesture_acceptance[0]); ASSERT_EQ(-1, g_gesture_acceptance[1]); ASSERT_EQ(-1, g_gesture_acceptance[2]); ASSERT_EQ(-1, g_gesture_acceptance[3]); ASSERT_EQ(0, g_gesture_acceptance[4]); } ./tests/gtest-nux-emmetrics.cpp0000644000004100000410000000735413313171755017054 0ustar www-datawww-data#include #include #include "Nux/Nux.h" #include "Nux/EMMetrics.h" namespace { TEST(TestMetrics, TestCreate) { // Test fallback (no display) of constructor, DPI of 96.0 will be used nux::EMMetrics* metrics5 = new nux::EMMetrics(NULL, 0, 5.0); nux::EMMetrics* metrics10 = new nux::EMMetrics(NULL, 0, 10.0); nux::EMMetrics* metrics15 = new nux::EMMetrics(NULL, 0, 15.0); nux::EMMetrics* metrics20 = new nux::EMMetrics(NULL, 0, 20.0); // Test conversion from pixel to EM (testing fallback-case) 5-point font EXPECT_EQ(metrics5->Pixel2EM(30), 4.5); EXPECT_EQ(metrics5->Pixel2EM(25), 3.75); EXPECT_EQ(metrics5->Pixel2EM(20), 3.0); EXPECT_EQ(metrics5->Pixel2EM(15), 2.25); EXPECT_EQ(metrics5->Pixel2EM(10), 1.5); EXPECT_EQ(metrics5->Pixel2EM(5), 0.75); EXPECT_EQ(metrics5->Pixel2EM(0), 0.0); // Test conversion from EM to pixel (testing fallback-case) 5-point font EXPECT_EQ(metrics5->EM2Pixel(4.5), 30); EXPECT_EQ(metrics5->EM2Pixel(3.75), 25); EXPECT_EQ(metrics5->EM2Pixel(3.0), 20); EXPECT_EQ(metrics5->EM2Pixel(2.25), 15); EXPECT_EQ(metrics5->EM2Pixel(1.5), 10); EXPECT_EQ(metrics5->EM2Pixel(0.75), 5); EXPECT_EQ(metrics5->EM2Pixel(0.0), 0); // Test conversion from pixel to EM (testing fallback-case) 10-point font EXPECT_EQ(metrics10->Pixel2EM(30), 2.25); EXPECT_EQ(metrics10->Pixel2EM(25), 1.875); EXPECT_EQ(metrics10->Pixel2EM(20), 1.5); EXPECT_EQ(metrics10->Pixel2EM(15), 1.125); EXPECT_EQ(metrics10->Pixel2EM(10), 0.75); EXPECT_EQ(metrics10->Pixel2EM(5), 0.375); EXPECT_EQ(metrics10->Pixel2EM(0), 0.0); // Test conversion from EM to pixel (testing fallback-case) 10-point font EXPECT_EQ(metrics10->EM2Pixel(2.25), 30); EXPECT_EQ(metrics10->EM2Pixel(1.875), 25); EXPECT_EQ(metrics10->EM2Pixel(1.5), 20); EXPECT_EQ(metrics10->EM2Pixel(1.125), 15); EXPECT_EQ(metrics10->EM2Pixel(0.75), 10); EXPECT_EQ(metrics10->EM2Pixel(0.375), 5); EXPECT_EQ(metrics10->EM2Pixel(0.0), 0); // Test conversion from pixel to EM (testing fallback-case) 15-point font EXPECT_EQ(metrics15->Pixel2EM(30), 1.5); EXPECT_EQ(metrics15->Pixel2EM(25), 1.25); EXPECT_EQ(metrics15->Pixel2EM(20), 1.0); EXPECT_EQ(metrics15->Pixel2EM(15), 0.75); EXPECT_EQ(metrics15->Pixel2EM(10), 0.5); EXPECT_EQ(metrics15->Pixel2EM(5), 0.25); EXPECT_EQ(metrics15->Pixel2EM(0), 0.0); // Test conversion from EM to pixel (testing fallback-case) 15-point font EXPECT_EQ(metrics15->EM2Pixel(1.5), 30); EXPECT_EQ(metrics15->EM2Pixel(1.25), 25); EXPECT_EQ(metrics15->EM2Pixel(1.0), 20); EXPECT_EQ(metrics15->EM2Pixel(0.75), 15); EXPECT_EQ(metrics15->EM2Pixel(0.5), 10); EXPECT_EQ(metrics15->EM2Pixel(0.25), 5); EXPECT_EQ(metrics15->EM2Pixel(0.0), 0); // Test conversion from pixel to EM (testing fallback-case) 20-point font EXPECT_EQ(metrics20->Pixel2EM(30), 1.125); EXPECT_EQ(metrics20->Pixel2EM(25), 0.9375); EXPECT_EQ(metrics20->Pixel2EM(20), 0.75); EXPECT_EQ(metrics20->Pixel2EM(15), 0.5625); EXPECT_EQ(metrics20->Pixel2EM(10), 0.375); EXPECT_EQ(metrics20->Pixel2EM(5), 0.1875); EXPECT_EQ(metrics20->Pixel2EM(0), 0.0); // Test conversion from EM to pixel (testing fallback-case) 20-point font EXPECT_EQ(metrics20->EM2Pixel(1.125), 30); EXPECT_EQ(metrics20->EM2Pixel(0.9375), 25); EXPECT_EQ(metrics20->EM2Pixel(0.75), 20); EXPECT_EQ(metrics20->EM2Pixel(0.5625), 15); EXPECT_EQ(metrics20->EM2Pixel(0.375), 10); EXPECT_EQ(metrics20->EM2Pixel(0.1875), 5); EXPECT_EQ(metrics20->EM2Pixel(0.0), 0); delete metrics5; delete metrics10; delete metrics15; delete metrics20; } } // unnamed namespace ./tests/gtest-nux-globals.h0000644000004100000410000000022013313171755016135 0ustar www-datawww-data#ifndef GTEST_NUX_GLOBALS_H #define GTEST_NUX_GLOBALS_H #include extern gint64 g_fake_monotonic_time; #endif // GTEST_NUX_GLOBALS_H ./tests/gtest-nuxcore-animation.cpp0000644000004100000410000006062413313171755017713 0ustar www-datawww-data/* * Now before you go changing any of the advance or tick values in the file, * it is worthwhile considering the impact that you'll see on 32 vs 64 bit * machines. Having a 1000 ms animation with 10 x 100ms ticks on a 64 bit * machine will seem to give fine integer interpolations to be exactly what is * expected, but on a 32 bit machine there are rounding errors. This is why * in a number of the tests, we'll advance 101 or 201 ms instead of a nice * round number. */ #include "NuxCore/Animation.h" #include "NuxCore/AnimationController.h" #include "NuxCore/EasingCurve.h" #include "NuxCore/Property.h" #include "NuxCore/PropertyAnimation.h" #include "NuxCore/Point.h" #include "NuxCore/Rect.h" #include "NuxCore/Colors.h" #include "Helpers.h" #include namespace na = nux::animation; namespace nt = nux::testing; using namespace testing; namespace { TEST(TestAnimationController, NoInstance) { ASSERT_THAT(na::Controller::Instance(), Eq(nullptr)); } class MockController : public na::Controller { MOCK_METHOD1(AddAnimation, void(na::Animation*)); MOCK_METHOD1(RemoveAnimation, void(na::Animation*)); MOCK_CONST_METHOD0(HasRunningAnimations, bool()); }; TEST(TestAnimationController, CreatingControllerSetsInstance) { StrictMock controller; ASSERT_THAT(na::Controller::Instance(), Eq(&controller)); } TEST(TestAnimationController, DestroyingControllerUnsetsInstance) { { StrictMock controller; } ASSERT_THAT(na::Controller::Instance(), Eq(nullptr)); } TEST(TestAnimationController, CreatingSecondControllerEmitsWarning) { nt::CaptureLogOutput log_output; StrictMock controller; { StrictMock controller2; // Second controller doesn't set controller ASSERT_THAT(na::Controller::Instance(), Eq(&controller)); } // Destructor of second controller doesn't unset instance. ASSERT_THAT(na::Controller::Instance(), Eq(&controller)); std::string log_text = log_output.GetOutput(); EXPECT_THAT(log_text, StartsWith("WARN")); EXPECT_THAT(log_text, HasSubstr("nux.animation")); EXPECT_THAT(log_text, HasSubstr("Multiple animation controllers created")); } class MockAnimationController : public na::AnimationController { public: MockAnimationController(na::TickSource& tick_source) : na::AnimationController(tick_source) {} // tick is expected to be ever increasing virtual void OnTick(long long tick) { ticks.push_back(tick); } std::vector ticks; }; TEST(TestAnimationController, TicksOnSourceAreListenedTo) { na::TickSource source; MockAnimationController controller(source); source.tick.emit(10); source.tick.emit(100); source.tick.emit(10000); ASSERT_THAT(controller.ticks.size(), Eq(3)); ASSERT_THAT(controller.ticks[0], Eq(10)); ASSERT_THAT(controller.ticks[1], Eq(100)); ASSERT_THAT(controller.ticks[2], Eq(10000)); } TEST(TestAnimationController, TicksAfterControllerDtorIgnored) { na::TickSource source; { MockAnimationController controller(source); source.tick.emit(10); } source.tick.emit(100); } /** * Animation base class testing connections to the AnimationController and * basic control functions. */ class MockAnimation : public na::Animation { public: MOCK_CONST_METHOD0(Duration, int()); MOCK_CONST_METHOD0(CurrentTimePosition, int()); MOCK_METHOD1(Advance, void(int)); MOCK_METHOD0(Restart, void()); }; TEST(TestAnimationController, HasRunningAnimations) { na::TickSource source; MockAnimationController controller(source); ASSERT_FALSE(controller.HasRunningAnimations()); NiceMock animation1; NiceMock animation2; controller.AddAnimation(&animation1); controller.AddAnimation(&animation2); ASSERT_FALSE(controller.HasRunningAnimations()); animation1.Start(); ASSERT_TRUE(controller.HasRunningAnimations()); animation1.Pause(); ASSERT_FALSE(controller.HasRunningAnimations()); animation1.Stop(); ASSERT_FALSE(controller.HasRunningAnimations()); } TEST(TestAnimationController, RemoveValueInTick) { na::TickSource source; na::AnimationController controller(source); std::shared_ptr> animation1(new na::AnimateValue(0,100,1000)); std::shared_ptr> animation2(new na::AnimateValue(0,100,1000)); int i = 0; animation1->updated.connect([this, &i, &animation2](int) { if (++i == 2) { animation2.reset(); } }); animation1->Start(); animation2->Start(); source.tick.emit(10000); ASSERT_THAT(animation1->CurrentState(), Eq(na::Animation::Running)); ASSERT_TRUE(animation2.get() == nullptr); animation1.reset(); animation2.reset(); } TEST(TestAnimation, TestInitialState) { MockAnimation animation; ASSERT_THAT(animation.CurrentState(), Eq(na::Animation::Stopped)); } TEST(TestAnimation, TestStarting) { NiceMock animation; // don't care about restart here animation.Start(); ASSERT_THAT(animation.CurrentState(), Eq(na::Animation::Running)); } TEST(TestAnimation, TestStoppingEmitsFinished) { NiceMock animation; // don't care about restart here nt::TestCallback finished_called; animation.finished.connect(finished_called.sigc_callback()); animation.Start(); animation.Stop(); ASSERT_THAT(animation.CurrentState(), Eq(na::Animation::Stopped)); ASSERT_TRUE(finished_called.happened); } TEST(TestAnimation, TestDestructorStops) { na::TickSource source; MockAnimationController controller(source); nt::TestCallback finished_called; { NiceMock animation; // don't care about restart here animation.finished.connect(finished_called.sigc_callback()); animation.Start(); ASSERT_TRUE(controller.HasRunningAnimations()); } ASSERT_FALSE(controller.HasRunningAnimations()); } TEST(TestAnimation, TestStoppingStoppedDoesntEmitsFinished) { NiceMock animation; // don't care about restart here nt::TestCallback finished_called; animation.finished.connect(finished_called.sigc_callback()); animation.Stop(); ASSERT_THAT(animation.CurrentState(), Eq(na::Animation::Stopped)); ASSERT_FALSE(finished_called.happened); } TEST(TestAnimation, TestCantPauseStopped) { NiceMock animation; // don't care about restart here animation.Pause(); ASSERT_THAT(animation.CurrentState(), Eq(na::Animation::Stopped)); } TEST(TestAnimation, TestPause) { NiceMock animation; // don't care about restart here animation.Start(); animation.Pause(); ASSERT_THAT(animation.CurrentState(), Eq(na::Animation::Paused)); } TEST(TestAnimation, TestResume) { NiceMock animation; // don't care about restart here animation.Start(); animation.Pause(); animation.Resume(); ASSERT_THAT(animation.CurrentState(), Eq(na::Animation::Running)); } TEST(TestAnimation, TestResumeStarted) { NiceMock animation; // don't care about restart here animation.Start(); animation.Resume(); ASSERT_THAT(animation.CurrentState(), Eq(na::Animation::Running)); } TEST(TestAnimation, TestResumeStopped) { NiceMock animation; // don't care about restart here animation.Resume(); ASSERT_THAT(animation.CurrentState(), Eq(na::Animation::Stopped)); } /** * Easing curves */ TEST(TestEasingCurve, TestLinear) { na::EasingCurve curve; ASSERT_THAT(curve.ValueForProgress(-0.5), DoubleEq(0)); ASSERT_THAT(curve.ValueForProgress(0.0), DoubleEq(0)); ASSERT_THAT(curve.ValueForProgress(0.1), DoubleEq(0.1)); ASSERT_THAT(curve.ValueForProgress(0.2), DoubleEq(0.2)); ASSERT_THAT(curve.ValueForProgress(0.3), DoubleEq(0.3)); ASSERT_THAT(curve.ValueForProgress(0.4), DoubleEq(0.4)); ASSERT_THAT(curve.ValueForProgress(0.5), DoubleEq(0.5)); ASSERT_THAT(curve.ValueForProgress(0.6), DoubleEq(0.6)); ASSERT_THAT(curve.ValueForProgress(0.7), DoubleEq(0.7)); ASSERT_THAT(curve.ValueForProgress(0.8), DoubleEq(0.8)); ASSERT_THAT(curve.ValueForProgress(0.9), DoubleEq(0.9)); ASSERT_THAT(curve.ValueForProgress(1.0), DoubleEq(1)); ASSERT_THAT(curve.ValueForProgress(1.5), DoubleEq(1)); } TEST(TestEasingCurve, TestInQuad) { na::EasingCurve curve(na::EasingCurve::Type::InQuad); ASSERT_THAT(curve.ValueForProgress(-0.5), DoubleEq(0)); ASSERT_THAT(curve.ValueForProgress(0.0), DoubleEq(0)); ASSERT_THAT(curve.ValueForProgress(0.1), DoubleEq(0.01)); ASSERT_THAT(curve.ValueForProgress(0.2), DoubleEq(0.04)); ASSERT_THAT(curve.ValueForProgress(0.3), DoubleEq(0.09)); ASSERT_THAT(curve.ValueForProgress(0.4), DoubleEq(0.16)); ASSERT_THAT(curve.ValueForProgress(0.5), DoubleEq(0.25)); ASSERT_THAT(curve.ValueForProgress(0.6), DoubleEq(0.36)); ASSERT_THAT(curve.ValueForProgress(0.7), DoubleEq(0.49)); ASSERT_THAT(curve.ValueForProgress(0.8), DoubleEq(0.64)); ASSERT_THAT(curve.ValueForProgress(0.9), DoubleEq(0.81)); ASSERT_THAT(curve.ValueForProgress(1.0), DoubleEq(1)); ASSERT_THAT(curve.ValueForProgress(1.5), DoubleEq(1)); } TEST(TestEasingCurve, TestOutQuad) { na::EasingCurve curve(na::EasingCurve::Type::OutQuad); ASSERT_THAT(curve.ValueForProgress(-0.5), DoubleEq(0)); ASSERT_THAT(curve.ValueForProgress(0.0), DoubleEq(0)); ASSERT_THAT(curve.ValueForProgress(0.1), DoubleEq(0.19)); ASSERT_THAT(curve.ValueForProgress(0.2), DoubleEq(0.36)); ASSERT_THAT(curve.ValueForProgress(0.3), DoubleEq(0.51)); ASSERT_THAT(curve.ValueForProgress(0.4), DoubleEq(0.64)); ASSERT_THAT(curve.ValueForProgress(0.5), DoubleEq(0.75)); ASSERT_THAT(curve.ValueForProgress(0.6), DoubleEq(0.84)); ASSERT_THAT(curve.ValueForProgress(0.7), DoubleEq(0.91)); ASSERT_THAT(curve.ValueForProgress(0.8), DoubleEq(0.96)); ASSERT_THAT(curve.ValueForProgress(0.9), DoubleEq(0.99)); ASSERT_THAT(curve.ValueForProgress(1.0), DoubleEq(1)); ASSERT_THAT(curve.ValueForProgress(1.5), DoubleEq(1)); } TEST(TestEasingCurve, TestInOutQuad) { na::EasingCurve curve(na::EasingCurve::Type::InOutQuad); ASSERT_THAT(curve.ValueForProgress(-0.5), DoubleEq(0)); ASSERT_THAT(curve.ValueForProgress(0.0), DoubleEq(0)); ASSERT_THAT(curve.ValueForProgress(0.1), DoubleEq(0.02)); ASSERT_THAT(curve.ValueForProgress(0.2), DoubleEq(0.08)); ASSERT_THAT(curve.ValueForProgress(0.3), DoubleEq(0.18)); ASSERT_THAT(curve.ValueForProgress(0.4), DoubleEq(0.32)); ASSERT_THAT(curve.ValueForProgress(0.5), DoubleEq(0.5)); ASSERT_THAT(curve.ValueForProgress(0.6), DoubleEq(0.68)); ASSERT_THAT(curve.ValueForProgress(0.7), DoubleEq(0.82)); ASSERT_THAT(curve.ValueForProgress(0.8), DoubleEq(0.92)); ASSERT_THAT(curve.ValueForProgress(0.9), DoubleEq(0.98)); ASSERT_THAT(curve.ValueForProgress(1.0), DoubleEq(1)); ASSERT_THAT(curve.ValueForProgress(1.5), DoubleEq(1)); } /** * Animating values */ TEST(TestAnimateValue, TestConstruction) { na::AnimateValue dafault_int_animation; ASSERT_THAT(dafault_int_animation.CurrentState(), Eq(na::Animation::Stopped)); ASSERT_THAT(dafault_int_animation.GetStartValue(), Eq(0)); ASSERT_THAT(dafault_int_animation.GetCurrentValue(), Eq(0)); ASSERT_THAT(dafault_int_animation.GetFinishValue(), Eq(0)); ASSERT_THAT(dafault_int_animation.Duration(), Eq(0)); ASSERT_THAT(dafault_int_animation.CurrentTimePosition(), Eq(0)); na::AnimateValue duration_int_animation(10); ASSERT_THAT(duration_int_animation.CurrentState(), Eq(na::Animation::Stopped)); ASSERT_THAT(duration_int_animation.GetStartValue(), Eq(0)); ASSERT_THAT(duration_int_animation.GetCurrentValue(), Eq(0)); ASSERT_THAT(duration_int_animation.GetFinishValue(), Eq(0)); ASSERT_THAT(duration_int_animation.Duration(), Eq(10)); ASSERT_THAT(duration_int_animation.CurrentTimePosition(), Eq(0)); na::AnimateValue value_int_animation(10, 20, 1000); ASSERT_THAT(value_int_animation.CurrentState(), Eq(na::Animation::Stopped)); ASSERT_THAT(value_int_animation.GetStartValue(), Eq(10)); ASSERT_THAT(value_int_animation.GetCurrentValue(), Eq(10)); ASSERT_THAT(value_int_animation.GetFinishValue(), Eq(20)); ASSERT_THAT(value_int_animation.Duration(), Eq(1000)); ASSERT_THAT(value_int_animation.CurrentTimePosition(), Eq(0)); } TEST(TestAnimateValue, TestStartEmitsInitialValue) { nt::ChangeRecorder recorder; na::AnimateValue animation(10, 20, 1000); animation.updated.connect(recorder.listener()); animation.Start(); ASSERT_THAT(recorder.size(), Eq(1)); ASSERT_THAT(recorder.changed_values[0], Eq(10)); } TEST(TestAnimateValue, TestAdvance) { nt::ChangeRecorder recorder; nt::TestCallback finished_called; na::AnimateValue animation(10, 20, 1000); animation.updated.connect(recorder.listener()); animation.finished.connect(finished_called.sigc_callback()); animation.Start(); int advance_msec = 101; for (int i = 0; i < 10; ++i) { int expected_value = advance_msec * (i + 1); animation.Advance(advance_msec); if (expected_value < animation.Duration()) ASSERT_THAT(animation.CurrentTimePosition(), Eq(101 * (i + 1))); } // Advance one more time than necessary animation.Advance(advance_msec); std::vector expected = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}; ASSERT_THAT(recorder.changed_values, Eq(expected)); ASSERT_TRUE(finished_called.happened); ASSERT_THAT(animation.CurrentState(), Eq(na::Animation::Stopped)); ASSERT_THAT(animation.GetCurrentValue(), Eq(20)); } TEST(TestAnimateValue, TestAdvanceOnlyRunning) { nt::ChangeRecorder recorder; na::AnimateValue animation(10, 20, 1000); animation.updated.connect(recorder.listener()); animation.Advance(100); ASSERT_THAT(recorder.size(), Eq(0)); animation.Start(); animation.Advance(400); std::vector expected = {10, 14}; ASSERT_THAT(recorder.changed_values, Eq(expected)); animation.Pause(); animation.Advance(400); ASSERT_THAT(recorder.changed_values, Eq(expected)); animation.Resume(); animation.Advance(400); expected.push_back(18); ASSERT_THAT(recorder.changed_values, Eq(expected)); } TEST(TestAnimateValue, TestUsesEasingFunction) { nt::ChangeRecorder recorder; na::AnimateValue animation(10, 20, 1000); animation.SetEasingCurve(na::EasingCurve(na::EasingCurve::Type::OutQuad)); animation.updated.connect(recorder.listener()); animation.Start(); for (int i = 0; i < 10; ++i) animation.Advance(200); std::vector expected = {10, 13.6, 16.4, 18.4, 19.6, 20}; ASSERT_THAT(recorder.size(), Eq(expected.size())); // Use FloatEq to check values as calculations may give truncated values. for (std::size_t i = 0; i < expected.size(); ++i) { ASSERT_THAT(recorder.changed_values[i], FloatEq(expected[i])); } } TEST(TestAnimateValue, TestAnimateIntReverseStopped) { na::AnimateValue animation(10, 20, 1000); animation.Reverse(); ASSERT_THAT(animation.GetStartValue(), Eq(20)); ASSERT_THAT(animation.GetFinishValue(), Eq(10)); ASSERT_THAT(animation.CurrentState(), Eq(na::Animation::Stopped)); } TEST(TestAnimateValue, TestAnimateIntReverse) { const int total_duration = 1000; nt::ChangeRecorder recorder; na::AnimateValue animation(10, 20, total_duration); animation.updated.connect(recorder.listener()); animation.Start(); for (int i = 0; i < 3; ++i) animation.Advance(201); double old_start = animation.GetStartValue(); double old_finish = animation.GetFinishValue(); int old_current_time_pos = animation.CurrentTimePosition(); animation.Reverse(); EXPECT_EQ(animation.GetStartValue(), old_finish); EXPECT_EQ(animation.GetFinishValue(), old_start); EXPECT_EQ(animation.CurrentTimePosition(), total_duration - old_current_time_pos); for (int i = 0; i < 6; ++i) animation.Advance(201); std::vector expected = {10, 12, 14, 16, 14, 12, 10}; ASSERT_THAT(recorder.changed_values, Eq(expected)); } TEST(TestAnimateValue, TestAnimateIntReversePaused) { const int total_duration = 1000; nt::ChangeRecorder recorder; na::AnimateValue animation(10, 20, total_duration); animation.updated.connect(recorder.listener()); animation.Start(); for (int i = 0; i < 3; ++i) animation.Advance(201); double old_start = animation.GetStartValue(); double old_finish = animation.GetFinishValue(); int old_current_time_pos = animation.CurrentTimePosition(); animation.Pause(); animation.Reverse(); EXPECT_EQ(animation.GetStartValue(), old_finish); EXPECT_EQ(animation.GetFinishValue(), old_start); EXPECT_EQ(animation.CurrentTimePosition(), total_duration - old_current_time_pos); animation.Resume(); for (int i = 0; i < 6; ++i) animation.Advance(201); std::vector expected = {10, 12, 14, 16, 14, 12, 10}; ASSERT_THAT(recorder.changed_values, Eq(expected)); } TEST(TestAnimateValue, TestAnimateIntReverseMultipleTimes) { const int total_duration = 1000; const int start_value = 10; const int finish_value = 20; bool finished = false; nt::ChangeRecorder recorder; na::AnimateValue animation(start_value, finish_value, total_duration); animation.updated.connect(recorder.listener()); animation.finished.connect([&finished]{ finished = true; }); animation.Start(); animation.Advance(201); // 12 animation.Advance(201); // 14 animation.Advance(201); // 16 ASSERT_FALSE(finished); int current_time_pos = animation.CurrentTimePosition(); animation.Reverse(); // decrementing ASSERT_EQ(animation.GetStartValue(), finish_value); ASSERT_EQ(animation.GetFinishValue(), start_value); ASSERT_EQ(animation.CurrentTimePosition(), total_duration - current_time_pos); animation.Advance(201); // 14 animation.Advance(201); // 12 ASSERT_FALSE(finished); current_time_pos = animation.CurrentTimePosition(); animation.Reverse(); // incrementing ASSERT_EQ(animation.GetStartValue(), start_value); ASSERT_EQ(animation.GetFinishValue(), finish_value); ASSERT_EQ(animation.CurrentTimePosition(), total_duration - current_time_pos); animation.Advance(201); // 14 animation.Advance(201); // 16 ASSERT_FALSE(finished); current_time_pos = animation.CurrentTimePosition(); animation.Reverse(); // decrementing ASSERT_EQ(animation.GetStartValue(), finish_value); ASSERT_EQ(animation.GetFinishValue(), start_value); ASSERT_EQ(animation.CurrentTimePosition(), total_duration - current_time_pos); animation.Advance(201); // 14 animation.Advance(201); // 12 animation.Advance(201); // 10 ASSERT_TRUE(finished); std::vector expected = {10, 12, 14, 16, 14, 12, 14, 16, 14, 12, 10}; ASSERT_EQ(recorder.changed_values, expected); } TEST(TestAnimateValue, TestAnimatePoint) { nt::ChangeRecorder recorder; na::AnimateValue animation(nux::Point(10, 10), nux::Point(20, 20), 1000); animation.updated.connect(recorder.listener()); animation.Start(); for (int i = 0; i < 10; ++i) animation.Advance(201); std::vector expected = {nux::Point(10,10), nux::Point(12,12), nux::Point(14,14), nux::Point(16,16), nux::Point(18,18), nux::Point(20,20)}; ASSERT_THAT(recorder.changed_values, Eq(expected)); } TEST(TestAnimateValue, TestAnimateRect) { nt::ChangeRecorder recorder; na::AnimateValue animation(nux::Rect(10, 10, 100, 200), nux::Rect(20, 20, 200, 400), 1000); animation.updated.connect(recorder.listener()); animation.Start(); for (int i = 0; i < 10; ++i) animation.Advance(200); std::vector expected = {nux::Rect(10, 10, 100, 200), nux::Rect(12, 12, 120, 240), nux::Rect(14, 14, 140, 280), nux::Rect(16, 16, 160, 320), nux::Rect(18, 18, 180, 360), nux::Rect(20, 20, 200, 400)}; ASSERT_THAT(recorder.changed_values, Eq(expected)); } TEST(TestAnimateValue, TestAnimateColor) { nt::ChangeRecorder recorder; na::AnimateValue animation(nux::Color(1.0f, 0.0f, 0.0f), nux::Color(0.0f, 0.5f, 0.0f), 1000); animation.updated.connect(recorder.listener()); animation.Start(); for (int i = 0; i < 5; ++i) animation.Advance(250); std::vector expected = {nux::Color(1.0f, 0.0f, 0.0f), nux::Color(0.75f, 0.125f, 0.0f), nux::Color(0.5f, 0.25f, 0.0f), nux::Color(0.25f, 0.375f, 0.0f), nux::Color(0.0f, 0.5f, 0.0f)}; ASSERT_THAT(recorder.size(), Eq(expected.size())); // Use FloatEq to check values as calculations may give truncated values. for (std::size_t i = 0; i < expected.size(); ++i) { nux::Color const& c = recorder.changed_values[i]; ASSERT_THAT(c.red, FloatEq(expected[i].red)); ASSERT_THAT(c.green, FloatEq(expected[i].green)); ASSERT_THAT(c.blue, FloatEq(expected[i].blue)); ASSERT_THAT(c.alpha, FloatEq(expected[i].alpha)); } } /** * Test the ticker hooked up to the animation controller advances animations. */ class TestTicker : public na::TickSource { public: TestTicker() : tick_value(0) {} void ms_tick(int ms) { tick_value += ms * 1000; tick.emit(tick_value); } private: long long tick_value; }; class TestAnimationHookup : public Test { public: TestAnimationHookup() : animation_controller(ticker) {} protected: TestTicker ticker; na::AnimationController animation_controller; }; TEST_F(TestAnimationHookup, TestSingleAnimation) { nt::ChangeRecorder recorder; na::AnimateValue animation(10, 20, 1000); animation.updated.connect(recorder.listener()); // Ticking along with no animations has no impact. ticker.ms_tick(101); EXPECT_THAT(recorder.size(), Eq(0)); animation.Start(); ticker.ms_tick(201); std::vector expected = {10, 12}; EXPECT_THAT(recorder.changed_values, Eq(expected)); // Pausing means no advancement animation.Pause(); ticker.ms_tick(200); EXPECT_THAT(recorder.changed_values, Eq(expected)); // Resuming allows updates. animation.Resume(); ticker.ms_tick(201); expected.push_back(14); EXPECT_THAT(recorder.changed_values, Eq(expected)); animation.Stop(); ticker.ms_tick(201); EXPECT_THAT(recorder.changed_values, Eq(expected)); } TEST_F(TestAnimationHookup, TestTwoAnimation) { nt::ChangeRecorder int_recorder; na::AnimateValue* int_animation; nt::ChangeRecorder double_recorder; na::AnimateValue* double_animation; int_animation = new na::AnimateValue(0, 100, 2000); int_animation->updated.connect(int_recorder.listener()); int_animation->Start(); ticker.ms_tick(201); double_animation = new na::AnimateValue(0, 10, 1000); double_animation->updated.connect(double_recorder.listener()); double_animation->Start(); ticker.ms_tick(201); ticker.ms_tick(201); // Removing one animation doesn't impact the other. delete double_animation; std::vector expected_doubles = {0, 2.01, 4.02}; // Use DoubleEq to check values as calculations may give truncated values. for (std::size_t i = 0; i < expected_doubles.size(); ++i) { ASSERT_THAT(double_recorder.changed_values[i], DoubleEq(expected_doubles[i])); } ticker.ms_tick(201); ticker.ms_tick(201); std::vector expected_ints = {0, 10, 20, 30, 40, 50}; EXPECT_THAT(int_recorder.changed_values, Eq(expected_ints)); int_animation->Stop(); ticker.ms_tick(201); EXPECT_THAT(int_recorder.changed_values, Eq(expected_ints)); delete int_animation; // Ticking away with no animations is fine. ticker.ms_tick(201); } TEST_F(TestAnimationHookup, TestIntProperty) { nux::Property int_property; EXPECT_THAT(int_property(), Eq(0)); std::shared_ptr > anim = na::animate_property(int_property, 10, 20, 1000); anim->finished.connect([&anim]() {anim.reset();}); anim->Start(); EXPECT_THAT(int_property(), Eq(10)); ticker.ms_tick(201); EXPECT_THAT(int_property(), Eq(12)); ticker.ms_tick(201); EXPECT_THAT(int_property(), Eq(14)); ticker.ms_tick(301); EXPECT_THAT(int_property(), Eq(17)); ticker.ms_tick(201); EXPECT_THAT(int_property(), Eq(19)); ticker.ms_tick(201); EXPECT_THAT(int_property(), Eq(20)); EXPECT_FALSE(bool(anim)); ticker.ms_tick(201); EXPECT_THAT(int_property(), Eq(20)); } } // anon namespace ./tests/gtest-nuxcore-logger.cpp0000644000004100000410000003067713313171755017220 0ustar www-datawww-data#include "NuxCore/Logger.h" #include "NuxCore/LoggerPrivate.h" #include "NuxCore/LoggingWriter.h" #include "Helpers.h" #include #include #include namespace nt = nux::testing; using namespace nux::logging; using namespace testing; namespace { TEST(TestLogger, TestSimpleConstruction) { Logger logger(""); EXPECT_EQ(logger.module(), ""); EXPECT_TRUE(logger.IsErrorEnabled()); EXPECT_TRUE(logger.IsWarningEnabled()); EXPECT_FALSE(logger.IsInfoEnabled()); EXPECT_FALSE(logger.IsDebugEnabled()); } TEST(TestLogger, TestModuleName) { Logger logger("nux.logging"); EXPECT_EQ(logger.module(), "nux.logging"); } TEST(TestLogger, TestSetLevel) { Logger logger("testing"); EXPECT_EQ(logger.GetLogLevel(), Level::NotSpecified); EXPECT_EQ(logger.GetEffectiveLogLevel(), Level::Warning); EXPECT_TRUE(logger.IsErrorEnabled()); EXPECT_TRUE(logger.IsWarningEnabled()); EXPECT_FALSE(logger.IsInfoEnabled()); EXPECT_FALSE(logger.IsDebugEnabled()); logger.SetLogLevel(Level::Debug); EXPECT_EQ(logger.GetLogLevel(), Level::Debug); EXPECT_EQ(logger.GetEffectiveLogLevel(), Level::Debug); EXPECT_TRUE(logger.IsErrorEnabled()); EXPECT_TRUE(logger.IsWarningEnabled()); EXPECT_TRUE(logger.IsInfoEnabled()); EXPECT_TRUE(logger.IsDebugEnabled()); logger.SetLogLevel(Level::Info); EXPECT_EQ(logger.GetLogLevel(), Level::Info); EXPECT_EQ(logger.GetEffectiveLogLevel(), Level::Info); EXPECT_TRUE(logger.IsErrorEnabled()); EXPECT_TRUE(logger.IsWarningEnabled()); EXPECT_TRUE(logger.IsInfoEnabled()); EXPECT_FALSE(logger.IsDebugEnabled()); logger.SetLogLevel(Level::Warning); EXPECT_EQ(logger.GetLogLevel(), Level::Warning); EXPECT_EQ(logger.GetEffectiveLogLevel(), Level::Warning); EXPECT_TRUE(logger.IsErrorEnabled()); EXPECT_TRUE(logger.IsWarningEnabled()); EXPECT_FALSE(logger.IsInfoEnabled()); EXPECT_FALSE(logger.IsDebugEnabled()); logger.SetLogLevel(Level::Error); EXPECT_EQ(logger.GetLogLevel(), Level::Error); EXPECT_EQ(logger.GetEffectiveLogLevel(), Level::Error); EXPECT_TRUE(logger.IsErrorEnabled()); EXPECT_FALSE(logger.IsWarningEnabled()); EXPECT_FALSE(logger.IsInfoEnabled()); EXPECT_FALSE(logger.IsDebugEnabled()); logger.SetLogLevel(Level::NotSpecified); EXPECT_EQ(logger.GetLogLevel(), Level::NotSpecified); EXPECT_EQ(logger.GetEffectiveLogLevel(), Level::Warning); } TEST(TestLogger, TestLevelsSharedForSameModule) { Logger logger1("testing.module"); Logger logger2("testing.module"); logger1.SetLogLevel(Level::Info); EXPECT_TRUE(logger1.IsInfoEnabled()); EXPECT_TRUE(logger2.IsInfoEnabled()); } TEST(TestLogger, TestModuleLowered) { Logger logger1("TESTING.MODULE"); Logger logger2("Testing"); EXPECT_THAT(logger1.module(), Eq("testing.module")); EXPECT_THAT(logger2.module(), Eq("testing")); } TEST(TestLogger, TestLevelsInherited) { Logger root(""); Logger first("first"); Logger second("first.second"); root.SetLogLevel(Level::Error); EXPECT_EQ(root.GetLogLevel(), Level::Error); EXPECT_EQ(root.GetEffectiveLogLevel(), Level::Error); EXPECT_EQ(first.GetLogLevel(), Level::NotSpecified); EXPECT_EQ(first.GetEffectiveLogLevel(), Level::Error); EXPECT_EQ(second.GetLogLevel(), Level::NotSpecified); EXPECT_EQ(second.GetEffectiveLogLevel(), Level::Error); first.SetLogLevel(Level::Debug); EXPECT_EQ(root.GetLogLevel(), Level::Error); EXPECT_EQ(root.GetEffectiveLogLevel(), Level::Error); EXPECT_EQ(first.GetLogLevel(), Level::Debug); EXPECT_EQ(first.GetEffectiveLogLevel(), Level::Debug); EXPECT_EQ(second.GetLogLevel(), Level::NotSpecified); EXPECT_EQ(second.GetEffectiveLogLevel(), Level::Debug); second.SetLogLevel(Level::Info); EXPECT_EQ(root.GetLogLevel(), Level::Error); EXPECT_EQ(root.GetEffectiveLogLevel(), Level::Error); EXPECT_EQ(first.GetLogLevel(), Level::Debug); EXPECT_EQ(first.GetEffectiveLogLevel(), Level::Debug); EXPECT_EQ(second.GetLogLevel(), Level::Info); EXPECT_EQ(second.GetEffectiveLogLevel(), Level::Info); first.SetLogLevel(Level::NotSpecified); EXPECT_EQ(root.GetLogLevel(), Level::Error); EXPECT_EQ(root.GetEffectiveLogLevel(), Level::Error); EXPECT_EQ(first.GetLogLevel(), Level::NotSpecified); EXPECT_EQ(first.GetEffectiveLogLevel(), Level::Error); EXPECT_EQ(second.GetLogLevel(), Level::Info); EXPECT_EQ(second.GetEffectiveLogLevel(), Level::Info); } class UseTimezone { public: UseTimezone(std::string const& tz) { char* old_tz = ::getenv("TZ"); if (old_tz) { // std::strings don't like beeing assigned NULL old_tz_ = old_tz; } ::setenv("TZ", tz.c_str(), true); ::tzset(); } ~UseTimezone() { if (old_tz_.empty()) { ::unsetenv("TZ"); } else { ::setenv("TZ", old_tz_.c_str(), true); } ::tzset(); } private: std::string old_tz_; }; TEST(TestLoggingWriter, TestWriteMessage) { nt::CaptureLogOutput log_output; // set a known timezone UseTimezone timezone(":Antarctica/Vostok"); // This time is known to be: 2010-09-10 12:34:45 (UTC+12) std::time_t when = 1284078885; Writer::Instance().WriteMessage(Level::Error, "test.module", "testfile.cpp", 1234, when, "my message"); std::string result = log_output.GetOutput(); // Vostok is UTC+6 EXPECT_THAT(result, Eq("ERROR 2010-09-10 06:34:45 test.module testfile.cpp:1234 my message\n")); } TEST(TestLogStream, TestSimpleConstruction) { // First test is to make sure a LogStream can be constructed and destructed. LogStream test(Level::Debug, "module", "filename", 42); } TEST(TestLogStream, TestOutput) { nt::CaptureLogOutput log_output; LogStream test(Level::Debug, "module", "filename", 42); test << "testing message" << std::flush; std::string result = log_output.GetOutput(); EXPECT_THAT(result, StartsWith("DEBUG")); EXPECT_THAT(result, HasSubstr("module filename:42")); EXPECT_THAT(result, EndsWith("testing message\n")); } TEST(TestLogStream, TestShortenedFilename) { // Filenames only show the last path segment. nt::CaptureLogOutput log_output; LogStream test(Level::Debug, "module", "/some/absolute/filename", 42); test << "testing message" << std::flush; std::string result = log_output.GetOutput(); EXPECT_THAT(result, HasSubstr("module filename:42")); } TEST(TestLogStream, TestTemporary) { // First test is to make sure a LogStream can be constructed and destructed. nt::CaptureLogOutput log_output; LogStream(Level::Debug, "module", "filename", 42).stream() << "testing message"; std::string result = log_output.GetOutput(); EXPECT_THAT(result, StartsWith("DEBUG")); EXPECT_THAT(result, HasSubstr(" module filename:42")); EXPECT_THAT(result, EndsWith("testing message\n")); } TEST(TestLogStream, TestDebugMacro) { // First test is to make sure a LogStream can be constructed and destructed. nt::CaptureLogOutput log_output; int counter = 0; Logger logger("test.module"); LOG_DEBUG(logger) << ++counter << "Not output, as not debug."; logger.SetLogLevel(Level::Debug); LOG_DEBUG(logger) << ++counter << " Is output now."; std::string result = log_output.GetOutput(); EXPECT_THAT(result, StartsWith("DEBUG")); EXPECT_THAT(result, HasSubstr(" test.module gtest-nuxcore-logger.cpp")); EXPECT_THAT(result, EndsWith("1 Is output now.\n")); // Also only one line. EXPECT_THAT(counter, Eq(1)); } TEST(TestLogStream, TestBlockTracer) { nt::CaptureLogOutput log_output; Logger logger("test"); logger.SetLogLevel(Level::Debug); { BlockTracer tracer(logger, Level::Debug, "func_name", "file_name", 42); } std::string result = log_output.GetOutput(); EXPECT_THAT(result, MatchesRegex("DEBUG .+ test file_name:42 \\+func_name\n" "DEBUG .+ test file_name:42 -func_name\n")); } TEST(TestLogHelpers, TestGetLoggingLevel) { EXPECT_THAT(get_logging_level("trace"), Eq(Level::Trace)); EXPECT_THAT(get_logging_level("TrAce"), Eq(Level::Trace)); EXPECT_THAT(get_logging_level("TRACE"), Eq(Level::Trace)); EXPECT_THAT(get_logging_level("debug"), Eq(Level::Debug)); EXPECT_THAT(get_logging_level("DEBUG"), Eq(Level::Debug)); EXPECT_THAT(get_logging_level("info"), Eq(Level::Info)); EXPECT_THAT(get_logging_level("INFO"), Eq(Level::Info)); EXPECT_THAT(get_logging_level("warn"), Eq(Level::Warning)); EXPECT_THAT(get_logging_level("WARN"), Eq(Level::Warning)); EXPECT_THAT(get_logging_level("warning"), Eq(Level::Warning)); EXPECT_THAT(get_logging_level("WARNING"), Eq(Level::Warning)); EXPECT_THAT(get_logging_level("error"), Eq(Level::Error)); EXPECT_THAT(get_logging_level("ERROR"), Eq(Level::Error)); // Unknown levels result in WARNING EXPECT_THAT(get_logging_level("critical"), Eq(Level::Warning)); EXPECT_THAT(get_logging_level("not_specified"), Eq(Level::Warning)); EXPECT_THAT(get_logging_level("other"), Eq(Level::Warning)); } TEST(TestLogHelpers, TestResetLogging) { // First set root and another. Logger("").SetLogLevel(Level::Debug); Logger("test.module").SetLogLevel(Level::Info); reset_logging(); std::string levels = dump_logging_levels(); EXPECT_THAT(levels, Eq(" WARNING")); } TEST(TestLogHelpers, TestHasModule) { LoggerModules& modules = LoggerModules::Instance(); EXPECT_FALSE(modules.HasModule("test.module.non.existent")); Logger("test.module.non.existent"); EXPECT_TRUE(modules.HasModule("test.module.non.existent")); } DECLARE_LOGGER(file_level_logger, "test.module.file.level"); TEST(TestStaticFileFunction, TestLoggerConstruction) { LoggerModules& modules = LoggerModules::Instance(); EXPECT_FALSE(modules.HasModule("test.module.file.level")); // Call the function file_level_logger(); EXPECT_TRUE(modules.HasModule("test.module.file.level")); } TEST(TestLoggerMacros, TestPassingObject) { nt::CaptureLogOutput log_output; configure_logging("test.module=trace"); Logger local("test.module"); LOG_TRACE(local) << "trace log"; EXPECT_THAT(log_output.GetOutput(), MatchesRegex("TRACE .+ trace log\n")); LOG_DEBUG(local) << "debug log"; EXPECT_THAT(log_output.GetOutput(), MatchesRegex("DEBUG .+ debug log\n")); LOG_INFO(local) << "info log"; EXPECT_THAT(log_output.GetOutput(), MatchesRegex("INFO .+ info log\n")); LOG_WARN(local) << "warn log"; EXPECT_THAT(log_output.GetOutput(), MatchesRegex("WARN .+ warn log\n")); LOG_ERROR(local) << "error log"; EXPECT_THAT(log_output.GetOutput(), MatchesRegex("ERROR .+ error log\n")); } DECLARE_LOGGER(test_logger, "test.module"); TEST(TestLoggerMacros, TestPassingFunction) { nt::CaptureLogOutput log_output; configure_logging("test.module=trace"); LoggerFunc the_func = test_logger; LOG_TRACE(test_logger) << "trace log"; EXPECT_THAT(log_output.GetOutput(), MatchesRegex("TRACE .+ trace log\n")); LOG_DEBUG(test_logger) << "debug log"; EXPECT_THAT(log_output.GetOutput(), MatchesRegex("DEBUG .+ debug log\n")); LOG_INFO(test_logger) << "info log"; EXPECT_THAT(log_output.GetOutput(), MatchesRegex("INFO .+ info log\n")); LOG_WARN(test_logger) << "warn log"; EXPECT_THAT(log_output.GetOutput(), MatchesRegex("WARN .+ warn log\n")); LOG_ERROR(test_logger) << "error log"; EXPECT_THAT(log_output.GetOutput(), MatchesRegex("ERROR .+ error log\n")); } TEST(TestLogHelpers, TestConfigureLoggingNull) { reset_logging(); Logger("").SetLogLevel(Level::Debug); Logger("test.module").SetLogLevel(Level::Info); // Configure passed a null pointer does nothing. configure_logging(NULL); std::string levels = dump_logging_levels(); EXPECT_THAT(levels, Eq(" DEBUG\n" "test.module INFO")); } TEST(TestLogHelpers, TestConfigureLoggingRoot) { reset_logging(); configure_logging("=debug"); std::string levels = dump_logging_levels(); EXPECT_THAT(levels, Eq(" DEBUG")); } TEST(TestLogHelpers, TestConfigureLoggingSingleModule) { reset_logging(); configure_logging("test.module=debug"); std::string levels = dump_logging_levels(); EXPECT_THAT(levels, Eq(" WARNING\n" "test.module DEBUG")); } TEST(TestLogHelpers, TestConfigureLoggingMultipleModules) { reset_logging(); configure_logging("module=info;sub.module=debug;other.module=warning"); std::string levels = dump_logging_levels(); EXPECT_THAT(levels, Eq(" WARNING\n" "module INFO\n" "other.module WARNING\n" "sub.module DEBUG")); } } // anon namespace ./tests/gtest-nux-main.cpp0000644000004100000410000000130613313171755015777 0ustar www-datawww-data#include #include #include "Nux/Nux.h" #ifdef NUX_GESTURES_SUPPORT #include "NuxGraphics/GestureEvent.h" #include "FakeGestureEvent.h" std::map g_gesture_acceptance; void nux::GestureEvent::Accept() { g_gesture_acceptance[gesture_id_] = g_gesture_acceptance[gesture_id_] + 1; } void nux::GestureEvent::Reject() { g_gesture_acceptance[gesture_id_] = g_gesture_acceptance[gesture_id_] - 1; } #endif // NUX_GESTURES_SUPPORT int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); #if G_ENCODE_VERSION (GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION) <= GLIB_VERSION_2_34 g_type_init(); #endif nux::NuxInitialize(0); return RUN_ALL_TESTS(); } ./tests/gtest-nuxgraphics-main.cpp0000644000004100000410000000050213313171755017515 0ustar www-datawww-data#include #include #include "NuxCore/NuxCore.h" int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); #if G_ENCODE_VERSION (GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION) <= GLIB_VERSION_2_34 g_type_init(); #endif nux::NuxCoreInitialize(0); return RUN_ALL_TESTS(); } ./tests/test-scrollview.h0000644000004100000410000000252113313171755015732 0ustar www-datawww-data/* * Copyright 2011 Inalogic Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY 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 * version 3 along with this program. If not, see * * * Authored by: Andrea Azzarone * */ #ifndef TEST_SCROLLVIEW_H #define TEST_SCROLLVIEW_H #include "Nux/ScrollView.h" #include "Nux/VScrollBar.h" class TestScrollView: public nux::ScrollView { NUX_DECLARE_OBJECT_TYPE(TestView, ScrollView); public: TestScrollView(NUX_FILE_LINE_PROTO); ~TestScrollView(); nux::Color GetColor() const; void ResetEvents(); nux::VScrollBar* GetVScrollbar() {return _vscrollbar;} bool registered_scroll_; protected: void Draw(nux::GraphicsEngine &graphics_engine, bool force_draw); void OnScrolling(int hscroll, int vscroll); private: nux::Color normal_color_; nux::Color current_color_; }; #endif // TEST_VIEW_H ./tests/xtest-mouse-events.cpp0000644000004100000410000001117113313171755016717 0ustar www-datawww-data/* * Copyright 2010 Inalogic Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY 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 * version 3 along with this program. If not, see * * * Authored by: Jay Taoko * */ #include "Nux/Nux.h" #include "Nux/WindowThread.h" #include "Nux/VLayout.h" #include "Nux/Layout.h" #include "Nux/ProgramFramework/ProgramTemplate.h" #include "Nux/ProgramFramework/TestView.h" #include #include #include "nux_automated_test_framework.h" class EventsTest: public ProgramTemplate { public: EventsTest(const char* program_name, int window_width, int window_height, int program_life_span); ~EventsTest(); virtual void UserInterfaceSetup(); void ResetEvents(); nux::TestView* test_view_; }; EventsTest::EventsTest(const char* program_name, int window_width, int window_height, int program_life_span) : ProgramTemplate(program_name, window_width, window_height, program_life_span) { ResetEvents(); test_view_ = NULL; } EventsTest::~EventsTest() { } void EventsTest::ResetEvents() { if (test_view_) test_view_->ResetEvents(); } void EventsTest::UserInterfaceSetup() { nux::VLayout* main_layout = new nux::VLayout(NUX_TRACKER_LOCATION); test_view_ = new nux::TestView(NUX_TRACKER_LOCATION); main_layout->AddView(test_view_, 1, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL); main_layout->SetPadding(10, 10); static_cast(window_thread_)->SetLayout(main_layout); nux::ColorLayer background(nux::Color(0xFF4D4D4D)); static_cast(window_thread_)->SetWindowBackgroundPaintLayer(&background); } EventsTest* event_test = NULL; void TestingThread(nux::NThread* /* thread */, void* user_data) { while (event_test->ReadyToGo() == false) { nuxDebugMsg("Waiting to start"); nux::SleepForMilliseconds(300); } nux::SleepForMilliseconds(1000); nux::WindowThread* wnd_thread = static_cast(user_data); NuxAutomatedTestFramework test(wnd_thread); test.Startup(); // Set the mouse at coordinates (0, 0) (top-left corner) on the display test.PutMouseAt(0, 0); test.TestReportMsg(event_test->test_view_, "TestView created"); event_test->ResetEvents(); test.ViewSendMouseMotionToCenter(event_test->test_view_); test.TestReportMsg(event_test->test_view_->registered_mouse_move_, "Mouse move event"); test.TestReportMsg(event_test->test_view_->registered_mouse_enter_, "Mouse enter event"); test.ViewSendMouseClick(0, 1); test.TestReportMsg(event_test->test_view_->registered_mouse_down_, "Mouse down event"); test.TestReportMsg(event_test->test_view_->registered_mouse_up_, "Mouse up event"); test.TestReportMsg(event_test->test_view_->registered_mouse_click_, "Mouse click event"); test.ViewSendMouseDrag(event_test->test_view_, 1, 0, 0, 50, 50); test.TestReportMsg(event_test->test_view_->registered_mouse_click_, "Mouse drag event"); test.ViewSendMouseMotionTo(event_test->test_view_, -5, -5); test.TestReportMsg(event_test->test_view_->registered_mouse_leave_, "Mouse leave event"); event_test->test_view_->EnableDoubleClick(true); test.ViewSendMouseDoubleClick(event_test->test_view_, 1); test.TestReportMsg(event_test->test_view_->registered_mouse_double_click_, "Mouse double click event"); event_test->ResetEvents(); // Deactivate double click and test if the view still receives it. event_test->test_view_->EnableDoubleClick(false); test.ViewSendMouseDoubleClick(event_test->test_view_, 1); test.TestReportMsg(!event_test->test_view_->registered_mouse_double_click_, "Mouse double click de-activated"); if (test.WhenDoneTerminateProgram()) { nux::SleepForMilliseconds(1000); wnd_thread->ExitMainLoop(); } nuxDebugMsg("Exit testing thread"); } int main() { XInitThreads(); event_test = new EventsTest("Events Test", 300, 300, 20000); event_test->Startup(); event_test->UserInterfaceSetup(); nux::SystemThread* test_thread = nux::CreateSystemThread(event_test->GetWindowThread(), &TestingThread, event_test->GetWindowThread()); test_thread->Start(event_test); event_test->Run(); delete test_thread; delete event_test; return 0; } ./tests/gtest-nuxcore-colorprivate.cpp0000644000004100000410000000505213313171755020437 0ustar www-datawww-data/* * Copyright 2012 Inalogic Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License version 3 along with this program. If not, see * * * Authored by: Andrea Azzarone * */ #include "NuxCore/ColorPrivate.h" using namespace nux::color; #include using namespace testing; namespace { TEST(TestColorPrivate, TestIsValidHex) { EXPECT_TRUE(IsValidHex("#abcdef")); EXPECT_TRUE(IsValidHex("abcdef")); EXPECT_TRUE(IsValidHex("#ABCDEF")); EXPECT_TRUE(IsValidHex("ABCDEF")); EXPECT_FALSE(IsValidHex("")); EXPECT_FALSE(IsValidHex("#")); EXPECT_FALSE(IsValidHex("#abcde")); EXPECT_FALSE(IsValidHex("#abcdefa")); EXPECT_FALSE(IsValidHex("abcde")); EXPECT_FALSE(IsValidHex("abcdefa")); EXPECT_FALSE(IsValidHex("#abcdeg")); } TEST(TestColorPrivate, TestHexToInt) { EXPECT_EQ(HexToInt("ab"), 0xab); EXPECT_EQ(HexToInt("AB"), 0xab); EXPECT_EQ(HexToInt("01"), 0x01); EXPECT_EQ(HexToInt("0a"), 0x0a); } TEST(TestColorPrivate, TestHexToRGBA) { float r, g, b, a; EXPECT_FALSE(HexToRGBA("", r, g, b, a)); EXPECT_FALSE(HexToRGBA("#ubuntu", r, g, b, a)); EXPECT_TRUE(HexToRGBA("#abc", r, g, b, a)); EXPECT_EQ(r, 0xaa / 255.0f); EXPECT_EQ(g, 0xbb / 255.0f); EXPECT_EQ(b, 0xcc / 255.0f); EXPECT_EQ(a, 1.0f); r = g = b = a = 0; EXPECT_TRUE(HexToRGBA("#abcd", r, g, b, a)); EXPECT_EQ(r, 0xaa / 255.0f); EXPECT_EQ(g, 0xbb / 255.0f); EXPECT_EQ(b, 0xcc / 255.0f); EXPECT_EQ(a, 0xdd / 255.0f); r = g = b = a = 0; EXPECT_TRUE(HexToRGBA("#abcdef", r, g, b, a)); EXPECT_EQ(r, 0xab / 255.0f); EXPECT_EQ(g, 0xcd / 255.0f); EXPECT_EQ(b, 0xef / 255.0f); EXPECT_EQ(a, 1.0f); r = g = b = a = 0; EXPECT_TRUE(HexToRGBA("#abcdefdd", r, g, b, a)); EXPECT_EQ(r, 0xab / 255.0f); EXPECT_EQ(g, 0xcd / 255.0f); EXPECT_EQ(b, 0xef / 255.0f); EXPECT_EQ(a, 0xdd / 255.0f); r = g = b = a = 0; EXPECT_TRUE(HexToRGBA("abcdef", r, g, b, a)); EXPECT_EQ(r, 0xab / 255.0f); EXPECT_EQ(g, 0xcd / 255.0f); EXPECT_EQ(b, 0xef / 255.0f); } } ./tests/xtest-text-entry-xim.cpp0000644000004100000410000002401213313171755017201 0ustar www-datawww-data/* * Copyright 2010 Inalogic Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY 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 * version 3 along with this program. If not, see * * * Authored by: Brandon Schaefer * */ #include "Nux/Nux.h" #include "Nux/WindowThread.h" #include "Nux/VLayout.h" #include "Nux/TextEntry.h" #include "Nux/InputMethodIBus.h" #include "Nux/ProgramFramework/ProgramTemplate.h" #include "Nux/ProgramFramework/TestView.h" #include #include #include "nux_automated_test_framework.h" #include #include #include #include #include class TextTextEntry: public ProgramTemplate { public: TextTextEntry(const char* program_name, int window_width, int window_height, int program_life_span); ~TextTextEntry(); virtual void UserInterfaceSetup(); void TextEntryClick(nux::TextEntry* text_entry); void OnActivated(); void OnCursorMoved(int); void ResetEvents(); nux::TextEntry* text_entry_; bool clicked_; bool activated_; bool cursor_moved_; }; TextTextEntry::TextTextEntry(const char* program_name, int window_width, int window_height, int program_life_span) : ProgramTemplate(program_name, window_width, window_height, program_life_span) , clicked_(false) , activated_(false) , cursor_moved_(false) { ResetEvents(); text_entry_ = NULL; } TextTextEntry::~TextTextEntry() { } void TextTextEntry::ResetEvents() { clicked_ = false; activated_ = false; cursor_moved_ = false; } void TextTextEntry::TextEntryClick(nux::TextEntry* text_entry) { if (text_entry_ == text_entry) { clicked_ = true; } } void TextTextEntry::OnActivated() { activated_ = true; } void TextTextEntry::OnCursorMoved(int position) { cursor_moved_ = true; } void TextTextEntry::UserInterfaceSetup() { nux::VLayout* main_layout = new nux::VLayout(NUX_TRACKER_LOCATION); text_entry_ = new nux::TextEntry("", NUX_TRACKER_LOCATION); text_entry_->activated.connect(sigc::mem_fun(this, &TextTextEntry::OnActivated)); text_entry_->cursor_moved.connect(sigc::mem_fun(this, &TextTextEntry::OnCursorMoved)); text_entry_->SetFontSize(76); main_layout->AddView(text_entry_, 0, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL); main_layout->SetSpaceBetweenChildren(10); main_layout->SetContentDistribution(nux::MAJOR_POSITION_CENTER); static_cast(window_thread_)->SetLayout(main_layout); nux::ColorLayer background(nux::Color(0xFF4D4D4D)); static_cast(window_thread_)->SetWindowBackgroundPaintLayer(&background); } TextTextEntry* test_textentry = NULL; // Returns dynamic memory, delete me! char* ReadInCommands(const char* path) { char* raw_file = NULL; long size; std::ifstream file(path, std::ios::in|std::ios::ate); if (file.is_open()) { size = file.tellg(); raw_file = new char[size+1]; file.seekg (0, std::ios::beg); file.read(raw_file, size); file.close(); } return raw_file; } void TokenizeCommands(char* raw_cmds, std::queue& token_queue) { int i = 0; int size = strlen(raw_cmds); while (i < size) { if (raw_cmds[i] == '/' && raw_cmds[i+1] == '/') { while (raw_cmds[i] != '\n' && i < size) { i++; } i++; } else if (raw_cmds[i] >= '0' && raw_cmds[i] <= '9') { std::string num = ""; while (raw_cmds[i] != ' ' && i < size) { num += raw_cmds[i]; i++; } token_queue.push(num); while (raw_cmds[i] == ' ') {i++;} std::string cmd = ""; while (raw_cmds[i] != '\n' && raw_cmds[i] != '\0' && i < size) { cmd += raw_cmds[i]; i++; } token_queue.push(cmd); } else { i++; } } } void KillInputMethod(const char* im_name) { FILE* f_ptr; char pgrep[128] = "pgrep "; char pid[128]; char* last = NULL; int cur_pid = 0; strcat(pgrep, im_name); if ((f_ptr = popen(pgrep, "r")) == NULL) return; while(fgets(pid, 128, f_ptr) != NULL) { cur_pid = strtol(pid, &last, 10); if (*last == '\0' || *last == '\n') { // Make sure it's dead kill(cur_pid, SIGKILL); kill(cur_pid, SIGSTOP); } } pclose(f_ptr); } void KillCurrentInputMethod() { const char* xmodifier; xmodifier = getenv("XMODIFIERS"); if (!xmodifier) return; KillInputMethod(strchr(xmodifier, '=')+1); } /* 0 - Name of Input method 1 - what keys we should press 2 - what to type 3 - what to expect 4 - we are done with this IM CFG (If someone complains that we need to check the input) **Note I cheated with Key, Letter and CJK...can be filled in S -> 0 L | 1 K | 2 L | 3 C | 4 K -> K+K | L -> LL | C -> CC | example: 0 fcitx 1 ctrl+space 2 ninhao Abstract Syntax IM = 0 KeyStrokes= 1 | 1 | 1 | 1 Input = 2 Expect = 3 Halt = 4 halt 0 -> popen(im_name) 1 -> RunKeyStrokes(keys) 2 -> TypeInput(input) 3 -> CheckInput(cjk) 4 -> pclose(im_name) */ std::vector& GetSplitEnvPath() { static std::vector split_path; if (split_path.empty()) { std::string tmp; size_t colon_ptr = 0, start_ptr = 0; const std::string env_path(getenv("PATH")); if (!env_path.empty()) { // Splits the env path var up on (":") while (colon_ptr != std::string::npos) { colon_ptr = env_path.find(":", start_ptr); tmp = env_path.substr(start_ptr, (colon_ptr-start_ptr)); start_ptr = colon_ptr+1; split_path.push_back(tmp); } } } return split_path; } bool CheckIMExist(const char* im_name) { std::vector split_path = GetSplitEnvPath(); std::string command("ls "); char buf [128]; FILE* path = NULL; for (unsigned int i = 0; i < split_path.size(); i++) { if ((path = popen((command + split_path[i]).c_str(),"r")) == NULL) return false; while (fgets(buf, 128, path) != NULL) { if (strstr(buf, im_name)) return true; } } return false; } FILE* OpenIM(const char* im_name) { FILE* open_file = NULL; if (CheckIMExist(im_name)) { open_file = popen(im_name,"r"); nux::SleepForMilliseconds(500); } return open_file; } bool CheckInput(const std::string cjk, NuxAutomatedTestFramework* test) { std::string message("Test is: " + cjk); test->TestReportMsg(test_textentry->text_entry_->GetText() == cjk, message.c_str()); test->ViewSendCtrlA(); nux::SleepForMilliseconds(500); test->ViewSendDelete(); nux::SleepForMilliseconds(500); return true; } std::string next_token (std::queue& tokens) { std::string next_token; if (!tokens.empty()) { next_token = tokens.front(); tokens.pop(); } return next_token; } bool RunCommands(std::queue& tokens, NuxAutomatedTestFramework* test) { std::string next_cmd; std::string im_name; std::string cur_cmd = next_token(tokens); FILE* start_im = NULL; while (!tokens.empty()) { next_cmd = next_token(tokens); if (cur_cmd == "0") { if ((start_im = OpenIM(next_cmd.c_str())) != NULL) { im_name = next_cmd.c_str(); nux::SleepForMilliseconds(500); } else { fprintf(stderr, "Command not found: %s\n", next_cmd.c_str()); // Skip the test while (cur_cmd != "4") { cur_cmd = next_token(tokens); } next_cmd = next_token(tokens); } } else if (cur_cmd == "1") { test->ViewSendKeys(next_cmd); } else if (cur_cmd == "2") { test->ViewSendString(next_cmd); } else if (cur_cmd == "3") { CheckInput(next_cmd, test); } else if (cur_cmd == "4") { KillInputMethod(im_name.c_str()); pclose(start_im); } else { fprintf(stderr, "Error - Incorrect command: %s\n", cur_cmd.c_str()); return false; } nux::SleepForMilliseconds(500); cur_cmd = next_token(tokens); } return true; } void TestingThread(nux::NThread* thread, void* user_data) { while (test_textentry->ReadyToGo() == false) { nuxDebugMsg("Waiting to start"); nux::SleepForMilliseconds(300); } nux::SleepForMilliseconds(1300); nux::WindowThread* wnd_thread = static_cast(user_data); NuxAutomatedTestFramework test(wnd_thread); test.Startup(); test.TestReportMsg(test_textentry->text_entry_, "TextEntry created"); test_textentry->ResetEvents(); test.ViewSendMouseMotionToCenter(test_textentry->text_entry_); test.ViewSendMouseClick(0,1); std::queue tokens; char* raw_commands; // Just kills what should be the current IM (if there is one) KillCurrentInputMethod(); raw_commands = ReadInCommands("xim-test-commands.txt"); if (raw_commands) { TokenizeCommands(raw_commands, tokens); delete raw_commands; RunCommands(tokens, &test); } if (test.WhenDoneTerminateProgram()) { wnd_thread->ExitMainLoop(); } nuxDebugMsg("Exit testing thread"); } int main(int argc, char** argv) { int xstatus = XInitThreads(); nuxAssertMsg(xstatus > 0, "XInitThreads has failed"); test_textentry = new TextTextEntry("Text Entry", 600, 200, 40000); test_textentry->Startup(); test_textentry->UserInterfaceSetup(); nux::SystemThread* test_thread = nux::CreateSystemThread(NULL, &TestingThread, test_textentry->GetWindowThread()); test_thread->Start(test_textentry); test_textentry->Run(); delete test_thread; delete test_textentry; return 0; } ./tests/gtest-nux-input-area.cpp0000644000004100000410000000545713313171755017133 0ustar www-datawww-data/* * Copyright 2010 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License version 3 along with this program. If not, see * * * Authored by: Marco Trevisan */ #include #include #include "Nux/Nux.h" namespace { struct TestInputArea : public testing::Test { void SetUp() { nux::NuxInitialize(0); wnd_thread.reset(nux::CreateNuxWindow("InputArea Test", 300, 200, nux::WINDOWSTYLE_NORMAL, NULL, false, NULL, NULL)); area = new nux::InputArea("InputArea"); } boost::shared_ptr wnd_thread; nux::ObjectPtr area; }; TEST_F(TestInputArea, GrabKeyboard) { area->GrabKeyboard(); EXPECT_TRUE(nux::GetWindowCompositor().IsInKeyboardGrabStack(area.GetPointer())); } TEST_F(TestInputArea, GrabPointer) { area->GrabPointer(); EXPECT_TRUE(nux::GetWindowCompositor().IsInPointerGrabStack(area.GetPointer())); } TEST_F(TestInputArea, UngrabsOnDestroy) { nux::InputArea* area1 = new nux::InputArea("InputArea1"); nux::InputArea* area2 = new nux::InputArea("InputArea2"); // Adding some grabs area1->GrabKeyboard(); area1->GrabPointer(); area2->GrabPointer(); area2->GrabKeyboard(); area1->GrabKeyboard(); ASSERT_TRUE(nux::GetWindowCompositor().IsInKeyboardGrabStack(area1)); ASSERT_TRUE(nux::GetWindowCompositor().IsInPointerGrabStack(area1)); ASSERT_TRUE(nux::GetWindowCompositor().IsInKeyboardGrabStack(area2)); ASSERT_TRUE(nux::GetWindowCompositor().IsInPointerGrabStack(area2)); // This should cleanup the references in the compositor area1->UnReference(); EXPECT_FALSE(nux::GetWindowCompositor().IsInKeyboardGrabStack(area1)); EXPECT_FALSE(nux::GetWindowCompositor().IsInPointerGrabStack(area1)); area2->UnReference(); EXPECT_FALSE(nux::GetWindowCompositor().IsInKeyboardGrabStack(area2)); EXPECT_FALSE(nux::GetWindowCompositor().IsInPointerGrabStack(area2)); } TEST_F(TestInputArea, IsTrackingChildMouseEvents) { ASSERT_FALSE(area->IsTrackingChildMouseEvents()); area->SetTrackChildMouseEvents(true); ASSERT_TRUE(area->IsTrackingChildMouseEvents()); area->SetTrackChildMouseEvents(false); ASSERT_FALSE(area->IsTrackingChildMouseEvents()); } } ./tests/xtest-focus-on-mouse-enter.cpp0000644000004100000410000001121713313171755020260 0ustar www-datawww-data/* * Copyright 2012 Inalogic Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY 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 * version 3 along with this program. If not, see * * * Authored by: Andrea Azzarone * */ #include "Nux/Nux.h" #include "Nux/WindowThread.h" #include "Nux/VLayout.h" #include "Nux/ProgramFramework/ProgramTemplate.h" #include "Nux/ProgramFramework/TestView.h" #include #include #include "nux_automated_test_framework.h" class FocusOnMouseEnterTest: public ProgramTemplate { public: FocusOnMouseEnterTest(const char* program_name, int window_width, int window_height, int program_life_span); ~FocusOnMouseEnterTest(); virtual void UserInterfaceSetup(); nux::TestView* focus_view_; nux::TestView* no_focus_view_; }; FocusOnMouseEnterTest::FocusOnMouseEnterTest(const char* program_name, int window_width, int window_height, int program_life_span) : ProgramTemplate(program_name, window_width, window_height, program_life_span) , focus_view_(nullptr) , no_focus_view_(nullptr) { } FocusOnMouseEnterTest::~FocusOnMouseEnterTest() {} void FocusOnMouseEnterTest::UserInterfaceSetup() { nux::VLayout* main_layout = new nux::VLayout(NUX_TRACKER_LOCATION); main_layout->SetSpaceBetweenChildren(10); main_layout->SetPadding(10, 10); no_focus_view_ = new nux::TestView(NUX_TRACKER_LOCATION); no_focus_view_->can_focus_ = true; no_focus_view_->SetAcceptKeyNavFocusOnMouseEnter(false); main_layout->AddView(no_focus_view_, 1, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL); focus_view_ = new nux::TestView(NUX_TRACKER_LOCATION); focus_view_->can_focus_ = true; focus_view_->SetAcceptKeyNavFocusOnMouseEnter(true); main_layout->AddView(focus_view_, 1, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL); static_cast(window_thread_)->SetLayout(main_layout); nux::ColorLayer background(nux::Color(0xFF4D4D4D)); static_cast(window_thread_)->SetWindowBackgroundPaintLayer(&background); } FocusOnMouseEnterTest* focus_on_mouse_enter_test = nullptr; void TestingThread(nux::NThread* /* thread */, void* user_data) { while (focus_on_mouse_enter_test->ReadyToGo() == false) { nuxDebugMsg("Waiting to start"); nux::SleepForMilliseconds(300); } nux::SleepForMilliseconds(1000); nux::WindowThread* wnd_thread = static_cast(user_data); NuxAutomatedTestFramework test(wnd_thread); test.Startup(); // Set the mouse at coordinates (0, 0) (top-left corner) on the display test.PutMouseAt(0, 0); test.TestReportMsg(focus_on_mouse_enter_test->focus_view_, "Focus view created"); test.TestReportMsg(focus_on_mouse_enter_test->no_focus_view_, "No focus view created"); // Move mouse to center of no_focus_view_ test.ViewSendMouseMotionToCenter(focus_on_mouse_enter_test->no_focus_view_); nux::SleepForMilliseconds(500); test.TestReportMsg(!focus_on_mouse_enter_test->no_focus_view_->has_focus_, "no_focus_view_ did not take the focus"); // Move mouse to center of focus_view_ test.ViewSendMouseMotionToCenter(focus_on_mouse_enter_test->focus_view_); nux::SleepForMilliseconds(500); test.TestReportMsg(focus_on_mouse_enter_test->focus_view_->has_focus_, "focus_view_ has the focus"); if (test.WhenDoneTerminateProgram()) { nux::SleepForMilliseconds(1000); wnd_thread->ExitMainLoop(); } nuxDebugMsg("Exit testing thread"); } int main() { XInitThreads(); focus_on_mouse_enter_test = new FocusOnMouseEnterTest("Focus On Mouse Enter Test", 300, 300, 15000); focus_on_mouse_enter_test->Startup(); focus_on_mouse_enter_test->UserInterfaceSetup(); nux::SystemThread* test_thread = nux::CreateSystemThread(focus_on_mouse_enter_test->GetWindowThread(), &TestingThread, focus_on_mouse_enter_test->GetWindowThread()); test_thread->Start(focus_on_mouse_enter_test); focus_on_mouse_enter_test->Run(); delete test_thread; delete focus_on_mouse_enter_test; return 0; } ./tests/gtest-nux-view.cpp0000644000004100000410000000427513313171755016035 0ustar www-datawww-data#include #include #include #include #include #include #include "Nux/Nux.h" #include "Nux/HLayout.h" #include "Nux/StaticText.h" #include "Nux/ProgramFramework/TestView.h" using namespace testing; namespace { TEST(TestView, TestViewEnable) { nux::NuxInitialize(0); nux::WindowThread *wnd_thread = nux::CreateNuxWindow("View Test", 300, 200, nux::WINDOWSTYLE_NORMAL, NULL, false, NULL, NULL); nux::TestView* test_view = new nux::TestView(""); test_view->EnableView(); EXPECT_TRUE(test_view->IsViewEnabled()); test_view->DisableView(); EXPECT_FALSE(test_view->IsViewEnabled()); test_view->UnReference(); delete wnd_thread; } TEST(TestView, TestQueueDraw) { nux::NuxInitialize(0); nux::WindowThread *wnd_thread = nux::CreateNuxWindow("View Test", 300, 200, nux::WINDOWSTYLE_NORMAL, NULL, false, NULL, NULL); nux::TestView* main_view = new nux::TestView(""); nux::HLayout* hlayout = new nux::HLayout(""); main_view->SetLayout(hlayout); nux::TestView* test_view1 = new nux::TestView(""); hlayout->AddView(test_view1); nux::TestView* test_view2 = new nux::TestView(""); hlayout->AddView(test_view2); nux::TestView* test_view3 = new nux::TestView(""); hlayout->AddView(test_view3); hlayout->ComputeContentSize(); EXPECT_EQ(main_view->calls_to_queue_draw_, 0); EXPECT_EQ(test_view1->calls_to_queue_draw_, 0); EXPECT_EQ(test_view2->calls_to_queue_draw_, 0); EXPECT_EQ(test_view3->calls_to_queue_draw_, 0); main_view->QueueDraw(); EXPECT_EQ(main_view->calls_to_queue_draw_, 1); EXPECT_EQ(test_view1->calls_to_queue_draw_, 1); EXPECT_EQ(test_view2->calls_to_queue_draw_, 1); EXPECT_EQ(test_view3->calls_to_queue_draw_, 1); int old_size = wnd_thread->GetDrawList().size(); main_view->QueueDraw(); test_view2->QueueDraw(); int new_size = wnd_thread->GetDrawList().size(); EXPECT_EQ(old_size, new_size); // LP: #1014610 EXPECT_EQ(main_view->calls_to_queue_draw_, 2); EXPECT_EQ(test_view1->calls_to_queue_draw_, 1); EXPECT_EQ(test_view2->calls_to_queue_draw_, 2); EXPECT_EQ(test_view3->calls_to_queue_draw_, 1); main_view->UnReference(); delete wnd_thread; } } ./tests/test-scrollview.cpp0000644000004100000410000000350013313171755016263 0ustar www-datawww-data/* * Copyright 2011 Inalogic Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY 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 * version 3 along with this program. If not, see * * * Authored by: Andrea Azzarone * */ #include "Nux/Nux.h" #include "test-scrollview.h" /* TestScrollView: This class is a Nux scrollview that process the mouse wheel events to make sure that everyghing work well. */ NUX_IMPLEMENT_OBJECT_TYPE(TestScrollView); TestScrollView::TestScrollView(NUX_FILE_LINE_DECL) : nux::ScrollView(NUX_FILE_LINE_PARAM) , registered_scroll_(false) , normal_color_(nux::color::Green) , current_color_(normal_color_) { EnableVerticalScrollBar(true); EnableHorizontalScrollBar(true); scrolling.connect(sigc::mem_fun(this, &TestScrollView::OnScrolling)); } TestScrollView::~TestScrollView() { } void TestScrollView::ResetEvents() { registered_scroll_ = false; current_color_ = normal_color_; } nux::Color TestScrollView::GetColor() const { return current_color_; } void TestScrollView::Draw(nux::GraphicsEngine &graphics_engine, bool /* force_draw */) { nux::Geometry geo = GetGeometry(); graphics_engine.QRP_Color(geo.x, geo.y, geo.width, geo.height, current_color_); } void TestScrollView::OnScrolling(int /* hscroll */, int /* vscroll */) { registered_scroll_ = true; QueueDraw(); } ./tests/gtest-nux-kineticscroller.cpp0000644000004100000410000001252313313171755020252 0ustar www-datawww-data/* * Copyright (C) 2012 - Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Daniel d'Andrada */ #include #include #include #include #include "gtest-nux-globals.h" using namespace nux; class FakeTickSource : public kinetic_scrolling::TickSourceInterface { public: FakeTickSource() : is_running(false) {} virtual void Start() { is_running = true; } virtual void Stop() { is_running = false; } bool is_running; }; class KineticScrollerTest : public ::testing::Test, public sigc::trackable { public: virtual void SetUp() { tick_source_ = new FakeTickSource; scroller_ = new KineticScroller(tick_source_); scroller_->content_position_changed.connect( sigc::mem_fun(this, &KineticScrollerTest::OnContentPositionChanged)); content_position_changed_ = false; g_fake_monotonic_time = 0; } virtual void TearDown() { /* will bring down tick_source along with him */ delete scroller_; scroller_ = nullptr; tick_source_ = nullptr; } void OnContentPositionChanged(int pos_x, int pos_y) { previous_pos_x_ = latest_pos_x_; previous_pos_y_ = latest_pos_y_; latest_pos_x_ = pos_x; latest_pos_y_ = pos_y; content_position_changed_ = true; } void PerformFlickUpwards() { scroller_->ProcessFingerDown(); /* flicking at a constant speed of 5 pixels/millisecond (considering 1 axis unit == 1 pixel-wide, the usual case) */ for (int i = 0; i < 30; ++i) { g_fake_monotonic_time += 10 * 1000; scroller_->ProcessFingerDrag(0, -50); } scroller_->ProcessFingerUp(); } int latest_pos_x_; int latest_pos_y_; int previous_pos_x_; int previous_pos_y_; bool content_position_changed_; FakeTickSource *tick_source_; KineticScroller *scroller_; }; TEST_F(KineticScrollerTest, FlickCausesDecelerationAnimation) { scroller_->SetViewportSize(100, 100); scroller_->SetContentSize(100, 3000); scroller_->SetContentPosition(0, 0); scroller_->SetBoundsBehavior(BoundsBehavior::StopAtBounds); scroller_->SetScrollableDirections(ScrollableDirections::ScrollableDirectionsVertical); PerformFlickUpwards(); content_position_changed_ = false; ASSERT_TRUE(tick_source_->is_running); int max_steps = 100000; int step_count = 0; std::vector pos_deltas; /* run the deceleration animation until movement stops or until we reach an iteration limit to avoid an infinite loop in case of buggy behavior. */ do { content_position_changed_ = false; tick_source_->tick.emit(16); /* ensure that the animation is always moving in the same direction and that it doesn't accelerate */ if (content_position_changed_) { ASSERT_LE(latest_pos_y_, previous_pos_y_); pos_deltas.push_back(latest_pos_y_ - previous_pos_y_); if (pos_deltas.size() < 1) { int curr_delta = pos_deltas[pos_deltas.size()-1]; int prev_delta = pos_deltas[pos_deltas.size()-2]; ASSERT_LE(fabs(curr_delta), fabs(prev_delta)); } } ++step_count; } while(step_count < max_steps && tick_source_->is_running && content_position_changed_); ASSERT_FALSE(tick_source_->is_running); } TEST_F(KineticScrollerTest, FingerDragUpwards_StopAtBounds) { scroller_->SetViewportSize(100, 100); scroller_->SetContentSize(100, 3000); int min_content_pos_y = -(3000 - 100); scroller_->SetContentPosition(0, min_content_pos_y); scroller_->SetBoundsBehavior(BoundsBehavior::StopAtBounds); scroller_->SetScrollableDirections(ScrollableDirections::ScrollableDirectionsVertical); scroller_->ProcessFingerDown(); /* drag upwards so that the content's bottom edge would be left above the viewport bottom edge if it followed the finger's movement */ scroller_->ProcessFingerDrag(0, -50); /* position.y should stay as min_content_pos_y */ if (content_position_changed_) { ASSERT_EQ(min_content_pos_y, latest_pos_y_); } } TEST_F(KineticScrollerTest, FingerDragDownwards_StopAtBounds) { scroller_->SetViewportSize(100, 100); scroller_->SetContentSize(100, 3000); scroller_->SetContentPosition(0, 0); scroller_->SetBoundsBehavior(BoundsBehavior::StopAtBounds); scroller_->SetScrollableDirections(ScrollableDirections::ScrollableDirectionsVertical); scroller_->ProcessFingerDown(); /* drag downwards so that the content's top edge would be left below the viewport top edge if it followed the finger's movement */ scroller_->ProcessFingerDrag(0, 50); /* position.y should stay 0 */ if (content_position_changed_) { ASSERT_EQ(0, latest_pos_y_); } } ./tests/geis_mock.h0000644000004100000410000000534713313171755014535 0ustar www-datawww-data/* * Copyright 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Daniel d'Andrada * */ #ifndef GEIS_MOCK_H #define GEIS_MOCK_H #include #include #include #include #include /* helper class */ class GeisAttributes { public: GeisAttr GetByName(GeisString name); GeisAttr GetByIndex(GeisSize index); GeisSize Count(); void AddBoolean(const char *name, GeisBoolean value); void AddFloat(const char *name, GeisFloat value); void AddInteger(const char *name, GeisInteger value); void AddPointer(const char *name, void *value); std::vector< std::unique_ptr > vector; }; struct _GeisAttr { GeisAttrType type; std::string name; GeisBoolean b; GeisFloat f; GeisInteger i; std::string s; void* p; }; struct GeisStructWithAttributes { GeisAttributes attributes; bool GetBoolean(const char *name) { return attributes.GetByName(name)->b; } float GetFloat(const char *name) { return attributes.GetByName(name)->f; } int GetInteger(const char *name) { return attributes.GetByName(name)->i; } std::string GetString(const char *name) { return attributes.GetByName(name)->s; } void* GetPointer(const char *name) { return attributes.GetByName(name)->p; } }; struct _Geis { int fd; std::list pending_events; }; struct _GeisGestureClass : GeisStructWithAttributes { int id; std::string name; }; struct _GeisEvent : GeisStructWithAttributes { GeisEventType type; }; struct _GeisDevice : GeisStructWithAttributes { int id; }; struct _GeisGroup { int id; std::vector vector; }; struct _GeisGroupSet { std::vector vector; }; struct _GeisTouch : GeisStructWithAttributes { int id; }; struct _GeisTouchSet { std::vector vector; }; struct _GeisFrame : GeisStructWithAttributes { int id; std::set class_ids; }; struct _GeisSubscription { int id; std::string name; std::vector filters; }; struct _GeisFilter { int foo; }; #endif ./tests/xtest-button.cpp0000644000004100000410000000713013313171755015600 0ustar www-datawww-data/* * Copyright 2010 Inalogic Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY 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 * version 3 along with this program. If not, see * * * Authored by: Jay Taoko * */ #include "Nux/Nux.h" #include "Nux/WindowThread.h" #include "Nux/VLayout.h" #include "Nux/Button.h" #include "Nux/ProgramFramework/ProgramTemplate.h" #include #include #include "nux_automated_test_framework.h" class TestButton: public ProgramTemplate { public: TestButton(const char* program_name, int window_width, int window_height, int program_life_span); ~TestButton(); virtual void UserInterfaceSetup(); void ButtonClick(nux::Button* button); void ResetEvents(); nux::Button* button_; bool clicked_; }; TestButton::TestButton(const char* program_name, int window_width, int window_height, int program_life_span) : ProgramTemplate(program_name, window_width, window_height, program_life_span) { ResetEvents(); button_ = NULL; } TestButton::~TestButton() { } void TestButton::ResetEvents() { clicked_ = false; } void TestButton::ButtonClick(nux::Button* button) { if (button_ == button) { clicked_ = true; } } void TestButton::UserInterfaceSetup() { nux::VLayout* main_layout = new nux::VLayout(NUX_TRACKER_LOCATION); button_ = new nux::Button("NUX", NUX_TRACKER_LOCATION); button_->SetLabelFontSize(76); main_layout->AddView(button_, 0, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_MATCHCONTENT); main_layout->SetVerticalInternalMargin(10); main_layout->SetContentDistribution(nux::MAJOR_POSITION_CENTER); button_->click.connect(sigc::mem_fun(this, &TestButton::ButtonClick)); static_cast(window_thread_)->SetLayout(main_layout); nux::ColorLayer background(nux::Color(0xFF4D4D4D)); static_cast(window_thread_)->SetWindowBackgroundPaintLayer(&background); } TestButton* test_button = NULL; void TestingThread(nux::NThread* /* thread */, void* user_data) { while (test_button->ReadyToGo() == false) { nuxDebugMsg("Waiting to start"); nux::SleepForMilliseconds(300); } nux::SleepForMilliseconds(1300); nux::WindowThread* wnd_thread = static_cast(user_data); NuxAutomatedTestFramework test(wnd_thread); test.Startup(); test.TestReportMsg(test_button->button_, "Button created"); test_button->ResetEvents(); test.ViewSendMouseMotionToCenter(test_button->button_); test.ViewSendMouseClick(0, 1); nux::SleepForMilliseconds(1000); test.TestReportMsg(test_button->clicked_, "Button clicked"); if (test.WhenDoneTerminateProgram()) { wnd_thread->ExitMainLoop(); } nuxDebugMsg("Exit testing thread"); } int main() { XInitThreads(); test_button = new TestButton("Button XTest", 300, 300, 10000); test_button->Startup(); test_button->UserInterfaceSetup(); nux::SystemThread* test_thread = nux::CreateSystemThread(NULL, &TestingThread, test_button->GetWindowThread()); test_thread->Start(test_button); test_button->Run(); delete test_thread; delete test_button; //nuxDebugMsg("Exit program"); return 0; } ./tests/xtest-text-entry-deadkeys.cpp0000644000004100000410000003440713313171755020206 0ustar www-datawww-data/* * Copyright 2010 Inalogic Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY 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 * version 3 along with this program. If not, see * * * Authored by: Jay Taoko * */ #include "Nux/Nux.h" #include "Nux/WindowThread.h" #include "Nux/VLayout.h" #include "Nux/TextEntry.h" #include "Nux/InputMethodIBus.h" #include "Nux/ProgramFramework/ProgramTemplate.h" #include "Nux/ProgramFramework/TestView.h" #include #include #include "nux_automated_test_framework.h" class TextTextEntry: public ProgramTemplate { public: TextTextEntry(const char* program_name, int window_width, int window_height, int program_life_span); ~TextTextEntry(); virtual void UserInterfaceSetup(); void TextEntryClick(nux::TextEntry* text_entry); void ResetEvents(); nux::TextEntry* text_entry_; bool clicked_; }; TextTextEntry::TextTextEntry(const char* program_name, int window_width, int window_height, int program_life_span) : ProgramTemplate(program_name, window_width, window_height, program_life_span) { ResetEvents(); text_entry_ = NULL; } TextTextEntry::~TextTextEntry() { } void TextTextEntry::ResetEvents() { clicked_ = false; } void TextTextEntry::TextEntryClick(nux::TextEntry* text_entry) { if (text_entry_ == text_entry) { clicked_ = true; } } void TextTextEntry::UserInterfaceSetup() { nux::VLayout* main_layout = new nux::VLayout(NUX_TRACKER_LOCATION); text_entry_ = new nux::TextEntry("", NUX_TRACKER_LOCATION); text_entry_->SetFontSize(76); main_layout->AddView(text_entry_, 0, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL); main_layout->SetSpaceBetweenChildren(10); main_layout->SetContentDistribution(nux::MAJOR_POSITION_CENTER); static_cast(window_thread_)->SetLayout(main_layout); nux::ColorLayer background(nux::Color(0xFF4D4D4D)); static_cast(window_thread_)->SetWindowBackgroundPaintLayer(&background); } TextTextEntry* test_textentry = NULL; void TestingThread(nux::NThread* /* thread */, void* user_data) { while (test_textentry->ReadyToGo() == false) { nuxDebugMsg("Waiting to start"); nux::SleepForMilliseconds(300); } nux::SleepForMilliseconds(1300); nux::WindowThread* wnd_thread = static_cast(user_data); NuxAutomatedTestFramework test(wnd_thread); test.Startup(); test.TestReportMsg(test_textentry->text_entry_, "TextEntry created"); test_textentry->ResetEvents(); test.ViewSendMouseMotionToCenter(test_textentry->text_entry_); test.ViewSendMouseClick(0, 1); if (test.CompositionKeysSupported()) { test.ViewSendCompositionKeys("`o"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "ò", "ò"); test.ViewSendCompositionKeys("~o"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "òõ", "òõ"); test.ViewSendCompositionKeys("^o"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "òõô", "òõô"); test.ViewSendCompositionKeys("c="); test.TestReportMsg(test_textentry->text_entry_->GetText() == "òõô€", "òõô€"); test.ViewSendCompositionKeys("oc"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "òõô€©", "òõô€©"); test.ViewSendCompositionKeys("\"w"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "òõô€©ẅ", "òõô€©ẅ"); test.ViewSendCompositionKeys("'S"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "òõô€©ẅŚ", "òõô€©ẅŚ"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100); //exclamdown # INVERTED EXCLAMATION MARK test.ViewSendCompositionKeys("!!"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "¡", "¡"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //CENT SIGN test.ViewSendCompositionKeys("|c"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "¢", "¢"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //POUND SIGN test.ViewSendCompositionKeys("-L"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "£", "£"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //currency # CURRENCY SIGN test.ViewSendCompositionKeys("xo"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "¤", "¤"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //yen # YEN SIGN test.ViewSendCompositionKeys("Y="); test.TestReportMsg(test_textentry->text_entry_->GetText() == "¥", "¥"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //FEMININE ORDINAL INDICATOR test.ViewSendCompositionKeys("^_a"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "ª", "ª"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //guillemotleft # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK test.ViewSendCompositionKeys("<<"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "«", "«"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //SUPERSCRIPT THREE test.ViewSendCompositionKeys("^3"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "³", "³"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //MIDDLE DOT test.ViewSendCompositionKeys(".."); test.TestReportMsg(test_textentry->text_entry_->GetText() == "·", "·"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //cedilla # CEDILLA test.ViewSendCompositionKeys(", "); test.TestReportMsg(test_textentry->text_entry_->GetText() == "¸", "¸"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //VULGAR FRACTION THREE QUARTERS test.ViewSendCompositionKeys("34"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "¾", "¾"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //questiondown # INVERTED QUESTION MARK test.ViewSendCompositionKeys("??"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "¿", "¿"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //LATIN CAPITAL LETTER A WITH GRAVE test.ViewSendCompositionKeys("`A"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "À", "À"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //LATIN CAPITAL LETTER A WITH ACUTE test.ViewSendCompositionKeys("'A"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "Á", "Á"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //LATIN CAPITAL LETTER A WITH CIRCUMFLEX test.ViewSendCompositionKeys("^A"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "Â", "Â"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //LATIN CAPITAL LETTER A WITH TILDE test.ViewSendCompositionKeys("~A"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "Ã", "Ã"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //LATIN CAPITAL LETTER A WITH DIAERESIS test.ViewSendCompositionKeys("\"A"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "Ä", "Ä"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //LATIN CAPITAL LETTER A WITH RING ABOVE test.ViewSendCompositionKeys("oA"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "Å", "Å"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //AE # LATIN CAPITAL LETTER AE test.ViewSendCompositionKeys("AE"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "Æ", "Æ"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //ssharp # LATIN SMALL LETTER SHARP S test.ViewSendCompositionKeys("ss"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "ß", "ß"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //LATIN SMALL LETTER A WITH GRAVE test.ViewSendCompositionKeys("`a"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "à", "à"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //LATIN SMALL LETTER A WITH ACUTE test.ViewSendCompositionKeys("'a"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "á", "á"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //LATIN SMALL LETTER A WITH CIRCUMFLEX test.ViewSendCompositionKeys("^a"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "â", "â"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //LATIN SMALL LETTER A WITH TILDE test.ViewSendCompositionKeys("~a"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "ã", "ã"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //LATIN SMALL LETTER A WITH DIAERESIS test.ViewSendCompositionKeys("\"a"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "ä", "ä"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //LATIN SMALL LETTER A WITH RING ABOVE test.ViewSendCompositionKeys("oa"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "å", "å"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //ae # LATIN SMALL LETTER AE test.ViewSendCompositionKeys("ae"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "æ", "æ"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //DIVISION SIGN test.ViewSendCompositionKeys("-:"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "÷", "÷"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //LATIN CAPITAL LETTER A WITH OGONEK test.ViewSendCompositionKeys(";A"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "Ą", "Ą"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //LATIN SMALL LETTER A WITH OGONEK test.ViewSendCompositionKeys(";a"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "ą", "ą"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //LATIN CAPITAL LETTER A WITH CARON test.ViewSendCompositionKeys("cA"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "Ǎ", "Ǎ"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100); //EN DASH test.ViewSendCompositionKeys("--."); test.TestReportMsg(test_textentry->text_entry_->GetText() == "–", "–"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100); //RIGHT SINGLE QUOTATION MARK test.ViewSendCompositionKeys(">'"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "’", "’"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100); //LEFT DOUBLE QUOTATION MARK test.ViewSendCompositionKeys("<\""); test.TestReportMsg(test_textentry->text_entry_->GetText() == "“", "“"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100); //RIGHT DOUBLE QUOTATION MARK test.ViewSendCompositionKeys("\">"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "”", "”"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100); //DOUBLE LOW-9 QUOTATION MARK test.ViewSendCompositionKeys("\","); test.TestReportMsg(test_textentry->text_entry_->GetText() == "„", "„"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100); //PER MILLE SIGN test.ViewSendCompositionKeys("%o"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "‰", "‰"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100); //SINGLE RIGHT-POINTING ANGLE QUOTATION MARK test.ViewSendCompositionKeys(".>"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "›", "›"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100); //EuroSign # EURO SIGN test.ViewSendCompositionKeys("=E"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "€", "€"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100); //REVERSED DOUBLE PRIME QUOTATION MARK test.ViewSendCompositionKeys("\"\\"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "〝", "〝"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100); } else { test.WarnCompositionKeysNotSupported(); } if (test.WhenDoneTerminateProgram()) { wnd_thread->ExitMainLoop(); } nuxDebugMsg("Exit testing thread"); } int main() { XInitThreads(); test_textentry = new TextTextEntry("Text Entry: Composition Characters", 600, 200, 40000); test_textentry->Startup(); test_textentry->UserInterfaceSetup(); nux::SystemThread* test_thread = nux::CreateSystemThread(NULL, &TestingThread, test_textentry->GetWindowThread()); test_thread->Start(test_textentry); test_textentry->Run(); delete test_thread; delete test_textentry; return 0; } ./tests/test-nux.cpp0000644000004100000410000000254713313171755014716 0ustar www-datawww-data/* * Copyright (C) 2010 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as * published by the Free Software Foundation. * * This program 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 this program. If not, see . * * Authored by Gordon Allott * */ #include #include #include #include #include void TestCanvasSuite(); void TestSystemSuite(); void test_timeline_create_suite (); gint main (gint argc, gchar *argv[]) { #if G_ENCODE_VERSION (GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION) <= GLIB_VERSION_2_34 g_type_init(); #endif g_test_init (&argc, &argv, NULL); nux::NuxInitialize(0); // Do not print Nux log messages to the console. GLogDevice.Disable (); /* First the Nux specific tests */ TestSystemSuite(); // TODO: fix the test // TestCanvasSuite(); /* Please keep this alphabetically ordered */ //test_timeline_create_suite (); return g_test_run (); } ./tests/gtest-nuxcore-main.cpp0000644000004100000410000000050213313171755016645 0ustar www-datawww-data#include #include #include "NuxCore/NuxCore.h" int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); #if G_ENCODE_VERSION (GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION) <= GLIB_VERSION_2_34 g_type_init(); #endif nux::NuxCoreInitialize(0); return RUN_ALL_TESTS(); } ./tests/manual-tests/0000755000004100000410000000000013313171755015030 5ustar www-datawww-data./tests/manual-tests/text-entry.txt0000644000004100000410000000103213313171755017710 0ustar www-datawww-dataText Entry - Mouse cursor ----------- This test makes sure that the mouse pointer changes when it is inside a text entry area. #. Make sure you're running Unity 3d; #. Press Super #. Move the cursor on dash text entry. Outcome The caret mouse cursor should be shown. Text Entry - Drag ----------- This test makes sure that the drag inside the dash works well. #. Make sure you're running Unity 3d; #. Press Super #. Type something inside dash search bar. #. Use mouse drag to select part of the test. Outcome It should work. ./tests/manual-tests/linaro-reference-fbo.txt0000644000004100000410000000114313313171755021554 0ustar www-datawww-data The logic behind the reference framebuffer: - by default there is no reference frame buffer set and Nux render to the opengl back buffer. - When a reference frame buffer is set Nux does its rendering into the reference frame buffer texture. - it is up to the caller to display the texture from the reference frame buffer into the back buffer. To test this, a sample program would set a reference frame buffer and have Nux render a single color quad all over the window. Then the program would dump the texture in the reference frame buffer to memory and compare a few texels with the color that was used. ./tests/xtest-text-entry-compositionkeys.cpp0000644000004100000410000003441613313171755021654 0ustar www-datawww-data/* * Copyright 2010 Inalogic Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY 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 * version 3 along with this program. If not, see * * * Authored by: Jay Taoko * */ #include "Nux/Nux.h" #include "Nux/WindowThread.h" #include "Nux/VLayout.h" #include "Nux/TextEntry.h" #include "Nux/InputMethodIBus.h" #include "Nux/ProgramFramework/ProgramTemplate.h" #include "Nux/ProgramFramework/TestView.h" #include #include #include "nux_automated_test_framework.h" class TextTextEntry: public ProgramTemplate { public: TextTextEntry(const char* program_name, int window_width, int window_height, int program_life_span); ~TextTextEntry(); virtual void UserInterfaceSetup(); void TextEntryClick(nux::TextEntry* text_entry); void ResetEvents(); nux::TextEntry* text_entry_; bool clicked_; }; TextTextEntry::TextTextEntry(const char* program_name, int window_width, int window_height, int program_life_span) : ProgramTemplate(program_name, window_width, window_height, program_life_span) { ResetEvents(); text_entry_ = NULL; } TextTextEntry::~TextTextEntry() { } void TextTextEntry::ResetEvents() { clicked_ = false; } void TextTextEntry::TextEntryClick(nux::TextEntry* text_entry) { if (text_entry_ == text_entry) { clicked_ = true; } } void TextTextEntry::UserInterfaceSetup() { nux::VLayout* main_layout = new nux::VLayout(NUX_TRACKER_LOCATION); text_entry_ = new nux::TextEntry("", NUX_TRACKER_LOCATION); text_entry_->SetFontSize(76); main_layout->AddView(text_entry_, 0, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL); main_layout->SetSpaceBetweenChildren(10); main_layout->SetContentDistribution(nux::MAJOR_POSITION_CENTER); static_cast(window_thread_)->SetLayout(main_layout); nux::ColorLayer background(nux::Color(0xFF4D4D4D)); static_cast(window_thread_)->SetWindowBackgroundPaintLayer(&background); } TextTextEntry* test_textentry = NULL; void TestingThread(nux::NThread* /* thread */, void* user_data) { while (test_textentry->ReadyToGo() == false) { nuxDebugMsg("Waiting to start"); nux::SleepForMilliseconds(300); } nux::SleepForMilliseconds(1300); nux::WindowThread* wnd_thread = static_cast(user_data); NuxAutomatedTestFramework test(wnd_thread); test.Startup(); test.TestReportMsg(test_textentry->text_entry_, "TextEntry created"); if (test.CompositionKeysSupported()) { test_textentry->ResetEvents(); test.ViewSendMouseMotionToCenter(test_textentry->text_entry_); test.ViewSendMouseClick(0, 1); test.ViewSendCompositionKeys("`o"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "ò", "ò"); test.ViewSendCompositionKeys("~o"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "òõ", "òõ"); test.ViewSendCompositionKeys("^o"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "òõô", "òõô"); test.ViewSendCompositionKeys("c="); test.TestReportMsg(test_textentry->text_entry_->GetText() == "òõô€", "òõô€"); test.ViewSendCompositionKeys("oc"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "òõô€©", "òõô€©"); test.ViewSendCompositionKeys("\"w"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "òõô€©ẅ", "òõô€©ẅ"); test.ViewSendCompositionKeys("'S"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "òõô€©ẅŚ", "òõô€©ẅŚ"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //exclamdown # INVERTED EXCLAMATION MARK test.ViewSendCompositionKeys("!!"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "¡", "¡"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //CENT SIGN test.ViewSendCompositionKeys("|c"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "¢", "¢"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //POUND SIGN test.ViewSendCompositionKeys("-L"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "£", "£"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //currency # CURRENCY SIGN test.ViewSendCompositionKeys("xo"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "¤", "¤"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //yen # YEN SIGN test.ViewSendCompositionKeys("Y="); test.TestReportMsg(test_textentry->text_entry_->GetText() == "¥", "¥"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //FEMININE ORDINAL INDICATOR test.ViewSendCompositionKeys("^_a"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "ª", "ª"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //guillemotleft # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK test.ViewSendCompositionKeys("<<"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "«", "«"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //SUPERSCRIPT THREE test.ViewSendCompositionKeys("^3"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "³", "³"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //MIDDLE DOT test.ViewSendCompositionKeys(".."); test.TestReportMsg(test_textentry->text_entry_->GetText() == "·", "·"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //cedilla # CEDILLA test.ViewSendCompositionKeys(", "); test.TestReportMsg(test_textentry->text_entry_->GetText() == "¸", "¸"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //VULGAR FRACTION THREE QUARTERS test.ViewSendCompositionKeys("34"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "¾", "¾"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //questiondown # INVERTED QUESTION MARK test.ViewSendCompositionKeys("??"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "¿", "¿"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //LATIN CAPITAL LETTER A WITH GRAVE test.ViewSendCompositionKeys("`A"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "À", "À"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //LATIN CAPITAL LETTER A WITH ACUTE test.ViewSendCompositionKeys("'A"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "Á", "Á"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //LATIN CAPITAL LETTER A WITH CIRCUMFLEX test.ViewSendCompositionKeys("^A"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "Â", "Â"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //LATIN CAPITAL LETTER A WITH TILDE test.ViewSendCompositionKeys("~A"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "Ã", "Ã"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //LATIN CAPITAL LETTER A WITH DIAERESIS test.ViewSendCompositionKeys("\"A"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "Ä", "Ä"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //LATIN CAPITAL LETTER A WITH RING ABOVE test.ViewSendCompositionKeys("oA"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "Å", "Å"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //AE # LATIN CAPITAL LETTER AE test.ViewSendCompositionKeys("AE"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "Æ", "Æ"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //ssharp # LATIN SMALL LETTER SHARP S test.ViewSendCompositionKeys("ss"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "ß", "ß"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //LATIN SMALL LETTER A WITH GRAVE test.ViewSendCompositionKeys("`a"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "à", "à"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //LATIN SMALL LETTER A WITH ACUTE test.ViewSendCompositionKeys("'a"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "á", "á"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //LATIN SMALL LETTER A WITH CIRCUMFLEX test.ViewSendCompositionKeys("^a"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "â", "â"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //LATIN SMALL LETTER A WITH TILDE test.ViewSendCompositionKeys("~a"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "ã", "ã"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //LATIN SMALL LETTER A WITH DIAERESIS test.ViewSendCompositionKeys("\"a"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "ä", "ä"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //LATIN SMALL LETTER A WITH RING ABOVE test.ViewSendCompositionKeys("oa"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "å", "å"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //ae # LATIN SMALL LETTER AE test.ViewSendCompositionKeys("ae"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "æ", "æ"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //DIVISION SIGN test.ViewSendCompositionKeys("-:"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "÷", "÷"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //LATIN CAPITAL LETTER A WITH OGONEK test.ViewSendCompositionKeys(";A"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "Ą", "Ą"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //LATIN SMALL LETTER A WITH OGONEK test.ViewSendCompositionKeys(";a"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "ą", "ą"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100);; //LATIN CAPITAL LETTER A WITH CARON test.ViewSendCompositionKeys("cA"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "Ǎ", "Ǎ"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100); //EN DASH test.ViewSendCompositionKeys("--."); test.TestReportMsg(test_textentry->text_entry_->GetText() == "–", "–"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100); //RIGHT SINGLE QUOTATION MARK test.ViewSendCompositionKeys(">'"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "’", "’"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100); //LEFT DOUBLE QUOTATION MARK test.ViewSendCompositionKeys("<\""); test.TestReportMsg(test_textentry->text_entry_->GetText() == "“", "“"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100); //RIGHT DOUBLE QUOTATION MARK test.ViewSendCompositionKeys("\">"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "”", "”"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100); //DOUBLE LOW-9 QUOTATION MARK test.ViewSendCompositionKeys("\","); test.TestReportMsg(test_textentry->text_entry_->GetText() == "„", "„"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100); //PER MILLE SIGN test.ViewSendCompositionKeys("%o"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "‰", "‰"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100); //SINGLE RIGHT-POINTING ANGLE QUOTATION MARK test.ViewSendCompositionKeys(".>"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "›", "›"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100); //EuroSign # EURO SIGN test.ViewSendCompositionKeys("=E"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "€", "€"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100); //REVERSED DOUBLE PRIME QUOTATION MARK test.ViewSendCompositionKeys("\"\\"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "〝", "〝"); test.ViewSendCtrlA(); test.ViewSendDelete(); nux::SleepForMilliseconds(100); } else { test.WarnCompositionKeysNotSupported(); } if (test.WhenDoneTerminateProgram()) { wnd_thread->ExitMainLoop(); } nuxDebugMsg("Exit testing thread"); } int main() { XInitThreads(); test_textentry = new TextTextEntry("Text Entry: Composition Characters", 600, 200, 40000); test_textentry->Startup(); test_textentry->UserInterfaceSetup(); nux::SystemThread* test_thread = nux::CreateSystemThread(NULL, &TestingThread, test_textentry->GetWindowThread()); test_thread->Start(test_textentry); test_textentry->Run(); delete test_thread; delete test_textentry; return 0; } ./tests/xtest-focus-on-mouse-down.cpp0000644000004100000410000001303513313171755020112 0ustar www-datawww-data/* * Copyright 2011 Inalogic Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY 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 * version 3 along with this program. If not, see * * * Authored by: Andrea Azzarone * */ #include "Nux/Nux.h" #include "Nux/WindowThread.h" #include "Nux/VLayout.h" #include "Nux/ProgramFramework/ProgramTemplate.h" #include "Nux/ProgramFramework/TestView.h" #include #include #include "nux_automated_test_framework.h" class FocusOnMouseDownTest: public ProgramTemplate { public: FocusOnMouseDownTest(const char* program_name, int window_width, int window_height, int program_life_span); ~FocusOnMouseDownTest(); virtual void UserInterfaceSetup(); nux::TestView* focus_view_; nux::TestView* no_focus_view_; }; FocusOnMouseDownTest::FocusOnMouseDownTest(const char* program_name, int window_width, int window_height, int program_life_span) : ProgramTemplate(program_name, window_width, window_height, program_life_span) , focus_view_(nullptr) , no_focus_view_(nullptr) { } FocusOnMouseDownTest::~FocusOnMouseDownTest() { } void FocusOnMouseDownTest::UserInterfaceSetup() { nux::VLayout* main_layout = new nux::VLayout(NUX_TRACKER_LOCATION); main_layout->SetSpaceBetweenChildren(10); main_layout->SetPadding(10, 10); focus_view_ = new nux::TestView(NUX_TRACKER_LOCATION); focus_view_->can_focus_ = true; focus_view_->SetAcceptKeyNavFocusOnMouseDown(true); main_layout->AddView(focus_view_, 1, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL); no_focus_view_ = new nux::TestView(NUX_TRACKER_LOCATION); no_focus_view_->can_focus_ = true; no_focus_view_->SetAcceptKeyNavFocusOnMouseDown(false); main_layout->AddView(no_focus_view_, 1, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL); static_cast(window_thread_)->SetLayout(main_layout); nux::ColorLayer background(nux::Color(0xFF4D4D4D)); static_cast(window_thread_)->SetWindowBackgroundPaintLayer(&background); } FocusOnMouseDownTest* focus_on_mouse_down_test = nullptr; void TestingThread(nux::NThread* /* thread */, void* user_data) { while (focus_on_mouse_down_test->ReadyToGo() == false) { nuxDebugMsg("Waiting to start"); nux::SleepForMilliseconds(300); } nux::SleepForMilliseconds(1000); nux::WindowThread* wnd_thread = static_cast(user_data); NuxAutomatedTestFramework test(wnd_thread); test.Startup(); // Set the mouse at coordinates (0, 0) (top-left corner) on the display test.PutMouseAt(0, 0); test.TestReportMsg(focus_on_mouse_down_test->focus_view_, "Focus view created"); test.TestReportMsg(focus_on_mouse_down_test->no_focus_view_, "No focus view created"); // Move mouse to center of focus_view test.ViewSendMouseMotionToCenter(focus_on_mouse_down_test->focus_view_); // Mouse down/up on focus_view_ test.ViewSendMouseClick(focus_on_mouse_down_test->focus_view_, 1); nux::SleepForMilliseconds(500); test.TestReportMsg(focus_on_mouse_down_test->focus_view_->has_focus_, "Mouse down: focus_view_ got the focus"); test.ViewSendMouseUp(focus_on_mouse_down_test->focus_view_, 1); nux::SleepForMilliseconds(500); test.TestReportMsg(focus_on_mouse_down_test->focus_view_->has_focus_, "Mouse up: focus is still on focus_view_"); // Move mouse to center of no_focus_view test.ViewSendMouseMotionToCenter(focus_on_mouse_down_test->no_focus_view_); // Mouse down/up on no_focus_view_ test.ViewSendMouseDown(focus_on_mouse_down_test->no_focus_view_, 1); nux::SleepForMilliseconds(500); test.TestReportMsg(!focus_on_mouse_down_test->no_focus_view_->has_focus_, "Mouse down: no_focus_view_ did not take the focus"); test.TestReportMsg(focus_on_mouse_down_test->focus_view_->has_focus_, "Mouse down: focus is still on focus_view_"); test.ViewSendMouseUp(focus_on_mouse_down_test->no_focus_view_, 1); nux::SleepForMilliseconds(500); test.TestReportMsg(!focus_on_mouse_down_test->no_focus_view_->has_focus_, "Mouse up: no_focus_view_ still doesn't have the focus"); test.TestReportMsg(focus_on_mouse_down_test->focus_view_->has_focus_, "Mouse up: focus is still on focus_view_"); if (test.WhenDoneTerminateProgram()) { nux::SleepForMilliseconds(1000); wnd_thread->ExitMainLoop(); } nuxDebugMsg("Exit testing thread"); } int main() { XInitThreads(); focus_on_mouse_down_test = new FocusOnMouseDownTest("Focus On Mouse Down Test", 300, 300, 15000); focus_on_mouse_down_test->Startup(); focus_on_mouse_down_test->UserInterfaceSetup(); nux::SystemThread* test_thread = nux::CreateSystemThread(focus_on_mouse_down_test->GetWindowThread(), &TestingThread, focus_on_mouse_down_test->GetWindowThread()); test_thread->Start(focus_on_mouse_down_test); focus_on_mouse_down_test->Run(); delete test_thread; delete focus_on_mouse_down_test; return 0; } ./tests/Readme.txt0000644000004100000410000000405613313171755014356 0ustar www-datawww-data Automated Tests --------------- Since the instruction for the simulated events are comming from a separate thread, the tests are very sensible to timing and can generate false negatives. For this reason, in some location of the code, there are sleeping periodes that have been added to allow time for events to be processed and for results to be generated. All test must be over in 20 seconds or less. Note on the Test: When using the nux::TestView class, a small white square at the top left corner of the TestView area indicate that the view has keyboard focus. Description of tests: --------------------- graphics_display_states: Test the graphics display states after it has been created. empty_window: Display an empty window and close it after 3 seconds. xtest-button: Using XTest, love the mouse around the boundaries of a button view and simulate click and drag mouse events. The program close itself after a delay. xtest-mouse-events: Test the following mouse events: - mouse down - mouse up - mouse click - mouse double-click - mouse drag - mouse enter - mouse leave - mouse move xtest-mouse-buttons: Make sure that only physical mouse button 1, 2 and 3 generate mouse-down and mouse-up events. The artificial button event 4 and 5 should not generate mouse-down or mouse-up events. xtest-hgrid-key-navigation Make sure that the key navigation works well in a GridHLayout. xtest-hlayout-key-navigation Make sure that the key naviagation works well in a HLayout. xtest-vlayout-key-navigation Make sure that the key navigation works well in a VLayout. xtest-focus-on-mouse-down Make sure that AcceptKeyNavFocusOnMouseDown works well. xtest-focus-on-mouse-enter Make sure that AcceptKeyNavFocusOnMouseEnter works well. xtest-keynav-direction Test key navigation. Especially test the direction a key nav is coming from when the view is getting the focus. xtest-text-entry Simulate various operations on the text entry xtest-text-entry-logic Test the state of TextEntry::text_input_mode_ before and after some text is typed in. ./tests/xtest-text-entry-logic.cpp0000644000004100000410000001105213313171755017501 0ustar www-datawww-data/* * Copyright 2010 Inalogic Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY 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 * version 3 along with this program. If not, see * * * Authored by: Jay Taoko * */ #include "Nux/Nux.h" #include "Nux/WindowThread.h" #include "Nux/VLayout.h" #include "Nux/TextEntry.h" #include "Nux/InputMethodIBus.h" #include "Nux/ProgramFramework/ProgramTemplate.h" #include "Nux/ProgramFramework/TestView.h" #include "Nux/ProgramFramework/TestTextEntry.h" #include #include #include "nux_automated_test_framework.h" class TestTextEntry: public ProgramTemplate { public: TestTextEntry(const char* program_name, int window_width, int window_height, int program_life_span); ~TestTextEntry(); virtual void UserInterfaceSetup(); void ResetEvents(); nux::TestTextEntry* text_entry_; }; TestTextEntry::TestTextEntry(const char* program_name, int window_width, int window_height, int program_life_span) : ProgramTemplate(program_name, window_width, window_height, program_life_span) , text_entry_(NULL) { ResetEvents(); } TestTextEntry::~TestTextEntry() { } void TestTextEntry::ResetEvents() { if (text_entry_) text_entry_->ResetEvents(); } void TestTextEntry::UserInterfaceSetup() { nux::VLayout* main_layout = new nux::VLayout(NUX_TRACKER_LOCATION); text_entry_ = new nux::TestTextEntry(NUX_TRACKER_LOCATION); text_entry_->SetFontSize(76); main_layout->AddView(text_entry_, 0, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL); main_layout->SetSpaceBetweenChildren(10); main_layout->SetContentDistribution(nux::MAJOR_POSITION_CENTER); static_cast(window_thread_)->SetLayout(main_layout); nux::ColorLayer background(nux::Color(0xFF4D4D4D)); static_cast(window_thread_)->SetWindowBackgroundPaintLayer(&background); } TestTextEntry* test_textentry = NULL; void TestingThread(nux::NThread* /* thread */, void* user_data) { while (test_textentry->ReadyToGo() == false) { nuxDebugMsg("Waiting to start"); nux::SleepForMilliseconds(300); } nux::SleepForMilliseconds(1300); nux::WindowThread* wnd_thread = static_cast(user_data); NuxAutomatedTestFramework test(wnd_thread); test.Startup(); test.TestReportMsg(test_textentry->text_entry_, "TextEntry created"); test_textentry->ResetEvents(); test.ViewSendMouseMotionToCenter(test_textentry->text_entry_); test.TestReportMsg(test_textentry->text_entry_->HasKeyFocus() == false, "Focus test"); test.TestReportMsg(test_textentry->text_entry_->IsInTextInputMode() == false, "Text input mode test"); test.ViewSendMouseClick(0, 1); test.TestReportMsg(test_textentry->text_entry_->HasKeyFocus() == true, "Focus test"); test.TestReportMsg(test_textentry->text_entry_->IsInTextInputMode() == false, "Text input mode test"); // Type "Nux" // The cursor is at the end of the line // Simulate CTRL+A to select the entire text // Simulate DELETE key to delete the text { test.ViewSendString("Nux"); test.TestReportMsg(test_textentry->text_entry_->GetText() == "Nux", "Typed \"Nux\""); test.TestReportMsg(test_textentry->text_entry_->IsInTextInputMode() == true, "Text input mode test"); test.ViewSendCtrlA(); nux::SleepForMilliseconds(500); test.TestReportMsg(test_textentry->text_entry_->GetTextSelection() == "Nux", "Selection is \"Nux\""); test.ViewSendDelete(); nux::SleepForMilliseconds(500); test.TestReportMsg(test_textentry->text_entry_->GetText() == "", "TextEntry is empty"); } if (test.WhenDoneTerminateProgram()) { wnd_thread->ExitMainLoop(); } nuxDebugMsg("Exit testing thread"); } int main() { XInitThreads(); test_textentry = new TestTextEntry("Text Entry", 600, 200, 10000); test_textentry->Startup(); test_textentry->UserInterfaceSetup(); nux::SystemThread* test_thread = nux::CreateSystemThread(NULL, &TestingThread, test_textentry->GetWindowThread()); test_thread->Start(test_textentry); test_textentry->Run(); delete test_thread; delete test_textentry; return 0; } ./tests/gtest-nux-windowcompositor.cpp0000644000004100000410000010034013313171755020477 0ustar www-datawww-data#include #include #include #include #include #include #include #include "Nux/Nux.h" #include "Nux/BaseWindow.h" #include "Nux/InputAreaProximity.h" #include "Nux/HLayout.h" #include "Nux/VLayout.h" #include "Nux/ProgramFramework/TestView.h" #ifdef NUX_GESTURES_SUPPORT #include "NuxGraphics/GestureEvent.h" #include "FakeGestureEvent.h" #endif using namespace testing; namespace { #ifdef NUX_GESTURES_SUPPORT class TestWindow : public nux::BaseWindow { public: virtual nux::GestureDeliveryRequest GestureEvent(const nux::GestureEvent &event) { gesture_events_received.push_back(event); return nux::GestureDeliveryRequest::NONE; } std::list gesture_events_received; }; class TestInputArea : public nux::InputArea { public: virtual nux::GestureDeliveryRequest GestureEvent(const nux::GestureEvent &event) { gesture_events_received.push_back(event); return nux::GestureDeliveryRequest::NONE; } std::list gesture_events_received; }; #endif struct TestBaseWindow : public nux::BaseWindow { TestBaseWindow() : input_area(new nux::InputArea()) { ShowWindow(true); } nux::Area* FindAreaUnderMouse(const nux::Point& /* mouse_position */, nux::NuxEventType /* event_type */) { return input_area.GetPointer(); } Area* FindKeyFocusArea(unsigned int /* key_symbol */, unsigned long /* x11_key_code */, unsigned long /* special_keys_state */) { return input_area.GetPointer(); } nux::ObjectPtr input_area; }; struct TestHLayout : public nux::HLayout { TestHLayout() : input_area(new nux::InputArea()) {} nux::Area* FindAreaUnderMouse(const nux::Point& /* mouse_position */, nux::NuxEventType /* event_type */) { return input_area.GetPointer(); } Area* FindKeyFocusArea(unsigned int /* key_symbol */, unsigned long /* x11_key_code */, unsigned long /* special_keys_state */) { return input_area.GetPointer(); } nux::ObjectPtr input_area; }; } namespace nux { struct TestWindowCompositor : public testing::Test { TestWindowCompositor() {} void SetUp() { nux::NuxInitialize(0); wnd_thread.reset(nux::CreateNuxWindow("WindowCompositor Test", 300, 200, nux::WINDOWSTYLE_NORMAL, NULL, false, NULL, NULL)); } void ForceSetKeyFocusArea(nux::InputArea* area) { nux::GetWindowCompositor().key_focus_area_ = area; } ObjectWeakPtr const& GetMouseOwnerArea() const { return nux::GetWindowCompositor().GetMouseOwnerArea(); } void SetMouseOwnerArea(InputArea* area) { nux::GetWindowCompositor().mouse_owner_area_ = area; } InputArea* GetMouseOverArea() { return nux::GetWindowCompositor().mouse_over_area_.GetPointer(); } void SetMouseOverArea(InputArea* area) { nux::GetWindowCompositor().mouse_over_area_ = area; } void GetAreaUnderMouse(const Point& mouse_position, NuxEventType event_type, ObjectWeakPtr& area) { return nux::GetWindowCompositor().FindAreaUnderMouse(mouse_position, event_type, area); } void FindKeyFocusArea(NuxEventType event_type, unsigned int key_symbol, unsigned int state, ObjectWeakPtr& key_focus_area, ObjectWeakPtr& window) { return nux::GetWindowCompositor().FindKeyFocusArea(event_type, key_symbol, state, key_focus_area, window); } boost::shared_ptr wnd_thread; }; namespace { typedef void (*NGLGenFramebuffers)(GLsizei, GLuint *); typedef void (*NGLGenRenderbuffers)(GLsizei, GLuint *); typedef void (*NGLBindFramebuffer)(GLenum, GLuint); typedef void (*NGLBindRenderbuffer)(GLenum, GLuint); typedef void (*NGLRenderbufferStorage)(GLenum, GLenum, GLsizei, GLsizei); typedef void (*NGLFramebufferRenderbuffer)(GLenum, GLenum, GLenum, GLuint); typedef void (*NGLDeleteFramebuffers)(GLsizei, const GLuint *); typedef void (*NGLDeleteRenderbuffers)(GLsizei, const GLuint *); #ifdef NUX_OPENGLES_20 GLuint NGL_RENDERBUFFER = GL_RENDERBUFFER; /* No separate draw or read targets on OpenGL|ES */ GLuint NGL_DRAW_FRAMEBUFFER = GL_FRAMEBUFFER; GLuint NGL_READ_FRAMEBUFFER = GL_FRAMEBUFFER; GLuint NGL_DRAW_FRAMEBUFFER_BINDING = GL_FRAMEBUFFER_BINDING; GLuint NGL_READ_FRAMEBUFFER_BINDING = GL_FRAMEBUFFER_BINDING; GLuint NGL_COLOR_ATTACHMENT0 = GL_COLOR_ATTACHMENT0; GLuint NGL_RGBA_STORAGE = GL_RGBA4; #else GLuint NGL_RENDERBUFFER = GL_RENDERBUFFER_EXT; GLuint NGL_DRAW_FRAMEBUFFER = GL_DRAW_FRAMEBUFFER_EXT; GLuint NGL_READ_FRAMEBUFFER = GL_READ_FRAMEBUFFER_EXT; GLuint NGL_DRAW_FRAMEBUFFER_BINDING = GL_DRAW_FRAMEBUFFER_BINDING_EXT; GLuint NGL_READ_FRAMEBUFFER_BINDING = GL_DRAW_FRAMEBUFFER_BINDING_EXT; GLuint NGL_COLOR_ATTACHMENT0 = GL_COLOR_ATTACHMENT0_EXT; GLuint NGL_RGBA_STORAGE = GL_RGBA8_EXT; #endif class ReferenceFramebuffer { public: ReferenceFramebuffer () { #ifdef NUX_OPENGLES_20 nglGenFramebuffers = &glGenFramebuffers; nglGenRenderbuffers = &glGenRenderbuffers; nglBindRenderbuffer = &glBindRenderbuffer; nglBindFramebuffer = &glBindFramebuffer; nglRenderbufferStorage = &glRenderbufferStorage; nglFramebufferRenderbuffer = &glFramebufferRenderbuffer; nglDeleteRenderbuffers = &glDeleteRenderbuffers; nglDeleteFramebuffers = &glDeleteFramebuffers; #else nglGenFramebuffers = glGenFramebuffersEXT; nglGenRenderbuffers = glGenRenderbuffersEXT; nglBindRenderbuffer = glBindRenderbufferEXT; nglBindFramebuffer = glBindFramebufferEXT; nglRenderbufferStorage = glRenderbufferStorageEXT; nglFramebufferRenderbuffer = glFramebufferRenderbufferEXT; nglDeleteRenderbuffers = glDeleteRenderbuffersEXT; nglDeleteFramebuffers = glDeleteFramebuffersEXT; #endif nglGenFramebuffers(1, &fboName); nglGenRenderbuffers(1, &rbName); nglBindRenderbuffer(NGL_RENDERBUFFER, rbName); nglRenderbufferStorage(NGL_RENDERBUFFER, NGL_RGBA_STORAGE, 300, 200); nglBindFramebuffer(NGL_DRAW_FRAMEBUFFER, fboName); nglBindFramebuffer(NGL_READ_FRAMEBUFFER, fboName); nglFramebufferRenderbuffer(NGL_DRAW_FRAMEBUFFER, NGL_COLOR_ATTACHMENT0, NGL_RENDERBUFFER, rbName); } ~ReferenceFramebuffer () { nglBindFramebuffer(NGL_DRAW_FRAMEBUFFER, 0); nglBindFramebuffer(NGL_READ_FRAMEBUFFER, 0); nglDeleteRenderbuffers(1, &rbName); nglDeleteFramebuffers(1, &fboName); } GLuint fboName, rbName; /* Each instance of the class needs to keep its own * copy of the extension functions as glewInit () needs * to be called in the desktop case before they are available */ NGLGenFramebuffers nglGenFramebuffers; NGLGenRenderbuffers nglGenRenderbuffers; NGLBindRenderbuffer nglBindRenderbuffer; NGLBindFramebuffer nglBindFramebuffer; NGLRenderbufferStorage nglRenderbufferStorage; NGLFramebufferRenderbuffer nglFramebufferRenderbuffer; NGLDeleteRenderbuffers nglDeleteRenderbuffers; NGLDeleteFramebuffers nglDeleteFramebuffers; }; } TEST_F(TestWindowCompositor, TestRestoreReferenceFramebufferDirect) { ReferenceFramebuffer reference; GLint dfbBinding, rfbBinding; glGetIntegerv(NGL_DRAW_FRAMEBUFFER_BINDING, &dfbBinding); glGetIntegerv(NGL_READ_FRAMEBUFFER_BINDING, &rfbBinding); ASSERT_EQ (dfbBinding, reference.fboName); wnd_thread->GetWindowCompositor().SetReferenceFramebuffer(dfbBinding, rfbBinding, nux::Geometry (0, 0, 300, 200)); ASSERT_TRUE (wnd_thread->GetWindowCompositor().RestoreReferenceFramebuffer()); glGetIntegerv(NGL_DRAW_FRAMEBUFFER_BINDING, &dfbBinding); glGetIntegerv(NGL_READ_FRAMEBUFFER_BINDING, &rfbBinding); ASSERT_EQ (dfbBinding, reference.fboName); ASSERT_EQ (rfbBinding, reference.fboName); } TEST_F(TestWindowCompositor, TestRestoreReferenceFramebufferThroughRestoreMain) { ReferenceFramebuffer reference; GLint dfbBinding, rfbBinding; glGetIntegerv(NGL_DRAW_FRAMEBUFFER_BINDING, &dfbBinding); glGetIntegerv(NGL_READ_FRAMEBUFFER_BINDING, &rfbBinding); ASSERT_EQ(dfbBinding, reference.fboName); wnd_thread->GetWindowCompositor().SetReferenceFramebuffer(dfbBinding, rfbBinding, nux::Geometry (0, 0, 300, 200)); wnd_thread->GetWindowCompositor().RestoreMainFramebuffer(); glGetIntegerv(NGL_DRAW_FRAMEBUFFER_BINDING, &dfbBinding); glGetIntegerv(NGL_READ_FRAMEBUFFER_BINDING, &rfbBinding); ASSERT_EQ(dfbBinding, reference.fboName); ASSERT_EQ(rfbBinding, reference.fboName); } TEST_F(TestWindowCompositor, TestRestoreBackbufferThroughRestoreMain) { ReferenceFramebuffer reference; GLint dfbBinding, rfbBinding; glGetIntegerv(NGL_DRAW_FRAMEBUFFER_BINDING, &dfbBinding); glGetIntegerv(NGL_READ_FRAMEBUFFER_BINDING, &rfbBinding); ASSERT_EQ (dfbBinding, reference.fboName); wnd_thread->GetWindowCompositor().RestoreMainFramebuffer(); glGetIntegerv(NGL_DRAW_FRAMEBUFFER_BINDING, &dfbBinding); glGetIntegerv(NGL_READ_FRAMEBUFFER_BINDING, &rfbBinding); ASSERT_EQ(dfbBinding, 0); ASSERT_EQ(rfbBinding, 0); } TEST_F(TestWindowCompositor, TestSetKeyFocusArea) { nux::TestView* test_view0 = new nux::TestView(); nux::TestView* test_view1 = new nux::TestView(); nux::HLayout* layout = new nux::HLayout(); layout->AddView(test_view0, 1); layout->AddView(test_view1, 1); wnd_thread->SetLayout(layout); // Set keyboard focus on test_view0 { wnd_thread->GetWindowCompositor().SetKeyFocusArea(test_view0); // Check that test_view0 has registered a keynav focus event EXPECT_EQ(test_view0->registered_begin_keynav_focus_, true); EXPECT_EQ(test_view0->registered_end_keynav_focus_, false); EXPECT_EQ(test_view1->registered_begin_keynav_focus_, false); EXPECT_EQ(test_view1->registered_end_keynav_focus_, false); test_view0->ResetKeyFocusEvents(); } // Set keyboard focus on test_view1 { wnd_thread->GetWindowCompositor().SetKeyFocusArea(test_view1); EXPECT_EQ(test_view0->registered_begin_keynav_focus_, false); // Check that test_view0 has loast the keynav focus. EXPECT_EQ(test_view0->registered_end_keynav_focus_, true); // Check that test_view1 has registered a keynav focus event EXPECT_EQ(test_view1->registered_begin_keynav_focus_, true); EXPECT_EQ(test_view1->registered_end_keynav_focus_, false); } } TEST_F(TestWindowCompositor, TestInputAreaProximityNullValue) { const int prox_size = nux::GetWindowCompositor().GetProximityListSize(); nux::InputAreaProximity* prox_area = new nux::InputAreaProximity(NULL, 10); ASSERT_EQ(nux::GetWindowCompositor().GetProximityListSize(), prox_size); delete prox_area; } #ifdef NUX_GESTURES_SUPPORT /* We have two windows: one subscribed to 2-touches' pinch (A) and another without any subscriptions (B). Send events of a 2-touches' pinch within window A's boundaries. Check that the gesture got accepted, that window A got the gesture events and that window B didn't get anything. */ TEST_F(TestWindowCompositor, GestureEventsDelivery_1) { nux::WindowCompositor &wnd_compositor = wnd_thread->GetWindowCompositor(); nux::FakeGestureEvent fake_event; TestWindow *target_window = new TestWindow; target_window->SetBaseXY(10, 10); target_window->SetBaseWidth(90); target_window->SetBaseHeight(90); target_window->ShowWindow(true); target_window->CreateGesturesSubscription(nux::PINCH_GESTURE, 2); TestWindow *innocent_window = new TestWindow; innocent_window->SetBaseXY(300, 300); innocent_window->SetBaseWidth(100); innocent_window->SetBaseHeight(100); innocent_window->ShowWindow(true); g_gesture_acceptance[0] = 0; fake_event.type = nux::EVENT_GESTURE_BEGIN; fake_event.gesture_id = 0; fake_event.gesture_classes = nux::PINCH_GESTURE | nux::ROTATE_GESTURE; fake_event.is_direct_touch = false; fake_event.focus.x = 30.0f; // hits target_window fake_event.focus.y = 30.0f; // in touch device's coordinate system (because it's not a direct device). // Thus not used by WindowCompositor fake_event.touches.push_back(nux::TouchPoint(0, 10.0f, 10.0f)); fake_event.touches.push_back(nux::TouchPoint(1, 20.0f, 20.0f)); fake_event.is_construction_finished = false; wnd_compositor.ProcessEvent(fake_event.ToGestureEvent()); ASSERT_EQ(0, g_gesture_acceptance[0]); ASSERT_EQ(0, target_window->gesture_events_received.size()); ASSERT_EQ(0, innocent_window->gesture_events_received.size()); fake_event.type = nux::EVENT_GESTURE_UPDATE; fake_event.focus.x += 2.0f; fake_event.focus.y += 2.0f; fake_event.touches.clear(); fake_event.touches.push_back(nux::TouchPoint(0, 11.0f, 11.0f)); fake_event.touches.push_back(nux::TouchPoint(1, 21.0f, 21.0f)); fake_event.is_construction_finished = true; wnd_compositor.ProcessEvent(fake_event.ToGestureEvent()); ASSERT_EQ(1, g_gesture_acceptance[0]); ASSERT_EQ(2, target_window->gesture_events_received.size()); ASSERT_EQ(0, innocent_window->gesture_events_received.size()); target_window->Dispose(); innocent_window->Dispose(); } /* We have two windows: one subscribed to 2-touches' pinch (A) and another without any subscriptions (B). Send events of a 2-touches' pinch within window B's boundaries. Check that the gesture got rejected and that no window got any gesture event. */ TEST_F(TestWindowCompositor, GestureEventsDelivery_2) { nux::FakeGestureEvent fake_event; nux::WindowCompositor& wnd_compositor = nux::GetWindowCompositor(); TestWindow *subscribed_window = new TestWindow; subscribed_window->SetBaseXY(10, 10); subscribed_window->SetBaseWidth(90); subscribed_window->SetBaseHeight(90); subscribed_window->ShowWindow(true); subscribed_window->CreateGesturesSubscription(nux::PINCH_GESTURE, 2); TestWindow *innocent_window = new TestWindow; innocent_window->SetBaseXY(300, 300); innocent_window->SetBaseWidth(100); innocent_window->SetBaseHeight(100); innocent_window->ShowWindow(true); g_gesture_acceptance[0] = 0; fake_event.type = nux::EVENT_GESTURE_BEGIN; fake_event.gesture_id = 0; fake_event.gesture_classes = nux::PINCH_GESTURE | nux::ROTATE_GESTURE; fake_event.is_direct_touch = false; fake_event.focus.x = 350.0f; // hits innocent_window fake_event.focus.y = 350.0f; // in touch device's coordinate system (because it's not a direct device). // Thus not used by WindowCompositor fake_event.touches.push_back(nux::TouchPoint(0, 10.0f, 10.0f)); fake_event.touches.push_back(nux::TouchPoint(1, 20.0f, 20.0f)); fake_event.is_construction_finished = false; wnd_compositor.ProcessEvent(fake_event.ToGestureEvent()); ASSERT_EQ(-1, g_gesture_acceptance[0]); ASSERT_EQ(0, subscribed_window->gesture_events_received.size()); ASSERT_EQ(0, innocent_window->gesture_events_received.size()); subscribed_window->Dispose(); innocent_window->Dispose(); } /* There are two input areas in main window's layout. They're both subscribed to 2-touches' pinch gestures. There's also a window on top that is subscribed to 2-touches' drag gestures. Send events of a 2-touches' pinch within that window's boundaries. Check that the gesture gets accepted and that only the input area behind that window gets the gesture events. */ TEST_F(TestWindowCompositor, GestureEventsDelivery_3) { nux::FakeGestureEvent fake_event; nux::WindowCompositor& wnd_compositor = nux::GetWindowCompositor(); TestWindow *window = new TestWindow; window->SetBaseXY(10, 10); window->SetBaseWidth(90); window->SetBaseHeight(90); window->ShowWindow(true); window->CreateGesturesSubscription(nux::DRAG_GESTURE, 2); TestInputArea *target_input_area = new TestInputArea; target_input_area->CreateGesturesSubscription(nux::PINCH_GESTURE, 2); TestInputArea *other_input_area = new TestInputArea; other_input_area->CreateGesturesSubscription(nux::PINCH_GESTURE, 2); nux::VLayout *root_layout = new nux::VLayout; root_layout->AddView(target_input_area); // should have geometry (0, 0, 500, 250) root_layout->AddView(other_input_area); // should have geometry (0, 250, 500, 250) wnd_thread->SetLayout(root_layout); g_gesture_acceptance[0] = 0; fake_event.type = nux::EVENT_GESTURE_BEGIN; fake_event.gesture_id = 0; fake_event.gesture_classes = nux::PINCH_GESTURE | nux::ROTATE_GESTURE; fake_event.is_direct_touch = false; fake_event.focus.x = 30.0f; // hits window and target_input_area behind it fake_event.focus.y = 30.0f; // in touch device's coordinate system (because it's not a direct device). // Thus not used by WindowCompositor fake_event.touches.push_back(nux::TouchPoint(0, 10.0f, 10.0f)); fake_event.touches.push_back(nux::TouchPoint(1, 20.0f, 20.0f)); fake_event.is_construction_finished = false; wnd_compositor.ProcessEvent(fake_event.ToGestureEvent()); // shouldn't be accepted right away because is_construction_finished == false ASSERT_EQ(0, g_gesture_acceptance[0]); ASSERT_EQ(0, window->gesture_events_received.size()); ASSERT_EQ(0, target_input_area->gesture_events_received.size()); ASSERT_EQ(0, other_input_area->gesture_events_received.size()); fake_event.type = nux::EVENT_GESTURE_UPDATE; fake_event.focus.x += 2.0f; fake_event.focus.y += 2.0f; fake_event.touches.clear(); fake_event.touches.push_back(nux::TouchPoint(0, 11.0f, 11.0f)); fake_event.touches.push_back(nux::TouchPoint(1, 21.0f, 21.0f)); fake_event.is_construction_finished = true; wnd_compositor.ProcessEvent(fake_event.ToGestureEvent()); ASSERT_EQ(1, g_gesture_acceptance[0]); ASSERT_EQ(0, window->gesture_events_received.size()); ASSERT_EQ(2, target_input_area->gesture_events_received.size()); ASSERT_EQ(0, other_input_area->gesture_events_received.size()); window->Dispose(); } /* Check that if a gesture gets its construction finished only on its end event, it still gets accepted and delivered. */ TEST_F(TestWindowCompositor, GestureEventsDelivery_4) { nux::FakeGestureEvent fake_event; nux::WindowCompositor& wnd_compositor = nux::GetWindowCompositor(); TestWindow *window = new TestWindow; window->SetBaseXY(10, 10); window->SetBaseWidth(90); window->SetBaseHeight(90); window->ShowWindow(true); window->CreateGesturesSubscription(nux::DRAG_GESTURE, 2); TestInputArea *target_input_area = new TestInputArea; target_input_area->CreateGesturesSubscription(nux::PINCH_GESTURE, 2); TestInputArea *other_input_area = new TestInputArea; other_input_area->CreateGesturesSubscription(nux::PINCH_GESTURE, 2); nux::VLayout *root_layout = new nux::VLayout; root_layout->AddView(target_input_area); // should have geometry (0, 0, 500, 250) root_layout->AddView(other_input_area); // should have geometry (0, 250, 500, 250) wnd_thread->SetLayout(root_layout); g_gesture_acceptance[0] = 0; fake_event.type = nux::EVENT_GESTURE_BEGIN; fake_event.gesture_id = 0; fake_event.gesture_classes = nux::PINCH_GESTURE | nux::ROTATE_GESTURE; fake_event.is_direct_touch = false; fake_event.focus.x = 30.0f; // hits window and target_input_area behind it fake_event.focus.y = 30.0f; // in touch device's coordinate system (because it's not a direct device). // Thus not used by WindowCompositor fake_event.touches.push_back(nux::TouchPoint(0, 10.0f, 10.0f)); fake_event.touches.push_back(nux::TouchPoint(1, 20.0f, 20.0f)); fake_event.is_construction_finished = false; wnd_compositor.ProcessEvent(fake_event.ToGestureEvent()); // shouldn't be accepted right away because is_construction_finished == false ASSERT_EQ(0, g_gesture_acceptance[0]); ASSERT_EQ(0, window->gesture_events_received.size()); ASSERT_EQ(0, target_input_area->gesture_events_received.size()); ASSERT_EQ(0, other_input_area->gesture_events_received.size()); fake_event.type = nux::EVENT_GESTURE_END; fake_event.focus.x += 2.0f; fake_event.focus.y += 2.0f; fake_event.touches.clear(); fake_event.touches.push_back(nux::TouchPoint(0, 11.0f, 11.0f)); fake_event.touches.push_back(nux::TouchPoint(1, 21.0f, 21.0f)); fake_event.is_construction_finished = true; wnd_compositor.ProcessEvent(fake_event.ToGestureEvent()); ASSERT_EQ(1, g_gesture_acceptance[0]); ASSERT_EQ(0, window->gesture_events_received.size()); ASSERT_EQ(2, target_input_area->gesture_events_received.size()); ASSERT_EQ(0, other_input_area->gesture_events_received.size()); window->Dispose(); } TEST_F(TestWindowCompositor, KeyFocusAreaAutomaticallyUnsets) { nux::WindowCompositor& wnd_compositor = nux::GetWindowCompositor(); nux::InputArea* test_area = new TestInputArea(); ForceSetKeyFocusArea(test_area); ASSERT_EQ(wnd_compositor.GetKeyFocusArea(), test_area); test_area->UnReference(); EXPECT_EQ(wnd_compositor.GetKeyFocusArea(), nullptr); } TEST_F(TestWindowCompositor, MouseOverAreaAutomaticallyUnsets) { nux::InputArea* test_area = new TestInputArea(); SetMouseOverArea(test_area); ASSERT_EQ(GetMouseOverArea(), test_area); test_area->UnReference(); EXPECT_EQ(GetMouseOverArea(), nullptr); } TEST_F(TestWindowCompositor, MouseOwnerAreaAutomaticallyUnsets) { nux::InputArea* test_area = new TestInputArea(); SetMouseOwnerArea(test_area); ASSERT_EQ(GetMouseOwnerArea(), test_area); test_area->UnReference(); EXPECT_EQ(GetMouseOwnerArea(), nullptr); } TEST_F(TestWindowCompositor, GetAreaUnderMouse) { ObjectWeakPtr area; TestBaseWindow* test_win = new TestBaseWindow(); GetAreaUnderMouse(Point(1, 2), NUX_MOUSE_MOVE, area); EXPECT_EQ(area.GetPointer(), test_win->input_area.GetPointer()); test_win->UnReference(); EXPECT_EQ(area.GetPointer(), nullptr); } TEST_F(TestWindowCompositor, GetAreaUnderMouseFallback) { ObjectWeakPtr area; TestHLayout* layout = new TestHLayout(); wnd_thread->SetLayout(layout); GetAreaUnderMouse(Point(1, 2), NUX_MOUSE_MOVE, area); EXPECT_EQ(area.GetPointer(), layout->input_area.GetPointer()); wnd_thread->SetLayout(nullptr); layout->UnReference(); EXPECT_EQ(area.GetPointer(), nullptr); } TEST_F(TestWindowCompositor, GetFocusedArea) { ObjectWeakPtr area; ObjectWeakPtr window; TestBaseWindow* test_win = new TestBaseWindow(); FindKeyFocusArea(NUX_KEYUP, 0, 0, area, window); EXPECT_EQ(area.GetPointer(), test_win->input_area.GetPointer()); EXPECT_EQ(window.GetPointer(), test_win); test_win->UnReference(); EXPECT_EQ(area.GetPointer(), nullptr); EXPECT_EQ(window.GetPointer(), nullptr); } TEST_F(TestWindowCompositor, GetFocusedAreaFallback) { ObjectWeakPtr area; ObjectWeakPtr window; TestHLayout* layout = new TestHLayout(); wnd_thread->SetLayout(layout); FindKeyFocusArea(NUX_KEYUP, 0, 0, area, window); EXPECT_EQ(area.GetPointer(), layout->input_area.GetPointer()); EXPECT_EQ(window.GetPointer(), nullptr); wnd_thread->SetLayout(nullptr); layout->UnReference(); EXPECT_EQ(area.GetPointer(), nullptr); } TEST_F(TestWindowCompositor, UpdateInputAreaMouseInsideOnRelease) { Event ev; ObjectPtr ia1(new TestBaseWindow()); ev.type = EVENT_MOUSE_DOWN; nux::GetWindowCompositor().ProcessEvent(ev); ASSERT_TRUE(ia1->input_area->IsMouseInside()); ASSERT_TRUE(ia1->input_area->IsMouseOwner()); ObjectPtr ia2(new TestBaseWindow()); ev.type = EVENT_MOUSE_UP; nux::GetWindowCompositor().ProcessEvent(ev); EXPECT_FALSE(ia1->input_area->IsMouseOwner()); EXPECT_FALSE(ia1->input_area->IsMouseInside()); EXPECT_NE(GetMouseOverArea(), ia1->input_area.GetPointer()); } TEST_F(TestWindowCompositor, UpdateNewInputAreaMouseInsideOnRelease) { Event ev; ObjectPtr ia1(new TestBaseWindow()); ev.type = EVENT_MOUSE_DOWN; nux::GetWindowCompositor().ProcessEvent(ev); ASSERT_TRUE(ia1->input_area->IsMouseInside()); ASSERT_TRUE(ia1->input_area->IsMouseOwner()); ObjectPtr ia2(new TestBaseWindow()); ev.type = EVENT_MOUSE_UP; nux::GetWindowCompositor().ProcessEvent(ev); EXPECT_FALSE(ia2->input_area->IsMouseOwner()); EXPECT_TRUE(ia2->input_area->IsMouseInside()); EXPECT_EQ(GetMouseOverArea(), ia2->input_area.GetPointer()); } TEST_F(TestWindowCompositor, UpdateNewInputAreaMouseOwnerBeforeSignalEmission) { Event ev; ObjectPtr ia1(new TestBaseWindow()); ev.type = EVENT_MOUSE_DOWN; nux::GetWindowCompositor().ProcessEvent(ev); ASSERT_TRUE(ia1->input_area->IsMouseInside()); ASSERT_TRUE(ia1->input_area->IsMouseOwner()); bool got_cb = false; ia1->input_area->mouse_up.connect([this, &ia1, &got_cb] (int, int, unsigned long, unsigned long) { got_cb = true; EXPECT_TRUE(ia1->input_area->IsMouseInside()); EXPECT_FALSE(ia1->input_area->IsMouseOwner()); }); ev.type = EVENT_MOUSE_UP; nux::GetWindowCompositor().ProcessEvent(ev); ASSERT_TRUE(got_cb); EXPECT_TRUE(ia1->input_area->IsMouseInside()); EXPECT_FALSE(ia1->input_area->IsMouseOwner()); EXPECT_EQ(GetMouseOverArea(), ia1->input_area.GetPointer()); } TEST_F(TestWindowCompositor, InvalidMouseOverAreaOnReleaseDontCrash) { Event ev; ObjectPtr ia1(new TestBaseWindow()); ev.type = EVENT_MOUSE_DOWN; nux::GetWindowCompositor().ProcessEvent(ev); ASSERT_TRUE(ia1->input_area->IsMouseInside()); ASSERT_TRUE(ia1->input_area->IsMouseOwner()); // We save a copy of the input area, so that WC still things it's alive but // the test window won't return it as the target area for events. auto old_mouse_owner_area = ia1->input_area; (void)old_mouse_owner_area; ia1->input_area.Release(); ev.type = EVENT_MOUSE_UP; nux::GetWindowCompositor().ProcessEvent(ev); } TEST_F(TestWindowCompositor, EmitMouseCancelOnReleasedMouseOwner) { Event ev; ObjectPtr ia1(new TestBaseWindow()); ev.type = EVENT_MOUSE_DOWN; nux::GetWindowCompositor().ProcessEvent(ev); ASSERT_TRUE(ia1->input_area->IsMouseOwner()); bool mouse_cancel_called = false; ia1->input_area->mouse_cancel.connect([this, &mouse_cancel_called] { mouse_cancel_called = true; }); ev.type = EVENT_MOUSE_UP; nux::GetWindowCompositor().ProcessEvent(ev); EXPECT_TRUE(mouse_cancel_called); } class DraggedWindow : public nux::BaseWindow { public: DraggedWindow() : mouse_drag_emission_count(0) , mouse_drag_x(0) , mouse_drag_y(0) , mouse_drag_dx(0) , mouse_drag_dy(0) {} protected: virtual void EmitMouseDragSignal(int x, int y, int dx, int dy, unsigned long /*mouse_button_state*/, unsigned long /*special_keys_state*/) { ++mouse_drag_emission_count; mouse_drag_x = x; mouse_drag_y = y; mouse_drag_dx = dx; mouse_drag_dy = dy; } public: int mouse_drag_emission_count; int mouse_drag_x; int mouse_drag_y; int mouse_drag_dx; int mouse_drag_dy; }; /* Regression test for lp1057995 */ TEST_F(TestWindowCompositor, MouseDrag) { nux::Event event; DraggedWindow *window = new DraggedWindow; window->SetBaseXY(60, 70); window->SetBaseWidth(200); window->SetBaseHeight(200); window->ShowWindow(true); event.type = NUX_MOUSE_PRESSED; event.x = 100; event.y = 200; nux::GetWindowCompositor().ProcessEvent(event); event.type = NUX_MOUSE_MOVE; event.x = 50; event.y = 250; nux::GetWindowCompositor().ProcessEvent(event); ASSERT_EQ(1, window->mouse_drag_emission_count); /* OBS: they're in local window coordinates */ ASSERT_EQ(50 - 60, window->mouse_drag_x); ASSERT_EQ(250 - 70, window->mouse_drag_y); ASSERT_EQ(50 - 100, window->mouse_drag_dx); ASSERT_EQ(250 - 200, window->mouse_drag_dy); window->Dispose(); } class TrackerWindow : public nux::BaseWindow { public: TrackerWindow() : mouse_up_emission_count(0) , mouse_drag_emission_count(0) , mouse_drag_dx(0) , mouse_drag_dy(0) {} virtual bool ChildMouseEvent(const nux::Event& event) { child_mouse_events_received.push_back(event); return wants_mouse_ownership; } std::vector child_mouse_events_received; bool wants_mouse_ownership; protected: virtual void EmitMouseUpSignal(int, int, unsigned long, unsigned long) { ++mouse_up_emission_count; } virtual void EmitMouseDragSignal(int, int, int dx, int dy, unsigned long, unsigned long) { ++mouse_drag_emission_count; mouse_drag_dx = dx; mouse_drag_dy = dy; } public: int mouse_up_emission_count; int mouse_drag_emission_count; int mouse_drag_dx; int mouse_drag_dy; }; class TrackedArea : public nux::InputArea { public: TrackedArea() : mouse_down_emission_count(0) , mouse_up_emission_count(0) , mouse_drag_emission_count(0) , mouse_cancel_emission_count(0) {} protected: virtual void EmitMouseDownSignal(int, int, unsigned long, unsigned long) { ++mouse_down_emission_count; } virtual void EmitMouseUpSignal(int, int, unsigned long, unsigned long) { ++mouse_up_emission_count; } virtual void EmitMouseDragSignal(int, int, int, int, unsigned long, unsigned long) { ++mouse_drag_emission_count; } virtual void EmitMouseCancelSignal() { ++mouse_cancel_emission_count; } public: int mouse_down_emission_count; int mouse_up_emission_count; int mouse_drag_emission_count; int mouse_cancel_emission_count; }; TEST_F(TestWindowCompositor, TrackingChildMouseEvents) { nux::WindowCompositor &wnd_compositor = wnd_thread->GetWindowCompositor(); TrackedArea *tracked_area = new TrackedArea; tracked_area->SetGeometry(0, 0, 100, 1000); tracked_area->SetMinimumSize(100, 1000); nux::VLayout *layout = new VLayout(NUX_TRACKER_LOCATION); layout->AddView(tracked_area, 1, eLeft, eFull); layout->Set2DTranslation(0, -123, 0); // x, y, z TrackerWindow *tracker_window = new TrackerWindow; tracker_window->SetBaseXY(0, 0); tracker_window->SetBaseWidth(100); tracker_window->SetBaseHeight(100); tracker_window->SetTrackChildMouseEvents(true); tracker_window->SetLayout(layout); tracker_window->ShowWindow(true); // Mouse pressed goes both to child and tracker window tracker_window->wants_mouse_ownership = false; tracked_area->mouse_down_emission_count = 0; nux::Event event; event.type = NUX_MOUSE_PRESSED; event.x = 50; // right in the center of tracker_window event.y = 50; wnd_compositor.ProcessEvent(event); ASSERT_EQ(1, tracker_window->child_mouse_events_received.size()); ASSERT_EQ(1, tracked_area->mouse_down_emission_count); // Mouse move goes both to child and tracker window, but tracker asks // for mouse ownership. Therefore child also gets a mouse cancel. tracker_window->child_mouse_events_received.clear(); tracker_window->wants_mouse_ownership = true; tracked_area->mouse_drag_emission_count = 0; tracked_area->mouse_cancel_emission_count = 0; event.type = NUX_MOUSE_MOVE; event.y = 60; wnd_compositor.ProcessEvent(event); ASSERT_EQ(1, tracker_window->child_mouse_events_received.size()); ASSERT_EQ(1, tracked_area->mouse_drag_emission_count); ASSERT_EQ(2, tracked_area->mouse_cancel_emission_count); // The second mouse move goes only to the window, but now as a regular // mouse event since he's mouse owner now. tracker_window->child_mouse_events_received.clear(); tracker_window->mouse_drag_emission_count = 0; tracked_area->mouse_drag_emission_count = 0; event.type = NUX_MOUSE_MOVE; event.y = 70; wnd_compositor.ProcessEvent(event); ASSERT_EQ(0, tracker_window->child_mouse_events_received.size()); ASSERT_EQ(1, tracker_window->mouse_drag_emission_count); ASSERT_EQ(0, tracked_area->mouse_drag_emission_count); ASSERT_EQ(10, tracker_window->mouse_drag_dy); // Mouse release goes only to the window, again as a regular // mouse event. tracker_window->child_mouse_events_received.clear(); tracker_window->mouse_up_emission_count = 0; tracked_area->mouse_up_emission_count = 0; event.type = NUX_MOUSE_RELEASED; wnd_compositor.ProcessEvent(event); ASSERT_EQ(0, tracker_window->child_mouse_events_received.size()); ASSERT_EQ(1, tracker_window->mouse_up_emission_count); ASSERT_EQ(0, tracked_area->mouse_up_emission_count); tracker_window->Dispose(); } #endif // NUX_GESTURES_SUPPORT } ./tests/test_empty_window.cpp0000644000004100000410000000326013313171755016704 0ustar www-datawww-data/* * Copyright 2010 Inalogic Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY 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 * version 3 along with this program. If not, see * * * Authored by: Jay Taoko * */ #include "Nux/Nux.h" #include "Nux/WindowThread.h" nux::TimeOutSignal *timeout_signal = NULL; void TimeOutCallback(void *data) { nux::WindowThread *thread = static_cast(data); thread->ExitMainLoop(); } void UserInterfaceInitialization(nux::NThread* thread, void* /* init_data */) { nux::ColorLayer background(nux::Color(0xFF4D4D4D)); static_cast(thread)->SetWindowBackgroundPaintLayer(&background); timeout_signal = new nux::TimeOutSignal(); timeout_signal->tick.connect(sigc::ptr_fun(TimeOutCallback)); static_cast(thread)->GetTimerHandler().AddOneShotTimer(1000, timeout_signal, thread, NULL); } int main() { // Initialize Nux subsystem nux::NuxInitialize (0); // Create a Window thread nux::WindowThread* wt = nux::CreateGUIThread( TEXT("Empty Window Test"), 300, 200, 0, &UserInterfaceInitialization, 0); // // Start the main loop wt->Run (0); delete wt; return 0; } ./tests/gtest-nuxgraphics-graphic-display.cpp0000644000004100000410000000205413313171755021655 0ustar www-datawww-data#include #include #include #include "Nux/Nux.h" #include "NuxGraphics/GraphicsDisplay.h" using namespace testing; using namespace nux; namespace { struct TestGraphicsDisplay : Test { TestGraphicsDisplay() : graphic_display_(nullptr) {} virtual void SetUp() { nux::NuxInitialize(0); wnd_thread.reset(nux::CreateNuxWindow("nux::TestGraphicsDisplay", 300, 200, nux::WINDOWSTYLE_NORMAL, NULL, false, NULL, NULL)); graphic_display_ = nux::GetGraphicsDisplay(); ASSERT_NE(graphic_display_, nullptr); } std::unique_ptr wnd_thread; GraphicsDisplay* graphic_display_; }; #if defined(USE_X11) TEST_F(TestGraphicsDisplay, X11TimestampOnButtonPress) { XEvent xevent; xevent.type = ButtonPress; xevent.xany.display = graphic_display_->GetX11Display(); xevent.xbutton.time = g_random_int(); graphic_display_->ProcessXEvent(xevent, true); auto event_time = nux::GetGraphicsDisplay()->GetCurrentEvent().x11_timestamp; EXPECT_EQ(xevent.xbutton.time, event_time); } #endif }./tests/test_graphics_display.cpp0000644000004100000410000000313713313171755017507 0ustar www-datawww-data/* * Copyright 2011 Inalogic Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY 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 * version 3 along with this program. If not, see * * * Authored by: Brandon Schaefer * */ #include #include "Nux/Nux.h" #include "Nux/VLayout.h" #include "Nux/WindowThread.h" void ThreadWidgetInit(nux::NThread* /* thread */, void* /* InitData */) { nux::VLayout* layout = new nux::VLayout(NUX_TRACKER_LOCATION); nux::GetWindowThread()->SetLayout(layout); } int main() { nux::NuxInitialize(0); // When the GUI thread is created, it creates the GraphicsDisplay. nux::WindowThread* wt = nux::CreateGUIThread(TEXT("Graphics Display"), 300, 200, 0, &ThreadWidgetInit, 0); // Test to see if the variable in GraphicsDisplay is initialized int result = 1; if (!nux::GetGraphicsDisplay()->PointerIsGrabbed()) { // Zero return code is good. result = 0; } else { std::cerr << "FAIL: GraphicsDisplay hasn't correctly initialized.\n"; } delete wt; return result; } ./tests/gtest-nuxcore-object.cpp0000644000004100000410000001350513313171755017176 0ustar www-datawww-data/* * Copyright 2010 Inalogic Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License version 3 along with this program. If not, see * * * Authored by: Jay Taoko * */ #include #include "NuxCore/NuxCore.h" #include "NuxCore/Object.h" #include "NuxCore/ObjectPtr.h" using namespace testing; namespace { const int ARRAY_SIZE = 1000; class OwnedObject: public nux::Object { public: OwnedObject(NUX_FILE_LINE_PROTO) : nux::Object(true, NUX_FILE_LINE_PARAM) { } ~OwnedObject() {} int array[ARRAY_SIZE]; }; class ChildOwnedObject: public OwnedObject { public: ChildOwnedObject(NUX_FILE_LINE_PROTO) : OwnedObject(NUX_FILE_LINE_PARAM) { } ~ChildOwnedObject() {} int array [ARRAY_SIZE]; }; class UnOwnedObject: public nux::Object { public: UnOwnedObject(NUX_FILE_LINE_PROTO) : nux::Object(false, NUX_FILE_LINE_PARAM) { } ~UnOwnedObject() {} int array [ARRAY_SIZE]; }; class ChildUnOwnedObject: public UnOwnedObject { public: ChildUnOwnedObject(NUX_FILE_LINE_PROTO) : UnOwnedObject (NUX_FILE_LINE_PARAM) { } ~ChildUnOwnedObject () {} int array [ARRAY_SIZE]; }; TEST(TestObject, TestObject) { OwnedObject* a = new OwnedObject(NUX_TRACKER_LOCATION); OwnedObject b(NUX_TRACKER_LOCATION); EXPECT_THAT(a, NotNull()); EXPECT_TRUE(a->IsHeapAllocated()); EXPECT_FALSE(b.IsHeapAllocated()); EXPECT_THAT(a->GetObjectSize(), Ge(ARRAY_SIZE)); a->UnReference(); } TEST(TestObject, TestObjectReference) { OwnedObject *a = new OwnedObject (NUX_TRACKER_LOCATION); // ref count = 1, owned UnOwnedObject *b = new UnOwnedObject (NUX_TRACKER_LOCATION); // ref count = 1, unowned EXPECT_THAT(a->GetReferenceCount(), Eq(1)); EXPECT_THAT(b->GetReferenceCount(), Eq(1)); EXPECT_FALSE(b->OwnsTheReference()); a->Reference (); // ref count = 2 a->Reference (); // ref count = 3 b->Reference (); // ref count = 1, owned EXPECT_THAT(a->GetReferenceCount(), Eq(3)); EXPECT_THAT(b->GetReferenceCount(), Eq(1)); EXPECT_TRUE(b->OwnsTheReference()); EXPECT_FALSE(a->UnReference()); EXPECT_THAT(a->GetReferenceCount(), Eq(2)); EXPECT_FALSE(a->UnReference()); EXPECT_THAT(a->GetReferenceCount(), Eq(1)); EXPECT_TRUE(a->UnReference()); // object destroyed EXPECT_TRUE(b->UnReference()); // object destroyed } TEST(TestObject, TestObjectPtr) { OwnedObject* a = new OwnedObject(NUX_TRACKER_LOCATION); // ref count = 1, owned nux::ObjectPtr object_ptr(a); // ref count = 2 EXPECT_THAT(a->GetReferenceCount(), Eq(2)); EXPECT_FALSE(a->UnReference()); // ref count = 1 EXPECT_THAT(a->GetReferenceCount(), Eq(1)); object_ptr.Release(); } TEST(TestObject, TestObjectPtrAdopt) { OwnedObject* a = new OwnedObject(NUX_TRACKER_LOCATION); // ref count = 1, owned nux::ObjectPtr object_ptr; object_ptr.Adopt(a); EXPECT_THAT(a->GetReferenceCount(), Eq(1)); } TEST(TestObject, TestObjectPtrGetPointer) { OwnedObject* a = new OwnedObject(NUX_TRACKER_LOCATION); // ref count = 1, owned nux::ObjectPtr object_ptr; object_ptr.Adopt(a); EXPECT_THAT(object_ptr.GetPointer(), Eq(a)); // Const too nux::ObjectPtr const& object_ptr_ref = object_ptr; EXPECT_THAT(object_ptr_ref.GetPointer(), Eq(a)); } TEST(TestObject, TestObjectPtr1) { ChildOwnedObject* c = new ChildOwnedObject(NUX_TRACKER_LOCATION); // ref count = 1, owned nux::ObjectPtr object_ptr0(c); // ref count = 2 EXPECT_THAT(c->GetReferenceCount(), Eq(2)); nux::ObjectPtr object_ptr1(object_ptr0); // ref count = 3 EXPECT_THAT(c->GetReferenceCount(), Eq(3)); EXPECT_FALSE(c->UnReference()); // ref count = 2 object_ptr1.Release(); EXPECT_THAT(c->GetReferenceCount(), Eq(1)); object_ptr0.Release (); } TEST(TestObject, TestObjectPtr2) { ChildOwnedObject *c = new ChildOwnedObject(NUX_TRACKER_LOCATION); nux::ObjectPtr obj_ptr(c); nux::ObjectWeakPtr weak_ptr(obj_ptr); EXPECT_THAT(c->GetReferenceCount(), Eq(2)); EXPECT_FALSE(c->UnReference()); EXPECT_THAT(c->GetReferenceCount(), Eq(1)); // Clearing the smart pointer deletes the object. EXPECT_TRUE(obj_ptr.Release()); EXPECT_FALSE(weak_ptr.IsValid()); EXPECT_TRUE(weak_ptr.IsNull()); EXPECT_FALSE(weak_ptr()); } bool g_signal_called = false; void on_destroyed_cb (nux::Object * /* obj */) { g_signal_called = true; } TEST(TestObject, TestObjectSignal) { nux::Object *obj = new nux::Object (); obj->OnDestroyed.connect(sigc::ptr_fun(on_destroyed_cb)); EXPECT_FALSE(g_signal_called); obj->UnReference (); EXPECT_TRUE(g_signal_called); } TEST(TestObject, TestObjectAdoptUnOwned) { UnOwnedObject* obj = new UnOwnedObject(NUX_TRACKER_LOCATION); EXPECT_THAT(obj->OwnsTheReference(), Eq(false)); nux::ObjectPtr obj_smart_ptr; obj_smart_ptr.Adopt(obj); EXPECT_THAT(obj->GetReferenceCount(), Eq(1)); EXPECT_THAT(obj->ObjectPtrCount(), Eq(1)); EXPECT_THAT(obj->OwnsTheReference(), Eq(true)); } TEST(TestObject, TestObjectAdoptOwned) { OwnedObject* obj = new OwnedObject(NUX_TRACKER_LOCATION); EXPECT_THAT(obj->OwnsTheReference(), Eq(true)); nux::ObjectPtr obj_smart_ptr; obj_smart_ptr.Adopt(obj); EXPECT_THAT(obj->GetReferenceCount(), Eq(1)); EXPECT_THAT(obj->ObjectPtrCount(), Eq(1)); } } ./tests/gtest-nuxgraphics-texture.cpp0000644000004100000410000000613213313171755020276 0ustar www-datawww-data#include #include #include #include "Nux/Nux.h" #include "Nux/HLayout.h" #include "NuxGraphics/NuxGraphics.h" #include "NuxGraphics/GLTextureResourceManager.h" #include "Nux/CairoWrapper.h" using namespace testing; using namespace nux; namespace { const char *FALLBACK_ENV = "NUX_FALLBACK_TEXTURE"; class TestTextures : public ::testing::Test { public: virtual void SetUp() { g_unsetenv(FALLBACK_ENV); nux::NuxInitialize(0); wnd_thread.reset(nux::CreateNuxWindow("nux::TestTextures", 300, 200, nux::WINDOWSTYLE_NORMAL, NULL, false, NULL, NULL)); } void EnableFallbackMode() { g_setenv(FALLBACK_ENV, "TRUE", TRUE); } std::unique_ptr wnd_thread; }; TEST_F(TestTextures, TestTextureSizes) { int max_size = GetGraphicsDisplay()->GetGpuDevice()->GetGpuInfo().GetMaxTextureSize(); int size = max_size/4; nux::ObjectPtr texture; while (size <= max_size * 4) { BitmapFormat bitmap_format = BITFMT_B8G8R8A8; NBitmapData* bitmap = new NTextureData (bitmap_format, 10, size, 1); texture.Adopt(GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableTexture()); GetGraphicsDisplay()->GetGraphicsEngine()->CacheResource(texture.GetPointer()); texture->Update(bitmap, true); delete bitmap; size*=2; } } TEST_F(TestTextures, TestCreateTexture2DFromIDAssignemnt) { GLuint texid; glGenTextures(1, &texid); glBindTexture(GL_TEXTURE_2D, texid); nux::ObjectPtr foreign_texture_as_nux_texture (nux::GetGraphicsDisplay()->GetGpuDevice()->CreateTexture2DFromID( texid, 1, 1, 0, nux::BITFMT_B8G8R8A8)); EXPECT_EQ(texid, foreign_texture_as_nux_texture->GetOpenGLID()); glBindTexture(GL_TEXTURE_2D, 0); glDeleteTextures(1, &texid); } TEST_F(TestTextures, FallbackTexture2DFromFile) { ASSERT_THAT(CreateTexture2DFromFile(nullptr, -1, false), IsNull()); EnableFallbackMode(); ASSERT_THAT(CreateTexture2DFromFile(nullptr, -1, false), NotNull()); } TEST_F(TestTextures, FallbackTexture2DFromPixbuf) { ASSERT_THAT(CreateTexture2DFromPixbuf(nullptr, false), IsNull()); EnableFallbackMode(); ASSERT_THAT(CreateTexture2DFromPixbuf(nullptr, false), NotNull()); } TEST_F(TestTextures, FallbackTextureFromPixbuf) { ASSERT_THAT(CreateTextureFromPixbuf(nullptr), IsNull()); EnableFallbackMode(); ASSERT_THAT(CreateTextureFromPixbuf(nullptr), NotNull()); } TEST_F(TestTextures, FallbackTextureFromFile) { ASSERT_THAT(CreateTextureFromFile(nullptr), IsNull()); EnableFallbackMode(); ASSERT_THAT(CreateTextureFromFile(nullptr), NotNull()); } TEST_F(TestTextures, FallbackTextureFromBitmapData) { ASSERT_THAT(CreateTextureFromBitmapData(nullptr), IsNull()); EnableFallbackMode(); ASSERT_THAT(CreateTextureFromBitmapData(nullptr), NotNull()); } TEST_F(TestTextures, FallbackTextureLoadFromFile) { ASSERT_THAT(LoadTextureFromFile(std::string()), IsNull()); EnableFallbackMode(); ASSERT_THAT(LoadTextureFromFile(std::string()), NotNull()); } } ./tests/gtest-nuxcore-async-file-writer.cpp0000644000004100000410000000513613313171755021275 0ustar www-datawww-data#include #include #include #include #include #include #include "NuxCore/AsyncFileWriter.h" #include "Helpers.h" namespace bf = boost::filesystem; using namespace testing; using namespace nux::testing; namespace { const std::string TEST_ROOT("/tmp/nux-test-cases"); class TestAsyncfileWriter : public ::testing::Test { protected: virtual void SetUp() { // Make sure that the tests start with and empty TEST_ROOT. bf::remove_all(TEST_ROOT); bf::create_directories(TEST_ROOT); } virtual void TearDown() { // Delete the unity test directory bf::remove_all(TEST_ROOT); } bool WaitForOpen(nux::AsyncFileWriter& writer, unsigned timeout = 5) { TestCallback opened; TestCallback timed_out; g_timeout_add_seconds(timeout, &TestCallback::glib_callback, &timed_out); writer.opened.connect(opened.sigc_callback()); while (!opened.happened && !timed_out.happened) { PumpGObjectMainLoop(); } return opened.happened; } bool WaitForClose(nux::AsyncFileWriter& writer, unsigned timeout = 5) { TestCallback closed; TestCallback timed_out; g_timeout_add_seconds(timeout, &TestCallback::glib_callback, &timed_out); writer.closed.connect(closed.sigc_callback()); while (!closed.happened && !timed_out.happened) { PumpGObjectMainLoop(); } return closed.happened; } }; TEST_F(TestAsyncfileWriter, TestConstructor) { std::string filename(TEST_ROOT + "/empty-file"); { nux::AsyncFileWriter writer(filename); bool opened = WaitForOpen(writer); EXPECT_TRUE(opened); } EXPECT_TRUE(bf::exists(filename)); EXPECT_THAT(ReadFile(filename), Eq("")); } TEST_F(TestAsyncfileWriter, TestWrites) { std::string filename(TEST_ROOT + "/write-file"); std::string data(200, 'x'); { nux::AsyncFileWriter writer(filename); writer.Write(data); writer.Close(); bool closed = WaitForClose(writer); EXPECT_TRUE(closed); } EXPECT_THAT(ReadFile(filename), Eq(data)); } TEST_F(TestAsyncfileWriter, TestWriteLots) { std::string filename(TEST_ROOT + "/lots-file"); std::string data(200, 'x'); const int loop_count = 1000; { nux::AsyncFileWriter writer(filename); for (int i = 0; i < loop_count; ++i) { writer.Write(data); } writer.Close(); bool closed = WaitForClose(writer); EXPECT_TRUE(closed); } std::string file_content = ReadFile(filename); EXPECT_THAT(file_content.size(), Eq(data.size() * loop_count)); // They are all x's. EXPECT_THAT(file_content, MatchesRegex("^x+$")); } } // anon namespace ./tests/xtest-mouse-buttons.cpp0000644000004100000410000001330713313171755017114 0ustar www-datawww-data/* * Copyright 2010 Inalogic Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY 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 * version 3 along with this program. If not, see * * * Authored by: Jay Taoko * */ #include "Nux/Nux.h" #include "Nux/WindowThread.h" #include "Nux/VLayout.h" #include "Nux/Layout.h" #include "Nux/ProgramFramework/ProgramTemplate.h" #include "Nux/ProgramFramework/TestView.h" #include #include #include "nux_automated_test_framework.h" class ButtonEventsTest: public ProgramTemplate { public: ButtonEventsTest(const char* program_name, int window_width, int window_height, int program_life_span); ~ButtonEventsTest(); virtual void UserInterfaceSetup(); void ResetEvents(); nux::TestView* test_view_; }; ButtonEventsTest::ButtonEventsTest(const char* program_name, int window_width, int window_height, int program_life_span) : ProgramTemplate(program_name, window_width, window_height, program_life_span) { ResetEvents(); test_view_ = NULL; } ButtonEventsTest::~ButtonEventsTest() { } void ButtonEventsTest::ResetEvents() { if (test_view_) test_view_->ResetEvents(); } void ButtonEventsTest::UserInterfaceSetup() { nux::VLayout* main_layout = new nux::VLayout(NUX_TRACKER_LOCATION); test_view_ = new nux::TestView(NUX_TRACKER_LOCATION); main_layout->AddView(test_view_, 1, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL); main_layout->SetPadding(10, 10); static_cast(window_thread_)->SetLayout(main_layout); nux::ColorLayer background(nux::Color(0xFF4D4D4D)); static_cast(window_thread_)->SetWindowBackgroundPaintLayer(&background); } ButtonEventsTest* button_event_test = NULL; void TestingThread(nux::NThread* /* thread */, void* user_data) { while (button_event_test->ReadyToGo() == false) { nuxDebugMsg("Waiting to start"); nux::SleepForMilliseconds(300); } nux::SleepForMilliseconds(1000); nux::WindowThread* wnd_thread = static_cast(user_data); NuxAutomatedTestFramework test(wnd_thread); test.Startup(); // Set the mouse at coordinates (0, 0) (top-left corner) on the display test.PutMouseAt(0, 0); test.TestReportMsg(button_event_test->test_view_, "TestView created"); // Move mouse to center of the view test.ViewSendMouseMotionToCenter(button_event_test->test_view_); // Mouse click with button 1 button_event_test->ResetEvents(); test.ViewSendMouseClick(button_event_test->test_view_, 1); test.TestReportMsg(button_event_test->test_view_->registered_mouse_down_, "Mouse button 1 down"); test.TestReportMsg(button_event_test->test_view_->registered_mouse_up_, "Mouse button 1 up"); // Mouse click with button 2 button_event_test->ResetEvents(); test.ViewSendMouseClick(button_event_test->test_view_, 2); test.TestReportMsg(button_event_test->test_view_->registered_mouse_down_, "Mouse button 2 down"); test.TestReportMsg(button_event_test->test_view_->registered_mouse_up_, "Mouse button 2 up"); // Mouse click with button 3 button_event_test->ResetEvents(); test.ViewSendMouseClick(button_event_test->test_view_, 3); test.TestReportMsg(button_event_test->test_view_->registered_mouse_down_, "Mouse button 3 down"); test.TestReportMsg(button_event_test->test_view_->registered_mouse_up_, "Mouse button 3 up"); // Mouse click with button 4 button_event_test->ResetEvents(); test.ViewSendMouseClick(button_event_test->test_view_, 4); test.TestReportMsg(!button_event_test->test_view_->registered_mouse_down_, "Mouse button 4 down"); test.TestReportMsg(!button_event_test->test_view_->registered_mouse_up_, "Mouse button 4 up"); // Mouse click with button 5 button_event_test->ResetEvents(); test.ViewSendMouseClick(button_event_test->test_view_, 5); test.TestReportMsg(!button_event_test->test_view_->registered_mouse_down_, "Mouse button 5 down"); test.TestReportMsg(!button_event_test->test_view_->registered_mouse_up_, "Mouse button 5 up"); // Mouse click with button 6 button_event_test->ResetEvents(); test.ViewSendMouseClick(button_event_test->test_view_, 6); test.TestReportMsg(!button_event_test->test_view_->registered_mouse_down_, "Mouse button 6 down"); test.TestReportMsg(!button_event_test->test_view_->registered_mouse_up_, "Mouse button 6 up"); // Mouse click with button 7 button_event_test->ResetEvents(); test.ViewSendMouseClick(button_event_test->test_view_, 7); test.TestReportMsg(!button_event_test->test_view_->registered_mouse_down_, "Mouse button 7 down"); test.TestReportMsg(!button_event_test->test_view_->registered_mouse_up_, "Mouse button 7 up"); if (test.WhenDoneTerminateProgram()) { nux::SleepForMilliseconds(1000); wnd_thread->ExitMainLoop(); } nuxDebugMsg("Exit testing thread"); } int main() { XInitThreads(); button_event_test = new ButtonEventsTest("Events Test", 300, 300, 30000); button_event_test->Startup(); button_event_test->UserInterfaceSetup(); nux::SystemThread* test_thread = nux::CreateSystemThread(button_event_test->GetWindowThread(), &TestingThread, button_event_test->GetWindowThread()); test_thread->Start(button_event_test); button_event_test->Run(); delete test_thread; delete button_event_test; return 0; } ./tests/xtest-keynav-directions.cpp0000644000004100000410000001451613313171755017731 0ustar www-datawww-data/* * Copyright 2012 Inalogic Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY 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 * version 3 along with this program. If not, see * * * Authored by: Jay Taoko * */ #include "Nux/Nux.h" #include "Nux/WindowThread.h" #include "Nux/VLayout.h" #include "Nux/ProgramFramework/ProgramTemplate.h" #include "Nux/ProgramFramework/TestView.h" #include #include #include "nux_automated_test_framework.h" class KeyNavDirectionTest: public ProgramTemplate { public: KeyNavDirectionTest(const char *program_name, int window_width, int window_height, int program_life_span); ~KeyNavDirectionTest(); virtual void UserInterfaceSetup(); nux::TestView* view0_; nux::TestView* view1_; nux::TestView* view2_; nux::TestView* view3_; }; KeyNavDirectionTest::KeyNavDirectionTest(const char* program_name, int window_width, int window_height, int program_life_span) : ProgramTemplate(program_name, window_width, window_height, program_life_span) , view0_(NULL) , view1_(NULL) , view2_(NULL) , view3_(NULL) { } KeyNavDirectionTest::~KeyNavDirectionTest() { } void KeyNavDirectionTest::UserInterfaceSetup() { nux::HLayout* main_layout = new nux::HLayout(NUX_TRACKER_LOCATION); main_layout->SetSpaceBetweenChildren(10); main_layout->SetPadding(10, 10); nux::VLayout* layout0 = new nux::VLayout(NUX_TRACKER_LOCATION); nux::VLayout* layout1 = new nux::VLayout(NUX_TRACKER_LOCATION); layout0->SetSpaceBetweenChildren(10); layout1->SetSpaceBetweenChildren(10); view0_ = new nux::TestView(NUX_TRACKER_LOCATION); view0_->can_focus_ = true; view0_->SetAcceptKeyNavFocusOnMouseDown(true); layout0->AddView(view0_, 1, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL); view1_ = new nux::TestView(NUX_TRACKER_LOCATION); view1_->can_focus_ = true; view1_->SetAcceptKeyNavFocusOnMouseDown(true); layout0->AddView(view1_, 1, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL); view2_ = new nux::TestView(NUX_TRACKER_LOCATION); view2_->can_focus_ = true; view2_->SetAcceptKeyNavFocusOnMouseDown(true); layout1->AddView(view2_, 1, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL); view3_ = new nux::TestView(NUX_TRACKER_LOCATION); view3_->can_focus_ = true; view3_->SetAcceptKeyNavFocusOnMouseDown(true); layout1->AddView(view3_, 1, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL); main_layout->AddLayout(layout0, 1); main_layout->AddLayout(layout1, 1); static_cast(window_thread_)->SetLayout(main_layout); nux::ColorLayer background(nux::Color(0xFF4D4D4D)); static_cast(window_thread_)->SetWindowBackgroundPaintLayer(&background); } KeyNavDirectionTest* keynav_direction_test = NULL; void TestingThread(nux::NThread* /* thread */, void* user_data) { while (keynav_direction_test->ReadyToGo() == false) { nuxDebugMsg("Waiting to start"); nux::SleepForMilliseconds(300); } nux::SleepForMilliseconds(1000); nux::WindowThread *wnd_thread = static_cast(user_data); NuxAutomatedTestFramework test(wnd_thread); test.Startup(); // Set the mouse at coordinates (0, 0) (top-left corner) on the display test.PutMouseAt(0, 0); // Move mouse to center of view0_ test.ViewSendMouseMotionToCenter(keynav_direction_test->view0_); // Mouse down/up on view0_ test.ViewSendMouseClick(keynav_direction_test->view0_, 1); nux::SleepForMilliseconds(500); test.SendFakeKeyEvent(XK_Down, 0); nux::SleepForMilliseconds(500); test.TestReportMsg(keynav_direction_test->view1_->has_focus_ && (keynav_direction_test->view1_->key_nav_direction_ == nux::KEY_NAV_DOWN), "View1 received key nav from top"); test.SendFakeKeyEvent(XK_Up, 0); nux::SleepForMilliseconds(500); test.TestReportMsg(keynav_direction_test->view0_->has_focus_ && (keynav_direction_test->view0_->key_nav_direction_ == nux::KEY_NAV_UP), "View0 received key nav from bottom"); test.SendFakeKeyEvent(XK_Right, 0); nux::SleepForMilliseconds(500); test.TestReportMsg(keynav_direction_test->view2_->has_focus_ && (keynav_direction_test->view0_->key_nav_direction_ == nux::KEY_NAV_RIGHT), "View2 received key nav from left"); test.SendFakeKeyEvent(XK_Down, 0); nux::SleepForMilliseconds(500); test.TestReportMsg(keynav_direction_test->view3_->has_focus_ && (keynav_direction_test->view3_->key_nav_direction_ == nux::KEY_NAV_DOWN), "View3 received key nav from top"); test.SendFakeKeyEvent(XK_Up, 0); nux::SleepForMilliseconds(500); test.TestReportMsg(keynav_direction_test->view2_->has_focus_ && (keynav_direction_test->view2_->key_nav_direction_ == nux::KEY_NAV_UP), "View2 received key nav from bottom"); test.SendFakeKeyEvent(XK_Left, 0); nux::SleepForMilliseconds(500); test.TestReportMsg(keynav_direction_test->view0_->has_focus_ && (keynav_direction_test->view0_->key_nav_direction_ == nux::KEY_NAV_LEFT), "View0 received key nav from right"); if (test.WhenDoneTerminateProgram()) { nux::SleepForMilliseconds(1000); wnd_thread->ExitMainLoop(); } nuxDebugMsg("Exit testing thread"); } int main() { XInitThreads(); keynav_direction_test = new KeyNavDirectionTest("Automated: KeyNav Directions", 300, 300, 15000); keynav_direction_test->Startup(); keynav_direction_test->UserInterfaceSetup(); nux::SystemThread *test_thread = nux::CreateSystemThread(keynav_direction_test->GetWindowThread(), &TestingThread, keynav_direction_test->GetWindowThread()); test_thread->Start(keynav_direction_test); keynav_direction_test->Run(); delete test_thread; delete keynav_direction_test; return 0; } ./tests/test-system.cpp0000644000004100000410000000513113313171755015420 0ustar www-datawww-data/* * Copyright 2010 Inalogic Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License version 3 along with this program. If not, see * * * Authored by: Jay Taoko * */ #include #include "Nux/Nux.h" #include "Nux/VLayout.h" #include "Nux/HLayout.h" #include "Nux/WindowThread.h" #include "Nux/Button.h" //static void TestMainWindow(void); //static void TestMainWindowStatus(void); //static void TestMainWindowSize(void); void TestSystemSuite (void) { #define TESTDOMAIN "/System/" // g_test_add_func (TESTDOMAIN"/TestMainWindow", TestMainWindow); // g_test_add_func (TESTDOMAIN"/TestMainWindowStatus", TestMainWindowStatus); // g_test_add_func (TESTDOMAIN"/TestMainWindowSize", TestMainWindowSize); } /* static void TestMainWindow (void) { // Warning: on windows the window can not be physically smaller than ~120x100 nux::WindowThread* wt = nux::CreateGUIThread(TEXT("TestMainWindow"), 120, 100, 0, 0, 0); g_assert (wt != 0); g_assert (nux::GetGraphicsThread () == wt); delete wt; } static void TestMainWindowStatus (void) { // Warning: on windows the window can not be physically smaller than ~120x100 nux::WindowThread* wt = nux::CreateGUIThread(TEXT("TestMainWindowStatus"), 120, 100, 0, 0, 0); g_assert (wt != 0); g_assert (nux::GetGraphicsThread () == wt); //g_assert (nux::GetWindow ().IsWindowVisible () == false); //nux::GetWindow ().ShowWindow (); //g_assert (nux::GetWindow ().IsWindowVisible () == true); //nux::GetWindow ().HideWindow (); //g_assert (nux::GetWindow ().IsWindowVisible () == false); delete wt; } static void TestMainWindowSize (void) { // Warning: on windows the window can not be physically smaller than ~120x100 nux::WindowThread* wt = nux::CreateGUIThread(TEXT("TestMainWindowSize"), 120, 100, 0, 0, 0); nux::GetWindow ().ShowWindow (); g_assert (wt != 0); g_assert (nux::GetGraphicsThread () == wt); g_assert (nux::GetWindow ().GetWindowWidth () == 120); g_assert (nux::GetWindow ().GetWindowHeight () == 100); delete wt; }*/ ./tests/nux_automated_test_framework.cpp0000644000004100000410000004457513313171755021127 0ustar www-datawww-data/* * Copyright 2010 Inalogic Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY 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 * version 3 along with this program. If not, see * * * Authored by: Jay Taoko * */ #include "Nux/Nux.h" #include #include #include "nux_automated_test_framework.h" #define MAX_KEYS 4 // Max keys int NuxAutomatedTestFramework::mouse_motion_time_span = 1000; // milliseconds int NuxAutomatedTestFramework::mouse_click_time_span = 300; // milliseconds int NuxAutomatedTestFramework::minimum_sleep_time = 600; // milliseconds int NuxAutomatedTestFramework::safety_border_inside_view = 1; // pixels NuxAutomatedTestFramework::NuxAutomatedTestFramework(nux::WindowThread *window_thread) : ready_to_start_(false) , display_(NULL) , window_thread_(window_thread) , window_x_(0) , window_y_(0) , window_width_(0) , window_height_(0) , terminate_when_test_over_(false) , composition_keys_supported_(false) { } NuxAutomatedTestFramework::~NuxAutomatedTestFramework() { XCloseDisplay(display_); } void NuxAutomatedTestFramework::WarnCompositionKeysNotSupported() { nuxWarningMsg("Composition keys are not supported by your server, " "not running the composition keys tests"); } bool NuxAutomatedTestFramework::CompositionKeysSupported() { return composition_keys_supported_; } void NuxAutomatedTestFramework::SetTerminateProgramWhenDone(bool terminate) { terminate_when_test_over_ = terminate; } bool NuxAutomatedTestFramework::WhenDoneTerminateProgram() { return terminate_when_test_over_; } void NuxAutomatedTestFramework::Startup() { display_ = XOpenDisplay(NULL); nux::Geometry rect = window_thread_->GetGraphicsDisplay().GetWindowGeometry(); //nuxDebugMsg("Window geometry: (%d, %d, %d, %d)", rect.x, rect.y, rect.width, rect.height); int min, max, per_keycode; // Get the min and max keycodes XDisplayKeycodes(display_, &min, &max); // Must be called with: // first_keycode: min, // keycode_count: max - min KeySym *syms = XGetKeyboardMapping(display_, min, max - min, &per_keycode); // Number of keysyms is (max - min) * keysyms_per_keycode for (int i = 0; i < (max - min) * per_keycode; ++i) { if (syms[i] == XK_Multi_key) composition_keys_supported_ = true; } XFree(syms); window_x_ = rect.x; window_y_ = rect.y; window_width_ = rect.width; window_height_ = rect.height; } void NuxAutomatedTestFramework::ViewSendMouseClick(nux::View *view, int button) { nux::Rect r; if (view) { r = view->GetAbsoluteGeometry(); r.OffsetPosition(window_x_ + r.width/2, window_y_ + r.height/2); } else { r = window_thread_->GetGraphicsDisplay().GetWindowGeometry(); r.OffsetPosition(r.width/2, r.height/2); } SendFakeMouseMotionEvent(r.x, r.y, NuxAutomatedTestFramework::mouse_motion_time_span); SendFakeMouseEvent(button, true); nux::SleepForMilliseconds(NuxAutomatedTestFramework::mouse_click_time_span); SendFakeMouseEvent(button, false); XSync(display_, False); nux::SleepForMilliseconds(NuxAutomatedTestFramework::minimum_sleep_time); } void NuxAutomatedTestFramework::ViewSendMouseDoubleClick(nux::View *view, int button) { nux::Rect r; if (view) { r = view->GetAbsoluteGeometry(); r.OffsetPosition(window_x_ + r.width/2, window_y_ + r.height/2); } else { r = window_thread_->GetGraphicsDisplay().GetWindowGeometry(); r.OffsetPosition(r.width/2, r.height/2); } // Send the mouse to the center of the view SendFakeMouseMotionEvent(r.x, r.y, NuxAutomatedTestFramework::mouse_motion_time_span); XTestFakeButtonEvent(display_, button, true, CurrentTime); XTestFakeButtonEvent(display_, button, false, CurrentTime); XTestFakeButtonEvent(display_, button, true, CurrentTime); XTestFakeButtonEvent(display_, button, false, CurrentTime); XSync(display_, False); nux::SleepForMilliseconds(NuxAutomatedTestFramework::minimum_sleep_time); } void NuxAutomatedTestFramework::ViewSendMouseDown(nux::View *view, int button) { XEvent event; /* Get the current pointer position */ XQueryPointer(display_, RootWindow(display_, 0), &event.xbutton.root, &event.xbutton.window, &event.xbutton.x_root, &event.xbutton.y_root, &event.xbutton.x, &event.xbutton.y, &event.xbutton.state); int current_x = event.xbutton.x - window_x_; int current_y = event.xbutton.y - window_y_; nux::Rect r = view->GetAbsoluteGeometry(); if (!r.IsInside(nux::Point(current_x, current_y))) { // The mouse pointer is not inside the view. // Move the mouse pointer to the center of the view. r.OffsetPosition(window_x_, window_y_); // Go to the center of the view int view_center_x = r.x + r.width/2; int view_center_y = r.y + r.height/2; SendFakeMouseMotionEvent(view_center_x, view_center_y, NuxAutomatedTestFramework::mouse_motion_time_span); nux::SleepForMilliseconds(minimum_sleep_time); } SendFakeMouseEvent(button, true); } void NuxAutomatedTestFramework::ViewSendMouseUp(nux::View * /* view */, int button) { // nux::Rect r = view->GetAbsoluteGeometry(); // r.OffsetPosition(window_x_, window_y_); // int view_center_x = r.x + r.width/2; // int view_center_y = r.y + r.height/2; // SendFakeMouseMotionEvent(view_center_x, view_center_y, 1000); // nux::SleepForMilliseconds(minimum_sleep_time); SendFakeMouseEvent(button, false); } void NuxAutomatedTestFramework::ViewSendMouseDrag(nux::View *view, int button_index, int x0, int y0, int x1, int y1) { nux::Rect r0 = view->GetAbsoluteGeometry(); nux::Rect r1 = view->GetAbsoluteGeometry(); r0.OffsetPosition(window_x_ + x0, window_y_ + y0); r1.OffsetPosition(window_x_ + x1, window_y_ + y1); // Go to first point SendFakeMouseMotionEvent(r0.x, r0.y, NuxAutomatedTestFramework::mouse_motion_time_span); nux::SleepForMilliseconds(minimum_sleep_time); // Mouse down ViewSendMouseDown(view, button_index); // Drag to second point SendFakeMouseMotionEvent(r1.x, r1.y, NuxAutomatedTestFramework::mouse_motion_time_span); nux::SleepForMilliseconds(minimum_sleep_time); // Mouse up ViewSendMouseUp(view, button_index); } void NuxAutomatedTestFramework::ViewSendMouseMotionTo(nux::View *view, int x, int y) { nux::Rect r; if (view) { r = view->GetAbsoluteGeometry(); r.OffsetPosition(window_x_ + x, window_y_ + y); } else { r = window_thread_->GetGraphicsDisplay().GetWindowGeometry(); r.OffsetPosition(x, y); } SendFakeMouseMotionEvent(r.x, r.y, NuxAutomatedTestFramework::mouse_motion_time_span); } void NuxAutomatedTestFramework::ViewSendMouseMotionToCenter(nux::View *view) { nux::Rect r; if (view) { r = view->GetAbsoluteGeometry(); r.OffsetPosition(window_x_, window_y_); } else { r = window_thread_->GetGraphicsDisplay().GetWindowGeometry(); } int view_center_x = r.x + r.width/2; int view_center_y = r.y + r.height/2; SendFakeMouseMotionEvent(view_center_x, view_center_y, NuxAutomatedTestFramework::mouse_motion_time_span); } void NuxAutomatedTestFramework::ViewSendMouseMotionToTopLeft(nux::View *view) { nux::Rect r = view->GetAbsoluteGeometry(); r.OffsetPosition(window_x_, window_y_); SendFakeMouseMotionEvent(r.x + safety_border_inside_view, r.y + safety_border_inside_view, NuxAutomatedTestFramework::mouse_motion_time_span); } void NuxAutomatedTestFramework::ViewSendMouseMotionToTopRight(nux::View *view) { nux::Rect r = view->GetAbsoluteGeometry(); r.OffsetPosition(window_x_, window_y_); SendFakeMouseMotionEvent(r.x + r.width-1, r.y+safety_border_inside_view, NuxAutomatedTestFramework::mouse_motion_time_span); } void NuxAutomatedTestFramework::ViewSendMouseMotionToBottomLeft(nux::View *view) { nux::Rect r = view->GetAbsoluteGeometry(); r.OffsetPosition(window_x_, window_y_); SendFakeMouseMotionEvent(r.x+safety_border_inside_view, r.y + r.height-1, NuxAutomatedTestFramework::mouse_motion_time_span); } void NuxAutomatedTestFramework::ViewSendMouseMotionToBottomRight(nux::View *view) { nux::Rect r = view->GetAbsoluteGeometry(); r.OffsetPosition(window_x_, window_y_); SendFakeMouseMotionEvent(r.x + r.width-1, r.y + r.height-1, NuxAutomatedTestFramework::mouse_motion_time_span); } void NuxAutomatedTestFramework::ViewSendChar(const char c) { KeySym modifier = 0; if ((c >= 'A') && (c <= 'Z')) { modifier = XK_Shift_L; } std::string s(1, c); if (c == ' ') { SendFakeKeyEvent(XK_space, modifier); } else { SendFakeKeyEvent(XStringToKeysym(s.c_str()), modifier); } nux::SleepForMilliseconds(300); } void NuxAutomatedTestFramework::ViewSendString(const std::string &str) { int l = str.length(); if (l == 0) return; int i = 0; while (i < l) { KeySym modifier = 0; char c = str[i++]; if ((c >= 'A') && (c <= 'Z')) { modifier = XK_Shift_L; } std::string s(1, c); if (c == ' ') { SendFakeKeyEvent(XK_space, modifier); } else if (c == '^') { SendFakeKeyEvent(XK_asciicircum, XK_Shift_L); } else if (c == '~') { SendFakeKeyEvent(XK_asciitilde, XK_Shift_L); } else if (c == '`') { SendFakeKeyEvent(XK_asciitilde, 0); } else if (c == '=') { SendFakeKeyEvent(XK_equal, 0); } else if (c == '\"') { SendFakeKeyEvent(XK_quotedbl, XK_Shift_L); } else if (c == '!') { SendFakeKeyEvent(XK_exclam, XK_Shift_L); } else if (c == '|') { SendFakeKeyEvent(XK_bar, XK_Shift_L); } else if (c == '/') { SendFakeKeyEvent(XK_slash, 0); } else if (c == '\\') { SendFakeKeyEvent(XK_backslash, 0); } else if (c == '-') { SendFakeKeyEvent(XK_minus, 0); } else if (c == '+') { SendFakeKeyEvent(XK_plus, XK_Shift_L); } else if (c == ',') { SendFakeKeyEvent(XK_comma, 0); } else if (c == '_') { SendFakeKeyEvent(XK_underscore, XK_Shift_L); } else if (c == '<') { SendFakeKeyEvent(XK_comma, XK_Shift_L); } else if (c == '>') { SendFakeKeyEvent(XK_greater, XK_Shift_L); } else if (c == '.') { SendFakeKeyEvent(XK_period, 0); } else if (c == '?') { SendFakeKeyEvent(XK_question, XK_Shift_L); } else if (c == '\'') { SendFakeKeyEvent(XK_quoteright, 0); } else if (c == ';') { SendFakeKeyEvent(XK_semicolon, 0); } else if (c == ':') { SendFakeKeyEvent(XK_colon, XK_Shift_L); } else if (c == '%') { SendFakeKeyEvent(XK_percent, XK_Shift_L); } else if (c == '(') { SendFakeKeyEvent(XK_parenleft, XK_Shift_L); } else if (c == ')') { SendFakeKeyEvent(XK_parenright, XK_Shift_L); } else { SendFakeKeyEvent(XStringToKeysym(s.c_str()), modifier); } nux::SleepForMilliseconds(300); } XFlush(display_); } void NuxAutomatedTestFramework::ViewSendCompositionKeys(const std::string& str) { int l = str.length(); if (l == 0) return; SendFakeKeyEvent(XK_Multi_key, 0); ViewSendString(str); } // Send strings in the format of "key+key+key" up to 4 where the last key is not a modifier // example "ctrl+alt+= void NuxAutomatedTestFramework::ViewSendKeys(const std::string& str) { std::string keys[MAX_KEYS]; KeySym keys_sym[MAX_KEYS] = {0}; size_t f_ptr = 0, s_ptr = 0; int i = 0; //Split up keys on the + while (s_ptr != std::string::npos && i < MAX_KEYS) { s_ptr = str.find("+", f_ptr); keys[i] = str.substr(f_ptr, (s_ptr-f_ptr)); f_ptr = s_ptr+1; i++; } // Find what the key_sym should be for each key for (int i = 0; i < MAX_KEYS; i++) { if (keys[i].empty()) { break; } else if (keys[i] == "ctrl") { keys_sym[i] = XK_Control_L; } else if (keys[i] == "alt") { keys_sym[i] = XK_Alt_L; } else if (keys[i] == "space") { keys_sym[i] = XK_space; } else if (keys[i] == "enter" || keys[i] == "return") { keys_sym[i] = XK_Return; } else if (keys[i] == "=") { keys_sym[i] = XK_equal; } else if (keys[i] == "[") { keys_sym[i] = XK_bracketleft; } else if (keys[i] =="shift") { keys_sym[i] = XK_Shift_L; } else { // If nothing is found try and find it... if (!(keys_sym[i] = XStringToKeysym(keys[i].c_str()))) printf("Undefinded Key: %s (Add it to this list)\n", keys[i].c_str()); } } XTestGrabControl(display_, True); KeyCode modcode[MAX_KEYS] = {0}; // Press the keys from 0,1,2,3 for (int i = 0; i < MAX_KEYS; i++) { if (keys_sym[i] != 0) { modcode[i] = XKeysymToKeycode(display_, keys_sym[i]); XTestFakeKeyEvent(display_, modcode[i], True, 0); } } // Release the keys from 3,2,1,0 for (int i = MAX_KEYS-1; i >= 0; i--) { if (keys_sym[i] != 0) { XTestFakeKeyEvent(display_, modcode[i], False, 0); } } XTestGrabControl(display_, False); XFlush(display_); } void NuxAutomatedTestFramework::ViewSendKeyCombo(KeySym modsym0, KeySym modsym1, KeySym modsym2, const char c) { KeyCode keycode = 0; KeyCode modcode0 = 0; KeyCode modcode1 = 0; KeyCode modcode2 = 0; if (c != 0) { printf("ViewSendKeyCombo"); std::string s(1, c); keycode = XKeysymToKeycode(display_, XStringToKeysym(s.c_str())); } XTestGrabControl(display_, True); /* Generate modkey press */ if (modsym0 != 0) { modcode0 = XKeysymToKeycode(display_, modsym0); XTestFakeKeyEvent(display_, modcode0, True, 0); } if (modsym1 != 0) { modcode1 = XKeysymToKeycode(display_, modsym1); XTestFakeKeyEvent(display_, modcode1, True, 0); } if (modsym2 != 0) { modcode2 = XKeysymToKeycode(display_, modsym2); XTestFakeKeyEvent(display_, modcode2, True, 0); } /* Generate regular key press and release */ if (keycode) { XTestFakeKeyEvent(display_, keycode, True, 0); XTestFakeKeyEvent(display_, keycode, False, 0); } /* Generate modkey release */ if (modsym0 != 0) { XTestFakeKeyEvent(display_, modcode0, False, 0); } if (modsym1 != 0) { XTestFakeKeyEvent(display_, modcode1, False, 0); } if (modsym2 != 0) { XTestFakeKeyEvent(display_, modcode2, False, 0); } XSync(display_, False); XTestGrabControl(display_, False); } void NuxAutomatedTestFramework::ViewSendCtrlA() { ViewSendKeyCombo(XK_Control_L, 0, 0, 'a'); } void NuxAutomatedTestFramework::ViewSendDelete() { SendFakeKeyEvent(XK_Delete, 0); } void NuxAutomatedTestFramework::ViewSendBackspace() { SendFakeKeyEvent(XK_BackSpace, 0); } void NuxAutomatedTestFramework::ViewSendEscape() { SendFakeKeyEvent(XK_Escape, 0); } void NuxAutomatedTestFramework::ViewSendTab() { SendFakeKeyEvent(XK_Tab, 0); } void NuxAutomatedTestFramework::ViewSendReturn() { SendFakeKeyEvent(XK_Return, 0); } void NuxAutomatedTestFramework::ViewSendRight() { SendFakeKeyEvent(XK_Right, 0); } void NuxAutomatedTestFramework::ViewSendLeft() { SendFakeKeyEvent(XK_Left, 0); } void NuxAutomatedTestFramework::ViewSendUp() { SendFakeKeyEvent(XK_Up, 0); } void NuxAutomatedTestFramework::ViewSendDown() { SendFakeKeyEvent(XK_Down, 0); } void NuxAutomatedTestFramework::ViewSendIBusToggle() { KeyCode modcode0 = 0; KeyCode modcode1 = 0; modcode0 = XKeysymToKeycode(display_, XK_Control_L); XTestFakeKeyEvent(display_, modcode0, True, 0); modcode1 = XKeysymToKeycode(display_, XK_space); XTestFakeKeyEvent(display_, modcode1, True, 0); // release /* Generate modkey release */ XTestFakeKeyEvent(display_, modcode1, False, 0); XTestFakeKeyEvent(display_, modcode0, False, 0); XFlush(display_); } void NuxAutomatedTestFramework::PutMouseAt(int x, int y) { XTestFakeMotionEvent(display_, XScreenNumberOfScreen(DefaultScreenOfDisplay(display_)), x, y, CurrentTime); XSync(display_, False); } void NuxAutomatedTestFramework::SendFakeKeyEvent(KeySym keysym, KeySym modsym) { KeyCode keycode = 0; KeyCode modcode = 0; keycode = XKeysymToKeycode(display_, keysym); XTestGrabControl(display_, True); /* Generate modkey press */ if (modsym != 0) { modcode = XKeysymToKeycode(display_, modsym); XTestFakeKeyEvent(display_, modcode, True, 0); } /* Generate regular key press and release */ XTestFakeKeyEvent(display_, keycode, True, 0); XTestFakeKeyEvent(display_, keycode, False, 0); /* Generate modkey release */ if (modsym != 0) { XTestFakeKeyEvent(display_, modcode, False, 0); } XSync(display_, False); XTestGrabControl(display_, False); } void NuxAutomatedTestFramework::SendFakeMouseEvent(int mouse_button_index, bool pressed) { XTestFakeButtonEvent(display_, mouse_button_index, pressed, CurrentTime); XSync(display_, False); } void NuxAutomatedTestFramework::SendFakeMouseMotionEvent(int x, int y, int ms_delay) { XEvent event; /* Get the current pointer position */ XQueryPointer(display_, RootWindow(display_, 0), &event.xbutton.root, &event.xbutton.window, &event.xbutton.x_root, &event.xbutton.y_root, &event.xbutton.x, &event.xbutton.y, &event.xbutton.state); int old_x = event.xbutton.x; int old_y = event.xbutton.y; int n_iteration = ms_delay / 16.0f; //nuxDebugMsg("n_iteration: %d", n_iteration); if (n_iteration < 1) { n_iteration = 1; } XSync(display_, False); for (int i = 0; i < n_iteration; i++) { float t = ((float)i + 1.0f) / n_iteration; int cx = (1.0f - t) * old_x + t * x; int cy = (1.0f - t) * old_y + t * y; XTestFakeMotionEvent(display_, XScreenNumberOfScreen(DefaultScreenOfDisplay(display_)), cx, cy, CurrentTime); XSync(display_, False); usleep(16*1000); } XTestFakeMotionEvent(display_, XScreenNumberOfScreen(DefaultScreenOfDisplay(display_)), x, y, CurrentTime); XSync(display_, False); nux::SleepForMilliseconds(NuxAutomatedTestFramework::minimum_sleep_time); } void NuxAutomatedTestFramework::TestReportMsg(bool b, const char* msg) { if (b) { nuxOkMsg("%s: %s", msg, "Ok"); } else { nuxAlertMsg("%s: %s", msg, "Failed"); } } ./tests/gtest-nuxcore-rolling-file-appender.cpp0000644000004100000410000001114613313171755022106 0ustar www-datawww-data#include #include #include #include #include #include #include #include "NuxCore/RollingFileAppender.h" #include "Helpers.h" namespace bf = boost::filesystem; using namespace nux::logging; using namespace nux::testing; using namespace testing; namespace { /** * Due to the asynchronous manner in which the rolling file appender writes * the data to disk, it is incredibly hard to test in a simple unit test as * the underlying file on the file system isn't created synchronously, nor is * the output written synchronously. * * A files_rolled event exists on the RollingFileAppender so we can at least * wait for that signal and check the underlying files on the file system at * that stage. This does mean that we aren't testing the smaller chunks of * how it works, but more only the complete system, which I guess has to be * good enough for this case. */ const std::string TEST_ROOT("/tmp/nux-test-cases"); class TestRollingFileAppender : public ::testing::Test { protected: virtual void SetUp() { // Make sure that the tests start with nothing there. bf::remove_all(TEST_ROOT); } virtual void TearDown() { // Delete the unity test directory bf::remove_all(TEST_ROOT); } bool WaitForRoll(RollingFileAppender& appender, unsigned timeout = 5) { TestCallback rolled; TestCallback timed_out; g_timeout_add_seconds(timeout, &TestCallback::glib_callback, &timed_out); appender.files_rolled.connect(rolled.sigc_callback()); while (!rolled.happened && !timed_out.happened) { PumpGObjectMainLoop(); } return rolled.happened; } }; TEST_F(TestRollingFileAppender, NoTestRoot) { // The test root should not exist. EXPECT_FALSE(bf::exists(TEST_ROOT)); } TEST_F(TestRollingFileAppender, TestLogFileRollsAtFlush) { std::string logfile = TEST_ROOT + "/nux.log"; unsigned max_log_size = 20; // roll every 20 characters RollingFileAppender output(logfile, 5, max_log_size); output << "Testing the rolling of the logfile" << std::endl; WaitForRoll(output); output << "Long line greater than max_log_size" << std::endl; WaitForRoll(output); // Since the log files are rolled on flush, if the last thing written out // takes the filesize greater than the max_log_size, the log files are // rolled and the current file being appended to is now empty. EXPECT_THAT(ReadFile(logfile + ".1"), Eq("Long line greater than max_log_size\n")); EXPECT_THAT(ReadFile(logfile + ".2"), Eq("Testing the rolling of the logfile\n")); } TEST_F(TestRollingFileAppender, TestExistingLogFileMoved) { std::string logfile = TEST_ROOT + "/nux.log"; { bf::create_directories(bf::path(logfile).parent_path()); std::ofstream output(logfile); output << "Existing file."; } EXPECT_TRUE(bf::exists(logfile)); RollingFileAppender output(logfile); EXPECT_THAT(ReadFile(logfile + ".1"), Eq("Existing file.")); } TEST_F(TestRollingFileAppender, TestDeletingOld) { std::string logfile = TEST_ROOT + "/nux.log"; // Two backups, size 20 bytes. RollingFileAppender output(logfile, 2, 20); // Due to the asynchronous manner in which the output is sent to the // underlying file, we explicitly wait for the roll here. Otherwise we may // just send all the logging lines to one file then it would roll. output << "Oldest line should be deleted." << std::endl; WaitForRoll(output); output << "This line will be in the last backup." << std::endl; WaitForRoll(output); output << "This is backup number 1." << std::endl; WaitForRoll(output); EXPECT_THAT(ReadFile(logfile + ".1"), Eq("This is backup number 1.\n")); EXPECT_THAT(ReadFile(logfile + ".2"), Eq("This line will be in the last backup.\n")); EXPECT_FALSE(bf::exists(logfile + ".3")); } TEST_F(TestRollingFileAppender, TestFullPathNeeded) { EXPECT_THROW(RollingFileAppender("nux.log"), std::runtime_error); EXPECT_THROW(RollingFileAppender("relative/nux.log"), std::runtime_error); } TEST_F(TestRollingFileAppender, TestFileNeeded) { // For some obscure reason, EXPECT_THROW won't accept: // RollingFileAppender(logfile) // as its first arg. std::string directory_path = TEST_ROOT + "/somedir"; bf::create_directories(directory_path); EXPECT_THROW(RollingFileAppender appender(directory_path), std::runtime_error); std::string symlink_path = TEST_ROOT + "/somelink"; bf::create_symlink(directory_path, symlink_path); EXPECT_THROW(RollingFileAppender appender(symlink_path), std::runtime_error); } } // anon namespace ./tests/gtest-nux-scrollview.cpp0000644000004100000410000001405613313171755017252 0ustar www-datawww-data// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- /* * Copyright 2012 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Andrea Azzarone * */ #include #include "Nux/Nux.h" #include "Nux/ScrollView.h" #include "Nux/VLayout.h" #include "Nux/HScrollBar.h" #include "Nux/VScrollBar.h" using namespace testing; namespace { class MockScrollView : public nux::ScrollView { NUX_DECLARE_OBJECT_TYPE(MockScrollView, ScrollView); public: MockScrollView(NUX_FILE_LINE_PROTO) : nux::ScrollView(NUX_FILE_LINE_PARAM) { } MOCK_METHOD0(QueueDraw, void()); void FakeMouseWheelSignal(int x, int y, int wheel_delta, unsigned long mouse_button_state, unsigned long special_keys_state) { EmitMouseWheelSignal(x, y, wheel_delta, mouse_button_state, special_keys_state); } nux::Area* FindAreaUnderMouse(const nux::Point& mouse_position, nux::NuxEventType event_type) { return ScrollView::FindAreaUnderMouse(mouse_position, event_type); } nux::HScrollBar* GetHScrollbar() const { return _hscrollbar; } nux::VScrollBar* GetVScrollbar() const { return _vscrollbar; } }; NUX_IMPLEMENT_OBJECT_TYPE(MockScrollView); class TestScrollView : public ::testing::Test { public: virtual void SetUp() { nux::NuxInitialize(0); wnd_thread.reset(nux::CreateNuxWindow("ScrollView test", 300, 200, nux::WINDOWSTYLE_NORMAL, NULL, false, NULL, NULL)); scrollview.Adopt(new MockScrollView(NUX_TRACKER_LOCATION)); scrollview->SetLayout(new nux::VLayout()); } std::unique_ptr wnd_thread; nux::ObjectPtr scrollview; }; TEST_F(TestScrollView, TestQueueDrawScrollDownNoScrollbars) { EXPECT_CALL(*scrollview, QueueDraw()) .Times(0); scrollview->FakeMouseWheelSignal(0, 0, -NUX_MOUSEWHEEL_DELTA, 0, 0); } TEST_F(TestScrollView, TestQueueDrawScrollUpNoScrollbars) { EXPECT_CALL(*scrollview, QueueDraw()) .Times(0); scrollview->FakeMouseWheelSignal(0, 0, NUX_MOUSEWHEEL_DELTA, 0, 0); } TEST_F(TestScrollView, TestQueueDrawScrollDown) { scrollview->m_ViewContentHeight = 500; scrollview->m_ViewHeight = 400; EXPECT_CALL(*scrollview, QueueDraw()) .Times(1); scrollview->FakeMouseWheelSignal(0, 0, -NUX_MOUSEWHEEL_DELTA, 0, 0); } TEST_F(TestScrollView, TestQueueDrawScrollUp) { scrollview->m_ViewContentHeight = 500; scrollview->m_ViewHeight = 400; scrollview->ScrollDown(1, 10); EXPECT_CALL(*scrollview, QueueDraw()) .Times(1); scrollview->FakeMouseWheelSignal(0, 0, NUX_MOUSEWHEEL_DELTA, 0, 0); } TEST_F(TestScrollView, TestQueueDrawScrollDownEnd) { scrollview->m_ViewContentHeight = 500; scrollview->m_ViewHeight = 400; scrollview->ScrollDown(1, 100); EXPECT_CALL(*scrollview, QueueDraw()) .Times(0); scrollview->FakeMouseWheelSignal(0, 0, -NUX_MOUSEWHEEL_DELTA, 0, 0); } TEST_F(TestScrollView, TestQueueDrawScrollUpStart) { scrollview->m_ViewContentHeight = 500; scrollview->m_ViewHeight = 400; EXPECT_CALL(*scrollview, QueueDraw()) .Times(0); scrollview->FakeMouseWheelSignal(0, 0, NUX_MOUSEWHEEL_DELTA, 0, 0); } TEST_F(TestScrollView, TestFindAreaUnderMouseScrollbars) { scrollview->m_ViewContentHeight = 500; scrollview->m_ViewHeight = 400; scrollview->EnableVerticalScrollBar(true); scrollview->EnableHorizontalScrollBar(true); nux::Area* scroll_area = scrollview.GetPointer(); nux::Area* vscrollbar = scrollview->GetVScrollbar(); nux::Area* hscrollbar = scrollview->GetHScrollbar(); EXPECT_CALL(*scrollview, QueueDraw()) .Times(0); nux::Geometry const& geo_scrollview = scrollview->GetAbsoluteGeometry(); nux::Geometry const& geo_vbar = vscrollbar->GetAbsoluteGeometry(); nux::Geometry const& geo_hbar = hscrollbar->GetAbsoluteGeometry(); nux::Area* middle_area = scrollview->FindAreaUnderMouse(geo_scrollview.GetCenter(), nux::NUX_MOUSE_MOVE); EXPECT_EQ(middle_area, scroll_area); nux::Area* right_area = scrollview->FindAreaUnderMouse(geo_vbar.GetCenter(), nux::NUX_MOUSE_MOVE); EXPECT_TRUE(right_area == vscrollbar || right_area->IsChildOf(vscrollbar)); nux::Area* bottom_area = scrollview->FindAreaUnderMouse(geo_hbar.GetCenter(), nux::NUX_MOUSE_MOVE); EXPECT_TRUE(bottom_area == hscrollbar || bottom_area->IsChildOf(hscrollbar)); } TEST_F(TestScrollView, TestFindAreaUnderMouseNoScrollbars) { scrollview->m_ViewContentHeight = 500; scrollview->m_ViewHeight = 400; scrollview->EnableVerticalScrollBar(true); scrollview->EnableHorizontalScrollBar(true); nux::Area* scroll_area = scrollview.GetPointer(); nux::Area* vscrollbar = scrollview->GetVScrollbar(); nux::Area* hscrollbar = scrollview->GetHScrollbar(); EXPECT_CALL(*scrollview, QueueDraw()) .Times(0); nux::Geometry const& geo_scrollview = scrollview->GetAbsoluteGeometry(); nux::Geometry const& geo_vbar = vscrollbar->GetAbsoluteGeometry(); nux::Geometry const& geo_hbar = hscrollbar->GetAbsoluteGeometry(); // Now, disable the scrollbars. scrollview->EnableVerticalScrollBar(false); scrollview->EnableHorizontalScrollBar(false); nux::Area* middle_area = scrollview->FindAreaUnderMouse(geo_scrollview.GetCenter(), nux::NUX_MOUSE_MOVE); EXPECT_EQ(middle_area, scroll_area); nux::Area* right_area = scrollview->FindAreaUnderMouse(geo_vbar.GetCenter(), nux::NUX_MOUSE_MOVE); EXPECT_EQ(right_area, scroll_area); nux::Area* bottom_area = scrollview->FindAreaUnderMouse(geo_hbar.GetCenter(), nux::NUX_MOUSE_MOVE); EXPECT_EQ(bottom_area, scroll_area); } } ./tests/gtest-nux-textentry.cpp0000644000004100000410000004134113313171755017124 0ustar www-datawww-data/* * Copyright 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License version 3 along with this program. If not, see * * * Authored by: Marco Trevisan * */ #include "gtest-nux-utils.h" #include #include "Nux/Nux.h" #include "Nux/TextEntry.h" #include "Nux/HLayout.h" #if defined(NUX_OS_LINUX) #include "Nux/InputMethodIBus.h" #include "Nux/TextEntryComposeSeqs.h" #endif using namespace testing; using namespace nux; namespace { class MockTextEntry : public TextEntry { public: MockTextEntry() : TextEntry("") {} bool InspectKeyEvent(Event const& event) { return TextEntry::InspectKeyEvent(event); } bool GetSelectionBounds(int* start, int* end) const { return TextEntry::GetSelectionBounds(start, end); } int GetCursor() const { return cursor_; } void SetCursor(int cursor) { TextEntry::SetCursor(cursor); } bool InCompositionMode() const { return TextEntry::IsInCompositionMode(); } bool HandleComposition(unsigned long keysym) { return TextEntry::HandleComposition(keysym); } void ClearText() { TextEntry::DeleteText(0, std::numeric_limits::max()); ASSERT_TRUE(GetText().empty()); } enum class CompositionResult { NO_MATCH, PARTIAL, MATCH }; CompositionResult GetCompositionForList(std::vector const& input, std::string& composition) { return static_cast(TextEntry::GetCompositionForList(input, composition)); } CompositionResult GetCompositionForString(std::string const& input, std::string& composition) { std::vector input_vec; #if defined(NUX_OS_LINUX) input_vec.push_back(XK_Multi_key); for (auto c : input) { input_vec.push_back(c); } #endif return GetCompositionForList(input_vec, composition); } nux::IBusIMEContext* ime() const { #if defined(NUX_OS_LINUX) return ime_; #else return nullptr; #endif } MOCK_METHOD0(CutClipboard, void()); MOCK_METHOD0(CopyClipboard, void()); MOCK_METHOD0(PasteClipboard, void()); #if defined(NUX_OS_LINUX) MOCK_METHOD0(PastePrimaryClipboard, void()); #endif }; class TestEvent : public Event { public: TestEvent(KeyModifier keymod, unsigned long keysym, EventType type = NUX_KEYDOWN) : TestEvent(keysym, type) { key_modifiers = keymod; } TestEvent(unsigned long keysym, EventType etype = NUX_KEYDOWN) { type = etype; #if defined(NUX_OS_LINUX) x11_keysym = keysym; dtext = new char[NUX_EVENT_TEXT_BUFFER_SIZE]; auto len = g_unichar_to_utf8(x11_keysym, dtext); dtext[len] = '\0'; #elif defined(NUX_OS_WINDOWS) win32_keysym = keysym; #endif } }; class TestTextEntry : public Test { public: virtual void SetUp() { wnd_thread.reset(CreateNuxWindow("Nux Window", 300, 200, WINDOWSTYLE_NORMAL, nullptr, false, NULL, NULL)); text_entry = new MockTextEntry(); HLayout* layout = new HLayout(); layout->AddView(text_entry); wnd_thread->SetLayout(layout); GetWindowCompositor().SetKeyFocusArea(text_entry); } void WaitEvent() { if (text_entry->im_running()) Utils::WaitForTimeoutMSec(20); } void SendEvent(Event& event) { GetWindowCompositor().ProcessEvent(event); WaitEvent(); } std::unique_ptr wnd_thread; MockTextEntry* text_entry; }; TEST_F(TestTextEntry, TestSetText) { EXPECT_EQ(text_entry->IsInTextInputMode(), false); text_entry->SetText("Nux"); EXPECT_EQ(text_entry->GetText() == std::string("Nux"), true); EXPECT_EQ(text_entry->IsInTextInputMode(), true); } TEST_F(TestTextEntry, TestEnterText) { EXPECT_EQ(text_entry->IsInTextInputMode(), false); text_entry->EnterText("Nux"); EXPECT_EQ(text_entry->GetText() == std::string("Nux"), true); EXPECT_EQ(text_entry->IsInTextInputMode(), true); } TEST_F(TestTextEntry, TestDeleteText) { EXPECT_EQ(text_entry->IsInTextInputMode(), false); text_entry->EnterText("Nux"); EXPECT_EQ(text_entry->GetText() == std::string("Nux"), true); EXPECT_EQ(text_entry->IsInTextInputMode(), true); GetWindowCompositor().SetKeyFocusArea(nullptr); GetWindowCompositor().SetKeyFocusArea(text_entry); EXPECT_EQ(text_entry->IsInTextInputMode(), false); text_entry->DeleteText(0, 3); EXPECT_EQ(text_entry->GetText() == std::string(""), true); EXPECT_EQ(text_entry->IsInTextInputMode(), true); } #if defined(NUX_OS_LINUX) TEST_F(TestTextEntry, AltLinuxKeybindings) { for (unsigned long keysym = 0; keysym < XK_VoidSymbol; ++keysym) { TestEvent event(KEY_MODIFIER_ALT, keysym); if (text_entry->ime()->IsHotkeyEvent(event.type, event.GetKeySym(), event.key_modifiers)) EXPECT_TRUE(text_entry->InspectKeyEvent(event)); else EXPECT_FALSE(text_entry->InspectKeyEvent(event)); } } TEST_F(TestTextEntry, SuperLinuxKeybindings) { for (unsigned long keysym = 0; keysym < XK_VoidSymbol; ++keysym) { TestEvent event(KEY_MODIFIER_SUPER, keysym); if (text_entry->ime()->IsHotkeyEvent(event.type, event.GetKeySym(), event.key_modifiers)) EXPECT_TRUE(text_entry->InspectKeyEvent(event)); else EXPECT_FALSE(text_entry->InspectKeyEvent(event)); } } #endif TEST_F(TestTextEntry, InvalidKeys) { std::vector invalid_chars = {"", "", "", "", "", "", "", "", "", "", "", "", ""}; for (auto c : invalid_chars) { unsigned int keysym = g_utf8_get_char(c.c_str()); text_entry->ClearText(); text_entry->key_down.emit(NUX_KEYDOWN, keysym, 0, c.c_str(), 1); WaitEvent(); EXPECT_EQ(text_entry->GetText(), ""); } } TEST_F(TestTextEntry, CopyCtrlC) { EXPECT_CALL(*text_entry, CopyClipboard()); TestEvent event(KEY_MODIFIER_CTRL, NUX_VK_c); SendEvent(event); } TEST_F(TestTextEntry, CopyCtrlIns) { EXPECT_CALL(*text_entry, CopyClipboard()); TestEvent event(KEY_MODIFIER_CTRL, NUX_VK_INSERT); SendEvent(event); } TEST_F(TestTextEntry, PasteCtrlV) { EXPECT_CALL(*text_entry, PasteClipboard()); TestEvent event(KEY_MODIFIER_CTRL, NUX_VK_v); SendEvent(event); } TEST_F(TestTextEntry, PasteShiftIns) { EXPECT_CALL(*text_entry, PasteClipboard()); TestEvent event(KEY_MODIFIER_SHIFT, NUX_VK_INSERT); SendEvent(event); } #if defined(NUX_OS_LINUX) TEST_F(TestTextEntry, PastePrimaryClipboard) { EXPECT_CALL(*text_entry, PastePrimaryClipboard()); text_entry->mouse_down.emit(0, 0, NUX_EVENT_BUTTON2_DOWN, 0); EXPECT_CALL(*text_entry, PastePrimaryClipboard()).Times(0); text_entry->mouse_down.emit(0, 0, NUX_EVENT_BUTTON1_DOWN, 0); EXPECT_CALL(*text_entry, PastePrimaryClipboard()).Times(0); text_entry->mouse_down.emit(0, 0, NUX_EVENT_BUTTON3_DOWN, 0); } #endif TEST_F(TestTextEntry, CutCtrlX) { EXPECT_CALL(*text_entry, CutClipboard()); TestEvent event(KEY_MODIFIER_CTRL, NUX_VK_x); SendEvent(event); } TEST_F(TestTextEntry, CutShiftDel) { EXPECT_CALL(*text_entry, CutClipboard()); TestEvent event(KEY_MODIFIER_SHIFT, NUX_VK_DELETE); SendEvent(event); } TEST_F(TestTextEntry, CtrlA) { TestEvent selectall(KEY_MODIFIER_CTRL, NUX_VK_a); int start, end; const std::string test_str("Nux"); text_entry->EnterText(test_str.c_str()); EXPECT_FALSE(text_entry->GetSelectionBounds(&start, &end)); ASSERT_EQ(start, end); ASSERT_EQ(start, test_str.length()); SendEvent(selectall); EXPECT_TRUE(text_entry->GetSelectionBounds(&start, &end)); EXPECT_EQ(start, 0); EXPECT_EQ(end, test_str.length()); } TEST_F(TestTextEntry, MoveKeys) { const std::string test_str("Nux"); text_entry->EnterText(test_str.c_str()); ASSERT_EQ(text_entry->GetCursor(), test_str.length()); text_entry->SetCursor(0); ASSERT_EQ(text_entry->GetCursor(), 0); TestEvent right(NUX_VK_RIGHT); SendEvent(right); EXPECT_EQ(text_entry->GetCursor(), 1); TestEvent end(NUX_VK_END); SendEvent(end); EXPECT_EQ(text_entry->GetCursor(), test_str.length()); TestEvent left(NUX_VK_LEFT); SendEvent(left); EXPECT_EQ(text_entry->GetCursor(), 2); TestEvent home(NUX_VK_HOME); SendEvent(home); EXPECT_EQ(text_entry->GetCursor(), 0); } TEST_F(TestTextEntry, CtrlMoveKeys) { const std::string test_str("Nux Text Entry"); text_entry->EnterText(test_str.c_str()); ASSERT_EQ(text_entry->GetCursor(), test_str.length()); text_entry->SetCursor(0); ASSERT_EQ(text_entry->GetCursor(), 0); TestEvent right(KEY_MODIFIER_CTRL, NUX_VK_RIGHT); SendEvent(right); EXPECT_EQ(text_entry->GetCursor(), 3); TestEvent left(KEY_MODIFIER_CTRL, NUX_VK_LEFT); SendEvent(left); EXPECT_EQ(text_entry->GetCursor(), 0); TestEvent end(KEY_MODIFIER_CTRL, NUX_VK_END); SendEvent(end); EXPECT_EQ(text_entry->GetCursor(), test_str.length()); TestEvent home(KEY_MODIFIER_CTRL, NUX_VK_HOME); SendEvent(home); EXPECT_EQ(text_entry->GetCursor(), 0); } TEST_F(TestTextEntry, DeleteKeys) { const std::string test_str("Nux"); text_entry->EnterText(test_str.c_str()); text_entry->SetCursor(0); TestEvent del(NUX_VK_DELETE); SendEvent(del); EXPECT_EQ(text_entry->GetText(), "ux"); text_entry->SetCursor(std::string(text_entry->GetText()).length()); TestEvent backspace(NUX_VK_BACKSPACE); SendEvent(backspace); EXPECT_EQ(text_entry->GetText(), "u"); } TEST_F(TestTextEntry, CtrlDeleteKeys) { const std::string test_str("Nux Text Entry"); text_entry->EnterText(test_str.c_str()); text_entry->SetCursor(0); TestEvent del(KEY_MODIFIER_CTRL, NUX_VK_DELETE); SendEvent(del); EXPECT_EQ(text_entry->GetText(), " Text Entry"); text_entry->SetCursor(std::string(text_entry->GetText()).length()); TestEvent backspace(KEY_MODIFIER_CTRL, NUX_VK_BACKSPACE); SendEvent(backspace); EXPECT_EQ(text_entry->GetText(), " Text "); } #if defined(NUX_OS_LINUX) TEST_F(TestTextEntry, CompositionStart) { ASSERT_FALSE(text_entry->InCompositionMode()); TestEvent compose(XK_Multi_key); SendEvent(compose); EXPECT_TRUE(text_entry->InCompositionMode()); } TEST_F(TestTextEntry, CompositionWrite) { ASSERT_FALSE(text_entry->InCompositionMode()); TestEvent compose(XK_Multi_key); SendEvent(compose); TestEvent tilde(XK_asciitilde); SendEvent(tilde); EXPECT_TRUE(text_entry->InCompositionMode()); TestEvent n(TestEvent(XK_n)); SendEvent(n); EXPECT_FALSE(text_entry->InCompositionMode()); EXPECT_EQ(text_entry->GetText(), "ñ"); text_entry->ClearText(); SendEvent(compose); TestEvent less(XK_less); SendEvent(less); EXPECT_TRUE(text_entry->InCompositionMode()); TestEvent three(TestEvent(XK_3)); SendEvent(three); EXPECT_FALSE(text_entry->InCompositionMode()); EXPECT_EQ(text_entry->GetText(), "♥"); } TEST_F(TestTextEntry, CompositionIgnoreModifiers) { ASSERT_FALSE(text_entry->InCompositionMode()); TestEvent compose(XK_Multi_key); SendEvent(compose); TestEvent tilde(XK_asciitilde); SendEvent(tilde); EXPECT_TRUE(text_entry->InCompositionMode()); for (auto keysym = XK_Shift_L; keysym <= XK_Hyper_R; ++keysym) { TestEvent modifier(keysym); SendEvent(modifier); EXPECT_TRUE(text_entry->InCompositionMode()); } TestEvent AltGr(XK_ISO_Level3_Shift); SendEvent(AltGr); EXPECT_TRUE(text_entry->InCompositionMode()); TestEvent n(TestEvent(XK_n)); SendEvent(n); EXPECT_FALSE(text_entry->InCompositionMode()); EXPECT_EQ(text_entry->GetText(), "ñ"); } TEST_F(TestTextEntry, CompositionDeadKey) { ASSERT_FALSE(text_entry->InCompositionMode()); TestEvent dead_key_cirucmflex(XK_dead_circumflex); SendEvent(dead_key_cirucmflex); EXPECT_TRUE(text_entry->InCompositionMode()); TestEvent a(XK_a); SendEvent(a); EXPECT_FALSE(text_entry->InCompositionMode()); EXPECT_EQ(text_entry->GetText(), "â"); text_entry->ClearText(); TestEvent dead_key_currency(XK_dead_currency); SendEvent(dead_key_currency); EXPECT_TRUE(text_entry->InCompositionMode()); TestEvent e(XK_e); SendEvent(e); EXPECT_FALSE(text_entry->InCompositionMode()); EXPECT_EQ(text_entry->GetText(), "€"); } TEST_F(TestTextEntry, CompositionDeadKeyRepeat) { ASSERT_FALSE(text_entry->InCompositionMode()); TestEvent dead_key(XK_dead_grave); SendEvent(dead_key); EXPECT_TRUE(text_entry->InCompositionMode()); SendEvent(dead_key); EXPECT_FALSE(text_entry->InCompositionMode()); EXPECT_EQ(text_entry->GetText(), "`"); } TEST_F(TestTextEntry, CompositionDeadKeyComplex) { ASSERT_FALSE(text_entry->InCompositionMode()); TestEvent dead_key(XK_dead_circumflex); SendEvent(dead_key); EXPECT_TRUE(text_entry->InCompositionMode()); SendEvent(dead_key); EXPECT_FALSE(text_entry->InCompositionMode()); EXPECT_EQ(text_entry->GetText(), "^"); SendEvent(dead_key); TestEvent o(XK_o); SendEvent(o); EXPECT_FALSE(text_entry->InCompositionMode()); EXPECT_EQ(text_entry->GetText(), "^ô"); } TEST_F(TestTextEntry, CompositionDeadKeysMix) { // Make sure that the two dead keys we use here aren't used any sequence ASSERT_FALSE(text_entry->InCompositionMode()); TestEvent dead_key1(XK_dead_macron); SendEvent(dead_key1); EXPECT_TRUE(text_entry->InCompositionMode()); TestEvent dead_key2(XK_dead_circumflex); SendEvent(dead_key2); EXPECT_FALSE(text_entry->InCompositionMode()); EXPECT_EQ(text_entry->GetText(), ""); } TEST_F(TestTextEntry, CompositionMultipleKeyCancel) { std::string composed; auto result = text_entry->GetCompositionForString("iii", composed); EXPECT_EQ(result, MockTextEntry::CompositionResult::NO_MATCH); EXPECT_EQ(composed, ""); TestEvent compose(XK_Multi_key); TestEvent i(XK_i); SendEvent(compose); SendEvent(i); SendEvent(i); SendEvent(i); EXPECT_FALSE(text_entry->InCompositionMode()); EXPECT_EQ(text_entry->GetText(), "i"); } TEST_F(TestTextEntry, CompositionResultValid) { std::string composed; auto result = text_entry->GetCompositionForString("o", composed); EXPECT_EQ(result, MockTextEntry::CompositionResult::PARTIAL); EXPECT_TRUE(composed.empty()); result = text_entry->GetCompositionForString("ox", composed); EXPECT_EQ(result, MockTextEntry::CompositionResult::MATCH); EXPECT_EQ(composed, "¤"); result = text_entry->GetCompositionForString("ubuntu", composed); EXPECT_EQ(result, MockTextEntry::CompositionResult::MATCH); EXPECT_EQ(composed, ""); } TEST_F(TestTextEntry, CompositionResultInvalid) { std::string composed; auto result = text_entry->GetCompositionForString("nux", composed); EXPECT_EQ(result, MockTextEntry::CompositionResult::NO_MATCH); EXPECT_TRUE(composed.empty()); } TEST_F(TestTextEntry, CompositionSequences) { for (unsigned i = 0; i < COMPOSE_SEQUENCES_SIZE; ++i) { ComposeSequence const& seq = COMPOSE_SEQUENCES[i]; std::vector input_vec; std::string composed; for (unsigned j = 0; j < ComposeSequence::MAX_SYMBOLS && seq.symbols[j] != XK_VoidSymbol; ++j) { input_vec.push_back(seq.symbols[j]); } std::string expected_result = seq.result; auto result = text_entry->GetCompositionForList(input_vec, composed); EXPECT_EQ(result, MockTextEntry::CompositionResult::MATCH); EXPECT_EQ(composed, expected_result); } } TEST_F(TestTextEntry, CompositionSequencesInput) { for (unsigned i = 0; i < COMPOSE_SEQUENCES_SIZE; ++i) { ComposeSequence const& seq = COMPOSE_SEQUENCES[i]; EXPECT_FALSE(text_entry->InCompositionMode()); for (unsigned j = 0; j < ComposeSequence::MAX_SYMBOLS && seq.symbols[j] != XK_VoidSymbol; ++j) { // We use a different strategy if ibus is active, to speedup the test if (text_entry->im_running()) { text_entry->HandleComposition(seq.symbols[j]); } else { TestEvent event(seq.symbols[j]); SendEvent(event); } if (seq.symbols[j+1] != XK_VoidSymbol) EXPECT_TRUE(text_entry->InCompositionMode()); } std::string expected_result = seq.result; EXPECT_FALSE(text_entry->InCompositionMode()); EXPECT_EQ(text_entry->GetText(), expected_result); text_entry->ClearText(); } } TEST_F(TestTextEntry, PasswordMode) { text_entry->SetPasswordMode(true); EXPECT_TRUE(text_entry->PasswordMode()); text_entry->SetPasswordChar("*"); EXPECT_EQ(text_entry->GetPasswordChar(), std::string("*")); text_entry->SetText("Nux"); EXPECT_EQ(text_entry->GetText(), std::string("Nux")); text_entry->SetPasswordMode(false); EXPECT_FALSE(text_entry->PasswordMode()); } #endif } ./tests/gtest-nux-inputarea-proximity.cpp0000644000004100000410000002046013313171755021107 0ustar www-datawww-data/* * Copyright 2012 Inalogic Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License version 3 along with this program. If not, see * * * Authored by: Brandon Schaefer * */ #include using namespace testing; #include "Nux/Nux.h" #include "Nux/InputAreaProximity.h" #include "Nux/WindowCompositor.h" #include "Nux/ProgramFramework/TestView.h" #include namespace { const int VIEW_WIDTH = 500; const int VIEW_HEIGHT = 500; class TestInputAreaProximity : public Test { public: TestInputAreaProximity() : top_proximity_(0) , near_signal_recived_(false) , beyond_signal_recived_(false) , approaching_signal_recived_(false) { nux::NuxInitialize(0); wnd_thread.reset(nux::CreateNuxWindow("View Test", 300, 200, nux::WINDOWSTYLE_NORMAL, NULL, false, NULL, NULL)); MoveMouse(VIEW_WIDTH+200, VIEW_HEIGHT+200); } ~TestInputAreaProximity() { while (!prox_areas_.empty()) RemoveInputAreaProximity(); } void AddNInputAreaProximities(int n, int proximity = 10) { for (int i = 0; i < n; i++) AddInputAreaProximity(proximity); } void AddInputAreaProximity(int proximity = 10) { nux::TestView* test_view = new nux::TestView(""); test_view->SetGeometry(nux::Geometry(0, 0, VIEW_WIDTH, VIEW_HEIGHT)); top_proximity_ = proximity; auto prox_area = std::make_shared(test_view, proximity); prox_area->mouse_near.connect([this] (const nux::Point&) { near_signal_recived_ = true; }); prox_area->mouse_beyond.connect([this] (const nux::Point&) { beyond_signal_recived_ = true; }); prox_area->mouse_approaching.connect([this] (const nux::Point&, const nux::Point& difference) { approaching_signal_recived_ = true; last_approaching_point_ = difference; }); prox_areas_.push(std::make_pair(prox_area, test_view)); } void RemoveInputAreaProximity() { if (!prox_areas_.empty()) { auto prox_area = prox_areas_.top(); prox_areas_.pop(); prox_area.second->UnReference(); } } void ResetSignalRecivedValues() { near_signal_recived_ = false; beyond_signal_recived_ = false; approaching_signal_recived_ = false; } bool NearSignalRecived() const { return near_signal_recived_; } bool BeyondSignalRecived() const { return beyond_signal_recived_; } bool ApproachingSignalRecived() const { return approaching_signal_recived_; } nux::Point GetLastApprochingPoint() { return last_approaching_point_; } void MoveMouseNear() { MoveMouse(VIEW_WIDTH+(top_proximity_-1), VIEW_HEIGHT+(top_proximity_-1)); } void MoveMouseBeyond() { MoveMouse(VIEW_WIDTH+(top_proximity_+1), VIEW_HEIGHT+(top_proximity_+1)); } void MoveMouse(int x, int y) { nux::Event event; event.type = nux::NUX_MOUSE_MOVE; event.x = x; event.y = y; nux::GetWindowCompositor().ProcessEvent(event); } void MoveMouseBeyondWindow() { nux::Event event; event.type = nux::NUX_WINDOW_MOUSELEAVE; event.x = VIEW_WIDTH + top_proximity_ + 10; event.y = VIEW_HEIGHT + top_proximity_ + 10; nux::GetWindowCompositor().ProcessEvent(event); } int GetProxListSize() { return nux::GetWindowCompositor().GetProximityListSize(); } private: std::unique_ptr wnd_thread; std::stack, nux::TestView*> > prox_areas_; nux::Point last_approaching_point_; int top_proximity_; bool near_signal_recived_; bool beyond_signal_recived_; bool approaching_signal_recived_; }; TEST_F(TestInputAreaProximity, TestAtemptToAddNullToList) { const int prox_size = GetProxListSize(); nux::InputAreaProximity* prox_area = new nux::InputAreaProximity(NULL, 10); MoveMouseNear(); MoveMouseBeyond(); delete prox_area; ASSERT_EQ(GetProxListSize(), prox_size); } TEST_F(TestInputAreaProximity, TestHandlesDeletedInputArea) { const int prox_size = GetProxListSize(); nux::TestView* test_view = new nux::TestView(""); test_view->SetGeometry(nux::Geometry(0, 0, VIEW_WIDTH, VIEW_HEIGHT)); nux::InputAreaProximity* prox_area = new nux::InputAreaProximity(test_view, 10); test_view->UnReference(); MoveMouseNear(); MoveMouseBeyond(); delete prox_area; ASSERT_EQ(GetProxListSize(), prox_size); } TEST_F(TestInputAreaProximity, TestAddsNullProximity) { const int prox_size = nux::GetWindowCompositor().GetProximityListSize(); nux::GetWindowThread()->GetWindowCompositor().AddAreaInProximityList(NULL); MoveMouseNear(); MoveMouseBeyond(); nux::GetWindowThread()->GetWindowCompositor().RemoveAreaInProximityList(NULL); ASSERT_EQ(nux::GetWindowCompositor().GetProximityListSize(), prox_size); } TEST_F(TestInputAreaProximity, TestProximityAreaAddsToList) { ASSERT_EQ(nux::GetWindowCompositor().GetProximityListSize(), 0); AddNInputAreaProximities(2); ASSERT_EQ(nux::GetWindowCompositor().GetProximityListSize(), 2); } TEST_F(TestInputAreaProximity, TestRemovesFromProximityList) { int num_prox_areas = 10; AddNInputAreaProximities(num_prox_areas); ASSERT_EQ(GetProxListSize(), num_prox_areas); for (int i = 0; i < num_prox_areas; i++) { RemoveInputAreaProximity(); ASSERT_EQ(GetProxListSize(), num_prox_areas - (i + 1)); } } TEST_F(TestInputAreaProximity, TestNearSignal) { AddInputAreaProximity(); MoveMouseBeyond(); ASSERT_FALSE(NearSignalRecived()); MoveMouseNear(); ASSERT_TRUE(NearSignalRecived()); } TEST_F(TestInputAreaProximity, TestApproachingSignal) { AddInputAreaProximity(); MoveMouseBeyond(); ASSERT_FALSE(ApproachingSignalRecived()); MoveMouseNear(); ASSERT_TRUE(ApproachingSignalRecived()); } TEST_F(TestInputAreaProximity, TestApproachingDoesNotEmitInsideArea) { AddInputAreaProximity(); MoveMouse(VIEW_WIDTH/2, VIEW_HEIGHT/2); ResetSignalRecivedValues(); MoveMouse(VIEW_WIDTH/4, VIEW_HEIGHT/4); ASSERT_FALSE(ApproachingSignalRecived()); MoveMouseNear(); ASSERT_TRUE(ApproachingSignalRecived()); } TEST_F(TestInputAreaProximity, TestApproachingSignalHorizontal) { int proximity = 10; AddInputAreaProximity(proximity); nux::Point difference; int expected_result; for (int i = 1; i <= proximity; i++) { MoveMouse(VIEW_WIDTH+(proximity-i), VIEW_HEIGHT+(proximity-1)); difference = GetLastApprochingPoint(); expected_result = -(proximity - i); ASSERT_EQ(expected_result, difference.x); ASSERT_EQ(-(proximity-1), difference.y); } } TEST_F(TestInputAreaProximity, TestApproachingSignalVertical) { int proximity = 10; AddInputAreaProximity(proximity); nux::Point difference; int expected_result; for (int i = 1; i <= proximity; i++) { MoveMouse(VIEW_WIDTH+(proximity-1), VIEW_HEIGHT+(proximity-i)); difference = GetLastApprochingPoint(); expected_result = -(proximity - i); ASSERT_EQ(-(proximity-1), difference.x); ASSERT_EQ(expected_result, difference.y); } } TEST_F(TestInputAreaProximity, TestApproachingSignalDiagonal) { int proximity = 10; AddInputAreaProximity(proximity); nux::Point difference; int expected_result; for (int i = 1; i <= proximity; i++) { MoveMouse(VIEW_WIDTH+(proximity-i), VIEW_HEIGHT+(proximity-i)); difference = GetLastApprochingPoint(); expected_result = -(proximity - i); ASSERT_EQ(expected_result, difference.x); ASSERT_EQ(expected_result, difference.y); } } TEST_F(TestInputAreaProximity, TestBeyondSignal) { AddInputAreaProximity(); MoveMouseNear(); ASSERT_FALSE(BeyondSignalRecived()); MoveMouseBeyond(); ASSERT_TRUE(BeyondSignalRecived()); } TEST_F(TestInputAreaProximity, TestBeyondSignalEmitWhenLeavingWindow) { AddInputAreaProximity(); MoveMouseNear(); ASSERT_FALSE(BeyondSignalRecived()); MoveMouseBeyondWindow(); ASSERT_TRUE(BeyondSignalRecived()); } } ./tests/Makefile.am0000644000004100000410000002575713313171755014467 0ustar www-datawww-dataif BUILD_TESTS nodist_libgtest_a_SOURCES = \ $(GMOCK_PREFIX)/src/gmock-all.cc \ $(GTEST_PREFIX)/src/gtest-all.cc libgtest_a_CPPFLAGS = $(GMOCK_CPPFLAGS) $(GTEST_CPPFLAGS) -w check_LIBRARIES = libgtest.a check_PROGRAMS = \ gtest-nux \ gtest-nux-slow \ gtest-nuxcore \ gtest-nuxgraphics \ test-graphics-display \ test-empty-window \ xtest-button \ xtest-mouse-events \ xtest-mouse-buttons \ xtest-hgrid-key-navigation \ xtest-hlayout-key-navigation \ xtest-vlayout-key-navigation \ xtest-scrollbar \ xtest-focus-on-mouse-down \ xtest-keynav-directions \ xtest-text-entry \ xtest-text-entry-deadkeys \ xtest-text-entry-compositionkeys \ xtest-text-entry-logic \ xtest-text-entry-xim \ xtest-focus-on-mouse-enter TestFlags = -I$(srcdir) \ -I$(top_srcdir) \ -DPREFIX=\""$(prefix)"\" \ -DLIBDIR=\""$(libdir)"\" \ -DDATADIR=\""$(datadir)"\" \ -DG_LOG_DOMAIN=\"NuxTests\" \ -DTESTDIR=\""$(top_srcdir)/tests"\" \ $(GCC_TESTS_FLAGS) \ $(NUX_CORE_CFLAGS) \ $(NUX_EXAMPLES_CFLAGS) \ $(NUX_CFLAGS) \ $(NUX_TESTS_CFLAGS) \ $(MAINTAINER_CFLAGS) \ $(IBUS_CFLAGS) \ $(GEIS_CFLAGS) TestLibs = $(top_builddir)/NuxCore/libnux-core-@NUX_API_VERSION@.la \ $(top_builddir)/NuxGraphics/libnux-graphics-@NUX_API_VERSION@.la \ $(top_builddir)/Nux/libnux-@NUX_API_VERSION@.la \ $(NUX_TESTS_LIBS) \ $(NUX_LIBS) GTestFlags = $(TestFlags) \ $(GMOCK_CPPFLAGS) \ $(GTEST_CPPFLAGS) GTestLibs = $(TestLibs) \ libgtest.a GTestLDFlags = -lboost_system \ -lboost_filesystem ##### gtest-nuxcore ###### gtest_nuxcore_SOURCES = \ Helpers.h \ Helpers.cpp \ $(top_srcdir)/NuxCore/ColorPrivate.cpp \ $(top_srcdir)/NuxCore/ColorPrivate.h \ gtest-nuxcore-animation.cpp \ gtest-nuxcore-async-file-writer.cpp \ gtest-nuxcore-color.cpp \ gtest-nuxcore-colorprivate.cpp \ gtest-nuxcore-logger.cpp \ gtest-nuxcore-main.cpp \ gtest-nuxcore-object.cpp \ gtest-nuxcore-properties.cpp \ gtest-nuxcore-rolling-file-appender.cpp gtest_nuxcore_CPPFLAGS = $(GTestFlags) gtest_nuxcore_LDADD = $(GTestLibs) gtest_nuxcore_LDFLAGS = $(GTestLDFlags) ##### gtest-nux ###### gtest_nux_SOURCES = \ FakeGestureEvent.h \ gtest-nux-axisdecelerationanimation.cpp \ gtest-nux-emmetrics.cpp \ gtest-nux-globals.cpp \ gtest-nux-globals.h \ gtest-nux-kineticscroller.cpp \ gtest-nux-inputmethodibus.cpp \ gtest-nux-velocitycalculator.cpp \ gtest-nux-main.cpp if HAVE_GEIS gtest_nux_SOURCES += \ geis_mock.h \ geis_mock.cpp \ gtest-nux-geisadapter.cpp \ gtest-nux-gesturebroker.cpp endif gtest_nux_CPPFLAGS = $(GTestFlags) gtest_nux_LDADD = $(GTestLibs) ##### gtest-nux-slow ###### gtest_nux_slow_SOURCES = \ gtest-nux-area.cpp \ gtest-nux-cairo-wrapper.cpp \ gtest-nux-input-area.cpp \ gtest-nux-main.cpp \ gtest-nux-inputarea-proximity.cpp \ gtest-nux-statictext.cpp \ gtest-nux-scrollview.cpp \ gtest-nux-textentry.cpp \ gtest-nux-utils.h \ gtest-nux-view.cpp \ gtest-nux-windowcompositor.cpp \ gtest-nux-windowthread.cpp gtest_nux_slow_CPPFLAGS = $(GTestFlags) gtest_nux_slow_LDADD = $(GTestLibs) gtest_nux_slow_LDFLAGS = $(GTestLDFlags) ##### gtest-nuxgraphics ###### gtest_nuxgraphics_SOURCES = \ gtest-nuxgraphics-main.cpp \ gtest-nuxgraphics-texture.cpp \ gtest-nuxgraphics-graphic-display.cpp gtest_nuxgraphics_CPPFLAGS = $(GTestFlags) gtest_nuxgraphics_LDADD = $(GTestLibs) test_graphics_display_SOURCES = test_graphics_display.cpp test_graphics_display_CPPFLAGS = $(TestFlags) test_graphics_display_LDADD = $(TestLibs) test_graphics_display_LDFLAGS = -lpthread test_empty_window_SOURCES = test_empty_window.cpp test_empty_window_CPPFLAGS = $(TestFlags) test_empty_window_LDADD = $(TestLibs) test_empty_window_LDFLAGS = -lpthread xtest_button_SOURCES = xtest-button.cpp \ nux_automated_test_framework.cpp \ nux_automated_test_framework.h xtest_button_CPPFLAGS = $(TestFlags) xtest_button_LDADD = $(TestLibs) xtest_button_LDFLAGS = -lpthread -lXtst xtest_mouse_events_SOURCES = xtest-mouse-events.cpp \ nux_automated_test_framework.cpp \ nux_automated_test_framework.h xtest_mouse_events_CPPFLAGS = $(TestFlags) xtest_mouse_events_LDADD = $(TestLibs) xtest_mouse_events_LDFLAGS = -lpthread -lXtst xtest_mouse_buttons_SOURCES = xtest-mouse-buttons.cpp \ nux_automated_test_framework.cpp \ nux_automated_test_framework.h xtest_mouse_buttons_CPPFLAGS = $(TestFlags) xtest_mouse_buttons_LDADD = $(TestLibs) xtest_mouse_buttons_LDFLAGS = -lpthread -lXtst xtest_hgrid_key_navigation_SOURCES = xtest-hgrid-key-navigation.cpp \ nux_automated_test_framework.cpp \ nux_automated_test_framework.h xtest_hgrid_key_navigation_CPPFLAGS = $(TestFlags) xtest_hgrid_key_navigation_LDADD = $(TestLibs) xtest_hgrid_key_navigation_LDFLAGS = -lpthread -lXtst xtest_hlayout_key_navigation_SOURCES = xtest-hlayout-key-navigation.cpp \ nux_automated_test_framework.cpp \ nux_automated_test_framework.h xtest_hlayout_key_navigation_CPPFLAGS = $(TestFlags) xtest_hlayout_key_navigation_LDADD = $(TestLibs) xtest_hlayout_key_navigation_LDFLAGS = -lpthread -lXtst xtest_vlayout_key_navigation_SOURCES = xtest-vlayout-key-navigation.cpp \ nux_automated_test_framework.cpp \ nux_automated_test_framework.h xtest_vlayout_key_navigation_CPPFLAGS = $(TestFlags) xtest_vlayout_key_navigation_LDADD = $(TestLibs) xtest_vlayout_key_navigation_LDFLAGS = -lpthread -lXtst xtest_focus_on_mouse_down_SOURCES = xtest-focus-on-mouse-down.cpp \ nux_automated_test_framework.cpp \ nux_automated_test_framework.h xtest_focus_on_mouse_down_CPPFLAGS = $(TestFlags) xtest_focus_on_mouse_down_LDADD = $(TestLibs) xtest_focus_on_mouse_down_LDFLAGS = -lpthread -lXtst xtest_focus_on_mouse_enter_SOURCES = xtest-focus-on-mouse-enter.cpp \ nux_automated_test_framework.cpp \ nux_automated_test_framework.h xtest_focus_on_mouse_enter_CPPFLAGS = $(TestFlags) xtest_focus_on_mouse_enter_LDADD = $(TestLibs) xtest_focus_on_mouse_enter_LDFLAGS = -lpthread -lXtst xtest_scrollbar_SOURCES = xtest-scrollbar.cpp \ nux_automated_test_framework.cpp \ nux_automated_test_framework.h \ test-scrollview.cpp \ test-scrollview.h xtest_scrollbar_CPPFLAGS = $(TestFlags) xtest_scrollbar_LDADD = $(TestLibs) xtest_scrollbar_LDFLAGS = -lpthread -lXtst xtest_keynav_directions_SOURCES = xtest-keynav-directions.cpp \ nux_automated_test_framework.cpp \ nux_automated_test_framework.h xtest_keynav_directions_CPPFLAGS = $(TestFlags) xtest_keynav_directions_LDADD = $(TestLibs) xtest_keynav_directions_LDFLAGS = -lpthread -lXtst xtest_text_entry_SOURCES = xtest-text-entry.cpp \ nux_automated_test_framework.cpp \ nux_automated_test_framework.h xtest_text_entry_CPPFLAGS = $(TestFlags) xtest_text_entry_LDADD = $(TestLibs) xtest_text_entry_LDFLAGS = -lpthread -lXtst -libus-1.0 -lgio-2.0 -lgobject-2.0 -lglib-2.0 xtest_text_entry_logic_SOURCES = xtest-text-entry-logic.cpp \ nux_automated_test_framework.cpp \ nux_automated_test_framework.h xtest_text_entry_logic_CPPFLAGS = $(TestFlags) xtest_text_entry_logic_LDADD = $(TestLibs) xtest_text_entry_logic_LDFLAGS = -lpthread -lXtst xtest_text_entry_deadkeys_SOURCES = xtest-text-entry-deadkeys.cpp \ nux_automated_test_framework.cpp \ nux_automated_test_framework.h xtest_text_entry_deadkeys_CPPFLAGS = $(TestFlags) xtest_text_entry_deadkeys_LDADD = $(TestLibs) xtest_text_entry_deadkeys_LDFLAGS = -lpthread -lXtst xtest_text_entry_compositionkeys_SOURCES = xtest-text-entry-compositionkeys.cpp \ nux_automated_test_framework.cpp \ nux_automated_test_framework.h xtest_text_entry_compositionkeys_CPPFLAGS = $(TestFlags) xtest_text_entry_compositionkeys_LDADD = $(TestLibs) xtest_text_entry_compositionkeys_LDFLAGS = -lpthread -lXtst xtest_text_entry_xim_SOURCES = xtest-text-entry-xim.cpp \ nux_automated_test_framework.cpp \ nux_automated_test_framework.h xtest_text_entry_xim_CPPFLAGS = $(TestFlags) xtest_text_entry_xim_LDADD = $(TestLibs) xtest_text_entry_xim_LDFLAGS = -lpthread -lXtst #run make test as part of make check check-local: test gtest test-apps test: @gtester --verbose -k -o=gtest-nux-results.xml ./gtest-nux gtest-build: gtest-nuxcore gtest-nuxgraphics gtest-nux gtest-nux-slow gtest: gtest-build ./gtest-nuxcore ./gtest-nuxgraphics ./gtest-nux ./gtest-nux-slow CHECK_GTEST_OPTIONS = if NUX_OPENGLES_20 # Disable EmbeddedContext tests when OpenGLES is enabled, they tend to crash CHECK_GTEST_OPTIONS = --gtest_filter=-EmbeddedContext* endif # NUX_OPENGLES_20 check-headless: gtest-nuxcore gtest-nuxgraphics gtest-nux gtest-nux-slow @./gtest-nuxcore --gtest_output=xml:./test-nux-core-results.xml $(CHECK_GTEST_OPTIONS) @./dummy-xorg-test-runner.sh ./gtest-nuxgraphics --gtest_output=xml:./test-nux-graphics-results.xml $(CHECK_GTEST_OPTIONS) @./dummy-xorg-test-runner.sh ./gtest-nux --gtest_output=xml:./test-nux-results.xml $(CHECK_GTEST_OPTIONS) @./dummy-xorg-test-runner.sh ./gtest-nux-slow --gtest_output=xml:./test-nux-slow-results.xml $(CHECK_GTEST_OPTIONS) check: gtest-nuxcore gtest-nuxgraphics gtest-nux gtest-nux-slow @./gtest-nuxcore --gtest_output=xml:./test-nux-core-results.xml @./gtest-nuxgraphics --gtest_output=xml:./test-nux-graphics-results.xml @./gtest-nux --gtest_output=xml:./test-nux-results.xml @./gtest-nux-slow --gtest_output=xml:./test-nux-slow-results.xml test-apps: test-graphics-display test-empty-window xtest-text-entry-xim xtest-text-entry xtest-button xtest-mouse-events xtest-mouse-buttons xtest-hgrid-key-navigation xtest-hlayout-key-navigation xtest-vlayout-key-navigation xtest-scrollbar xtest-focus-on-mouse-down xtest-focus-on-mouse-enter xtest-keynav-directions xtest-text-entry-logic xtest-text-entry-deadkeys xtest-text-entry-compositionkeys ./test-graphics-display ./test-empty-window ./xtest-text-entry ./xtest-button ./xtest-mouse-events ./xtest-mouse-buttons ./xtest-hgrid-key-navigation ./xtest-hlayout-key-navigation ./xtest-vlayout-key-navigation ./xtest-scrollbar ./xtest-focus-on-mouse-down ./xtest-focus-on-mouse-enter ./xtest-keynav-directions ./xtest-text-entry-logic ./xtest-text-entry-deadkeys ./xtest-text-entry-compositionkeys check-report: @gtester -k -o=test-nux-results.xml -k ./test-nux \ && ( gtester-report test-nux-results.xml \ | sed 's/GTester Unit Test ReportGTester Unit Test Report (normal) test-nux-results.html ) \ && gnome-open ./test-nux-results.html full-report: @gtester -k -o=test-nux-results.xml -k -m=slow ./test-nux \ && ( gtester-report test-nux-results.xml \ | sed 's/>GTester Unit Test ReportGTester Unit Test Report (normal) test-nux-results.html ) CLEANFILES = \ test-nux-results.xml test-nux-results.html \ gtest-nux-results.xml .PHONY: check check-report full-report gtest test check-headless endif unused_src = \ manual-tests/linaro-reference-fbo.txt \ manual-tests/text-entry.txt \ test-canvas.cpp \ test-nux.cpp \ test-system.cpp \ test-timeline.cpp \ xim-test-commands.txt EXTRA_DIST = Readme.txt ${unused_src} ./tests/FakeGestureEvent.h0000644000004100000410000000313013313171755015770 0ustar www-datawww-data#ifndef FAKE_GESTURE_EVENT_H #define FAKE_GESTURE_EVENT_H #include #include namespace nux { class FakeGestureEvent { public: nux::EventType type; int gesture_id; int gesture_classes; bool is_direct_touch; int timestamp; nux::Point2D focus; nux::Point2D delta; float angle; float angle_delta; float angular_velocity; int tap_duration; nux::Point2D velocity; float radius; float radius_delta; float radial_velocity; std::vector touches; bool is_construction_finished; nux::GestureEvent &ToGestureEvent() { event_.type = type; event_.gesture_id_ = gesture_id; event_.gesture_classes_ = gesture_classes; event_.is_direct_touch_ = is_direct_touch; event_.timestamp_ = timestamp; event_.focus_ = focus; event_.delta_ = delta; event_.angle_ = angle; event_.angle_delta_ = angle_delta; event_.angular_velocity_ = angular_velocity; event_.tap_duration_ = tap_duration; event_.velocity_ = velocity; event_.radius_ = radius; event_.radius_delta_ = radius_delta; event_.radial_velocity_ = radial_velocity; event_.touches_ = touches; event_.is_construction_finished_ = is_construction_finished; return event_; } private: nux::GestureEvent event_; }; } // namespace nux // maps a gesture id to its acceptance // each Accept() increments by one and each Reject() decrements by one. extern std::map g_gesture_acceptance; #endif // FAKE_GESTURE_EVENT_H ./tests/gtest-nux-globals.cpp0000644000004100000410000000017013313171755016474 0ustar www-datawww-data#include gint64 g_fake_monotonic_time = 0; gint64 g_get_monotonic_time() { return g_fake_monotonic_time; } ./tests/gtest-nux-velocitycalculator.cpp0000644000004100000410000000513613313171755020770 0ustar www-datawww-data/* * Copyright (C) 2012 - Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Daniel d'Andrada */ #include #include #include "gtest-nux-globals.h" using namespace nux; TEST(VelocityCalculator, SimpleSamples) { VelocityCalculator vel_calc; g_fake_monotonic_time = 10 * 1000; vel_calc.ProcessMovement(20); g_fake_monotonic_time = 20 * 1000; vel_calc.ProcessMovement(20); g_fake_monotonic_time = 30 * 1000; vel_calc.ProcessMovement(20); float velocity = vel_calc.CalculateVelocity(); ASSERT_FLOAT_EQ(2.0f, velocity); } TEST(VelocityCalculator, NoSamples) { VelocityCalculator vel_calc; float velocity = vel_calc.CalculateVelocity(); ASSERT_FLOAT_EQ(0.0f, velocity); } TEST(VelocityCalculator, OverflowSamples) { VelocityCalculator vel_calc; for (int i = 0; i < 1000; ++i) { g_fake_monotonic_time += 10 * 1000; vel_calc.ProcessMovement(20); } /* overwrite all existing samples with faster ones */ for (int i = 0; i < VelocityCalculator::MAX_SAMPLES; ++i) { g_fake_monotonic_time += 10 * 1000; vel_calc.ProcessMovement(40); } float velocity = vel_calc.CalculateVelocity(); /* check that the calculated velocity correspond to the latest, faster, samples */ ASSERT_FLOAT_EQ(4.0f, velocity); } TEST(VelocityCalculator, Average) { VelocityCalculator vel_calc; g_fake_monotonic_time = 10 * 1000; vel_calc.ProcessMovement(20); g_fake_monotonic_time = 20 * 1000; vel_calc.ProcessMovement(20); /* the last sample is an erratic one and would yield a big velocity if considered isolatedly */ g_fake_monotonic_time = 30 * 1000; vel_calc.ProcessMovement(100); float velocity = vel_calc.CalculateVelocity(); /* calculated velocity is lower than the one from the last sample */ ASSERT_TRUE(velocity < 9.0f); /* but it's higher the the slow samples */ ASSERT_TRUE(velocity > 2.5f); } ./tests/test-timeline.cpp0000644000004100000410000000521313313171755015703 0ustar www-datawww-data/* * Copyright (C) 2010 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as * published by the Free Software Foundation. * * This program 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 this program. If not, see . * * Authored by Gordon Allott * */ #include #include "Nux/Nux.h" #include "Nux/VLayout.h" #include "Nux/HLayout.h" #include "Nux/WindowThread.h" #include "Nux/Button.h" static void test_timeline (void); void test_timeline_create_suite (void) { #define TESTDOMAIN "/Timeline/" g_test_add_func (TESTDOMAIN"/Timeline", test_timeline); } class TimelineTestClass { public: nux::Button *button; nux::Timeline *timeline_1; TimelineTestClass () { has_got_new_frame = false; } void OnNewFrame (unsigned long msecs) { has_got_new_frame = true; } void OnCompleted () { nux::GetGraphicsThread ()->NuxMainLoopQuit (); } void Init (nux::Layout *layout) { } bool has_got_new_frame; }; void ThreadWidgetInit(nux::NThread* thread, void* InitData) { TimelineTestClass *self = (TimelineTestClass*) InitData; nux::VLayout* MainVLayout = new nux::VLayout(TEXT(""), NUX_TRACKER_LOCATION); MainVLayout->SetContentDistribution(nux::eStackCenter); self->Init (MainVLayout); nux::GetGraphicsThread()->SetLayout(MainVLayout); nux::ColorLayer background(nux::Color(0xFF4D4D4D)); static_cast(thread)->SetWindowBackgroundPaintLayer(&background); } static void test_timeline (void) { TimelineTestClass *test_class = new TimelineTestClass (); nux::WindowThread* wt = nux::CreateGUIThread(TEXT("Timeline Test"), 400, 300, 0, ThreadWidgetInit, test_class); nux::Timeline *timeline = new nux::Timeline (1000, "My Timeline", NUX_TRACKER_LOCATION); timeline->Looping = false; timeline->NewFrame.connect (sigc::mem_fun (test_class, &TimelineTestClass::OnNewFrame)); timeline->Completed.connect (sigc::mem_fun (test_class, &TimelineTestClass::OnCompleted)); gint64 micro_secs = g_get_real_time(); unsigned long current_time = micro_secs / 1000; wt->AddTimeline (timeline); wt->Run(NULL); micro_secs = g_get_real_time(); g_assert(micro_secs / 1000 - current_time > 1000); g_assert (test_class->has_got_new_frame); delete test_class; delete wt; } ./tests/xtest-hgrid-key-navigation.cpp0000644000004100000410000001517413313171755020314 0ustar www-datawww-data/* * Copyright 2011 Inalogic Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY 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 * version 3 along with this program. If not, see * * * Authored by: Andrea Azzarone * */ #include "Nux/Nux.h" #include "Nux/WindowThread.h" #include "Nux/GridHLayout.h" #include "Nux/ProgramFramework/ProgramTemplate.h" #include "Nux/ProgramFramework/TestView.h" #include #include #include "nux_automated_test_framework.h" // 0 1 2 3 // 4 5 6 7 // 8 9 10 class HGridKeyNavigationTest: public ProgramTemplate { public: HGridKeyNavigationTest(const char* program_name, int window_width, int window_height, int program_life_span); ~HGridKeyNavigationTest(); virtual void UserInterfaceSetup(); nux::TestView* CreateTile(); void AddTile(nux::TestView* tile); nux::VLayout* vlayout_; nux::GridHLayout* grid_layout_; nux::TestView* tiles_[11]; nux::TestView* bottom_view_; }; HGridKeyNavigationTest::HGridKeyNavigationTest(const char* program_name, int window_width, int window_height, int program_life_span) : ProgramTemplate(program_name, window_width, window_height, program_life_span) { } HGridKeyNavigationTest::~HGridKeyNavigationTest() { } nux::TestView* HGridKeyNavigationTest::CreateTile() { nux::TestView* tile = new nux::TestView(); return tile; } void HGridKeyNavigationTest::AddTile(nux::TestView* tile) { grid_layout_->AddView(tile, 1); } void HGridKeyNavigationTest::UserInterfaceSetup() { vlayout_ = new nux::VLayout(NUX_TRACKER_LOCATION); grid_layout_ = new nux::GridHLayout(NUX_TRACKER_LOCATION); grid_layout_->ForceChildrenSize(true); grid_layout_->SetChildrenSize(100, 100); grid_layout_->EnablePartialVisibility(false); grid_layout_->SetPadding(20, 20); grid_layout_->SetSpaceBetweenChildren(10, 10); vlayout_->AddLayout(grid_layout_); for (int i=0; i<11; ++i) { tiles_[i] = CreateTile(); AddTile(tiles_[i]); } bottom_view_ = CreateTile(); vlayout_->AddView(bottom_view_); nux::GetWindowCompositor().SetKeyFocusArea(bottom_view_); static_cast(window_thread_)->SetLayout(vlayout_); nux::ColorLayer background(nux::Color(0xFF4D4D4D)); static_cast(window_thread_)->SetWindowBackgroundPaintLayer(&background); } HGridKeyNavigationTest* key_navigation_test = NULL; void TestingThread(nux::NThread* /* thread */, void* user_data) { while (key_navigation_test->ReadyToGo() == false) { nuxDebugMsg("Waiting to start"); nux::SleepForMilliseconds(300); } nux::SleepForMilliseconds(1000); nux::WindowThread* wnd_thread = static_cast(user_data); NuxAutomatedTestFramework test(wnd_thread); test.Startup(); // Set the mouse at coordinates (0, 0) (top-left corner) on the display test.PutMouseAt(0, 0); test.TestReportMsg(key_navigation_test->grid_layout_, "TestView created"); test.TestReportMsg(key_navigation_test->bottom_view_->has_focus_, "bottom_view has key focus"); // Up key, must focus (last row, first column) item test.SendFakeKeyEvent(XK_Up, 0); nux::SleepForMilliseconds(500); test.TestReportMsg(key_navigation_test->tiles_[8]->has_focus_, "KEY_NAV_UP test"); key_navigation_test->bottom_view_->can_focus_ = false; for (int i = 0; i < 2; ++i) test.SendFakeKeyEvent(XK_Up, 0); nux::SleepForMilliseconds(500); // Rigth key for (int i=0; i<3; ++i) { test.SendFakeKeyEvent(XK_Right, 0); nux::SleepForMilliseconds(500); test.TestReportMsg(!key_navigation_test->tiles_[i]->has_focus_, "Right: key focus out"); test.TestReportMsg(key_navigation_test->tiles_[i+1]->has_focus_, "Right: key focus in"); } // Another right key, should do nothing test.SendFakeKeyEvent(XK_Right, 0); nux::SleepForMilliseconds(500); test.TestReportMsg(key_navigation_test->tiles_[3]->has_focus_, "Right key, last element"); // Left key for (int i=3; i>0; --i) { test.SendFakeKeyEvent(XK_Left, 0); nux::SleepForMilliseconds(500); test.TestReportMsg(!key_navigation_test->tiles_[i]->has_focus_, "Left: key focus out"); test.TestReportMsg(key_navigation_test->tiles_[i-1]->has_focus_, "Left: key focus in"); } // Another left key, should do nothing test.SendFakeKeyEvent(XK_Left, 0); nux::SleepForMilliseconds(500); test.TestReportMsg(key_navigation_test->tiles_[0]->has_focus_, "Left key, fist element"); // Down key for (int i=0; i<2; ++i) { test.SendFakeKeyEvent(XK_Down, 0); nux::SleepForMilliseconds(500); test.TestReportMsg(!key_navigation_test->tiles_[4*i]->has_focus_, "Down: key focus out"); test.TestReportMsg(key_navigation_test->tiles_[4*(i+1)]->has_focus_, "Down: key focus in"); } // Another down key, should do nothing test.SendFakeKeyEvent(XK_Down, 0); nux::SleepForMilliseconds(500); test.TestReportMsg(key_navigation_test->tiles_[8]->has_focus_, "Down key, last row"); // Up key for (int i=2; i>0; --i) { test.SendFakeKeyEvent(XK_Up, 0); nux::SleepForMilliseconds(500); test.TestReportMsg(!key_navigation_test->tiles_[4*i]->has_focus_, "Up: key focus out"); test.TestReportMsg(key_navigation_test->tiles_[4*(i-1)]->has_focus_, "Up: key focus in"); } // Another up key, should do nothing test.SendFakeKeyEvent(XK_Up, 0); nux::SleepForMilliseconds(500); test.TestReportMsg(key_navigation_test->tiles_[0]->has_focus_, "Up key, first row"); if (test.WhenDoneTerminateProgram()) { nux::SleepForMilliseconds(1000); wnd_thread->ExitMainLoop(); } nuxDebugMsg("Exit testing thread"); } int main() { XInitThreads(); key_navigation_test = new HGridKeyNavigationTest("Key navigation Test", 500, 400, 20000); key_navigation_test->Startup(); key_navigation_test->UserInterfaceSetup(); nux::SystemThread* test_thread = nux::CreateSystemThread(key_navigation_test->GetWindowThread(), &TestingThread, key_navigation_test->GetWindowThread()); test_thread->Start(key_navigation_test); key_navigation_test->Run(); delete test_thread; delete key_navigation_test; return 0; } ./tests/gtest-nuxcore-properties.cpp0000644000004100000410000006044113313171755020125 0ustar www-datawww-data#include "NuxCore/Property.h" #include #include #include #include #include #include "Helpers.h" using namespace testing; namespace nt = nux::testing; namespace { template T to_and_from_string(T const& value) { std::string temp = nux::type::PropertyTrait::to_string(value); std::pair result = nux::type::PropertyTrait::from_string(temp); if (!result.second) { throw std::runtime_error("Failed to convert."); } return result.first; } enum TestEnum { FirstValue, MiddleValue, LastValue, }; struct TestClass { int value; }; TEST(TestTypeTraits, TestSerialization) { EXPECT_EQ("hello", nux::type::PropertyTrait::to_string("hello")); EXPECT_EQ("42", nux::type::PropertyTrait::to_string(42)); EXPECT_EQ("42", nux::type::PropertyTrait::to_string(42)); EXPECT_EQ("true", nux::type::PropertyTrait::to_string(true)); EXPECT_EQ("false", nux::type::PropertyTrait::to_string(false)); EXPECT_EQ("0", nux::type::PropertyTrait::to_string(0)); EXPECT_EQ("25.5", nux::type::PropertyTrait::to_string(25.5)); EXPECT_EQ("1", nux::type::PropertyTrait::to_string(MiddleValue)); } TEST(TestTypeTraits, TestDeserialization) { std::pair sr = nux::type::PropertyTrait::from_string("hello"); EXPECT_EQ("hello", sr.first); EXPECT_TRUE(sr.second); std::pair int_result = nux::type::PropertyTrait::from_string("42"); EXPECT_EQ(42, int_result.first); EXPECT_TRUE(int_result.second); int_result = nux::type::PropertyTrait::from_string("OMG!"); EXPECT_EQ(0, int_result.first); EXPECT_FALSE(int_result.second); std::pair unsigned_result = nux::type::PropertyTrait::from_string("42"); EXPECT_EQ(42, unsigned_result.first); EXPECT_TRUE(unsigned_result.second); unsigned_result = nux::type::PropertyTrait::from_string("OMG!"); EXPECT_EQ(0, unsigned_result.first); EXPECT_FALSE(unsigned_result.second); std::pair bool_result = nux::type::PropertyTrait::from_string("true"); EXPECT_TRUE(bool_result.first); EXPECT_TRUE(bool_result.second); bool_result = nux::type::PropertyTrait::from_string("false"); EXPECT_FALSE(bool_result.first); EXPECT_TRUE(bool_result.second); bool_result = nux::type::PropertyTrait::from_string("what?"); EXPECT_FALSE(bool_result.first); EXPECT_FALSE(bool_result.second); std::pair double_result = nux::type::PropertyTrait::from_string("25.5"); EXPECT_EQ(25.5, double_result.first); EXPECT_TRUE(double_result.second); double_result = nux::type::PropertyTrait::from_string("2e6"); EXPECT_EQ(2000000.0, double_result.first); EXPECT_TRUE(double_result.second); double_result = nux::type::PropertyTrait::from_string("what?"); EXPECT_EQ(0, double_result.first); EXPECT_FALSE(double_result.second); std::pair enum_result = nux::type::PropertyTrait::from_string("0"); EXPECT_EQ(FirstValue, enum_result.first); EXPECT_TRUE(enum_result.second); // This is tested to show behaviour even though it is undesirable (as there // isn't an enum value for 42). enum_result = nux::type::PropertyTrait::from_string("42"); EXPECT_EQ(42, enum_result.first); EXPECT_TRUE(enum_result.second); } TEST(TestTypeTraits, TestConversionHolds) { std::string string_value("Hello World!"); EXPECT_EQ(string_value, to_and_from_string(string_value)); double double_value = 34.345; EXPECT_EQ(double_value, to_and_from_string(double_value)); } TEST(TestProperty, TestDefaultConstructor) { nux::Property string_prop; // Need either an assignment or static cast to check the operator VALUE_TYPE // due to google-mock's template matching. std::string value = string_prop; EXPECT_THAT(value, Eq("")); EXPECT_THAT(string_prop.Get(), Eq("")); EXPECT_THAT(string_prop(), Eq("")); } TEST(TestProperty, TestValueExplicitConstructor) { nux::Property string_prop("Hello world!"); // Need either an assignment or static cast to check the operator VALUE_TYPE // due to google-mock's template matching. std::string value = string_prop; EXPECT_THAT(value, Eq("Hello world!")); EXPECT_THAT(string_prop.Get(), Eq("Hello world!")); EXPECT_THAT(string_prop(), Eq("Hello world!")); } TEST(TestProperty, TestAssignment) { nux::Property string_prop; // Need either an assignment or static cast to check the operator VALUE_TYPE // due to google-mock's template matching. string_prop = "Assignment operator"; std::string value = string_prop; EXPECT_THAT(value, Eq("Assignment operator")); EXPECT_THAT(string_prop.Get(), Eq("Assignment operator")); EXPECT_THAT(string_prop(), Eq("Assignment operator")); string_prop.Set("Set method"); value = string_prop; EXPECT_THAT(value, Eq("Set method")); EXPECT_THAT(string_prop.Get(), Eq("Set method")); EXPECT_THAT(string_prop(), Eq("Set method")); string_prop("Function call assignment"); value = string_prop; EXPECT_THAT(value, Eq("Function call assignment")); EXPECT_THAT(string_prop.Get(), Eq("Function call assignment")); EXPECT_THAT(string_prop(), Eq("Function call assignment")); } TEST(TestProperty, TestChanged) { nux::Property string_prop; nt::ChangeRecorder recorder; string_prop.changed.connect(recorder.listener()); string_prop = "Hello world" ; EXPECT_THAT(1, Eq(recorder.size())); EXPECT_THAT("Hello world", Eq(recorder.last())); // No notification if not changed. string_prop = std::string("Hello world"); EXPECT_THAT(1, Eq(recorder.size())); } TEST(TestProperty, TestEnableAndDisableNotifications) { nux::Property string_prop; nt::ChangeRecorder recorder; string_prop.changed.connect(recorder.listener()); string_prop.DisableNotifications(); string_prop = "Hello world" ; EXPECT_THAT(0, Eq(recorder.size())); string_prop.EnableNotifications(); // No notification if not changed. string_prop = "Hello world" ; EXPECT_THAT(0, Eq(recorder.size())); string_prop = "New value" ; EXPECT_THAT(1, Eq(recorder.size())); EXPECT_THAT("New value", Eq(recorder.last())); } bool string_prefix(std::string& target, std::string const& value) { bool changed = false; std::string prefixed("prefix-" + value); if (target != prefixed) { target = prefixed; changed = true; } return changed; } TEST(TestProperty, TestSetterConstructor) { nux::Property string_prop("", sigc::ptr_fun(&string_prefix)); string_prop = "foo"; // Need either an assignment or static cast to check the operator VALUE_TYPE // due to google-mock's template matching. std::string value = string_prop; EXPECT_THAT(value, Eq("prefix-foo")); EXPECT_THAT(string_prop.Get(), Eq("prefix-foo")); EXPECT_THAT(string_prop(), Eq("prefix-foo")); } class FloatClamp { public: FloatClamp(float min, float max) : min_(min), max_(max) { } bool Set(float& target, float const& value) { bool changed = false; float new_val = std::min(max_, std::max(min_, value)); if (target != new_val) { target = new_val; changed = true; } return changed; } private: float min_; float max_; }; TEST(TestProperty, TestCustomSetterFunction) { nux::Property float_prop; FloatClamp clamp(0, 1); float_prop.SetSetterFunction(sigc::mem_fun(&clamp, &FloatClamp::Set)); nt::ChangeRecorder recorder; float_prop.changed.connect(recorder.listener()); // Since the default value for a float is zero, and we clamp at zero, // setting to a negative value will result in setting to zero, which will // not signal a changed event. float_prop = -2; EXPECT_THAT(float_prop(), Eq(0)); EXPECT_THAT(0, Eq(recorder.size())); float_prop = 0.5; EXPECT_THAT(float_prop(), Eq(0.5)); EXPECT_THAT(1, Eq(recorder.size())); EXPECT_THAT(0.5, Eq(recorder.last())); float_prop = 4; EXPECT_THAT(float_prop(), Eq(1)); EXPECT_THAT(2, Eq(recorder.size())); EXPECT_THAT(1, Eq(recorder.last())); } TEST(TestProperty, TestCustomSetterFunctionLambda) { nux::Property float_prop; FloatClamp clamp(0, 1); float_prop.SetSetterFunction([&clamp] (float &target, float const& value) { return clamp.Set(target, value); }); nt::ChangeRecorder recorder; float_prop.changed.connect(recorder.listener()); // Since the default value for a float is zero, and we clamp at zero, // setting to a negative value will result in setting to zero, which will // not signal a changed event. float_prop = -2; EXPECT_THAT(float_prop(), Eq(0)); EXPECT_THAT(0, Eq(recorder.size())); float_prop = 0.5; EXPECT_THAT(float_prop(), Eq(0.5)); EXPECT_THAT(1, Eq(recorder.size())); EXPECT_THAT(0.5, Eq(recorder.last())); float_prop = 4; EXPECT_THAT(float_prop(), Eq(1)); EXPECT_THAT(2, Eq(recorder.size())); EXPECT_THAT(1, Eq(recorder.last())); } TEST(TestProperty, TestIntOperators) { nux::Property int_prop(42); EXPECT_TRUE(int_prop == 42); EXPECT_TRUE(42 == int_prop); EXPECT_FALSE(int_prop != 42); EXPECT_FALSE(42 != int_prop); EXPECT_FALSE(int_prop == 5); EXPECT_FALSE(5 == int_prop); EXPECT_TRUE(int_prop != 5); EXPECT_TRUE(5 != int_prop); EXPECT_FALSE(int_prop < 5); EXPECT_FALSE(int_prop <= 5); EXPECT_TRUE(int_prop > 5); EXPECT_TRUE(int_prop >= 5); EXPECT_TRUE(5 < int_prop); EXPECT_TRUE(5 <= int_prop); EXPECT_FALSE(5 > int_prop); EXPECT_FALSE(5 >= int_prop); nux::Property int_prop2(42); EXPECT_TRUE(int_prop2 == int_prop); EXPECT_FALSE(int_prop2 != int_prop); int_prop2 = 5; EXPECT_FALSE(int_prop2 == int_prop); EXPECT_TRUE(int_prop2 != int_prop); EXPECT_FALSE(int_prop < int_prop2); EXPECT_FALSE(int_prop <= int_prop2); EXPECT_TRUE(int_prop > int_prop2); EXPECT_TRUE(int_prop >= int_prop2); } // Only testing strings and ints, to show that the template classes work with // both primitive types and classes. TEST(TestProperty, TestStringOperators) { std::string value("Hello"); nux::Property str_prop(value); EXPECT_TRUE(str_prop == "Hello"); EXPECT_TRUE("Hello" == str_prop); EXPECT_FALSE(str_prop != "Hello"); EXPECT_FALSE("Hello" != str_prop); EXPECT_TRUE(str_prop == value); EXPECT_TRUE(value == str_prop); EXPECT_FALSE(str_prop != value); EXPECT_FALSE(value != str_prop); EXPECT_FALSE(str_prop == "World"); EXPECT_FALSE("World" == str_prop); EXPECT_TRUE(str_prop != "World"); EXPECT_TRUE("World" != str_prop); EXPECT_FALSE(str_prop < "Aardvark"); EXPECT_FALSE(str_prop <= "Aardvark"); EXPECT_TRUE(str_prop > "Aardvark"); EXPECT_TRUE(str_prop >= "Aardvark"); EXPECT_TRUE("Aardvark" < str_prop); EXPECT_TRUE("Aardvark" <= str_prop); EXPECT_FALSE("Aardvark" > str_prop); EXPECT_FALSE("Aardvark" >= str_prop); nux::Property str_prop2(value); EXPECT_TRUE(str_prop2 == str_prop); EXPECT_FALSE(str_prop2 != str_prop); str_prop2 = "Aardvark"; EXPECT_FALSE(str_prop2 == str_prop); EXPECT_TRUE(str_prop2 != str_prop); EXPECT_FALSE(str_prop < str_prop2); EXPECT_FALSE(str_prop <= str_prop2); EXPECT_TRUE(str_prop > str_prop2); EXPECT_TRUE(str_prop >= str_prop2); } TEST(TestROProperty, TestDefaultConstructor) { nux::ROProperty int_prop; int value = int_prop; EXPECT_THAT(value, Eq(0)); EXPECT_THAT(int_prop(), Eq(0)); EXPECT_THAT(int_prop.Get(), Eq(0)); nux::ROProperty string_prop; std::string svalue = string_prop; EXPECT_THAT(svalue, Eq("")); EXPECT_THAT(string_prop(), Eq("")); EXPECT_THAT(string_prop.Get(), Eq("")); } int simple_int_result() { return 42; } TEST(TestROProperty, TestGetterConstructor) { nux::ROProperty int_prop(sigc::ptr_fun(&simple_int_result)); int value = int_prop; EXPECT_THAT(value, Eq(42)); EXPECT_THAT(int_prop(), Eq(42)); EXPECT_THAT(int_prop.Get(), Eq(42)); } class Incrementer { public: Incrementer() : value_(0) {} int value() { return ++value_; } private: int value_; }; TEST(TestROProperty, TestSetGetter) { nux::ROProperty int_prop; Incrementer incrementer; int_prop.SetGetterFunction(sigc::mem_fun(&incrementer, &Incrementer::value)); int value = int_prop; EXPECT_THAT(value, Eq(1)); EXPECT_THAT(int_prop(), Eq(2)); EXPECT_THAT(int_prop.Get(), Eq(3)); } #if __cplusplus >= 201100L || defined (__GXX_EXPERIMENTAL_CXX0X__) TEST(TestROProperty, TestSetGetterLambda) { nux::ROProperty int_prop; int_prop.SetGetterFunction([] { static int value = 0; return ++value; }); int value = int_prop; EXPECT_THAT(value, Eq(1)); EXPECT_THAT(int_prop(), Eq(2)); EXPECT_THAT(int_prop.Get(), Eq(3)); } #endif TEST(TestROProperty, TestChangedEvent) { // RO Properties have a changed event, but it is up to the continer of the // property to emit the events as nothing is done automatically. nux::ROProperty int_prop; nt::ChangeRecorder recorder; int_prop.changed.connect(recorder.listener()); int_prop.EmitChanged(42); EXPECT_THAT(1, Eq(recorder.size())); EXPECT_THAT(42, Eq(recorder.last())); } // A simple class that just has a reader functon. template class ROPropHolder { public: ROPropHolder(VALUE_TYPE const& initial) : prop(sigc::mem_fun(this, &ROPropHolder::get_prop)) , prop_(initial) {} nux::ROProperty prop; VALUE_TYPE get_prop() const { return prop_; } VALUE_TYPE prop_; }; TEST(TestROProperty, TestIntOperators) { ROPropHolder int_prop(42); EXPECT_TRUE(int_prop.prop == 42); EXPECT_TRUE(42 == int_prop.prop); EXPECT_FALSE(int_prop.prop != 42); EXPECT_FALSE(42 != int_prop.prop); EXPECT_FALSE(int_prop.prop == 5); EXPECT_FALSE(5 == int_prop.prop); EXPECT_TRUE(int_prop.prop != 5); EXPECT_TRUE(5 != int_prop.prop); EXPECT_FALSE(int_prop.prop < 5); EXPECT_FALSE(int_prop.prop <= 5); EXPECT_TRUE(int_prop.prop > 5); EXPECT_TRUE(int_prop.prop >= 5); EXPECT_TRUE(5 < int_prop.prop); EXPECT_TRUE(5 <= int_prop.prop); EXPECT_FALSE(5 > int_prop.prop); EXPECT_FALSE(5 >= int_prop.prop); ROPropHolder int_prop2(42); EXPECT_TRUE(int_prop2.prop == int_prop.prop); EXPECT_FALSE(int_prop2.prop != int_prop.prop); int_prop2.prop_ = 5; EXPECT_FALSE(int_prop2.prop == int_prop.prop); EXPECT_TRUE(int_prop2.prop != int_prop.prop); EXPECT_FALSE(int_prop.prop < int_prop2.prop); EXPECT_FALSE(int_prop.prop <= int_prop2.prop); EXPECT_TRUE(int_prop.prop > int_prop2.prop); EXPECT_TRUE(int_prop.prop >= int_prop2.prop); } // Only testing strings and ints, to show that the template classes work with // both primitive types and classes. TEST(TestROProperty, TestStringOperators) { std::string value("Hello"); ROPropHolder str_prop(value); EXPECT_TRUE(str_prop.prop == "Hello"); EXPECT_TRUE("Hello" == str_prop.prop); EXPECT_FALSE(str_prop.prop != "Hello"); EXPECT_FALSE("Hello" != str_prop.prop); EXPECT_TRUE(str_prop.prop == value); EXPECT_TRUE(value == str_prop.prop); EXPECT_FALSE(str_prop.prop != value); EXPECT_FALSE(value != str_prop.prop); EXPECT_FALSE(str_prop.prop == "World"); EXPECT_FALSE("World" == str_prop.prop); EXPECT_TRUE(str_prop.prop != "World"); EXPECT_TRUE("World" != str_prop.prop); EXPECT_FALSE(str_prop.prop < "Aardvark"); EXPECT_FALSE(str_prop.prop <= "Aardvark"); EXPECT_TRUE(str_prop.prop > "Aardvark"); EXPECT_TRUE(str_prop.prop >= "Aardvark"); EXPECT_TRUE("Aardvark" < str_prop.prop); EXPECT_TRUE("Aardvark" <= str_prop.prop); EXPECT_FALSE("Aardvark" > str_prop.prop); EXPECT_FALSE("Aardvark" >= str_prop.prop); ROPropHolder str_prop2(value); EXPECT_TRUE(str_prop2.prop == str_prop.prop); EXPECT_FALSE(str_prop2.prop != str_prop.prop); str_prop2.prop_ = "Aardvark"; EXPECT_FALSE(str_prop2.prop == str_prop.prop); EXPECT_TRUE(str_prop2.prop != str_prop.prop); EXPECT_FALSE(str_prop.prop < str_prop2.prop); EXPECT_FALSE(str_prop.prop <= str_prop2.prop); EXPECT_TRUE(str_prop.prop > str_prop2.prop); EXPECT_TRUE(str_prop.prop >= str_prop2.prop); } TEST(TestRWProperty, TestDefaultConstructor) { nux::RWProperty int_prop; nt::ChangeRecorder recorder; int_prop.changed.connect(recorder.listener()); int_prop = 42; int value = int_prop; EXPECT_THAT(value, Eq(0)); EXPECT_THAT(int_prop(), Eq(0)); EXPECT_THAT(int_prop.Get(), Eq(0)); EXPECT_THAT(recorder.size(), Eq(0)); } bool is_even(int const& value) { return value % 2 == 0; } TEST(TestRWProperty, TestFunctionConstructor) { // This is a somewhat convoluted example. The setter emits if the value is // even, but the value being emitted is controlled by the incrementer. Incrementer incrementer; nux::RWProperty int_prop(sigc::mem_fun(&incrementer, &Incrementer::value), sigc::ptr_fun(&is_even)); nt::ChangeRecorder recorder; int_prop.changed.connect(recorder.listener()); int_prop = 42; EXPECT_THAT(recorder.size(), Eq(1)); EXPECT_THAT(recorder.last(), Eq(1)); // Catch the return value of the assignment. The getter is called. int assign_result = int_prop = 13; EXPECT_THAT(recorder.size(), Eq(1)); EXPECT_THAT(assign_result, Eq(2)); // each access increments the value. int value = int_prop; EXPECT_THAT(value, Eq(3)); EXPECT_THAT(int_prop(), Eq(4)); EXPECT_THAT(int_prop.Get(), Eq(5)); } // This bit would normally be in the header file. class HiddenImpl { public: HiddenImpl(); nux::RWProperty name; private: class Impl; boost::scoped_ptr pimpl; }; // This bit is in the implementation file. class HiddenImpl::Impl { public: bool set_name(std::string const& name) { bool changed = false; std::string new_name("Impl::" + name); if (name_ != new_name) { name_ = new_name; changed = true; } return changed; } std::string get_name() const { return name_; } private: std::string name_; }; HiddenImpl::HiddenImpl() : pimpl(new Impl()) { name.SetSetterFunction(sigc::mem_fun(pimpl.get(), &HiddenImpl::Impl::set_name)); name.SetGetterFunction(sigc::mem_fun(pimpl.get(), &HiddenImpl::Impl::get_name)); } TEST(TestRWProperty, TestPimplClassExample) { HiddenImpl hidden; nt::ChangeRecorder recorder; hidden.name.changed.connect(recorder.listener()); hidden.name = "NewName"; EXPECT_THAT(recorder.size(), Eq(1)); EXPECT_THAT(recorder.last(), Eq("Impl::NewName")); // Since the name is updated before comparison, no event emitted. hidden.name = "NewName"; EXPECT_THAT(recorder.size(), Eq(1)); std::string value = hidden.name; EXPECT_THAT(value, Eq("Impl::NewName")); EXPECT_THAT(hidden.name(), Eq("Impl::NewName")); EXPECT_THAT(hidden.name.Get(), Eq("Impl::NewName")); } // A simple class that just has a reader and writer functon. template class RWPropHolder { public: RWPropHolder(VALUE_TYPE const& initial) : prop(sigc::mem_fun(this, &RWPropHolder::get_prop), sigc::mem_fun(this, &RWPropHolder::set_prop)) , prop_(initial) {} nux::RWProperty prop; private: VALUE_TYPE get_prop() const { return prop_; } bool set_prop(VALUE_TYPE const& prop) { prop_ = prop; return true; } VALUE_TYPE prop_; }; TEST(TestRWProperty, TestIntOperators) { RWPropHolder int_prop(42); EXPECT_TRUE(int_prop.prop == 42); EXPECT_TRUE(42 == int_prop.prop); EXPECT_FALSE(int_prop.prop != 42); EXPECT_FALSE(42 != int_prop.prop); EXPECT_FALSE(int_prop.prop == 5); EXPECT_FALSE(5 == int_prop.prop); EXPECT_TRUE(int_prop.prop != 5); EXPECT_TRUE(5 != int_prop.prop); EXPECT_FALSE(int_prop.prop < 5); EXPECT_FALSE(int_prop.prop <= 5); EXPECT_TRUE(int_prop.prop > 5); EXPECT_TRUE(int_prop.prop >= 5); EXPECT_TRUE(5 < int_prop.prop); EXPECT_TRUE(5 <= int_prop.prop); EXPECT_FALSE(5 > int_prop.prop); EXPECT_FALSE(5 >= int_prop.prop); RWPropHolder int_prop2(42); EXPECT_TRUE(int_prop2.prop == int_prop.prop); EXPECT_FALSE(int_prop2.prop != int_prop.prop); int_prop2.prop = 5; EXPECT_FALSE(int_prop2.prop == int_prop.prop); EXPECT_TRUE(int_prop2.prop != int_prop.prop); EXPECT_FALSE(int_prop.prop < int_prop2.prop); EXPECT_FALSE(int_prop.prop <= int_prop2.prop); EXPECT_TRUE(int_prop.prop > int_prop2.prop); EXPECT_TRUE(int_prop.prop >= int_prop2.prop); } // Only testing strings and ints, to show that the template classes work with // both primitive types and classes. TEST(TestRWProperty, TestStringOperators) { std::string value("Hello"); RWPropHolder str_prop(value); EXPECT_TRUE(str_prop.prop == "Hello"); EXPECT_TRUE("Hello" == str_prop.prop); EXPECT_FALSE(str_prop.prop != "Hello"); EXPECT_FALSE("Hello" != str_prop.prop); EXPECT_TRUE(str_prop.prop == value); EXPECT_TRUE(value == str_prop.prop); EXPECT_FALSE(str_prop.prop != value); EXPECT_FALSE(value != str_prop.prop); EXPECT_FALSE(str_prop.prop == "World"); EXPECT_FALSE("World" == str_prop.prop); EXPECT_TRUE(str_prop.prop != "World"); EXPECT_TRUE("World" != str_prop.prop); EXPECT_FALSE(str_prop.prop < "Aardvark"); EXPECT_FALSE(str_prop.prop <= "Aardvark"); EXPECT_TRUE(str_prop.prop > "Aardvark"); EXPECT_TRUE(str_prop.prop >= "Aardvark"); EXPECT_TRUE("Aardvark" < str_prop.prop); EXPECT_TRUE("Aardvark" <= str_prop.prop); EXPECT_FALSE("Aardvark" > str_prop.prop); EXPECT_FALSE("Aardvark" >= str_prop.prop); RWPropHolder str_prop2(value); EXPECT_TRUE(str_prop2.prop == str_prop.prop); EXPECT_FALSE(str_prop2.prop != str_prop.prop); str_prop2.prop = "Aardvark"; EXPECT_FALSE(str_prop2.prop == str_prop.prop); EXPECT_TRUE(str_prop2.prop != str_prop.prop); EXPECT_FALSE(str_prop.prop < str_prop2.prop); EXPECT_FALSE(str_prop.prop <= str_prop2.prop); EXPECT_TRUE(str_prop.prop > str_prop2.prop); EXPECT_TRUE(str_prop.prop >= str_prop2.prop); } struct TestProperties : nux::Introspectable { TestProperties() : name(this, "name") , index(this, "index") {} nux::SerializableProperty name; nux::SerializableProperty index; }; TEST(TestIntrospectableProperty, TestSimplePropertyAccess) { TestProperties props; nt::ChangeRecorder recorder; props.name.changed.connect(recorder.listener()); EXPECT_EQ("", props.name()); EXPECT_EQ(0, props.index()); props.name = "Testing"; props.index = 5; EXPECT_EQ("Testing", props.name()); props.name("New Value"); EXPECT_EQ("New Value", props.name()); props.name.Set("Another"); EXPECT_EQ("Another", props.name()); EXPECT_EQ(3, recorder.size()); EXPECT_EQ("Testing", recorder.changed_values[0]); EXPECT_EQ("New Value", recorder.changed_values[1]); EXPECT_EQ("Another", recorder.changed_values[2]); } TEST(TestIntrospectableProperty, TestPropertyAccessByName) { TestProperties props; nt::ChangeRecorder name_recorder; nt::ChangeRecorder index_recorder; props.name.changed.connect(name_recorder.listener()); props.index.changed.connect(index_recorder.listener()); props.name = "Testing"; props.index = 5; EXPECT_EQ("Testing", props.GetProperty("name")); EXPECT_EQ("5", props.GetProperty("index")); EXPECT_EQ(5, props.GetProperty("index")); bool assigned = props.SetProperty("name", "New value"); EXPECT_TRUE(assigned); EXPECT_EQ("New value", props.name()); EXPECT_EQ("New value", props.GetProperty("name")); // A little dangreous, but legal. EXPECT_EQ(0, props.GetProperty("name")); assigned = props.SetProperty("name", 42); EXPECT_TRUE(assigned); EXPECT_EQ("42", props.name()); EXPECT_EQ("42", props.GetProperty("name")); // A little dangreous, but legal. EXPECT_EQ(42, props.GetProperty("name")); assigned = props.SetProperty("index", 42); EXPECT_TRUE(assigned); EXPECT_EQ(42, props.index()); EXPECT_EQ("42", props.GetProperty("index")); EXPECT_EQ(42, props.GetProperty("index")); assigned = props.SetProperty("index", "hello"); EXPECT_FALSE(assigned); EXPECT_EQ(42, props.index()); EXPECT_EQ("42", props.GetProperty("index")); EXPECT_EQ(42, props.GetProperty("index")); // Gettin a non-existant property returns a default constructed instance. std::string surname = props.GetProperty("surname"); EXPECT_EQ("", surname); int foo = props.GetProperty("foo"); EXPECT_EQ(0, foo); assigned = props.SetProperty("non-existant", "hello"); EXPECT_FALSE(assigned); } } ./tests/Helpers.h0000644000004100000410000000423113313171755014166 0ustar www-datawww-data// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- /* * Copyright 2011 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Tim Penhey * */ #ifndef NUX_TESTS_FILE_HELPERS_H #define NUX_TESTS_FILE_HELPERS_H #include #include #include #include #include #include namespace nux { namespace testing { std::string ReadFile(std::string const& filename); void PumpGObjectMainLoop(); class TestCallback { public: TestCallback() : happened(false) {} sigc::slot sigc_callback() { return sigc::mem_fun(this, &TestCallback::callback); } static gboolean glib_callback(gpointer data) { TestCallback* test = reinterpret_cast(data); test->callback(); return FALSE; } void callback() { happened = true; } bool happened; }; class CaptureLogOutput { public: CaptureLogOutput(); ~CaptureLogOutput(); std::string GetOutput(); private: std::ostringstream sout_; }; template struct ChangeRecorder : sigc::trackable { typedef std::function Listener; Listener listener() { return sigc::mem_fun(this, &ChangeRecorder::value_changed); } void value_changed(T const& value) { changed_values.push_back(value); } typedef std::vector ChangedValues; ChangedValues changed_values; int size() const { return changed_values.size(); } T last() const { return *changed_values.rbegin(); } }; } } #endif ./doxygen.cfg0000644000004100000410000020513413313171755013414 0ustar www-datawww-data# Doxyfile 1.7.1 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # http://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = $(PROJECT)-$(VERSION) # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = $(DOCDIR) # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, # Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English # messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, # Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, # Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = YES # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = $(SRCDIR) # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = $(SRCDIR) # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = YES # If the QT_AUTOBRIEF tag is set to YES then Doxygen will # interpret the first line (until the first dot) of a Qt-style # comment as the brief description. If set to NO, the comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for # Java. For instance, namespaces will be presented as packages, qualified # scopes will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources only. Doxygen will then generate output that is more tailored for # Fortran. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for # VHDL. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given extension. # Doxygen has a built-in mapping, but you can override or extend it using this # tag. The format is ext=language, where ext is a file extension, and language # is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, # C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make # doxygen treat .inc files as Fortran files (default is PHP), and .f files as C # (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions # you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. EXTENSION_MAPPING = # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = YES # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. # Doxygen will parse them like normal C++ but will assume all classes use public # instead of private inheritance when no explicit protection keyword is present. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate getter # and setter methods for a property. Setting this option to YES (the default) # will make doxygen to replace the get and set methods by a property in the # documentation. This will only work if the methods are indeed getting or # setting a simple type. If this is not the case, or you want to show the # methods anyway, you should set this option to NO. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum # is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically # be useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. TYPEDEF_HIDES_STRUCT = NO # The SYMBOL_CACHE_SIZE determines the size of the internal cache use to # determine which symbols to keep in memory and which to flush to disk. # When the cache is full, less often used symbols will be written to disk. # For small to medium size projects (<1000 input files) the default value is # probably good enough. For larger projects a too small cache size can cause # doxygen to be busy swapping symbols to and from disk most of the time # causing a significant performance penality. # If the system has enough physical memory increasing the cache will improve the # performance by keeping more symbols in memory. Note that the value works on # a logarithmic scale so increasing the size by one will rougly double the # memory usage. The cache size is given by this formula: # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols SYMBOL_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base # name of the file that contains the anonymous namespace. By default # anonymous namespace are hidden. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = NO # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen # will list include files with double quotes in the documentation # rather than with sharp brackets. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen # will sort the (brief and detailed) documentation of class members so that # constructors and destructors are listed first. If set to NO (the default) # the constructors will appear in the respective orders defined by # SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. # This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO # and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the # hierarchy of group names into alphabetical order. If set to NO (the default) # the group names will appear in their defined order. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = NO # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = NO # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = NO # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. The default is NO. SHOW_DIRECTORIES = YES # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the # Namespaces page. # This will remove the Namespaces entry from the Quick Index # and from the Folder Tree View (if specified). The default is YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. The create the layout file # that represents doxygen's defaults, run doxygen with the -l option. # You can optionally specify a file name after the option, if omitted # DoxygenLayout.xml will be used as the name of the layout file. LAYOUT_FILE = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = YES # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be abled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = doxy-warnings.log #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = $(SRCDIR) # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # also the default input encoding. Doxygen uses libiconv (or the iconv built # into libc) for the transcoding. See http://www.gnu.org/software/libiconv for # the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx # *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 FILE_PATTERNS = *.cpp \ *.h # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used select whether or not files or # directories that are symbolic links (a Unix filesystem feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = $(SRCDIR) # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. # If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. # Doxygen will compare the file name with each pattern and apply the # filter if there is a match. # The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = YES # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. # Otherwise they will link to the documentation. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = $(GENERATE_HTML) # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. # Doxygen will adjust the colors in the stylesheet and background images # according to this color. Hue is specified as an angle on a colorwheel, # see http://en.wikipedia.org/wiki/Hue for more information. # For instance the value 0 represents red, 60 is yellow, 120 is green, # 180 is cyan, 240 is blue, 300 purple, and 360 is red again. # The allowed range is 0 to 359. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of # the colors in the HTML output. For a value of 0 the output will use # grayscales only. A value of 255 will produce the most vivid colors. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to # the luminance component of the colors in the HTML output. Values below # 100 gradually make the output lighter, whereas values above 100 make # the output darker. The value divided by 100 is the actual gamma applied, # so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, # and 100 does not change the gamma. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting # this to NO can help when comparing the output of multiple runs. HTML_TIMESTAMP = YES # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. For this to work a browser that supports # JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox # Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). HTML_DYNAMIC_SECTIONS = NO # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 # integrated development environment, introduced with OSX 10.5 (Leopard). # To create a documentation set, doxygen will generate a Makefile in the # HTML output directory. Running make will produce the docset in that # directory and running "make install" will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find # it at startup. # See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. GENERATE_DOCSET = NO # When GENERATE_DOCSET tag is set to YES, this tag determines the name of the # feed. A documentation feed provides an umbrella under which multiple # documentation sets from a single provider (such as a company or product suite) # can be grouped. DOCSET_FEEDNAME = "Doxygen generated docs" # When GENERATE_DOCSET tag is set to YES, this tag specifies a string that # should uniquely identify the documentation set bundle. This should be a # reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen # will append .docset to the name. DOCSET_BUNDLE_ID = org.doxygen.Project # When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = $(GENERATE_CHM) # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = ../$(PROJECT).chm # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = $(HHC_PATH) # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = $(GENERATE_CHI) # If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING # is used to encode HtmlHelp index (hhk), content (hhc) and project file # content. CHM_INDEX_ENCODING = # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated # that can be used as input for Qt's qhelpgenerator to generate a # Qt Compressed Help (.qch) of the generated HTML documentation. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can # be used to specify the file name of the resulting .qch file. # The path specified is relative to the HTML output folder. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#namespace QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#virtual-folders QHP_VIRTUAL_FOLDER = doc # If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to # add. For more information please see # http://doc.trolltech.com/qthelpproject.html#custom-filters QHP_CUST_FILTER_NAME = # The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see # # Qt Help Project / Custom Filters. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's # filter section matches. # # Qt Help Project / Filter Attributes. QHP_SECT_FILTER_ATTRS = # If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can # be used to specify the location of Qt's qhelpgenerator. # If non-empty doxygen will try to run qhelpgenerator on the generated # .qhp file. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files # will be generated, which together with the HTML files, form an Eclipse help # plugin. To install this plugin and make it available under the help contents # menu in Eclipse, the contents of the directory containing the HTML and XML # files needs to be copied into the plugins directory of eclipse. The name of # the directory within the plugins directory should be the same as # the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before # the help appears. GENERATE_ECLIPSEHELP = NO # A unique identifier for the eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have # this name. ECLIPSE_DOC_ID = org.doxygen.Project # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. # If the tag value is set to YES, a side panel will be generated # containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). # Windows users are probably better off using the HTML help feature. GENERATE_TREEVIEW = YES # By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, # and Class Hierarchy pages using a tree view instead of an ordered list. USE_INLINE_TREES = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 # When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open # links to external symbols imported via tag files in a separate window. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of Latex formulas included # as images in the HTML documentation. The default is 10. Note that # when you change the font size after a successful doxygen run you need # to manually remove any form_*.png images from the HTML output directory # to force them to be regenerated. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are # not supported properly for IE 6.0, but are supported on all modern browsers. # Note that when changing this option you need to delete any form_*.png files # in the HTML output before the changes have effect. FORMULA_TRANSPARENT = YES # When the SEARCHENGINE tag is enabled doxygen will generate a search box # for the HTML output. The underlying search engine uses javascript # and DHTML and should work on any modern browser. Note that when using # HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets # (GENERATE_DOCSET) there is already a search function so this one should # typically be disabled. For large projects the javascript based search engine # can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. SEARCHENGINE = YES # When the SERVER_BASED_SEARCH tag is enabled the search engine will be # implemented using a PHP enabled web server instead of at the web client # using Javascript. Doxygen will generate the search PHP script and index # file to put on the web server. The advantage of the server # based approach is that it scales better to large projects and allows # full text search. The disadvances is that it is more difficult to setup # and does not have live searching capabilities. SERVER_BASED_SEARCH = NO #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = $(GENERATE_LATEX) # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. # Note that when enabling USE_PDFLATEX this option is only used for # generating bitmaps for formulas in the HTML output, but not in the # Makefile that is written to the output directory. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = $(PAPER_SIZE) # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = NO # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = NO # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = YES # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO # If LATEX_SOURCE_CODE is set to YES then doxygen will include # source code with syntax highlighting in the LaTeX output. # Note that which sources are shown also depends on other settings # such as SOURCE_BROWSER. LATEX_SOURCE_CODE = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = $(GENERATE_RTF) # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = $(GENERATE_MAN) # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .1 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = $(GENERATE_XML) # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. # This is useful # if you want to understand what is going on. # On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse # the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = $(DOCDIR)/$(PROJECT).tag # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = $(PERL_PATH) #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option is superseded by the HAVE_DOT option below. This is only a # fallback. It is recommended to install and use dot, since it yields more # powerful graphs. CLASS_DIAGRAMS = YES # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the # documentation. The MSCGEN_PATH tag allows you to specify the directory where # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = $(HAVE_DOT) # The DOT_NUM_THREADS specifies the number of dot invocations doxygen is # allowed to run in parallel. When set to 0 (the default) doxygen will # base this on the number of processors available in the system. You can set it # explicitly to a value larger than 0 to get control over the balance # between CPU load and processing speed. DOT_NUM_THREADS = 0 # By default doxygen will write a font called FreeSans.ttf to the output # directory and reference it in all dot files that doxygen generates. This # font does not include all possible unicode characters however, so when you need # these (or just want a differently looking font) you can specify the font name # using DOT_FONTNAME. You need need to make sure dot is able to find the font, # which can be done by putting it in a standard location or by setting the # DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory # containing the font. DOT_FONTNAME = FreeSans.ttf # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. DOT_FONTSIZE = 10 # By default doxygen will tell dot to use the output directory to look for the # FreeSans.ttf font (which doxygen will put there itself). If you specify a # different font using DOT_FONTNAME you can set the path where dot # can find it using this tag. DOT_FONTPATH = # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT options are set to YES then # doxygen will generate a call dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable call graphs # for selected functions only using the \callgraph command. CALL_GRAPH = NO # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then # doxygen will generate a caller dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable caller # graphs for selected functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = $(DOT_PATH) # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the # number of direct children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, because dot on Windows does not # seem to support this out of the box. Warning: Depending on the platform used, # enabling this option may lead to badly anti-aliased labels on the edges of # a graph (i.e. they become hard to read). DOT_TRANSPARENT = NO # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = YES # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES ./TODO0000644000004100000410000000001513313171755011735 0ustar www-datawww-dataWrite README ./NuxCore/0000755000004100000410000000000013313171755012634 5ustar www-datawww-data./NuxCore/PropertyOperators.h0000644000004100000410000001644313313171755016540 0ustar www-datawww-data// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- /* * Copyright 2011 Inalogic® Inc. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License, as * published by the Free Software Foundation; either version 2.1 or 3.0 * of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License along with this program. If not, see * * Authored by: Tim Penhey * */ #if defined(NUX_OS_WINDOWS) #pragma warning(disable : 4519) // error C4519: default template arguments are only allowed on a class template #endif #ifndef NUXCORE_PROPERTY_OPERATORS_H #define NUXCORE_PROPERTY_OPERATORS_H namespace nux { /** * This is a very boring file. * * It adds boolean operators for properties. The challenge has been making * operators that work for properties and only properties. Since we don't * want to add explicit methods for each type of property we have, we have the * default template argument VT which gets the ValueType from the Property * definition. Since things like std::_list_iterator doesn't have a * ValueType typedef, these functions are discarded from the possible choices, * but since the Property templates do, they are valid, and get chosen. * * However as much as I'd like to have more generic operators for !=, <=, > * and >=, we can't really without making these functions choosable for types * that we don't want, so we have three functions defined for each operator. */ // operator == template