diff --git a/3rdparty/stb_truetype/stb_truetype.h b/3rdparty/stb_truetype/stb_truetype.h new file mode 100644 index 00000000..2db3ce0e --- /dev/null +++ b/3rdparty/stb_truetype/stb_truetype.h @@ -0,0 +1,2064 @@ +// stb_truetype.h - v0.6c - public domain +// authored from 2009-2012 by Sean Barrett / RAD Game Tools +// +// This library processes TrueType files: +// parse files +// extract glyph metrics +// extract glyph shapes +// render glyphs to one-channel bitmaps with antialiasing (box filter) +// +// Todo: +// non-MS cmaps +// crashproof on bad data +// hinting? (no longer patented) +// cleartype-style AA? +// optimize: use simple memory allocator for intermediates +// optimize: build edge-list directly from curves +// optimize: rasterize directly from curves? +// +// ADDITIONAL CONTRIBUTORS +// +// Mikko Mononen: compound shape support, more cmap formats +// Tor Andersson: kerning, subpixel rendering +// +// Bug/warning reports: +// "Zer" on mollyrocket (with fix) +// Cass Everitt +// stoiko (Haemimont Games) +// Brian Hook +// Walter van Niftrik +// +// VERSION HISTORY +// +// 0.6c (2012-07-24) improve documentation +// 0.6b (2012-07-20) fix a few more warnings +// 0.6 (2012-07-17) fix warnings; added stbtt_ScaleForMappingEmToPixels, +// stbtt_GetFontBoundingBox, stbtt_IsGlyphEmpty +// 0.5 (2011-12-09) bugfixes: +// subpixel glyph renderer computed wrong bounding box +// first vertex of shape can be off-curve (FreeSans) +// 0.4b (2011-12-03) fixed an error in the font baking example +// 0.4 (2011-12-01) kerning, subpixel rendering (tor) +// bugfixes for: +// codepoint-to-glyph conversion using table fmt=12 +// codepoint-to-glyph conversion using table fmt=4 +// stbtt_GetBakedQuad with non-square texture (Zer) +// updated Hello World! sample to use kerning and subpixel +// fixed some warnings +// 0.3 (2009-06-24) cmap fmt=12, compound shapes (MM) +// userdata, malloc-from-userdata, non-zero fill (STB) +// 0.2 (2009-03-11) Fix unsigned/signed char warnings +// 0.1 (2009-03-09) First public release +// +// LICENSE +// +// This software is in the public domain. Where that dedication is not +// recognized, you are granted a perpetual, irrevokable license to copy +// and modify this file as you see fit. +// +// USAGE +// +// Include this file in whatever places neeed to refer to it. In ONE C/C++ +// file, write: +// #define STB_TRUETYPE_IMPLEMENTATION +// before the #include of this file. This expands out the actual +// implementation into that C/C++ file. +// +// Simple 3D API (don't ship this, but it's fine for tools and quick start, +// and you can cut and paste from it to move to more advanced) +// stbtt_BakeFontBitmap() -- bake a font to a bitmap for use as texture +// stbtt_GetBakedQuad() -- compute quad to draw for a given char +// +// "Load" a font file from a memory buffer (you have to keep the buffer loaded) +// stbtt_InitFont() +// stbtt_GetFontOffsetForIndex() -- use for TTC font collections +// +// Render a unicode codepoint to a bitmap +// stbtt_GetCodepointBitmap() -- allocates and returns a bitmap +// stbtt_MakeCodepointBitmap() -- renders into bitmap you provide +// stbtt_GetCodepointBitmapBox() -- how big the bitmap must be +// +// Character advance/positioning +// stbtt_GetCodepointHMetrics() +// stbtt_GetFontVMetrics() +// stbtt_GetCodepointKernAdvance() +// +// ADDITIONAL DOCUMENTATION +// +// Immediately after this block comment are a series of sample programs. +// +// After the sample programs is the "header file" section. This section +// includes documentation for each API function. +// +// Some important concepts to understand to use this library: +// +// Codepoint +// Characters are defined by unicode codepoints, e.g. 65 is +// uppercase A, 231 is lowercase c with a cedilla, 0x7e30 is +// the hiragana for "ma". +// +// Glyph +// A visual character shape (every codepoint is rendered as +// some glyph) +// +// Glyph index +// A font-specific integer ID representing a glyph +// +// Baseline +// Glyph shapes are defined relative to a baseline, which is the +// bottom of uppercase characters. Characters extend both above +// and below the baseline. +// +// Current Point +// As you draw text to the screen, you keep track of a "current point" +// which is the origin of each character. The current point's vertical +// position is the baseline. Even "baked fonts" use this model. +// +// Vertical Font Metrics +// The vertical qualities of the font, used to vertically position +// and space the characters. See docs for stbtt_GetFontVMetrics. +// +// Font Size in Pixels or Points +// The preferred interface for specifying font sizes in stb_truetype +// is to specify how tall the font's vertical extent should be in pixels. +// If that sounds good enough, skip the next paragraph. +// +// Most font APIs instead use "points", which are a common typographic +// measurement for describing font size, defined as 72 points per inch. +// stb_truetype provides a point API for compatibility. However, true +// "per inch" conventions don't make much sense on computer displays +// since they different monitors have different number of pixels per +// inch. For example, Windows traditionally uses a convention that +// there are 96 pixels per inch, thus making 'inch' measurements have +// nothing to do with inches, and thus effectively defining a point to +// be 1.333 pixels. Additionally, the TrueType font data provides +// an explicit scale factor to scale a given font's glyphs to points, +// but the author has observed that this scale factor is often wrong +// for non-commercial fonts, thus making fonts scaled in points +// according to the TrueType spec incoherently sized in practice. +// +// ADVANCED USAGE +// +// Quality: +// +// - Use the functions with Subpixel at the end to allow your characters +// to have subpixel positioning. Since the font is anti-aliased, not +// hinted, this is very import for quality. (This is not possible with +// baked fonts.) +// +// - Kerning is now supported, and if you're supporting subpixel rendering +// then kerning is worth using to give your text a polished look. +// +// Performance: +// +// - Convert Unicode codepoints to glyph indexes and operate on the glyphs; +// if you don't do this, stb_truetype is forced to do the conversion on +// every call. +// +// - There are a lot of memory allocations. We should modify it to take +// a temp buffer and allocate from the temp buffer (without freeing), +// should help performance a lot. +// +// NOTES +// +// The system uses the raw data found in the .ttf file without changing it +// and without building auxiliary data structures. This is a bit inefficient +// on little-endian systems (the data is big-endian), but assuming you're +// caching the bitmaps or glyph shapes this shouldn't be a big deal. +// +// It appears to be very hard to programmatically determine what font a +// given file is in a general way. I provide an API for this, but I don't +// recommend it. +// +// +// SOURCE STATISTICS (based on v0.6c, 2050 LOC) +// +// Documentation & header file 520 LOC \___ 660 LOC documentation +// Sample code 140 LOC / +// Truetype parsing 620 LOC ---- 620 LOC TrueType +// Software rasterization 240 LOC \ . +// Curve tesselation 120 LOC \__ 550 LOC Bitmap creation +// Bitmap management 100 LOC / +// Baked bitmap interface 70 LOC / +// Font name matching & access 150 LOC ---- 150 +// C runtime library abstraction 60 LOC ---- 60 + + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +//// +//// SAMPLE PROGRAMS +//// +// +// Incomplete text-in-3d-api example, which draws quads properly aligned to be lossless +// +#if 0 +#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation +#include "stb_truetype.h" + +char ttf_buffer[1<<20]; +unsigned char temp_bitmap[512*512]; + +stbtt_bakedchar cdata[96]; // ASCII 32..126 is 95 glyphs +GLstbtt_uint ftex; + +void my_stbtt_initfont(void) +{ + fread(ttf_buffer, 1, 1<<20, fopen("c:/windows/fonts/times.ttf", "rb")); + stbtt_BakeFontBitmap(data,0, 32.0, temp_bitmap,512,512, 32,96, cdata); // no guarantee this fits! + // can free ttf_buffer at this point + glGenTextures(1, &ftex); + glBindTexture(GL_TEXTURE_2D, ftex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 512,512, 0, GL_ALPHA, GL_UNSIGNED_BYTE, temp_bitmap); + // can free temp_bitmap at this point + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); +} + +void my_stbtt_print(float x, float y, char *text) +{ + // assume orthographic projection with units = screen pixels, origin at top left + glBindTexture(GL_TEXTURE_2D, ftex); + glBegin(GL_QUADS); + while (*text) { + if (*text >= 32 && *text < 128) { + stbtt_aligned_quad q; + stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);//1=opengl,0=old d3d + glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y0); + glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y0); + glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y1); + glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y1); + } + ++text; + } + glEnd(); +} +#endif +// +// +////////////////////////////////////////////////////////////////////////////// +// +// Complete program (this compiles): get a single bitmap, print as ASCII art +// +#if 0 +#include +#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation +#include "stb_truetype.h" + +char ttf_buffer[1<<25]; + +int main(int argc, char **argv) +{ + stbtt_fontinfo font; + unsigned char *bitmap; + int w,h,i,j,c = (argc > 1 ? atoi(argv[1]) : 'a'), s = (argc > 2 ? atoi(argv[2]) : 20); + + fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] : "c:/windows/fonts/arialbd.ttf", "rb")); + + stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer,0)); + bitmap = stbtt_GetCodepointBitmap(&font, 0,stbtt_ScaleForPixelHeight(&font, s), c, &w, &h, 0,0); + + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) + putchar(" .:ioVM@"[bitmap[j*w+i]>>5]); + putchar('\n'); + } + return 0; +} +#endif +// +// Output: +// +// .ii. +// @@@@@@. +// V@Mio@@o +// :i. V@V +// :oM@@M +// :@@@MM@M +// @@o o@M +// :@@. M@M +// @@@o@@@@ +// :M@@V:@@. +// +////////////////////////////////////////////////////////////////////////////// +// +// Complete program: print "Hello World!" banner, with bugs +// +#if 0 +char buffer[24<<20]; +unsigned char screen[20][79]; + +int main(int arg, char **argv) +{ + stbtt_fontinfo font; + int i,j,ascent,baseline,ch=0; + float scale, xpos=0; + char *text = "Heljo World!"; + + fread(buffer, 1, 1000000, fopen("c:/windows/fonts/arialbd.ttf", "rb")); + stbtt_InitFont(&font, buffer, 0); + + scale = stbtt_ScaleForPixelHeight(&font, 15); + stbtt_GetFontVMetrics(&font, &ascent,0,0); + baseline = (int) (ascent*scale); + + while (text[ch]) { + int advance,lsb,x0,y0,x1,y1; + float x_shift = xpos - (float) floor(xpos); + stbtt_GetCodepointHMetrics(&font, text[ch], &advance, &lsb); + stbtt_GetCodepointBitmapBoxSubpixel(&font, text[ch], scale,scale,x_shift,0, &x0,&y0,&x1,&y1); + stbtt_MakeCodepointBitmapSubpixel(&font, &screen[baseline + y0][(int) xpos + x0], x1-x0,y1-y0, 79, scale,scale,x_shift,0, text[ch]); + // note that this stomps the old data, so where character boxes overlap (e.g. 'lj') it's wrong + // because this API is really for baking character bitmaps into textures. if you want to render + // a sequence of characters, you really need to render each bitmap to a temp buffer, then + // "alpha blend" that into the working buffer + xpos += (advance * scale); + if (text[ch+1]) + xpos += scale*stbtt_GetCodepointKernAdvance(&font, text[ch],text[ch+1]); + ++ch; + } + + for (j=0; j < 20; ++j) { + for (i=0; i < 78; ++i) + putchar(" .:ioVM@"[screen[j][i]>>5]); + putchar('\n'); + } + + return 0; +} +#endif + + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +//// +//// INTEGRATION WITH YOUR CODEBASE +//// +//// The following sections allow you to supply alternate definitions +//// of C library functions used by stb_truetype. + +#ifdef STB_TRUETYPE_IMPLEMENTATION + // #define your own (u)stbtt_int8/16/32 before including to override this + #ifndef stbtt_uint8 + typedef unsigned char stbtt_uint8; + typedef signed char stbtt_int8; + typedef unsigned short stbtt_uint16; + typedef signed short stbtt_int16; + typedef unsigned int stbtt_uint32; + typedef signed int stbtt_int32; + #endif + + typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1]; + typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1]; + + // #define your own STBTT_sort() to override this to avoid qsort + #ifndef STBTT_sort + #include + #define STBTT_sort(data,num_items,item_size,compare_func) qsort(data,num_items,item_size,compare_func) + #endif + + // #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h + #ifndef STBTT_ifloor + #include + #define STBTT_ifloor(x) ((int) floor(x)) + #define STBTT_iceil(x) ((int) ceil(x)) + #endif + + // #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h + #ifndef STBTT_malloc + #include + #define STBTT_malloc(x,u) malloc(x) + #define STBTT_free(x,u) free(x) + #endif + + #ifndef STBTT_assert + #include + #define STBTT_assert(x) assert(x) + #endif + + #ifndef STBTT_strlen + #include + #define STBTT_strlen(x) strlen(x) + #endif + + #ifndef STBTT_memcpy + #include + #define STBTT_memcpy memcpy + #define STBTT_memset memset + #endif +#endif + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +//// +//// INTERFACE +//// +//// + +#ifndef __STB_INCLUDE_STB_TRUETYPE_H__ +#define __STB_INCLUDE_STB_TRUETYPE_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// TEXTURE BAKING API +// +// If you use this API, you only have to call two functions ever. +// + +typedef struct +{ + unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap + float xoff,yoff,xadvance; +} stbtt_bakedchar; + +extern int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) + float pixel_height, // height of font in pixels + unsigned char *pixels, int pw, int ph, // bitmap to be filled in + int first_char, int num_chars, // characters to bake + stbtt_bakedchar *chardata); // you allocate this, it's num_chars long +// if return is positive, the first unused row of the bitmap +// if return is negative, returns the negative of the number of characters that fit +// if return is 0, no characters fit and no rows were used +// This uses a very crappy packing. + +typedef struct +{ + float x0,y0,s0,t0; // top-left + float x1,y1,s1,t1; // bottom-right +} stbtt_aligned_quad; + +extern void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, // same data as above + int char_index, // character to display + float *xpos, float *ypos, // pointers to current position in screen pixel space + stbtt_aligned_quad *q, // output: quad to draw + int opengl_fillrule); // true if opengl fill rule; false if DX9 or earlier +// Call GetBakedQuad with char_index = 'character - first_char', and it +// creates the quad you need to draw and advances the current position. +// +// The coordinate system used assumes y increases downwards. +// +// Characters will extend both above and below the current position; +// see discussion of "BASELINE" above. +// +// It's inefficient; you might want to c&p it and optimize it. + + +////////////////////////////////////////////////////////////////////////////// +// +// FONT LOADING +// +// + +extern int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index); +// Each .ttf/.ttc file may have more than one font. Each font has a sequential +// index number starting from 0. Call this function to get the font offset for +// a given index; it returns -1 if the index is out of range. A regular .ttf +// file will only define one font and it always be at offset 0, so it will +// return '0' for index 0, and -1 for all other indices. You can just skip +// this step if you know it's that kind of font. + + +// The following structure is defined publically so you can declare one on +// the stack or as a global or etc, but you should treat it as opaque. +typedef struct stbtt_fontinfo +{ + void * userdata; + unsigned char * data; // pointer to .ttf file + int fontstart; // offset of start of font + + int numGlyphs; // number of glyphs, needed for range checking + + int loca,head,glyf,hhea,hmtx,kern; // table locations as offset from start of .ttf + int index_map; // a cmap mapping for our chosen character encoding + int indexToLocFormat; // format needed to map from glyph index to glyph +} stbtt_fontinfo; + +extern int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset); +// Given an offset into the file that defines a font, this function builds +// the necessary cached info for the rest of the system. You must allocate +// the stbtt_fontinfo yourself, and stbtt_InitFont will fill it out. You don't +// need to do anything special to free it, because the contents are pure +// value data with no additional data structures. Returns 0 on failure. + + +////////////////////////////////////////////////////////////////////////////// +// +// CHARACTER TO GLYPH-INDEX CONVERSIOn + +int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint); +// If you're going to perform multiple operations on the same character +// and you want a speed-up, call this function with the character you're +// going to process, then use glyph-based functions instead of the +// codepoint-based functions. + + +////////////////////////////////////////////////////////////////////////////// +// +// CHARACTER PROPERTIES +// + +extern float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels); +// computes a scale factor to produce a font whose "height" is 'pixels' tall. +// Height is measured as the distance from the highest ascender to the lowest +// descender; in other words, it's equivalent to calling stbtt_GetFontVMetrics +// and computing: +// scale = pixels / (ascent - descent) +// so if you prefer to measure height by the ascent only, use a similar calculation. + +extern float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels); +// computes a scale factor to produce a font whose EM size is mapped to +// 'pixels' tall. This is probably what traditional APIs compute, but +// I'm not positive. + +extern void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap); +// ascent is the coordinate above the baseline the font extends; descent +// is the coordinate below the baseline the font extends (i.e. it is typically negative) +// lineGap is the spacing between one row's descent and the next row's ascent... +// so you should advance the vertical position by "*ascent - *descent + *lineGap" +// these are expressed in unscaled coordinates, so you must multiply by +// the scale factor for a given size + +extern void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1); +// the bounding box around all possible characters + +extern void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing); +// leftSideBearing is the offset from the current horizontal position to the left edge of the character +// advanceWidth is the offset from the current horizontal position to the next horizontal position +// these are expressed in unscaled coordinates + +extern int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2); +// an additional amount to add to the 'advance' value between ch1 and ch2 +// @TODO; for now always returns 0! + +extern int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1); +// Gets the bounding box of the visible part of the glyph, in unscaled coordinates + +extern void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing); +extern int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2); +extern int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); +// as above, but takes one or more glyph indices for greater efficiency + + +////////////////////////////////////////////////////////////////////////////// +// +// GLYPH SHAPES (you probably don't need these, but they have to go before +// the bitmaps for C declaration-order reasons) +// + +#ifndef STBTT_vmove // you can predefine these to use different values (but why?) + enum { + STBTT_vmove=1, + STBTT_vline, + STBTT_vcurve + }; +#endif + +#ifndef stbtt_vertex // you can predefine this to use different values + // (we share this with other code at RAD) + #define stbtt_vertex_type short // can't use stbtt_int16 because that's not visible in the header file + typedef struct + { + stbtt_vertex_type x,y,cx,cy; + unsigned char type,padding; + } stbtt_vertex; +#endif + +extern int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index); +// returns non-zero if nothing is drawn for this glyph + +extern int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices); +extern int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices); +// returns # of vertices and fills *vertices with the pointer to them +// these are expressed in "unscaled" coordinates + +extern void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices); +// frees the data allocated above + +////////////////////////////////////////////////////////////////////////////// +// +// BITMAP RENDERING +// + +extern void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata); +// frees the bitmap allocated below + +extern unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff); +// allocates a large-enough single-channel 8bpp bitmap and renders the +// specified character/glyph at the specified scale into it, with +// antialiasing. 0 is no coverage (transparent), 255 is fully covered (opaque). +// *width & *height are filled out with the width & height of the bitmap, +// which is stored left-to-right, top-to-bottom. +// +// xoff/yoff are the offset it pixel space from the glyph origin to the top-left of the bitmap + +extern unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff); +// the same as stbtt_GetCodepoitnBitmap, but you can specify a subpixel +// shift for the character + +extern void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint); +// the same as stbtt_GetCodepointBitmap, but you pass in storage for the bitmap +// in the form of 'output', with row spacing of 'out_stride' bytes. the bitmap +// is clipped to out_w/out_h bytes. Call stbtt_GetCodepointBitmapBox to get the +// width and height and positioning info for it first. + +extern void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint); +// same as stbtt_MakeCodepointBitmap, but you can specify a subpixel +// shift for the character + +extern void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); +// get the bbox of the bitmap centered around the glyph origin; so the +// bitmap width is ix1-ix0, height is iy1-iy0, and location to place +// the bitmap top left is (leftSideBearing*scale,iy0). +// (Note that the bitmap uses y-increases-down, but the shape uses +// y-increases-up, so CodepointBitmapBox and CodepointBox are inverted.) + +extern void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1); +// same as stbtt_GetCodepointBitmapBox, but you can specify a subpixel +// shift for the character + +// the following functions are equivalent to the above functions, but operate +// on glyph indices instead of Unicode codepoints (for efficiency) +extern unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff); +extern unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff); +extern void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph); +extern void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph); +extern void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); +extern void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1); + + +// @TODO: don't expose this structure +typedef struct +{ + int w,h,stride; + unsigned char *pixels; +} stbtt__bitmap; + +extern void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata); + +////////////////////////////////////////////////////////////////////////////// +// +// Finding the right font... +// +// You should really just solve this offline, keep your own tables +// of what font is what, and don't try to get it out of the .ttf file. +// That's because getting it out of the .ttf file is really hard, because +// the names in the file can appear in many possible encodings, in many +// possible languages, and e.g. if you need a case-insensitive comparison, +// the details of that depend on the encoding & language in a complex way +// (actually underspecified in truetype, but also gigantic). +// +// But you can use the provided functions in two possible ways: +// stbtt_FindMatchingFont() will use *case-sensitive* comparisons on +// unicode-encoded names to try to find the font you want; +// you can run this before calling stbtt_InitFont() +// +// stbtt_GetFontNameString() lets you get any of the various strings +// from the file yourself and do your own comparisons on them. +// You have to have called stbtt_InitFont() first. + + +extern int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags); +// returns the offset (not index) of the font that matches, or -1 if none +// if you use STBTT_MACSTYLE_DONTCARE, use a font name like "Arial Bold". +// if you use any other flag, use a font name like "Arial"; this checks +// the 'macStyle' header field; i don't know if fonts set this consistently +#define STBTT_MACSTYLE_DONTCARE 0 +#define STBTT_MACSTYLE_BOLD 1 +#define STBTT_MACSTYLE_ITALIC 2 +#define STBTT_MACSTYLE_UNDERSCORE 4 +#define STBTT_MACSTYLE_NONE 8 // <= not same as 0, this makes us check the bitfield is 0 + +extern int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2); +// returns 1/0 whether the first string interpreted as utf8 is identical to +// the second string interpreted as big-endian utf16... useful for strings from next func + +extern const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID); +// returns the string (which may be big-endian double byte, e.g. for unicode) +// and puts the length in bytes in *length. +// +// some of the values for the IDs are below; for more see the truetype spec: +// http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6name.html +// http://www.microsoft.com/typography/otspec/name.htm + +enum { // platformID + STBTT_PLATFORM_ID_UNICODE =0, + STBTT_PLATFORM_ID_MAC =1, + STBTT_PLATFORM_ID_ISO =2, + STBTT_PLATFORM_ID_MICROSOFT =3 +}; + +enum { // encodingID for STBTT_PLATFORM_ID_UNICODE + STBTT_UNICODE_EID_UNICODE_1_0 =0, + STBTT_UNICODE_EID_UNICODE_1_1 =1, + STBTT_UNICODE_EID_ISO_10646 =2, + STBTT_UNICODE_EID_UNICODE_2_0_BMP=3, + STBTT_UNICODE_EID_UNICODE_2_0_FULL=4 +}; + +enum { // encodingID for STBTT_PLATFORM_ID_MICROSOFT + STBTT_MS_EID_SYMBOL =0, + STBTT_MS_EID_UNICODE_BMP =1, + STBTT_MS_EID_SHIFTJIS =2, + STBTT_MS_EID_UNICODE_FULL =10 +}; + +enum { // encodingID for STBTT_PLATFORM_ID_MAC; same as Script Manager codes + STBTT_MAC_EID_ROMAN =0, STBTT_MAC_EID_ARABIC =4, + STBTT_MAC_EID_JAPANESE =1, STBTT_MAC_EID_HEBREW =5, + STBTT_MAC_EID_CHINESE_TRAD =2, STBTT_MAC_EID_GREEK =6, + STBTT_MAC_EID_KOREAN =3, STBTT_MAC_EID_RUSSIAN =7 +}; + +enum { // languageID for STBTT_PLATFORM_ID_MICROSOFT; same as LCID... + // problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs + STBTT_MS_LANG_ENGLISH =0x0409, STBTT_MS_LANG_ITALIAN =0x0410, + STBTT_MS_LANG_CHINESE =0x0804, STBTT_MS_LANG_JAPANESE =0x0411, + STBTT_MS_LANG_DUTCH =0x0413, STBTT_MS_LANG_KOREAN =0x0412, + STBTT_MS_LANG_FRENCH =0x040c, STBTT_MS_LANG_RUSSIAN =0x0419, + STBTT_MS_LANG_GERMAN =0x0407, STBTT_MS_LANG_SPANISH =0x0409, + STBTT_MS_LANG_HEBREW =0x040d, STBTT_MS_LANG_SWEDISH =0x041D +}; + +enum { // languageID for STBTT_PLATFORM_ID_MAC + STBTT_MAC_LANG_ENGLISH =0 , STBTT_MAC_LANG_JAPANESE =11, + STBTT_MAC_LANG_ARABIC =12, STBTT_MAC_LANG_KOREAN =23, + STBTT_MAC_LANG_DUTCH =4 , STBTT_MAC_LANG_RUSSIAN =32, + STBTT_MAC_LANG_FRENCH =1 , STBTT_MAC_LANG_SPANISH =6 , + STBTT_MAC_LANG_GERMAN =2 , STBTT_MAC_LANG_SWEDISH =5 , + STBTT_MAC_LANG_HEBREW =10, STBTT_MAC_LANG_CHINESE_SIMPLIFIED =33, + STBTT_MAC_LANG_ITALIAN =3 , STBTT_MAC_LANG_CHINESE_TRAD =19 +}; + +#ifdef __cplusplus +} +#endif + +#endif // __STB_INCLUDE_STB_TRUETYPE_H__ + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +//// +//// IMPLEMENTATION +//// +//// + +#ifdef STB_TRUETYPE_IMPLEMENTATION + +////////////////////////////////////////////////////////////////////////// +// +// accessors to parse data from file +// + +// on platforms that don't allow misaligned reads, if we want to allow +// truetype fonts that aren't padded to alignment, define ALLOW_UNALIGNED_TRUETYPE + +#define ttBYTE(p) (* (stbtt_uint8 *) (p)) +#define ttCHAR(p) (* (stbtt_int8 *) (p)) +#define ttFixed(p) ttLONG(p) + +#if defined(STB_TRUETYPE_BIGENDIAN) && !defined(ALLOW_UNALIGNED_TRUETYPE) + + #define ttUSHORT(p) (* (stbtt_uint16 *) (p)) + #define ttSHORT(p) (* (stbtt_int16 *) (p)) + #define ttULONG(p) (* (stbtt_uint32 *) (p)) + #define ttLONG(p) (* (stbtt_int32 *) (p)) + +#else + + stbtt_uint16 ttUSHORT(const stbtt_uint8 *p) { return p[0]*256 + p[1]; } + stbtt_int16 ttSHORT(const stbtt_uint8 *p) { return p[0]*256 + p[1]; } + stbtt_uint32 ttULONG(const stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } + stbtt_int32 ttLONG(const stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } + +#endif + +#define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3)) +#define stbtt_tag(p,str) stbtt_tag4(p,str[0],str[1],str[2],str[3]) + +static int stbtt__isfont(const stbtt_uint8 *font) +{ + // check the version number + if (stbtt_tag4(font, '1',0,0,0)) return 1; // TrueType 1 + if (stbtt_tag(font, "typ1")) return 1; // TrueType with type 1 font -- we don't support this! + if (stbtt_tag(font, "OTTO")) return 1; // OpenType with CFF + if (stbtt_tag4(font, 0,1,0,0)) return 1; // OpenType 1.0 + return 0; +} + +// @OPTIMIZE: binary search +static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart, const char *tag) +{ + stbtt_int32 num_tables = ttUSHORT(data+fontstart+4); + stbtt_uint32 tabledir = fontstart + 12; + stbtt_int32 i; + for (i=0; i < num_tables; ++i) { + stbtt_uint32 loc = tabledir + 16*i; + if (stbtt_tag(data+loc+0, tag)) + return ttULONG(data+loc+8); + } + return 0; +} + +int stbtt_GetFontOffsetForIndex(const unsigned char *font_collection, int index) +{ + // if it's just a font, there's only one valid index + if (stbtt__isfont(font_collection)) + return index == 0 ? 0 : -1; + + // check if it's a TTC + if (stbtt_tag(font_collection, "ttcf")) { + // version 1? + if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) { + stbtt_int32 n = ttLONG(font_collection+8); + if (index >= n) + return -1; + return ttULONG(font_collection+12+index*14); + } + } + return -1; +} + +int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data2, int fontstart) +{ + stbtt_uint8 *data = (stbtt_uint8 *) data2; + stbtt_uint32 cmap, t; + stbtt_int32 i,numTables; + + info->data = data; + info->fontstart = fontstart; + + cmap = stbtt__find_table(data, fontstart, "cmap"); // required + info->loca = stbtt__find_table(data, fontstart, "loca"); // required + info->head = stbtt__find_table(data, fontstart, "head"); // required + info->glyf = stbtt__find_table(data, fontstart, "glyf"); // required + info->hhea = stbtt__find_table(data, fontstart, "hhea"); // required + info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); // required + info->kern = stbtt__find_table(data, fontstart, "kern"); // not required + if (!cmap || !info->loca || !info->head || !info->glyf || !info->hhea || !info->hmtx) + return 0; + + t = stbtt__find_table(data, fontstart, "maxp"); + if (t) + info->numGlyphs = ttUSHORT(data+t+4); + else + info->numGlyphs = 0xffff; + + // find a cmap encoding table we understand *now* to avoid searching + // later. (todo: could make this installable) + // the same regardless of glyph. + numTables = ttUSHORT(data + cmap + 2); + info->index_map = 0; + for (i=0; i < numTables; ++i) { + stbtt_uint32 encoding_record = cmap + 4 + 8 * i; + // find an encoding we understand: + switch(ttUSHORT(data+encoding_record)) { + case STBTT_PLATFORM_ID_MICROSOFT: + switch (ttUSHORT(data+encoding_record+2)) { + case STBTT_MS_EID_UNICODE_BMP: + case STBTT_MS_EID_UNICODE_FULL: + // MS/Unicode + info->index_map = cmap + ttULONG(data+encoding_record+4); + break; + } + break; + } + } + if (info->index_map == 0) + return 0; + + info->indexToLocFormat = ttUSHORT(data+info->head + 50); + return 1; +} + +int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint) +{ + stbtt_uint8 *data = info->data; + stbtt_uint32 index_map = info->index_map; + + stbtt_uint16 format = ttUSHORT(data + index_map + 0); + if (format == 0) { // apple byte encoding + stbtt_int32 bytes = ttUSHORT(data + index_map + 2); + if (unicode_codepoint < bytes-6) + return ttBYTE(data + index_map + 6 + unicode_codepoint); + return 0; + } else if (format == 6) { + stbtt_uint32 first = ttUSHORT(data + index_map + 6); + stbtt_uint32 count = ttUSHORT(data + index_map + 8); + if ((stbtt_uint32) unicode_codepoint >= first && (stbtt_uint32) unicode_codepoint < first+count) + return ttUSHORT(data + index_map + 10 + (unicode_codepoint - first)*2); + return 0; + } else if (format == 2) { + STBTT_assert(0); // @TODO: high-byte mapping for japanese/chinese/korean + return 0; + } else if (format == 4) { // standard mapping for windows fonts: binary search collection of ranges + stbtt_uint16 segcount = ttUSHORT(data+index_map+6) >> 1; + stbtt_uint16 searchRange = ttUSHORT(data+index_map+8) >> 1; + stbtt_uint16 entrySelector = ttUSHORT(data+index_map+10); + stbtt_uint16 rangeShift = ttUSHORT(data+index_map+12) >> 1; + stbtt_uint16 item, offset, start, end; + + // do a binary search of the segments + stbtt_uint32 endCount = index_map + 14; + stbtt_uint32 search = endCount; + + if (unicode_codepoint > 0xffff) + return 0; + + // they lie from endCount .. endCount + segCount + // but searchRange is the nearest power of two, so... + if (unicode_codepoint >= ttUSHORT(data + search + rangeShift*2)) + search += rangeShift*2; + + // now decrement to bias correctly to find smallest + search -= 2; + while (entrySelector) { + searchRange >>= 1; + start = ttUSHORT(data + search + 2 + segcount*2 + 2); + end = ttUSHORT(data + search + 2); + start = ttUSHORT(data + search + searchRange*2 + segcount*2 + 2); + end = ttUSHORT(data + search + searchRange*2); + if (unicode_codepoint > end) + search += searchRange*2; + --entrySelector; + } + search += 2; + + item = (stbtt_uint16) ((search - endCount) >> 1); + + STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2*item)); + start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item); + end = ttUSHORT(data + index_map + 14 + 2 + 2*item); + if (unicode_codepoint < start) + return 0; + + offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item); + if (offset == 0) + return (stbtt_uint16) (unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item)); + + return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item); + } else if (format == 12 || format == 13) { + stbtt_uint32 ngroups = ttULONG(data+index_map+12); + stbtt_int32 low,high; + low = 0; high = (stbtt_int32)ngroups; + // Binary search the right group. + while (low < high) { + stbtt_int32 mid = low + ((high-low) >> 1); // rounds down, so low <= mid < high + stbtt_uint32 start_char = ttULONG(data+index_map+16+mid*12); + stbtt_uint32 end_char = ttULONG(data+index_map+16+mid*12+4); + if ((stbtt_uint32) unicode_codepoint < start_char) + high = mid; + else if ((stbtt_uint32) unicode_codepoint > end_char) + low = mid+1; + else { + stbtt_uint32 start_glyph = ttULONG(data+index_map+16+mid*12+8); + if (format == 12) + return start_glyph + unicode_codepoint-start_char; + else // format == 13 + return start_glyph; + } + } + return 0; // not found + } + // @TODO + STBTT_assert(0); + return 0; +} + +int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices) +{ + return stbtt_GetGlyphShape(info, stbtt_FindGlyphIndex(info, unicode_codepoint), vertices); +} + +static void stbtt_setvertex(stbtt_vertex *v, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy) +{ + v->type = type; + v->x = (stbtt_int16) x; + v->y = (stbtt_int16) y; + v->cx = (stbtt_int16) cx; + v->cy = (stbtt_int16) cy; +} + +static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index) +{ + int g1,g2; + + if (glyph_index >= info->numGlyphs) return -1; // glyph index out of range + if (info->indexToLocFormat >= 2) return -1; // unknown index->glyph map format + + if (info->indexToLocFormat == 0) { + g1 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2) * 2; + g2 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2; + } else { + g1 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4); + g2 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4 + 4); + } + + return g1==g2 ? -1 : g1; // if length is 0, return -1 +} + +int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1) +{ + int g = stbtt__GetGlyfOffset(info, glyph_index); + if (g < 0) return 0; + + if (x0) *x0 = ttSHORT(info->data + g + 2); + if (y0) *y0 = ttSHORT(info->data + g + 4); + if (x1) *x1 = ttSHORT(info->data + g + 6); + if (y1) *y1 = ttSHORT(info->data + g + 8); + return 1; +} + +int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1) +{ + return stbtt_GetGlyphBox(info, stbtt_FindGlyphIndex(info,codepoint), x0,y0,x1,y1); +} + +int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index) +{ + stbtt_int16 numberOfContours; + int g = stbtt__GetGlyfOffset(info, glyph_index); + if (g < 0) return 1; + numberOfContours = ttSHORT(info->data + g); + return numberOfContours == 0; +} + +static int stbtt__close_shape(stbtt_vertex *vertices, int num_vertices, int was_off, int start_off, + stbtt_int32 sx, stbtt_int32 sy, stbtt_int32 scx, stbtt_int32 scy, stbtt_int32 cx, stbtt_int32 cy) +{ + if (start_off) { + if (was_off) + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy); + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, sx,sy,scx,scy); + } else { + if (was_off) + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve,sx,sy,cx,cy); + else + stbtt_setvertex(&vertices[num_vertices++], STBTT_vline,sx,sy,0,0); + } + return num_vertices; +} + +int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) +{ + stbtt_int16 numberOfContours; + stbtt_uint8 *endPtsOfContours; + stbtt_uint8 *data = info->data; + stbtt_vertex *vertices=0; + int num_vertices=0; + int g = stbtt__GetGlyfOffset(info, glyph_index); + + *pvertices = NULL; + + if (g < 0) return 0; + + numberOfContours = ttSHORT(data + g); + + if (numberOfContours > 0) { + stbtt_uint8 flags=0,flagcount; + stbtt_int32 ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0; + stbtt_int32 x,y,cx,cy,sx,sy, scx,scy; + stbtt_uint8 *points; + endPtsOfContours = (data + g + 10); + ins = ttUSHORT(data + g + 10 + numberOfContours * 2); + points = data + g + 10 + numberOfContours * 2 + 2 + ins; + + n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2); + + m = n + 2*numberOfContours; // a loose bound on how many vertices we might need + vertices = (stbtt_vertex *) STBTT_malloc(m * sizeof(vertices[0]), info->userdata); + if (vertices == 0) + return 0; + + next_move = 0; + flagcount=0; + + // in first pass, we load uninterpreted data into the allocated array + // above, shifted to the end of the array so we won't overwrite it when + // we create our final data starting from the front + + off = m - n; // starting offset for uninterpreted data, regardless of how m ends up being calculated + + // first load flags + + for (i=0; i < n; ++i) { + if (flagcount == 0) { + flags = *points++; + if (flags & 8) + flagcount = *points++; + } else + --flagcount; + vertices[off+i].type = flags; + } + + // now load x coordinates + x=0; + for (i=0; i < n; ++i) { + flags = vertices[off+i].type; + if (flags & 2) { + stbtt_int16 dx = *points++; + x += (flags & 16) ? dx : -dx; // ??? + } else { + if (!(flags & 16)) { + x = x + (stbtt_int16) (points[0]*256 + points[1]); + points += 2; + } + } + vertices[off+i].x = (stbtt_int16) x; + } + + // now load y coordinates + y=0; + for (i=0; i < n; ++i) { + flags = vertices[off+i].type; + if (flags & 4) { + stbtt_int16 dy = *points++; + y += (flags & 32) ? dy : -dy; // ??? + } else { + if (!(flags & 32)) { + y = y + (stbtt_int16) (points[0]*256 + points[1]); + points += 2; + } + } + vertices[off+i].y = (stbtt_int16) y; + } + + // now convert them to our format + num_vertices=0; + sx = sy = cx = cy = scx = scy = 0; + for (i=0; i < n; ++i) { + flags = vertices[off+i].type; + x = (stbtt_int16) vertices[off+i].x; + y = (stbtt_int16) vertices[off+i].y; + + if (next_move == i) { + if (i != 0) + num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); + + // now start the new one + start_off = !(flags & 1); + if (start_off) { + // if we start off with an off-curve point, then when we need to find a point on the curve + // where we can start, and we need to save some state for when we wraparound. + scx = x; + scy = y; + if (!(vertices[off+i+1].type & 1)) { + // next point is also a curve point, so interpolate an on-point curve + sx = (x + (stbtt_int32) vertices[off+i+1].x) >> 1; + sy = (y + (stbtt_int32) vertices[off+i+1].y) >> 1; + } else { + // otherwise just use the next point as our start point + sx = (stbtt_int32) vertices[off+i+1].x; + sy = (stbtt_int32) vertices[off+i+1].y; + ++i; // we're using point i+1 as the starting point, so skip it + } + } else { + sx = x; + sy = y; + } + stbtt_setvertex(&vertices[num_vertices++], STBTT_vmove,sx,sy,0,0); + was_off = 0; + next_move = 1 + ttUSHORT(endPtsOfContours+j*2); + ++j; + } else { + if (!(flags & 1)) { // if it's a curve + if (was_off) // two off-curve control points in a row means interpolate an on-curve midpoint + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy); + cx = x; + cy = y; + was_off = 1; + } else { + if (was_off) + stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, x,y, cx, cy); + else + stbtt_setvertex(&vertices[num_vertices++], STBTT_vline, x,y,0,0); + was_off = 0; + } + } + } + num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); + } else if (numberOfContours == -1) { + // Compound shapes. + int more = 1; + stbtt_uint8 *comp = data + g + 10; + num_vertices = 0; + vertices = 0; + while (more) { + stbtt_uint16 flags, gidx; + int comp_num_verts = 0, i; + stbtt_vertex *comp_verts = 0, *tmp = 0; + float mtx[6] = {1,0,0,1,0,0}, m, n; + + flags = ttSHORT(comp); comp+=2; + gidx = ttSHORT(comp); comp+=2; + + if (flags & 2) { // XY values + if (flags & 1) { // shorts + mtx[4] = ttSHORT(comp); comp+=2; + mtx[5] = ttSHORT(comp); comp+=2; + } else { + mtx[4] = ttCHAR(comp); comp+=1; + mtx[5] = ttCHAR(comp); comp+=1; + } + } + else { + // @TODO handle matching point + STBTT_assert(0); + } + if (flags & (1<<3)) { // WE_HAVE_A_SCALE + mtx[0] = mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; + mtx[1] = mtx[2] = 0; + } else if (flags & (1<<6)) { // WE_HAVE_AN_X_AND_YSCALE + mtx[0] = ttSHORT(comp)/16384.0f; comp+=2; + mtx[1] = mtx[2] = 0; + mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; + } else if (flags & (1<<7)) { // WE_HAVE_A_TWO_BY_TWO + mtx[0] = ttSHORT(comp)/16384.0f; comp+=2; + mtx[1] = ttSHORT(comp)/16384.0f; comp+=2; + mtx[2] = ttSHORT(comp)/16384.0f; comp+=2; + mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; + } + + // Find transformation scales. + m = (float) sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]); + n = (float) sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]); + + // Get indexed glyph. + comp_num_verts = stbtt_GetGlyphShape(info, gidx, &comp_verts); + if (comp_num_verts > 0) { + // Transform vertices. + for (i = 0; i < comp_num_verts; ++i) { + stbtt_vertex* v = &comp_verts[i]; + stbtt_vertex_type x,y; + x=v->x; y=v->y; + v->x = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); + v->y = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); + x=v->cx; y=v->cy; + v->cx = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); + v->cy = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); + } + // Append vertices. + tmp = (stbtt_vertex*)STBTT_malloc((num_vertices+comp_num_verts)*sizeof(stbtt_vertex), info->userdata); + if (!tmp) { + if (vertices) STBTT_free(vertices, info->userdata); + if (comp_verts) STBTT_free(comp_verts, info->userdata); + return 0; + } + if (num_vertices > 0) memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex)); + memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex)); + if (vertices) STBTT_free(vertices, info->userdata); + vertices = tmp; + STBTT_free(comp_verts, info->userdata); + num_vertices += comp_num_verts; + } + // More components ? + more = flags & (1<<5); + } + } else if (numberOfContours < 0) { + // @TODO other compound variations? + STBTT_assert(0); + } else { + // numberOfCounters == 0, do nothing + } + + *pvertices = vertices; + return num_vertices; +} + +void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing) +{ + stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->data+info->hhea + 34); + if (glyph_index < numOfLongHorMetrics) { + if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*glyph_index); + if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*glyph_index + 2); + } else { + if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1)); + if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics)); + } +} + +int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) +{ + stbtt_uint8 *data = info->data + info->kern; + stbtt_uint32 needle, straw; + int l, r, m; + + // we only look at the first table. it must be 'horizontal' and format 0. + if (!info->kern) + return 0; + if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 + return 0; + if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format + return 0; + + l = 0; + r = ttUSHORT(data+10) - 1; + needle = glyph1 << 16 | glyph2; + while (l <= r) { + m = (l + r) >> 1; + straw = ttULONG(data+18+(m*6)); // note: unaligned read + if (needle < straw) + r = m - 1; + else if (needle > straw) + l = m + 1; + else + return ttSHORT(data+22+(m*6)); + } + return 0; +} + +int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2) +{ + if (!info->kern) // if no kerning table, don't waste time looking up both codepoint->glyphs + return 0; + return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info,ch1), stbtt_FindGlyphIndex(info,ch2)); +} + +void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing) +{ + stbtt_GetGlyphHMetrics(info, stbtt_FindGlyphIndex(info,codepoint), advanceWidth, leftSideBearing); +} + +void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap) +{ + if (ascent ) *ascent = ttSHORT(info->data+info->hhea + 4); + if (descent) *descent = ttSHORT(info->data+info->hhea + 6); + if (lineGap) *lineGap = ttSHORT(info->data+info->hhea + 8); +} + +void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1) +{ + *x0 = ttSHORT(info->data + info->head + 36); + *y0 = ttSHORT(info->data + info->head + 38); + *x1 = ttSHORT(info->data + info->head + 40); + *y1 = ttSHORT(info->data + info->head + 42); +} + +float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float height) +{ + int fheight = ttSHORT(info->data + info->hhea + 4) - ttSHORT(info->data + info->hhea + 6); + return (float) height / fheight; +} + +float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels) +{ + int unitsPerEm = ttUSHORT(info->data + info->head + 18); + return pixels / unitsPerEm; +} + +void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v) +{ + STBTT_free(v, info->userdata); +} + +////////////////////////////////////////////////////////////////////////////// +// +// antialiasing software rasterizer +// + +void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1) +{ + int x0,y0,x1,y1; + if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) + x0=y0=x1=y1=0; // e.g. space character + // now move to integral bboxes (treating pixels as little squares, what pixels get touched)? + if (ix0) *ix0 = STBTT_ifloor(x0 * scale_x + shift_x); + if (iy0) *iy0 = -STBTT_iceil (y1 * scale_y + shift_y); + if (ix1) *ix1 = STBTT_iceil (x1 * scale_x + shift_x); + if (iy1) *iy1 = -STBTT_ifloor(y0 * scale_y + shift_y); +} +void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1) +{ + stbtt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1); +} + +void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1) +{ + stbtt_GetGlyphBitmapBoxSubpixel(font, stbtt_FindGlyphIndex(font,codepoint), scale_x, scale_y,shift_x,shift_y, ix0,iy0,ix1,iy1); +} + +void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1) +{ + stbtt_GetCodepointBitmapBoxSubpixel(font, codepoint, scale_x, scale_y,0.0f,0.0f, ix0,iy0,ix1,iy1); +} + +typedef struct stbtt__edge { + float x0,y0, x1,y1; + int invert; +} stbtt__edge; + +typedef struct stbtt__active_edge +{ + int x,dx; + float ey; + struct stbtt__active_edge *next; + int valid; +} stbtt__active_edge; + +#define FIXSHIFT 10 +#define FIX (1 << FIXSHIFT) +#define FIXMASK (FIX-1) + +static stbtt__active_edge *new_active(stbtt__edge *e, int off_x, float start_point, void *userdata) +{ + stbtt__active_edge *z = (stbtt__active_edge *) STBTT_malloc(sizeof(*z), userdata); // @TODO: make a pool of these!!! + float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); + STBTT_assert(e->y0 <= start_point); + if (!z) return z; + // round dx down to avoid going too far + if (dxdy < 0) + z->dx = -STBTT_ifloor(FIX * -dxdy); + else + z->dx = STBTT_ifloor(FIX * dxdy); + z->x = STBTT_ifloor(FIX * (e->x0 + dxdy * (start_point - e->y0))); + z->x -= off_x * FIX; + z->ey = e->y1; + z->next = 0; + z->valid = e->invert ? 1 : -1; + return z; +} + +// note: this routine clips fills that extend off the edges... ideally this +// wouldn't happen, but it could happen if the truetype glyph bounding boxes +// are wrong, or if the user supplies a too-small bitmap +static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__active_edge *e, int max_weight) +{ + // non-zero winding fill + int x0=0, w=0; + + while (e) { + if (w == 0) { + // if we're currently at zero, we need to record the edge start point + x0 = e->x; w += e->valid; + } else { + int x1 = e->x; w += e->valid; + // if we went to zero, we need to draw + if (w == 0) { + int i = x0 >> FIXSHIFT; + int j = x1 >> FIXSHIFT; + + if (i < len && j >= 0) { + if (i == j) { + // x0,x1 are the same pixel, so compute combined coverage + scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> FIXSHIFT); + } else { + if (i >= 0) // add antialiasing for x0 + scanline[i] = scanline[i] + (stbtt_uint8) (((FIX - (x0 & FIXMASK)) * max_weight) >> FIXSHIFT); + else + i = -1; // clip + + if (j < len) // add antialiasing for x1 + scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & FIXMASK) * max_weight) >> FIXSHIFT); + else + j = len; // clip + + for (++i; i < j; ++i) // fill pixels between x0 and x1 + scanline[i] = scanline[i] + (stbtt_uint8) max_weight; + } + } + } + } + + e = e->next; + } +} + +static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata) +{ + stbtt__active_edge *active = NULL; + int y,j=0; + int max_weight = (255 / vsubsample); // weight per vertical scanline + int s; // vertical subsample index + unsigned char scanline_data[512], *scanline; + + if (result->w > 512) + scanline = (unsigned char *) STBTT_malloc(result->w, userdata); + else + scanline = scanline_data; + + y = off_y * vsubsample; + e[n].y0 = (off_y + result->h) * (float) vsubsample + 1; + + while (j < result->h) { + STBTT_memset(scanline, 0, result->w); + for (s=0; s < vsubsample; ++s) { + // find center of pixel for this scanline + float scan_y = y + 0.5f; + stbtt__active_edge **step = &active; + + // update all active edges; + // remove all active edges that terminate before the center of this scanline + while (*step) { + stbtt__active_edge * z = *step; + if (z->ey <= scan_y) { + *step = z->next; // delete from list + STBTT_assert(z->valid); + z->valid = 0; + STBTT_free(z, userdata); + } else { + z->x += z->dx; // advance to position for current scanline + step = &((*step)->next); // advance through list + } + } + + // resort the list if needed + for(;;) { + int changed=0; + step = &active; + while (*step && (*step)->next) { + if ((*step)->x > (*step)->next->x) { + stbtt__active_edge *t = *step; + stbtt__active_edge *q = t->next; + + t->next = q->next; + q->next = t; + *step = q; + changed = 1; + } + step = &(*step)->next; + } + if (!changed) break; + } + + // insert all edges that start before the center of this scanline -- omit ones that also end on this scanline + while (e->y0 <= scan_y) { + if (e->y1 > scan_y) { + stbtt__active_edge *z = new_active(e, off_x, scan_y, userdata); + // find insertion point + if (active == NULL) + active = z; + else if (z->x < active->x) { + // insert at front + z->next = active; + active = z; + } else { + // find thing to insert AFTER + stbtt__active_edge *p = active; + while (p->next && p->next->x < z->x) + p = p->next; + // at this point, p->next->x is NOT < z->x + z->next = p->next; + p->next = z; + } + } + ++e; + } + + // now process all active edges in XOR fashion + if (active) + stbtt__fill_active_edges(scanline, result->w, active, max_weight); + + ++y; + } + STBTT_memcpy(result->pixels + j * result->stride, scanline, result->w); + ++j; + } + + while (active) { + stbtt__active_edge *z = active; + active = active->next; + STBTT_free(z, userdata); + } + + if (scanline != scanline_data) + STBTT_free(scanline, userdata); +} + +static int stbtt__edge_compare(const void *p, const void *q) +{ + stbtt__edge *a = (stbtt__edge *) p; + stbtt__edge *b = (stbtt__edge *) q; + + if (a->y0 < b->y0) return -1; + if (a->y0 > b->y0) return 1; + return 0; +} + +typedef struct +{ + float x,y; +} stbtt__point; + +static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcount, int windings, float scale_x, float scale_y, float shift_x, float shift_y, int off_x, int off_y, int invert, void *userdata) +{ + float y_scale_inv = invert ? -scale_y : scale_y; + stbtt__edge *e; + int n,i,j,k,m; + int vsubsample = result->h < 8 ? 15 : 5; + // vsubsample should divide 255 evenly; otherwise we won't reach full opacity + + // now we have to blow out the windings into explicit edge lists + n = 0; + for (i=0; i < windings; ++i) + n += wcount[i]; + + e = (stbtt__edge *) STBTT_malloc(sizeof(*e) * (n+1), userdata); // add an extra one as a sentinel + if (e == 0) return; + n = 0; + + m=0; + for (i=0; i < windings; ++i) { + stbtt__point *p = pts + m; + m += wcount[i]; + j = wcount[i]-1; + for (k=0; k < wcount[i]; j=k++) { + int a=k,b=j; + // skip the edge if horizontal + if (p[j].y == p[k].y) + continue; + // add edge from j to k to the list + e[n].invert = 0; + if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) { + e[n].invert = 1; + a=j,b=k; + } + e[n].x0 = p[a].x * scale_x + shift_x; + e[n].y0 = p[a].y * y_scale_inv * vsubsample + shift_y; + e[n].x1 = p[b].x * scale_x + shift_x; + e[n].y1 = p[b].y * y_scale_inv * vsubsample + shift_y; + ++n; + } + } + + // now sort the edges by their highest point (should snap to integer, and then by x) + STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare); + + // now, traverse the scanlines and find the intersections on each scanline, use xor winding rule + stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata); + + STBTT_free(e, userdata); +} + +static void stbtt__add_point(stbtt__point *points, int n, float x, float y) +{ + if (!points) return; // during first pass, it's unallocated + points[n].x = x; + points[n].y = y; +} + +// tesselate until threshhold p is happy... @TODO warped to compensate for non-linear stretching +static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float objspace_flatness_squared, int n) +{ + // midpoint + float mx = (x0 + 2*x1 + x2)/4; + float my = (y0 + 2*y1 + y2)/4; + // versus directly drawn line + float dx = (x0+x2)/2 - mx; + float dy = (y0+y2)/2 - my; + if (n > 16) // 65536 segments on one curve better be enough! + return 1; + if (dx*dx+dy*dy > objspace_flatness_squared) { // half-pixel error allowed... need to be smaller if AA + stbtt__tesselate_curve(points, num_points, x0,y0, (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1); + stbtt__tesselate_curve(points, num_points, mx,my, (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1); + } else { + stbtt__add_point(points, *num_points,x2,y2); + *num_points = *num_points+1; + } + return 1; +} + +// returns number of contours +stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata) +{ + stbtt__point *points=0; + int num_points=0; + + float objspace_flatness_squared = objspace_flatness * objspace_flatness; + int i,n=0,start=0, pass; + + // count how many "moves" there are to get the contour count + for (i=0; i < num_verts; ++i) + if (vertices[i].type == STBTT_vmove) + ++n; + + *num_contours = n; + if (n == 0) return 0; + + *contour_lengths = (int *) STBTT_malloc(sizeof(**contour_lengths) * n, userdata); + + if (*contour_lengths == 0) { + *num_contours = 0; + return 0; + } + + // make two passes through the points so we don't need to realloc + for (pass=0; pass < 2; ++pass) { + float x=0,y=0; + if (pass == 1) { + points = (stbtt__point *) STBTT_malloc(num_points * sizeof(points[0]), userdata); + if (points == NULL) goto error; + } + num_points = 0; + n= -1; + for (i=0; i < num_verts; ++i) { + switch (vertices[i].type) { + case STBTT_vmove: + // start the next contour + if (n >= 0) + (*contour_lengths)[n] = num_points - start; + ++n; + start = num_points; + + x = vertices[i].x, y = vertices[i].y; + stbtt__add_point(points, num_points++, x,y); + break; + case STBTT_vline: + x = vertices[i].x, y = vertices[i].y; + stbtt__add_point(points, num_points++, x, y); + break; + case STBTT_vcurve: + stbtt__tesselate_curve(points, &num_points, x,y, + vertices[i].cx, vertices[i].cy, + vertices[i].x, vertices[i].y, + objspace_flatness_squared, 0); + x = vertices[i].x, y = vertices[i].y; + break; + } + } + (*contour_lengths)[n] = num_points - start; + } + + return points; +error: + STBTT_free(points, userdata); + STBTT_free(*contour_lengths, userdata); + *contour_lengths = 0; + *num_contours = 0; + return NULL; +} + +void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata) +{ + float scale = scale_x > scale_y ? scale_y : scale_x; + int winding_count, *winding_lengths; + stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata); + if (windings) { + stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata); + STBTT_free(winding_lengths, userdata); + STBTT_free(windings, userdata); + } +} + +void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata) +{ + STBTT_free(bitmap, userdata); +} + +unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff) +{ + int ix0,iy0,ix1,iy1; + stbtt__bitmap gbm; + stbtt_vertex *vertices; + int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); + + if (scale_x == 0) scale_x = scale_y; + if (scale_y == 0) { + if (scale_x == 0) return NULL; + scale_y = scale_x; + } + + stbtt_GetGlyphBitmapBox(info, glyph, scale_x, scale_y, &ix0,&iy0,&ix1,&iy1); + + // now we get the size + gbm.w = (ix1 - ix0); + gbm.h = (iy1 - iy0); + gbm.pixels = NULL; // in case we error + + if (width ) *width = gbm.w; + if (height) *height = gbm.h; + if (xoff ) *xoff = ix0; + if (yoff ) *yoff = iy0; + + if (gbm.w && gbm.h) { + gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata); + if (gbm.pixels) { + gbm.stride = gbm.w; + + stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0, iy0, 1, info->userdata); + } + } + STBTT_free(vertices, info->userdata); + return gbm.pixels; +} + +unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff) +{ + return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y, 0.0f, 0.0f, glyph, width, height, xoff, yoff); +} + +void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph) +{ + int ix0,iy0; + stbtt_vertex *vertices; + int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); + stbtt__bitmap gbm; + + stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,0,0); + gbm.pixels = output; + gbm.w = out_w; + gbm.h = out_h; + gbm.stride = out_stride; + + if (gbm.w && gbm.h) + stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0,iy0, 1, info->userdata); + + STBTT_free(vertices, info->userdata); +} + +void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph) +{ + stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, glyph); +} + +unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff) +{ + return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff); +} + +void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint) +{ + stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, stbtt_FindGlyphIndex(info,codepoint)); +} + +unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff) +{ + return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f,0.0f, codepoint, width,height,xoff,yoff); +} + +void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint) +{ + stbtt_MakeCodepointBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, codepoint); +} + +////////////////////////////////////////////////////////////////////////////// +// +// bitmap baking +// +// This is SUPER-CRAPPY packing to keep source code small + +extern int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) + float pixel_height, // height of font in pixels + unsigned char *pixels, int pw, int ph, // bitmap to be filled in + int first_char, int num_chars, // characters to bake + stbtt_bakedchar *chardata) +{ + float scale; + int x,y,bottom_y, i; + stbtt_fontinfo f; + stbtt_InitFont(&f, data, offset); + STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels + x=y=1; + bottom_y = 1; + + scale = stbtt_ScaleForPixelHeight(&f, pixel_height); + + for (i=0; i < num_chars; ++i) { + int advance, lsb, x0,y0,x1,y1,gw,gh; + int g = stbtt_FindGlyphIndex(&f, first_char + i); + stbtt_GetGlyphHMetrics(&f, g, &advance, &lsb); + stbtt_GetGlyphBitmapBox(&f, g, scale,scale, &x0,&y0,&x1,&y1); + gw = x1-x0; + gh = y1-y0; + if (x + gw + 1 >= pw) + y = bottom_y, x = 1; // advance to next row + if (y + gh + 1 >= ph) // check if it fits vertically AFTER potentially moving to next row + return -i; + STBTT_assert(x+gw < pw); + STBTT_assert(y+gh < ph); + stbtt_MakeGlyphBitmap(&f, pixels+x+y*pw, gw,gh,pw, scale,scale, g); + chardata[i].x0 = (stbtt_int16) x; + chardata[i].y0 = (stbtt_int16) y; + chardata[i].x1 = (stbtt_int16) (x + gw); + chardata[i].y1 = (stbtt_int16) (y + gh); + chardata[i].xadvance = scale * advance; + chardata[i].xoff = (float) x0; + chardata[i].yoff = (float) y0; + x = x + gw + 2; + if (y+gh+2 > bottom_y) + bottom_y = y+gh+2; + } + return bottom_y; +} + +void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule) +{ + float d3d_bias = opengl_fillrule ? 0 : -0.5f; + float ipw = 1.0f / pw, iph = 1.0f / ph; + stbtt_bakedchar *b = chardata + char_index; + int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5); + int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5); + + q->x0 = round_x + d3d_bias; + q->y0 = round_y + d3d_bias; + q->x1 = round_x + b->x1 - b->x0 + d3d_bias; + q->y1 = round_y + b->y1 - b->y0 + d3d_bias; + + q->s0 = b->x0 * ipw; + q->t0 = b->y0 * iph; + q->s1 = b->x1 * ipw; + q->t1 = b->y1 * iph; + + *xpos += b->xadvance; +} + +////////////////////////////////////////////////////////////////////////////// +// +// font name matching -- recommended not to use this +// + +// check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string +static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(const stbtt_uint8 *s1, stbtt_int32 len1, const stbtt_uint8 *s2, stbtt_int32 len2) +{ + stbtt_int32 i=0; + + // convert utf16 to utf8 and compare the results while converting + while (len2) { + stbtt_uint16 ch = s2[0]*256 + s2[1]; + if (ch < 0x80) { + if (i >= len1) return -1; + if (s1[i++] != ch) return -1; + } else if (ch < 0x800) { + if (i+1 >= len1) return -1; + if (s1[i++] != 0xc0 + (ch >> 6)) return -1; + if (s1[i++] != 0x80 + (ch & 0x3f)) return -1; + } else if (ch >= 0xd800 && ch < 0xdc00) { + stbtt_uint32 c; + stbtt_uint16 ch2 = s2[2]*256 + s2[3]; + if (i+3 >= len1) return -1; + c = ((ch - 0xd800) << 10) + (ch2 - 0xdc00) + 0x10000; + if (s1[i++] != 0xf0 + (c >> 18)) return -1; + if (s1[i++] != 0x80 + ((c >> 12) & 0x3f)) return -1; + if (s1[i++] != 0x80 + ((c >> 6) & 0x3f)) return -1; + if (s1[i++] != 0x80 + ((c ) & 0x3f)) return -1; + s2 += 2; // plus another 2 below + len2 -= 2; + } else if (ch >= 0xdc00 && ch < 0xe000) { + return -1; + } else { + if (i+2 >= len1) return -1; + if (s1[i++] != 0xe0 + (ch >> 12)) return -1; + if (s1[i++] != 0x80 + ((ch >> 6) & 0x3f)) return -1; + if (s1[i++] != 0x80 + ((ch ) & 0x3f)) return -1; + } + s2 += 2; + len2 -= 2; + } + return i; +} + +int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2) +{ + return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((const stbtt_uint8*) s1, len1, (const stbtt_uint8*) s2, len2); +} + +// returns results in whatever encoding you request... but note that 2-byte encodings +// will be BIG-ENDIAN... use stbtt_CompareUTF8toUTF16_bigendian() to compare +const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID) +{ + stbtt_int32 i,count,stringOffset; + stbtt_uint8 *fc = font->data; + stbtt_uint32 offset = font->fontstart; + stbtt_uint32 nm = stbtt__find_table(fc, offset, "name"); + if (!nm) return NULL; + + count = ttUSHORT(fc+nm+2); + stringOffset = nm + ttUSHORT(fc+nm+4); + for (i=0; i < count; ++i) { + stbtt_uint32 loc = nm + 6 + 12 * i; + if (platformID == ttUSHORT(fc+loc+0) && encodingID == ttUSHORT(fc+loc+2) + && languageID == ttUSHORT(fc+loc+4) && nameID == ttUSHORT(fc+loc+6)) { + *length = ttUSHORT(fc+loc+8); + return (const char *) (fc+stringOffset+ttUSHORT(fc+loc+10)); + } + } + return NULL; +} + +static int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *name, stbtt_int32 nlen, stbtt_int32 target_id, stbtt_int32 next_id) +{ + stbtt_int32 i; + stbtt_int32 count = ttUSHORT(fc+nm+2); + stbtt_int32 stringOffset = nm + ttUSHORT(fc+nm+4); + + for (i=0; i < count; ++i) { + stbtt_uint32 loc = nm + 6 + 12 * i; + stbtt_int32 id = ttUSHORT(fc+loc+6); + if (id == target_id) { + // find the encoding + stbtt_int32 platform = ttUSHORT(fc+loc+0), encoding = ttUSHORT(fc+loc+2), language = ttUSHORT(fc+loc+4); + + // is this a Unicode encoding? + if (platform == 0 || (platform == 3 && encoding == 1) || (platform == 3 && encoding == 10)) { + stbtt_int32 slen = ttUSHORT(fc+loc+8), off = ttUSHORT(fc+loc+10); + + // check if there's a prefix match + stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc+stringOffset+off,slen); + if (matchlen >= 0) { + // check for target_id+1 immediately following, with same encoding & language + if (i+1 < count && ttUSHORT(fc+loc+12+6) == next_id && ttUSHORT(fc+loc+12) == platform && ttUSHORT(fc+loc+12+2) == encoding && ttUSHORT(fc+loc+12+4) == language) { + stbtt_int32 slen = ttUSHORT(fc+loc+12+8), off = ttUSHORT(fc+loc+12+10); + if (slen == 0) { + if (matchlen == nlen) + return 1; + } else if (matchlen < nlen && name[matchlen] == ' ') { + ++matchlen; + if (stbtt_CompareUTF8toUTF16_bigendian((char*) (name+matchlen), nlen-matchlen, (char*)(fc+stringOffset+off),slen)) + return 1; + } + } else { + // if nothing immediately following + if (matchlen == nlen) + return 1; + } + } + } + + // @TODO handle other encodings + } + } + return 0; +} + +static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *name, stbtt_int32 flags) +{ + stbtt_int32 nlen = (stbtt_int32) STBTT_strlen((char *) name); + stbtt_uint32 nm,hd; + if (!stbtt__isfont(fc+offset)) return 0; + + // check italics/bold/underline flags in macStyle... + if (flags) { + hd = stbtt__find_table(fc, offset, "head"); + if ((ttUSHORT(fc+hd+44) & 7) != (flags & 7)) return 0; + } + + nm = stbtt__find_table(fc, offset, "name"); + if (!nm) return 0; + + if (flags) { + // if we checked the macStyle flags, then just check the family and ignore the subfamily + if (stbtt__matchpair(fc, nm, name, nlen, 16, -1)) return 1; + if (stbtt__matchpair(fc, nm, name, nlen, 1, -1)) return 1; + if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1; + } else { + if (stbtt__matchpair(fc, nm, name, nlen, 16, 17)) return 1; + if (stbtt__matchpair(fc, nm, name, nlen, 1, 2)) return 1; + if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1; + } + + return 0; +} + +int stbtt_FindMatchingFont(const unsigned char *font_collection, const char *name_utf8, stbtt_int32 flags) +{ + stbtt_int32 i; + for (i=0;;++i) { + stbtt_int32 off = stbtt_GetFontOffsetForIndex(font_collection, i); + if (off < 0) return off; + if (stbtt__matches((stbtt_uint8 *) font_collection, off, (stbtt_uint8*) name_utf8, flags)) + return off; + } +} + +#endif // STB_TRUETYPE_IMPLEMENTATION diff --git a/README.md b/README.md index 3fa6f510..01e39b6e 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -bgfx +bgfx {#mainpage} ==== https://github.com/bkaradzic/bgfx @@ -43,7 +43,7 @@ Premake 4.4 beta4 [http://industriousone.com/premake/download](http://industriousone.com/premake/download) GNU make and CoreUtils -Windows users download GNU make utility from: +Windows users download GNU utilities from: [http://gnuwin32.sourceforge.net/packages/make.htm](http://gnuwin32.sourceforge.net/packages/make.htm) [http://gnuwin32.sourceforge.net/packages/coreutils.htm](http://gnuwin32.sourceforge.net/packages/coreutils.htm) @@ -172,7 +172,7 @@ Internals --------- bgfx is using sort-based draw call bucketing. This means that submission order -doesn't necessarily matches the rendering order, but on the low-level they +doesn't necessarily match the rendering order, but on the low-level they will be sorted and ordered correctly. On the high level this allows more optimal way of submitting draw calls for all passes at one place, and on the low-level this allows better optimization of rendering order. This sometimes @@ -299,6 +299,9 @@ Bunny Uffizi [Light Probe Image Gallery ](http://www.pauldebevec.com/Probes/) +Droid Sans +[http://www.fontsquirrel.com/license/Droid-Sans](http://www.fontsquirrel.com/license/Droid-Sans) + Contributors ------------ diff --git a/examples/00-helloworld/helloworld.cpp b/examples/00-helloworld/helloworld.cpp index c210a341..238a7be8 100644 --- a/examples/00-helloworld/helloworld.cpp +++ b/examples/00-helloworld/helloworld.cpp @@ -14,7 +14,7 @@ int _main_(int /*_argc*/, char** /*_argv*/) uint32_t width = 1280; uint32_t height = 720; uint32_t debug = BGFX_DEBUG_TEXT; - uint32_t reset = BGFX_RESET_NONE; + uint32_t reset = BGFX_RESET_VSYNC; bgfx::init(); bgfx::reset(width, height); diff --git a/examples/01-cubes/cubes.cpp b/examples/01-cubes/cubes.cpp index 2d633106..a50318d1 100644 --- a/examples/01-cubes/cubes.cpp +++ b/examples/01-cubes/cubes.cpp @@ -99,7 +99,7 @@ int _main_(int /*_argc*/, char** /*_argv*/) uint32_t width = 1280; uint32_t height = 720; uint32_t debug = BGFX_DEBUG_TEXT; - uint32_t reset = BGFX_RESET_NONE; + uint32_t reset = BGFX_RESET_VSYNC; bgfx::init(); bgfx::reset(width, height); @@ -183,6 +183,8 @@ int _main_(int /*_argc*/, char** /*_argv*/) // Set view and projection matrix for view 0. bgfx::setViewTransform(0, view, proj); + int64_t timeOffset = bx::getHPCounter(); + while (!processEvents(width, height, debug, reset) ) { // Set view 0 default viewport. @@ -199,14 +201,14 @@ int _main_(int /*_argc*/, char** /*_argv*/) const double freq = double(bx::getHPFrequency() ); const double toMs = 1000.0/freq; + float time = (float)( (now-timeOffset)/double(bx::getHPFrequency() ) ); + // Use debug font to print information about this example. bgfx::dbgTextClear(); bgfx::dbgTextPrintf(0, 1, 0x4f, "bgfx/examples/01-cube"); bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: Rendering simple static mesh."); bgfx::dbgTextPrintf(0, 3, 0x0f, "Frame: % 7.3f[ms]", double(frameTime)*toMs); - float time = (float)(bx::getHPCounter()/double(bx::getHPFrequency() ) ); - // Submit 11x11 cubes. for (uint32_t yy = 0; yy < 11; ++yy) { diff --git a/examples/02-metaballs/metaballs.cpp b/examples/02-metaballs/metaballs.cpp index 60dc8a94..325a51f1 100644 --- a/examples/02-metaballs/metaballs.cpp +++ b/examples/02-metaballs/metaballs.cpp @@ -499,7 +499,7 @@ int _main_(int /*_argc*/, char** /*_argv*/) uint32_t width = 1280; uint32_t height = 720; uint32_t debug = BGFX_DEBUG_TEXT; - uint32_t reset = BGFX_RESET_NONE; + uint32_t reset = BGFX_RESET_VSYNC; bgfx::init(); bgfx::reset(width, height); @@ -572,6 +572,8 @@ int _main_(int /*_argc*/, char** /*_argv*/) const uint32_t zpitch = DIMS*DIMS; const float invdim = 1.0f/float(DIMS-1); + int64_t timeOffset = bx::getHPCounter(); + while (!processEvents(width, height, debug, reset) ) { // Set view 0 default viewport. @@ -587,6 +589,7 @@ int _main_(int /*_argc*/, char** /*_argv*/) last = now; const double freq = double(bx::getHPFrequency() ); const double toMs = 1000.0/freq; + float time = (float)( (now - timeOffset)/double(bx::getHPFrequency() ) ); // Use debug font to print information about this example. bgfx::dbgTextClear(); @@ -604,8 +607,6 @@ int _main_(int /*_argc*/, char** /*_argv*/) // Set view and projection matrix for view 0. bgfx::setViewTransform(0, view, proj); - float time = (float)(bx::getHPCounter()/double(bx::getHPFrequency() ) ); - // Stats. uint32_t numVertices = 0; int64_t profUpdate = 0; diff --git a/examples/03-raymarch/raymarch.cpp b/examples/03-raymarch/raymarch.cpp index e1b1c842..3731b540 100644 --- a/examples/03-raymarch/raymarch.cpp +++ b/examples/03-raymarch/raymarch.cpp @@ -178,7 +178,7 @@ int _main_(int /*_argc*/, char** /*_argv*/) uint32_t width = 1280; uint32_t height = 720; uint32_t debug = BGFX_DEBUG_TEXT; - uint32_t reset = BGFX_RESET_NONE; + uint32_t reset = BGFX_RESET_VSYNC; bgfx::init(); bgfx::reset(width, height); @@ -232,6 +232,8 @@ int _main_(int /*_argc*/, char** /*_argv*/) bgfx::ProgramHandle raymarching = loadProgram("vs_raymarching", "fs_raymarching"); + int64_t timeOffset = bx::getHPCounter(); + while (!processEvents(width, height, debug, reset) ) { // Set view 0 default viewport. @@ -274,7 +276,7 @@ int _main_(int /*_argc*/, char** /*_argv*/) // Set view and projection matrix for view 0. bgfx::setViewTransform(1, NULL, ortho); - float time = (float)(bx::getHPCounter()/double(bx::getHPFrequency() ) ); + float time = (float)( (bx::getHPCounter()-timeOffset)/double(bx::getHPFrequency() ) ); float vp[16]; mtxMul(vp, view, proj); diff --git a/examples/04-mesh/mesh.cpp b/examples/04-mesh/mesh.cpp index 37b77bd9..2e9418f9 100644 --- a/examples/04-mesh/mesh.cpp +++ b/examples/04-mesh/mesh.cpp @@ -283,7 +283,7 @@ int _main_(int /*_argc*/, char** /*_argv*/) uint32_t width = 1280; uint32_t height = 720; uint32_t debug = BGFX_DEBUG_TEXT; - uint32_t reset = BGFX_RESET_NONE; + uint32_t reset = BGFX_RESET_VSYNC; bgfx::init(); bgfx::reset(width, height); @@ -331,6 +331,8 @@ int _main_(int /*_argc*/, char** /*_argv*/) Mesh mesh; mesh.load("meshes/bunny.bin"); + int64_t timeOffset = bx::getHPCounter(); + while (!processEvents(width, height, debug, reset) ) { // Set view 0 default viewport. @@ -346,7 +348,7 @@ int _main_(int /*_argc*/, char** /*_argv*/) last = now; const double freq = double(bx::getHPFrequency() ); const double toMs = 1000.0/freq; - float time = (float)(bx::getHPCounter()/double(bx::getHPFrequency() ) ); + float time = (float)( (bx::getHPCounter()-timeOffset)/double(bx::getHPFrequency() ) ); bgfx::setUniform(u_time, &time); // Use debug font to print information about this example. diff --git a/examples/05-instancing/instancing.cpp b/examples/05-instancing/instancing.cpp index 379cafbe..39b7bb74 100644 --- a/examples/05-instancing/instancing.cpp +++ b/examples/05-instancing/instancing.cpp @@ -99,7 +99,7 @@ int _main_(int /*_argc*/, char** /*_argv*/) uint32_t width = 1280; uint32_t height = 720; uint32_t debug = BGFX_DEBUG_TEXT; - uint32_t reset = BGFX_RESET_NONE; + uint32_t reset = BGFX_RESET_VSYNC; bgfx::init(); bgfx::reset(width, height); @@ -172,6 +172,8 @@ int _main_(int /*_argc*/, char** /*_argv*/) bgfx::destroyVertexShader(vsh); bgfx::destroyFragmentShader(fsh); + int64_t timeOffset = bx::getHPCounter(); + while (!processEvents(width, height, debug, reset) ) { // Set view 0 default viewport. @@ -187,6 +189,7 @@ int _main_(int /*_argc*/, char** /*_argv*/) last = now; const double freq = double(bx::getHPFrequency() ); const double toMs = 1000.0/freq; + float time = (float)( (now - timeOffset)/double(bx::getHPFrequency() ) ); // Use debug font to print information about this example. bgfx::dbgTextClear(); @@ -205,8 +208,6 @@ int _main_(int /*_argc*/, char** /*_argv*/) // Set view and projection matrix for view 0. bgfx::setViewTransform(0, view, proj); - float time = (float)(bx::getHPCounter()/double(bx::getHPFrequency() ) ); - const uint16_t instanceStride = 80; const bgfx::InstanceDataBuffer* idb = bgfx::allocInstanceDataBuffer(121, instanceStride); if (NULL != idb) diff --git a/examples/06-bump/bump.cpp b/examples/06-bump/bump.cpp index 1e5175f3..f3fe9fa3 100644 --- a/examples/06-bump/bump.cpp +++ b/examples/06-bump/bump.cpp @@ -255,7 +255,7 @@ int _main_(int /*_argc*/, char** /*_argv*/) uint32_t width = 1280; uint32_t height = 720; uint32_t debug = BGFX_DEBUG_TEXT; - uint32_t reset = BGFX_RESET_NONE; + uint32_t reset = BGFX_RESET_VSYNC; bgfx::init(); bgfx::reset(width, height); @@ -348,6 +348,8 @@ int _main_(int /*_argc*/, char** /*_argv*/) mem = loadTexture("fieldstone-n.dds"); bgfx::TextureHandle textureNormal = bgfx::createTexture(mem); + int64_t timeOffset = bx::getHPCounter(); + while (!processEvents(width, height, debug, reset) ) { // Set view 0 default viewport. @@ -364,7 +366,7 @@ int _main_(int /*_argc*/, char** /*_argv*/) const double freq = double(bx::getHPFrequency() ); const double toMs = 1000.0/freq; - float time = (float)(now/freq); + float time = (float)( (now-timeOffset)/freq); // Use debug font to print information about this example. bgfx::dbgTextClear(); diff --git a/examples/08-update/update.cpp b/examples/08-update/update.cpp index c979bbd7..33e33813 100644 --- a/examples/08-update/update.cpp +++ b/examples/08-update/update.cpp @@ -130,7 +130,7 @@ int _main_(int /*_argc*/, char** /*_argv*/) uint32_t width = 1280; uint32_t height = 720; uint32_t debug = BGFX_DEBUG_TEXT; - uint32_t reset = BGFX_RESET_NONE; + uint32_t reset = BGFX_RESET_VSYNC; bgfx::init(); bgfx::reset(width, height); @@ -228,6 +228,8 @@ int _main_(int /*_argc*/, char** /*_argv*/) uint32_t miss = 0; std::list quads; + int64_t timeOffset = bx::getHPCounter(); + while (!processEvents(width, height, debug, reset) ) { // Set view 0 default viewport. @@ -243,6 +245,7 @@ int _main_(int /*_argc*/, char** /*_argv*/) last = now; const int64_t freq = bx::getHPFrequency(); const double toMs = 1000.0/double(freq); + float time = (float)( (now - timeOffset)/double(bx::getHPFrequency() ) ); // Use debug font to print information about this example. bgfx::dbgTextClear(); @@ -310,8 +313,6 @@ int _main_(int /*_argc*/, char** /*_argv*/) // Set view and projection matrix for view 0. bgfx::setViewTransform(0, view, proj); - float time = (float)(bx::getHPCounter()/double(bx::getHPFrequency() ) ); - float mtx[16]; mtxRotateXY(mtx, time, time*0.37f); diff --git a/examples/09-hdr/hdr.cpp b/examples/09-hdr/hdr.cpp index 04cadf4e..55ee14e2 100644 --- a/examples/09-hdr/hdr.cpp +++ b/examples/09-hdr/hdr.cpp @@ -12,8 +12,8 @@ #include "../common/dbg.h" #include "../common/math.h" #include "../common/processevents.h" +#include "../common/imgui/imgui.h" -#include #include #include #include @@ -257,12 +257,12 @@ struct Mesh // Set render states. bgfx::setState(0 - |BGFX_STATE_RGB_WRITE - |BGFX_STATE_ALPHA_WRITE - |BGFX_STATE_DEPTH_WRITE - |BGFX_STATE_DEPTH_TEST_LESS - |BGFX_STATE_CULL_CCW - |BGFX_STATE_MSAA + | BGFX_STATE_RGB_WRITE + | BGFX_STATE_ALPHA_WRITE + | BGFX_STATE_DEPTH_WRITE + | BGFX_STATE_DEPTH_TEST_LESS + | BGFX_STATE_CULL_CCW + | BGFX_STATE_MSAA ); // Submit primitive for rendering to view 0. @@ -410,7 +410,7 @@ int _main_(int /*_argc*/, char** /*_argv*/) uint32_t width = 1280; uint32_t height = 720; uint32_t debug = BGFX_DEBUG_TEXT; - uint32_t reset = BGFX_RESET_NONE; + uint32_t reset = BGFX_RESET_VSYNC; bgfx::init(); bgfx::reset(width, height); @@ -493,10 +493,32 @@ int _main_(int /*_argc*/, char** /*_argv*/) bgfx::RenderTargetHandle blur; blur = bgfx::createRenderTarget(width/8, height/8, BGFX_RENDER_TARGET_COLOR_RGBA8); + FILE* file = fopen("font/droidsans.ttf", "rb"); + uint32_t size = (uint32_t)fsize(file); + void* data = malloc(size); + size_t ignore = fread(data, 1, size, file); + BX_UNUSED(ignore); + fclose(file); + + imguiCreate(data, size); + + free(data); + + float speed = 0.37f; + float middleGray = 0.18f; + float white = 1.1f; + float treshold = 1.5f; + + int32_t scrollArea = 0; + uint32_t oldWidth = 0; uint32_t oldHeight = 0; - while (!processEvents(width, height, debug, reset) ) + MouseState mouseState; + + float time = 0.0f; + + while (!processEvents(width, height, debug, reset, &mouseState) ) { if (oldWidth != width || oldHeight != height) @@ -513,6 +535,28 @@ int _main_(int /*_argc*/, char** /*_argv*/) blur = bgfx::createRenderTarget(width/8, height/8, BGFX_RENDER_TARGET_COLOR_RGBA8); } + imguiBeginFrame(mouseState.m_mx + , mouseState.m_my + , (mouseState.m_buttons[entry::MouseButton::Left ] ? IMGUI_MBUT_LEFT : 0) + | (mouseState.m_buttons[entry::MouseButton::Right ] ? IMGUI_MBUT_RIGHT : 0) + , 0 + , width + , height + ); + + imguiBeginScrollArea("Settings", width - width / 5 - 10, 10, width / 5, height / 3, &scrollArea); + imguiSeparatorLine(); + + imguiSlider("Speed", &speed, 0.0f, 1.0f, 0.01f); + imguiSeparator(); + + imguiSlider("Middle gray", &middleGray, 0.1f, 1.0f, 0.01f); + imguiSlider("White point", &white, 0.1f, 2.0f, 0.01f); + imguiSlider("Treshold", &treshold, 0.1f, 2.0f, 0.01f); + + imguiEndScrollArea(); + imguiEndFrame(); + // This dummy draw call is here to make sure that view 0 is cleared // if no other draw calls are submitted to view 0. bgfx::submit(0); @@ -524,7 +568,7 @@ int _main_(int /*_argc*/, char** /*_argv*/) const double freq = double(bx::getHPFrequency() ); const double toMs = 1000.0/freq; - float time = (float)(now/freq); + time += (float)(frameTime*speed/freq); bgfx::setUniform(u_time, &time); @@ -588,7 +632,7 @@ int _main_(int /*_argc*/, char** /*_argv*/) float mtx[16]; mtxRotateXY(mtx , 0.0f - , time*0.37f + , time ); float temp[4]; @@ -653,7 +697,7 @@ int _main_(int /*_argc*/, char** /*_argv*/) screenSpaceQuad(1.0f, 1.0f, s_flipV); bgfx::submit(6); - float tonemap[4] = { 0.18f, square(1.1f), 1.5f, 0.0f }; + float tonemap[4] = { middleGray, square(white), treshold, 0.0f }; bgfx::setUniform(u_tonemap, tonemap); // Bright pass treshold is tonemap[3]. @@ -686,6 +730,8 @@ int _main_(int /*_argc*/, char** /*_argv*/) bgfx::frame(); } + imguiDestroy(); + // Cleanup. mesh.unload(); diff --git a/examples/common/dbg.cpp b/examples/common/dbg.cpp index 6e671e28..bae0edb0 100755 --- a/examples/common/dbg.cpp +++ b/examples/common/dbg.cpp @@ -12,24 +12,7 @@ #include "dbg.h" #include - -#if BX_PLATFORM_ANDROID -# include -#elif BX_PLATFORM_WINDOWS || BX_PLATFORM_XBOX360 -extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA(const char* _str); -#endif // BX_PLATFORM_WINDOWS - -void dbgOutput(const char* _out) -{ -#if BX_PLATFORM_ANDROID - __android_log_write(ANDROID_LOG_DEBUG, "", _out); -#elif BX_PLATFORM_WINDOWS || BX_PLATFORM_XBOX360 - OutputDebugStringA(_out); -#elif BX_PLATFORM_NACL || BX_PLATFORM_LINUX || BX_PLATFORM_OSX - fputs(_out, stderr); - fflush(stderr); -#endif // BX_PLATFORM_ -} +#include void dbgPrintfVargs(const char* _format, va_list _argList) { @@ -42,7 +25,7 @@ void dbgPrintfVargs(const char* _format, va_list _argList) len = bx::vsnprintf(out, len, _format, _argList); } out[len] = '\0'; - dbgOutput(out); + bx::debugOutput(out); } void dbgPrintf(const char* _format, ...) diff --git a/examples/common/dbg.h b/examples/common/dbg.h index b4c8e6be..370cf663 100644 --- a/examples/common/dbg.h +++ b/examples/common/dbg.h @@ -7,6 +7,7 @@ #define __DBG_H__ #include // va_list +#include #define DBG_STRINGIZE(_x) DBG_STRINGIZE_(_x) #define DBG_STRINGIZE_(_x) #_x diff --git a/examples/common/imgui/fs_imgui_color.bin.h b/examples/common/imgui/fs_imgui_color.bin.h new file mode 100644 index 00000000..3d61a2c3 --- /dev/null +++ b/examples/common/imgui/fs_imgui_color.bin.h @@ -0,0 +1,58 @@ +static const uint8_t fs_imgui_color_dx9[137] = +{ + 0x46, 0x53, 0x48, 0x01, 0xa4, 0x8b, 0xef, 0x49, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x03, 0xff, 0xff, // FSH....I..|..... + 0xfe, 0xff, 0x16, 0x00, 0x43, 0x54, 0x41, 0x42, 0x1c, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, // ....CTAB....#... + 0x00, 0x03, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, // ................ + 0x1c, 0x00, 0x00, 0x00, 0x70, 0x73, 0x5f, 0x33, 0x5f, 0x30, 0x00, 0x4d, 0x69, 0x63, 0x72, 0x6f, // ....ps_3_0.Micro + 0x73, 0x6f, 0x66, 0x74, 0x20, 0x28, 0x52, 0x29, 0x20, 0x48, 0x4c, 0x53, 0x4c, 0x20, 0x53, 0x68, // soft (R) HLSL Sh + 0x61, 0x64, 0x65, 0x72, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x39, 0x2e, // ader Compiler 9. + 0x32, 0x39, 0x2e, 0x39, 0x35, 0x32, 0x2e, 0x33, 0x31, 0x31, 0x31, 0x00, 0x1f, 0x00, 0x00, 0x02, // 29.952.3111..... + 0x0a, 0x00, 0x00, 0x80, 0x00, 0x00, 0x0f, 0x90, 0x01, 0x00, 0x00, 0x02, 0x00, 0x08, 0x0f, 0x80, // ................ + 0x00, 0x00, 0xe4, 0x90, 0xff, 0xff, 0x00, 0x00, 0x00, // ......... +}; +static const uint8_t fs_imgui_color_dx11[494] = +{ + 0x46, 0x53, 0x48, 0x01, 0xa4, 0x8b, 0xef, 0x49, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, // FSH....I........ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x01, 0x44, 0x58, 0x42, // .............DXB + 0x43, 0xa9, 0x98, 0xd1, 0xdb, 0x4a, 0xa2, 0x9c, 0xfe, 0x9c, 0xf1, 0xe4, 0xd0, 0x2c, 0xa5, 0xd6, // C....J.......,.. + 0xb6, 0x01, 0x00, 0x00, 0x00, 0xd0, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, // .............4.. + 0x00, 0x8c, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, 0x54, 0x01, 0x00, // .............T.. + 0x00, 0x52, 0x44, 0x45, 0x46, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // .RDEFP.......... + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x04, 0xff, 0xff, 0x00, 0x91, 0x00, // ................ + 0x00, 0x1c, 0x00, 0x00, 0x00, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x28, // .....Microsoft ( + 0x52, 0x29, 0x20, 0x48, 0x4c, 0x53, 0x4c, 0x20, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x43, // R) HLSL Shader C + 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x39, 0x2e, 0x32, 0x39, 0x2e, 0x39, 0x35, 0x32, // ompiler 9.29.952 + 0x2e, 0x33, 0x31, 0x31, 0x31, 0x00, 0xab, 0xab, 0xab, 0x49, 0x53, 0x47, 0x4e, 0x4c, 0x00, 0x00, // .3111....ISGNL.. + 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // .........8...... + 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, // ................ + 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, // .D.............. + 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x53, 0x56, 0x5f, 0x50, 0x4f, 0x53, 0x49, // .........SV_POSI + 0x54, 0x49, 0x4f, 0x4e, 0x00, 0x43, 0x4f, 0x4c, 0x4f, 0x52, 0x00, 0xab, 0xab, 0x4f, 0x53, 0x47, // TION.COLOR...OSG + 0x4e, 0x2c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, // N,........... .. + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x0f, 0x00, 0x00, 0x00, 0x53, 0x56, 0x5f, 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x00, 0xab, // .....SV_TARGET.. + 0xab, 0x53, 0x48, 0x44, 0x52, 0x38, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, // .SHDR8...@...... + 0x00, 0x62, 0x10, 0x00, 0x03, 0xf2, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, // .b...........e.. + 0x03, 0xf2, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0xf2, 0x20, 0x10, // .. ......6.... . + 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x1e, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, // .....F.......>.. + 0x01, 0x53, 0x54, 0x41, 0x54, 0x74, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // .STATt.......... + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // .............. +}; +static const uint8_t fs_imgui_color_glsl[130] = +{ + 0x46, 0x53, 0x48, 0x01, 0xa4, 0x8b, 0xef, 0x49, 0x23, 0x69, 0x66, 0x64, 0x65, 0x66, 0x20, 0x47, // FSH....I#ifdef G + 0x4c, 0x5f, 0x45, 0x53, 0x0a, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x68, // L_ES.precision h + 0x69, 0x67, 0x68, 0x70, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x3b, 0x0a, 0x23, 0x65, 0x6e, 0x64, // ighp float;.#end + 0x69, 0x66, 0x20, 0x2f, 0x2f, 0x20, 0x47, 0x4c, 0x5f, 0x45, 0x53, 0x0a, 0x0a, 0x76, 0x61, 0x72, // if // GL_ES..var + 0x79, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x76, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, // ying vec4 v_colo + 0x72, 0x30, 0x3b, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x20, 0x28, 0x29, // r0;.void main () + 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x67, 0x6c, 0x5f, 0x46, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6c, 0x6f, // .{. gl_FragColo + 0x72, 0x20, 0x3d, 0x20, 0x76, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x30, 0x3b, 0x0a, 0x7d, 0x0a, // r = v_color0;.}. + 0x0a, 0x00, // .. +}; diff --git a/examples/common/imgui/fs_imgui_color.sc b/examples/common/imgui/fs_imgui_color.sc new file mode 100644 index 00000000..7796aa19 --- /dev/null +++ b/examples/common/imgui/fs_imgui_color.sc @@ -0,0 +1,13 @@ +$input v_color0 + +/* + * Copyright 2011-2013 Branimir Karadzic. All rights reserved. + * License: http://www.opensource.org/licenses/BSD-2-Clause + */ + +#include + +void main() +{ + gl_FragColor = v_color0; +} diff --git a/examples/common/imgui/fs_imgui_texture.bin.h b/examples/common/imgui/fs_imgui_texture.bin.h new file mode 100644 index 00000000..5baae37c --- /dev/null +++ b/examples/common/imgui/fs_imgui_texture.bin.h @@ -0,0 +1,91 @@ +static const uint8_t fs_imgui_texture_dx9[241] = +{ + 0x46, 0x53, 0x48, 0x01, 0x01, 0x83, 0xf2, 0xe1, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x03, 0xff, 0xff, // FSH............. + 0xfe, 0xff, 0x22, 0x00, 0x43, 0x54, 0x41, 0x42, 0x1c, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, // ..".CTAB....S... + 0x00, 0x03, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, // ................ + 0x4c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, // L...0........... + 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x5f, 0x74, 0x65, 0x78, 0x43, 0x6f, 0x6c, // <.......u_texCol + 0x6f, 0x72, 0x00, 0xab, 0x04, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, // or.............. + 0x00, 0x00, 0x00, 0x00, 0x70, 0x73, 0x5f, 0x33, 0x5f, 0x30, 0x00, 0x4d, 0x69, 0x63, 0x72, 0x6f, // ....ps_3_0.Micro + 0x73, 0x6f, 0x66, 0x74, 0x20, 0x28, 0x52, 0x29, 0x20, 0x48, 0x4c, 0x53, 0x4c, 0x20, 0x53, 0x68, // soft (R) HLSL Sh + 0x61, 0x64, 0x65, 0x72, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x39, 0x2e, // ader Compiler 9. + 0x32, 0x39, 0x2e, 0x39, 0x35, 0x32, 0x2e, 0x33, 0x31, 0x31, 0x31, 0x00, 0x1f, 0x00, 0x00, 0x02, // 29.952.3111..... + 0x0a, 0x00, 0x00, 0x80, 0x00, 0x00, 0x0f, 0x90, 0x1f, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x80, // ................ + 0x01, 0x00, 0x03, 0x90, 0x1f, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x90, 0x00, 0x08, 0x0f, 0xa0, // ................ + 0x42, 0x00, 0x00, 0x03, 0x00, 0x00, 0x0f, 0x80, 0x01, 0x00, 0xe4, 0x90, 0x00, 0x08, 0xe4, 0xa0, // B............... + 0x05, 0x00, 0x00, 0x03, 0x00, 0x08, 0x08, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0xff, 0x90, // ................ + 0x01, 0x00, 0x00, 0x02, 0x00, 0x08, 0x07, 0x80, 0x00, 0x00, 0xe4, 0x90, 0xff, 0xff, 0x00, 0x00, // ................ + 0x00, // . +}; +static const uint8_t fs_imgui_texture_dx11[738] = +{ + 0x46, 0x53, 0x48, 0x01, 0x01, 0x83, 0xf2, 0xe1, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, // FSH............. + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc4, 0x02, 0x44, 0x58, 0x42, // .............DXB + 0x43, 0x8f, 0x77, 0x55, 0xdc, 0xbb, 0x5d, 0x37, 0x2c, 0xed, 0xde, 0x24, 0x6d, 0xe4, 0xbc, 0xf1, // C.wU..]7,..$m... + 0x76, 0x01, 0x00, 0x00, 0x00, 0xc4, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, // v............4.. + 0x00, 0xf0, 0x00, 0x00, 0x00, 0x64, 0x01, 0x00, 0x00, 0x98, 0x01, 0x00, 0x00, 0x48, 0x02, 0x00, // .....d.......H.. + 0x00, 0x52, 0x44, 0x45, 0x46, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // .RDEF........... + 0x00, 0x02, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x04, 0xff, 0xff, 0x00, 0x91, 0x00, // ................ + 0x00, 0x80, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, // ................ + 0x00, 0x01, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, // .....n.......... + 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, // ................ + 0x00, 0x0d, 0x00, 0x00, 0x00, 0x75, 0x5f, 0x74, 0x65, 0x78, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, // .....u_texColorS + 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x00, 0x75, 0x5f, 0x74, 0x65, 0x78, 0x43, 0x6f, 0x6c, 0x6f, // ampler.u_texColo + 0x72, 0x54, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x00, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, // rTexture.Microso + 0x66, 0x74, 0x20, 0x28, 0x52, 0x29, 0x20, 0x48, 0x4c, 0x53, 0x4c, 0x20, 0x53, 0x68, 0x61, 0x64, // ft (R) HLSL Shad + 0x65, 0x72, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x39, 0x2e, 0x32, 0x39, // er Compiler 9.29 + 0x2e, 0x39, 0x35, 0x32, 0x2e, 0x33, 0x31, 0x31, 0x31, 0x00, 0xab, 0xab, 0xab, 0x49, 0x53, 0x47, // .952.3111....ISG + 0x4e, 0x6c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, // Nl...........P.. + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x0f, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x62, 0x00, 0x00, // .............b.. + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, // ................ + 0x00, 0x03, 0x03, 0x00, 0x00, 0x53, 0x56, 0x5f, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, // .....SV_POSITION + 0x00, 0x43, 0x4f, 0x4c, 0x4f, 0x52, 0x00, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, // .COLOR.TEXCOORD. + 0xab, 0x4f, 0x53, 0x47, 0x4e, 0x2c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, // .OSGN,.......... + 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, // . .............. + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x53, 0x56, 0x5f, 0x54, 0x41, 0x52, 0x47, // .........SV_TARG + 0x45, 0x54, 0x00, 0xab, 0xab, 0x53, 0x48, 0x44, 0x52, 0xa8, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, // ET...SHDR....@.. + 0x00, 0x2a, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x03, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, // .*...Z....`..... + 0x00, 0x58, 0x18, 0x00, 0x04, 0x00, 0x70, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, // .X....p......UU. + 0x00, 0x62, 0x10, 0x00, 0x03, 0xf2, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x62, 0x10, 0x00, // .b...........b.. + 0x03, 0x32, 0x10, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x03, 0xf2, 0x20, 0x10, // .2.......e.... . + 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, // .....h.......E.. + 0x09, 0xf2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x10, 0x10, 0x00, 0x02, 0x00, 0x00, // .........F...... + 0x00, 0x46, 0x7e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, // .F~.......`..... + 0x00, 0x38, 0x00, 0x00, 0x07, 0x82, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, // .8.... ......... + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, // .....:.......6.. + 0x05, 0x72, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x12, 0x10, 0x00, 0x01, 0x00, 0x00, // .r ......F...... + 0x00, 0x3e, 0x00, 0x00, 0x01, 0x53, 0x54, 0x41, 0x54, 0x74, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, // .>...STATt...... + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, // ................ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, // .. +}; +static const uint8_t fs_imgui_texture_glsl[303] = +{ + 0x46, 0x53, 0x48, 0x01, 0x01, 0x83, 0xf2, 0xe1, 0x23, 0x69, 0x66, 0x64, 0x65, 0x66, 0x20, 0x47, // FSH.....#ifdef G + 0x4c, 0x5f, 0x45, 0x53, 0x0a, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x68, // L_ES.precision h + 0x69, 0x67, 0x68, 0x70, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x3b, 0x0a, 0x23, 0x65, 0x6e, 0x64, // ighp float;.#end + 0x69, 0x66, 0x20, 0x2f, 0x2f, 0x20, 0x47, 0x4c, 0x5f, 0x45, 0x53, 0x0a, 0x0a, 0x75, 0x6e, 0x69, // if // GL_ES..uni + 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x32, 0x44, 0x20, 0x75, // form sampler2D u + 0x5f, 0x74, 0x65, 0x78, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x3b, 0x0a, 0x76, 0x61, 0x72, 0x79, 0x69, // _texColor;.varyi + 0x6e, 0x67, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, 0x76, 0x5f, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, // ng vec2 v_texcoo + 0x72, 0x64, 0x30, 0x3b, 0x0a, 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, 0x63, // rd0;.varying vec + 0x34, 0x20, 0x76, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x30, 0x3b, 0x0a, 0x76, 0x6f, 0x69, 0x64, // 4 v_color0;.void + 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x20, 0x28, 0x29, 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x76, 0x65, 0x63, // main ().{. vec + 0x34, 0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x31, 0x3b, 0x0a, 0x20, 0x20, 0x74, 0x6d, // 4 tmpvar_1;. tm + 0x70, 0x76, 0x61, 0x72, 0x5f, 0x31, 0x2e, 0x78, 0x79, 0x7a, 0x20, 0x3d, 0x20, 0x76, 0x5f, 0x63, // pvar_1.xyz = v_c + 0x6f, 0x6c, 0x6f, 0x72, 0x30, 0x2e, 0x78, 0x79, 0x7a, 0x3b, 0x0a, 0x20, 0x20, 0x74, 0x6d, 0x70, // olor0.xyz;. tmp + 0x76, 0x61, 0x72, 0x5f, 0x31, 0x2e, 0x77, 0x20, 0x3d, 0x20, 0x28, 0x76, 0x5f, 0x63, 0x6f, 0x6c, // var_1.w = (v_col + 0x6f, 0x72, 0x30, 0x2e, 0x77, 0x20, 0x2a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x32, // or0.w * texture2 + 0x44, 0x20, 0x28, 0x75, 0x5f, 0x74, 0x65, 0x78, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x2c, 0x20, 0x76, // D (u_texColor, v + 0x5f, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x30, 0x29, 0x2e, 0x78, 0x29, 0x3b, 0x0a, // _texcoord0).x);. + 0x20, 0x20, 0x67, 0x6c, 0x5f, 0x46, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x3d, // gl_FragColor = + 0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x31, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x00, // tmpvar_1;.}... +}; diff --git a/examples/common/imgui/fs_imgui_texture.sc b/examples/common/imgui/fs_imgui_texture.sc new file mode 100644 index 00000000..08467ea8 --- /dev/null +++ b/examples/common/imgui/fs_imgui_texture.sc @@ -0,0 +1,16 @@ +$input v_texcoord0, v_color0 + +/* + * Copyright 2011-2013 Branimir Karadzic. All rights reserved. + * License: http://www.opensource.org/licenses/BSD-2-Clause + */ + +#include + +SAMPLER2D(u_texColor, 0); + +void main() +{ + float alpha = texture2D(u_texColor, v_texcoord0).x; + gl_FragColor = vec4(v_color0.xyz, v_color0.w * alpha); +} diff --git a/examples/common/imgui/imgui.cpp b/examples/common/imgui/imgui.cpp new file mode 100644 index 00000000..91f1d00d --- /dev/null +++ b/examples/common/imgui/imgui.cpp @@ -0,0 +1,1520 @@ +/* + * Copyright 2011-2013 Branimir Karadzic. All rights reserved. + * License: http://www.opensource.org/licenses/BSD-2-Clause + */ + +// This code is based on: +// +// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. +// +// Source altered and distributed from https://github.com/AdrienHerubel/imgui + +#include +#include +#include +#include + +#include "imgui.h" +#include "../math.h" + +#include "vs_imgui_color.bin.h" +#include "fs_imgui_color.bin.h" +#include "vs_imgui_texture.bin.h" +#include "fs_imgui_texture.bin.h" + +#define MAX_TEMP_COORDS 100 +#define NUM_CIRCLE_VERTS (8 * 4) + +static const int32_t BUTTON_HEIGHT = 20; +static const int32_t SLIDER_HEIGHT = 20; +static const int32_t SLIDER_MARKER_WIDTH = 10; +static const int32_t CHECK_SIZE = 8; +static const int32_t DEFAULT_SPACING = 4; +static const int32_t TEXT_HEIGHT = 8; +static const int32_t SCROLL_AREA_PADDING = 6; +static const int32_t INDENT_SIZE = 16; +static const int32_t AREA_HEADER = 28; +static const float s_tabStops[4] = {150, 210, 270, 330}; + +static void* imguiMalloc(size_t size, void* /*_userptr*/) +{ + return malloc(size); +} + +static void imguiFree(void* _ptr, void* /*_userptr*/) +{ + free(_ptr); +} + +#define STBTT_malloc(_x, _y) imguiMalloc(_x, _y) +#define STBTT_free(_x, _y) imguiFree(_x, _y) +#define STB_TRUETYPE_IMPLEMENTATION +#include + +struct PosColorVertex +{ + float m_x; + float m_y; + uint32_t m_abgr; + + static void init() + { + ms_decl.begin(); + ms_decl.add(bgfx::Attrib::Position, 2, bgfx::AttribType::Float); + ms_decl.add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true); + ms_decl.end(); + } + + static bgfx::VertexDecl ms_decl; +}; + +bgfx::VertexDecl PosColorVertex::ms_decl; + +struct PosColorUvVertex +{ + float m_x; + float m_y; + float m_u; + float m_v; + uint32_t m_abgr; + + static void init() + { + ms_decl.begin(); + ms_decl.add(bgfx::Attrib::Position, 2, bgfx::AttribType::Float); + ms_decl.add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float); + ms_decl.add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true); + ms_decl.end(); + } + + static bgfx::VertexDecl ms_decl; +}; + +bgfx::VertexDecl PosColorUvVertex::ms_decl; + +struct Imgui +{ + Imgui() + : m_mx(-1) + , m_my(-1) + , m_scroll(0) + , m_active(0) + , m_hot(0) + , m_hotToBe(0) + , m_dragX(0) + , m_dragY(0) + , m_dragOrig(0) + , m_widgetX(0) + , m_widgetY(0) + , m_widgetW(100) + , m_left(false) + , m_leftPressed(false) + , m_leftReleased(false) + , m_isHot(false) + , m_isActive(false) + , m_wentActive(false) + , m_insideCurrentScroll(false) + , m_areaId(0) + , m_widgetId(0) + , m_scrollTop(0) + , m_scrollBottom(0) + , m_scrollRight(0) + , m_scrollAreaTop(0) + , m_scrollVal(NULL) + , m_focusTop(0) + , m_focusBottom(0) + , m_scrollId(0) + , m_insideScrollArea(false) + , m_textureWidth(512) + , m_textureHeight(512) + , m_halfTexel(0.0f) + , m_view(31) + { + m_invTextureWidth = 1.0f/m_textureWidth; + m_invTextureHeight = 1.0f/m_textureHeight; + + u_texColor.idx = bgfx::invalidHandle; + m_fontTexture.idx = bgfx::invalidHandle; + m_colorProgram.idx = bgfx::invalidHandle; + m_textureProgram.idx = bgfx::invalidHandle; + } + + bool create(void* _data, uint32_t /*_size*/) + { + for (int32_t ii = 0; ii < NUM_CIRCLE_VERTS; ++ii) + { + float a = (float)ii / (float)NUM_CIRCLE_VERTS * (float)(M_PI * 2.0); + m_circleVerts[ii * 2 + 0] = cosf(a); + m_circleVerts[ii * 2 + 1] = sinf(a); + } + + PosColorVertex::init(); + PosColorUvVertex::init(); + + u_texColor = bgfx::createUniform("u_texColor", bgfx::UniformType::Uniform1i); + + const bgfx::Memory* vs_imgui_color; + const bgfx::Memory* fs_imgui_color; + const bgfx::Memory* vs_imgui_texture; + const bgfx::Memory* fs_imgui_texture; + + switch (bgfx::getRendererType() ) + { + case bgfx::RendererType::Direct3D9: + vs_imgui_color = bgfx::makeRef(vs_imgui_color_dx9, sizeof(vs_imgui_color_dx9) ); + fs_imgui_color = bgfx::makeRef(fs_imgui_color_dx9, sizeof(fs_imgui_color_dx9) ); + vs_imgui_texture = bgfx::makeRef(vs_imgui_texture_dx9, sizeof(vs_imgui_texture_dx9) ); + fs_imgui_texture = bgfx::makeRef(fs_imgui_texture_dx9, sizeof(fs_imgui_texture_dx9) ); + m_halfTexel = 0.5f; + break; + + case bgfx::RendererType::Direct3D11: + vs_imgui_color = bgfx::makeRef(vs_imgui_color_dx11, sizeof(vs_imgui_color_dx11) ); + fs_imgui_color = bgfx::makeRef(fs_imgui_color_dx11, sizeof(fs_imgui_color_dx11) ); + vs_imgui_texture = bgfx::makeRef(vs_imgui_texture_dx11, sizeof(vs_imgui_texture_dx11) ); + fs_imgui_texture = bgfx::makeRef(fs_imgui_texture_dx11, sizeof(fs_imgui_texture_dx11) ); + break; + + default: + vs_imgui_color = bgfx::makeRef(vs_imgui_color_glsl, sizeof(vs_imgui_color_glsl) ); + fs_imgui_color = bgfx::makeRef(fs_imgui_color_glsl, sizeof(fs_imgui_color_glsl) ); + vs_imgui_texture = bgfx::makeRef(vs_imgui_texture_glsl, sizeof(vs_imgui_texture_glsl) ); + fs_imgui_texture = bgfx::makeRef(fs_imgui_texture_glsl, sizeof(fs_imgui_texture_glsl) ); + break; + } + + bgfx::VertexShaderHandle vsh; + bgfx::FragmentShaderHandle fsh; + + vsh = bgfx::createVertexShader(vs_imgui_color); + fsh = bgfx::createFragmentShader(fs_imgui_color); + m_colorProgram = bgfx::createProgram(vsh, fsh); + bgfx::destroyVertexShader(vsh); + bgfx::destroyFragmentShader(fsh); + + vsh = bgfx::createVertexShader(vs_imgui_texture); + fsh = bgfx::createFragmentShader(fs_imgui_texture); + m_textureProgram = bgfx::createProgram(vsh, fsh); + bgfx::destroyVertexShader(vsh); + bgfx::destroyFragmentShader(fsh); + + const bgfx::Memory* mem = bgfx::alloc(m_textureWidth * m_textureHeight); + stbtt_BakeFontBitmap( (uint8_t*)_data, 0, 15.0f, mem->data, m_textureWidth, m_textureHeight, 32, 96, m_cdata); + m_fontTexture = bgfx::createTexture2D(m_textureWidth, m_textureHeight, 1, bgfx::TextureFormat::L8, BGFX_TEXTURE_NONE, mem); + + return true; + } + + void destroy() + { + bgfx::destroyUniform(u_texColor); + bgfx::destroyTexture(m_fontTexture); + } + + bool anyActive() const + { + return m_active != 0; + } + + bool isActive(uint32_t _id) const + { + return m_active == _id; + } + + bool isHot(uint32_t _id) const + { + return m_hot == _id; + } + + bool inRect(int32_t _x, int32_t _y, int32_t _width, int32_t _height, bool _checkScroll = true) const + { + return (!_checkScroll || m_insideCurrentScroll) + && m_mx >= _x + && m_mx <= _x + _width + && m_my >= _y + && m_my <= _y + _height; + } + + void clearInput() + { + m_leftPressed = false; + m_leftReleased = false; + m_scroll = 0; + } + + void clearActive() + { + m_active = 0; + // mark all UI for this frame as processed + clearInput(); + } + + void setActive(uint32_t _id) + { + m_active = _id; + m_wentActive = true; + } + + void setHot(uint32_t _id) + { + m_hotToBe = _id; + } + + bool buttonLogic(uint32_t _id, bool _over) + { + bool res = false; + // process down + if (!anyActive() ) + { + if (_over) + { + setHot(_id); + } + + if (isHot(_id) + && m_leftPressed) + { + setActive(_id); + } + } + + // if button is active, then react on left up + if (isActive(_id) ) + { + m_isActive = true; + if (_over) + { + setHot(_id); + } + + if (m_leftReleased) + { + if (isHot(_id) ) + { + res = true; + } + + clearActive(); + } + } + + if (isHot(_id) ) + { + m_isHot = true; + } + + return res; + } + + void updateInput(int32_t _mx, int32_t _my, uint8_t _button, int32_t _scroll) + { + bool left = (_button & IMGUI_MBUT_LEFT) != 0; + + m_mx = _mx; + m_my = _my; + m_leftPressed = !m_left && left; + m_leftReleased = m_left && !left; + m_left = left; + m_scroll = _scroll; + } + + void beginFrame(int32_t _mx, int32_t _my, uint8_t _button, int32_t _scroll, uint16_t _width, uint16_t _height, uint8_t _view) + { + m_view = _view; + bgfx::setViewSeq(_view, true); + bgfx::setViewRect(_view, 0, 0, _width, _height); + + float proj[16]; + mtxOrtho(proj, 0.0f, (float)_width, (float)_height, 0.0f, 0.0f, 1000.0f); + bgfx::setViewTransform(_view, NULL, proj); + + updateInput(_mx, _my, _button, _scroll); + + m_hot = m_hotToBe; + m_hotToBe = 0; + + m_wentActive = false; + m_isActive = false; + m_isHot = false; + + m_widgetX = 0; + m_widgetY = 0; + m_widgetW = 0; + + m_areaId = 1; + m_widgetId = 1; + } + + void endFrame() + { + clearInput(); + } + + bool beginScrollArea(const char* _name, int32_t _x, int32_t _y, int32_t _width, int32_t _height, int32_t* _scroll) + { + m_areaId++; + m_widgetId = 0; + m_scrollId = (m_areaId << 16) | m_widgetId; + + m_widgetX = _x + SCROLL_AREA_PADDING; + m_widgetY = _y + + AREA_HEADER + (*_scroll); + m_widgetW = _width - SCROLL_AREA_PADDING * 4; + m_scrollTop = _y + SCROLL_AREA_PADDING; + m_scrollBottom = _y - AREA_HEADER + _height; + m_scrollRight = _x + _width - SCROLL_AREA_PADDING * 3; + m_scrollVal = _scroll; + + m_scrollAreaTop = m_widgetY; + + m_focusTop = _y - AREA_HEADER; + m_focusBottom = _y - AREA_HEADER + _height; + + m_insideScrollArea = inRect(_x, _y, _width, _height, false); + m_insideCurrentScroll = m_insideScrollArea; + + drawRoundedRect( (float)_x + , (float)_y + , (float)_width + , (float)_height + , 6 + , imguiRGBA(0, 0, 0, 192) + ); + + drawText(_x + AREA_HEADER / 2 + , _y + AREA_HEADER / 2 + , IMGUI_ALIGN_LEFT + , _name + , imguiRGBA(255, 255, 255, 128) + ); + +// setScissor(_x + SCROLL_AREA_PADDING, _y + SCROLL_AREA_PADDING, _width - SCROLL_AREA_PADDING * 4, _height - AREA_HEADER - SCROLL_AREA_PADDING); + + return m_insideScrollArea; + } + + void endScrollArea() + { + // Disable scissoring. +// setScissor(-1, -1, -1, -1); + + // Draw scroll bar + int32_t xx = m_scrollRight + SCROLL_AREA_PADDING / 2; + int32_t yy = m_scrollTop; + int32_t width = SCROLL_AREA_PADDING * 2; + int32_t height = m_scrollBottom - m_scrollTop; + + int32_t stop = m_scrollAreaTop; + int32_t sbot = m_widgetY; + int32_t sh = sbot - stop; // The scrollable area height. + + float barHeight = (float)height / (float)sh; + + if (barHeight < 1) + { + float barY = (float)(yy - sbot) / (float)sh; + if (barY < 0) + { + barY = 0; + } + + if (barY > 1) + { + barY = 1; + } + + // Handle scroll bar logic. + uint32_t hid = m_scrollId; + int32_t hx = xx; + int32_t hy = yy + (int)(barY * height); + int32_t hw = width; + int32_t hh = (int)(barHeight * height); + + const int32_t range = height - (hh - 1); + bool over = inRect(hx, hy, hw, hh); + buttonLogic(hid, over); + if (isActive(hid) ) + { + float u = (float)(hy - yy) / (float)range; + if (m_wentActive) + { + m_dragY = m_my; + m_dragOrig = u; + } + + if (m_dragY != m_my) + { + u = m_dragOrig + (m_my - m_dragY) / (float)range; + if (u < 0) + { + u = 0; + } + + if (u > 1) + { + u = 1; + } + + *m_scrollVal = (int)( (1 - u) * (sh - height) ); + } + } + + // BG + drawRoundedRect( (float)xx + , (float)yy + , (float)width + , (float)height + , (float)width / 2 - 1 + , imguiRGBA(0, 0, 0, 196) + ); + + // Bar + if (isActive(hid) ) + { + drawRoundedRect( (float)hx + , (float)hy + , (float)hw + , (float)hh + , (float)width / 2 - 1 + , imguiRGBA(255, 196, 0, 196) + ); + } + else + { + drawRoundedRect( (float)hx + , (float)hy + , (float)hw + , (float)hh + , (float)width / 2 - 1 + , isHot(hid) ? imguiRGBA(255, 196, 0, 96) : imguiRGBA(255, 255, 255, 64) + ); + } + + // Handle mouse scrolling. + if (m_insideScrollArea) // && !anyActive()) + { + if (m_scroll) + { + *m_scrollVal += 20 * m_scroll; + if (*m_scrollVal < 0) + { + *m_scrollVal = 0; + } + + if (*m_scrollVal > (sh - height) ) + { + *m_scrollVal = (sh - height); + } + } + } + } + + m_insideCurrentScroll = false; + } + + bool button(const char* _text, bool _enabled) + { + m_widgetId++; + uint32_t id = (m_areaId << 16) | m_widgetId; + + int32_t xx = m_widgetX; + int32_t yy = m_widgetY; + int32_t width = m_widgetW; + int32_t height = BUTTON_HEIGHT; + m_widgetY += BUTTON_HEIGHT + DEFAULT_SPACING; + + bool over = _enabled && inRect(xx, yy, width, height); + bool res = buttonLogic(id, over); + + drawRoundedRect( (float)xx + , (float)yy + , (float)width + , (float)height + , (float)BUTTON_HEIGHT / 2 - 1 + , imguiRGBA(128, 128, 128, isActive(id) ? 196 : 96) + ); + + if (_enabled) + { + drawText(xx + BUTTON_HEIGHT / 2 + , yy + BUTTON_HEIGHT / 2 + TEXT_HEIGHT / 2 + , IMGUI_ALIGN_LEFT + , _text + , isHot(id) ? imguiRGBA(255, 196, 0, 255) : imguiRGBA(255, 255, 255, 200) + ); + } + else + { + drawText(xx + BUTTON_HEIGHT / 2 + , yy + BUTTON_HEIGHT / 2 + TEXT_HEIGHT / 2 + , IMGUI_ALIGN_LEFT + , _text + , imguiRGBA(128, 128, 128, 200) + ); + } + + return res; + } + + bool item(const char* _text, bool _enabled) + { + m_widgetId++; + uint32_t id = (m_areaId << 16) | m_widgetId; + + int32_t xx = m_widgetX; + int32_t yy = m_widgetY; + int32_t width = m_widgetW; + int32_t height = BUTTON_HEIGHT; + m_widgetY += BUTTON_HEIGHT + DEFAULT_SPACING; + + bool over = _enabled && inRect(xx, yy, width, height); + bool res = buttonLogic(id, over); + + if (isHot(id) ) + { + drawRoundedRect( (float)xx + , (float)yy + , (float)width + , (float)height + , 2.0f + , imguiRGBA(255, 196, 0, isActive(id) ? 196 : 96) + ); + } + + if (_enabled) + { + drawText(xx + BUTTON_HEIGHT / 2 + , yy + BUTTON_HEIGHT / 2 + TEXT_HEIGHT / 2 + , IMGUI_ALIGN_LEFT + , _text + , imguiRGBA(255, 255, 255, 200) + ); + } + else + { + drawText(xx + BUTTON_HEIGHT / 2 + , yy + BUTTON_HEIGHT / 2 + TEXT_HEIGHT / 2 + , IMGUI_ALIGN_LEFT + , _text + , imguiRGBA(128, 128, 128, 200) + ); + } + + return res; + } + + bool check(const char* _text, bool _checked, bool _enabled) + { + m_widgetId++; + uint32_t id = (m_areaId << 16) | m_widgetId; + + int32_t xx = m_widgetX; + int32_t yy = m_widgetY; + int32_t width = m_widgetW; + int32_t height = BUTTON_HEIGHT; + m_widgetY += BUTTON_HEIGHT + DEFAULT_SPACING; + + bool over = _enabled && inRect(xx, yy, width, height); + bool res = buttonLogic(id, over); + + const int32_t cx = xx + BUTTON_HEIGHT / 2 - CHECK_SIZE / 2; + const int32_t cy = yy + BUTTON_HEIGHT / 2 - CHECK_SIZE / 2; + drawRoundedRect( (float)cx - 3 + , (float)cy - 3 + , (float)CHECK_SIZE + 6 + , (float)CHECK_SIZE + 6 + , 4 + , imguiRGBA(128, 128, 128, isActive(id) ? 196 : 96) + ); + + if (_checked) + { + if (_enabled) + { + drawRoundedRect( (float)cx + , (float)cy + , (float)CHECK_SIZE + , (float)CHECK_SIZE + , (float)CHECK_SIZE / 2 - 1 + , imguiRGBA(255, 255, 255, isActive(id) ? 255 : 200) + ); + } + else + { + drawRoundedRect( (float)cx + , (float)cy + , (float)CHECK_SIZE + , (float)CHECK_SIZE + , (float)CHECK_SIZE / 2 - 1 + , imguiRGBA(128, 128, 128, 200) + ); + } + } + + if (_enabled) + { + drawText(xx + BUTTON_HEIGHT + , yy + BUTTON_HEIGHT / 2 + TEXT_HEIGHT / 2 + , IMGUI_ALIGN_LEFT + , _text + , isHot(id) ? imguiRGBA(255, 196, 0, 255) : imguiRGBA(255, 255, 255, 200) + ); + } + else + { + drawText(xx + BUTTON_HEIGHT + , yy + BUTTON_HEIGHT / 2 + TEXT_HEIGHT / 2 + , IMGUI_ALIGN_LEFT + , _text + , imguiRGBA(128, 128, 128, 200) + ); + } + + return res; + } + + bool collapse(const char* _text, const char* _subtext, bool _checked, bool _enabled) + { + m_widgetId++; + uint32_t id = (m_areaId << 16) | m_widgetId; + + int32_t xx = m_widgetX; + int32_t yy = m_widgetY; + int32_t width = m_widgetW; + int32_t height = BUTTON_HEIGHT; + m_widgetY += BUTTON_HEIGHT + DEFAULT_SPACING; + + const int32_t cx = xx + BUTTON_HEIGHT / 2 - CHECK_SIZE / 2; + const int32_t cy = yy + BUTTON_HEIGHT / 2 - CHECK_SIZE / 2; + + bool over = _enabled && inRect(xx, yy, width, height); + bool res = buttonLogic(id, over); + + if (_checked) + { + drawTriangle(cx + , cy + , CHECK_SIZE + , CHECK_SIZE + , 2 + , imguiRGBA(255, 255, 255, isActive(id) ? 255 : 200) + ); + } + else + { + drawTriangle(cx + , cy + , CHECK_SIZE + , CHECK_SIZE + , 1 + , imguiRGBA(255, 255, 255, isActive(id) ? 255 : 200) + ); + } + + if (_enabled) + { + drawText(xx + BUTTON_HEIGHT + , yy + BUTTON_HEIGHT / 2 + TEXT_HEIGHT / 2 + , IMGUI_ALIGN_LEFT + , _text + , isHot(id) ? imguiRGBA(255, 196, 0, 255) : imguiRGBA(255, 255, 255, 200) + ); + } + else + { + drawText(xx + BUTTON_HEIGHT + , yy + BUTTON_HEIGHT / 2 + TEXT_HEIGHT / 2 + , IMGUI_ALIGN_LEFT + , _text + , imguiRGBA(128, 128, 128, 200) + ); + } + + if (_subtext) + { + drawText(xx + width - BUTTON_HEIGHT / 2 + , yy + BUTTON_HEIGHT / 2 + TEXT_HEIGHT / 2 + , IMGUI_ALIGN_RIGHT + , _subtext + , imguiRGBA(255, 255, 255, 128) + ); + } + + return res; + } + + void labelVargs(const char* _format, va_list _argList) + { + char temp[8192]; + char* out = temp; + int32_t len = bx::vsnprintf(out, sizeof(temp), _format, _argList); + if ( (int32_t)sizeof(temp) < len) + { + out = (char*)alloca(len+1); + len = bx::vsnprintf(out, len, _format, _argList); + } + out[len] = '\0'; + + int32_t xx = m_widgetX; + int32_t yy = m_widgetY; + m_widgetY += BUTTON_HEIGHT; + drawText(xx + , yy + BUTTON_HEIGHT / 2 + TEXT_HEIGHT / 2 + , IMGUI_ALIGN_LEFT + , out + , imguiRGBA(255, 255, 255, 255) + ); + } + + void value(const char* _text) + { + const int32_t xx = m_widgetX; + const int32_t yy = m_widgetY; + const int32_t ww = m_widgetW; + m_widgetY += BUTTON_HEIGHT; + + drawText(xx + ww - BUTTON_HEIGHT / 2 + , yy + BUTTON_HEIGHT / 2 + TEXT_HEIGHT / 2 + , IMGUI_ALIGN_RIGHT + , _text + , imguiRGBA(255, 255, 255, 200) + ); + } + + bool slider(const char* _text, float* _val, float _vmin, float _vmax, float _vinc, bool _enabled) + { + m_widgetId++; + uint32_t id = (m_areaId << 16) | m_widgetId; + + int32_t xx = m_widgetX; + int32_t yy = m_widgetY; + int32_t width = m_widgetW; + int32_t height = SLIDER_HEIGHT; + m_widgetY += SLIDER_HEIGHT + DEFAULT_SPACING; + + drawRoundedRect( (float)xx, (float)yy, (float)width, (float)height, 4.0f, imguiRGBA(0, 0, 0, 128) ); + + const int32_t range = width - SLIDER_MARKER_WIDTH; + + float uu = (*_val - _vmin) / (_vmax - _vmin); + if (uu < 0) + { + uu = 0; + } + + if (uu > 1) + { + uu = 1; + } + + int32_t m = (int)(uu * range); + + bool over = _enabled && inRect(xx + m, yy, SLIDER_MARKER_WIDTH, SLIDER_HEIGHT); + bool res = buttonLogic(id, over); + bool valChanged = false; + + if (isActive(id) ) + { + if (m_wentActive) + { + m_dragX = m_mx; + m_dragOrig = uu; + } + + if (m_dragX != m_mx) + { + uu = m_dragOrig + (float)(m_mx - m_dragX) / (float)range; + if (uu < 0) + { + uu = 0; + } + + if (uu > 1) + { + uu = 1; + } + + *_val = _vmin + uu * (_vmax - _vmin); + *_val = floorf(*_val / _vinc + 0.5f) * _vinc; // Snap to vinc + m = (int)(uu * range); + valChanged = true; + } + } + + if (isActive(id) ) + { + drawRoundedRect( (float)(xx + m) + , (float)yy + , (float)SLIDER_MARKER_WIDTH + , (float)SLIDER_HEIGHT + , 4.0f + , imguiRGBA(255, 255, 255, 255) + ); + } + else + { + drawRoundedRect( (float)(xx + m) + , (float)yy + , (float)SLIDER_MARKER_WIDTH + , (float)SLIDER_HEIGHT + , 4.0f + , isHot(id) ? imguiRGBA(255, 196, 0, 128) : imguiRGBA(255, 255, 255, 64) + ); + } + + // TODO: fix this, take a look at 'nicenum'. + int32_t digits = (int)(ceilf(log10f(_vinc) ) ); + char fmt[16]; + bx::snprintf(fmt, 16, "%%.%df", digits >= 0 ? 0 : -digits); + char msg[128]; + bx::snprintf(msg, 128, fmt, *_val); + + if (_enabled) + { + drawText(xx + SLIDER_HEIGHT / 2 + , yy + SLIDER_HEIGHT / 2 + TEXT_HEIGHT / 2 + , IMGUI_ALIGN_LEFT + , _text + , isHot(id) ? imguiRGBA(255, 196, 0, 255) : imguiRGBA(255, 255, 255, 200) + ); + + drawText(xx + width - SLIDER_HEIGHT / 2 + , yy + SLIDER_HEIGHT / 2 + TEXT_HEIGHT / 2 + , IMGUI_ALIGN_RIGHT + , msg + , isHot(id) ? imguiRGBA(255, 196, 0, 255) : imguiRGBA(255, 255, 255, 200) + ); + } + else + { + drawText(xx + SLIDER_HEIGHT / 2 + , yy + SLIDER_HEIGHT / 2 + TEXT_HEIGHT / 2 + , IMGUI_ALIGN_LEFT + , _text + , imguiRGBA(128, 128, 128, 200) + ); + + drawText(xx + width - SLIDER_HEIGHT / 2 + , yy + SLIDER_HEIGHT / 2 + TEXT_HEIGHT / 2 + , IMGUI_ALIGN_RIGHT + , msg + , imguiRGBA(128, 128, 128, 200) + ); + } + + return res || valChanged; + } + + void indent() + { + m_widgetX += INDENT_SIZE; + m_widgetW -= INDENT_SIZE; + } + + void unindent() + { + m_widgetX -= INDENT_SIZE; + m_widgetW += INDENT_SIZE; + } + + void separator() + { + m_widgetY += DEFAULT_SPACING * 3; + } + + void separatorLine() + { + int32_t xx = m_widgetX; + int32_t yy = m_widgetY; + int32_t width = m_widgetW; + int32_t height = 1; + m_widgetY += DEFAULT_SPACING * 4; + + drawRect( (float)xx + , (float)yy + , (float)width + , (float)height + , imguiRGBA(255, 255, 255, 32) + ); + } + + void drawPolygon(const float* _coords, uint32_t _numCoords, float _r, uint32_t _abgr) + { + _numCoords = bx::uint32_min(_numCoords, MAX_TEMP_COORDS); + + for (uint32_t ii = 0, jj = _numCoords - 1; ii < _numCoords; jj = ii++) + { + const float* v0 = &_coords[jj * 2]; + const float* v1 = &_coords[ii * 2]; + float dx = v1[0] - v0[0]; + float dy = v1[1] - v0[1]; + float d = sqrtf(dx * dx + dy * dy); + if (d > 0) + { + d = 1.0f / d; + dx *= d; + dy *= d; + } + + m_tempNormals[jj * 2 + 0] = dy; + m_tempNormals[jj * 2 + 1] = -dx; + } + + for (uint32_t ii = 0, jj = _numCoords - 1; ii < _numCoords; jj = ii++) + { + float dlx0 = m_tempNormals[jj * 2 + 0]; + float dly0 = m_tempNormals[jj * 2 + 1]; + float dlx1 = m_tempNormals[ii * 2 + 0]; + float dly1 = m_tempNormals[ii * 2 + 1]; + float dmx = (dlx0 + dlx1) * 0.5f; + float dmy = (dly0 + dly1) * 0.5f; + float dmr2 = dmx * dmx + dmy * dmy; + if (dmr2 > 0.000001f) + { + float scale = 1.0f / dmr2; + if (scale > 10.0f) + { + scale = 10.0f; + } + + dmx *= scale; + dmy *= scale; + } + + m_tempCoords[ii * 2 + 0] = _coords[ii * 2 + 0] + dmx * _r; + m_tempCoords[ii * 2 + 1] = _coords[ii * 2 + 1] + dmy * _r; + } + + uint32_t numVertices = _numCoords*6 + (_numCoords-2)*3; + if (bgfx::checkAvailTransientVertexBuffer(numVertices, PosColorVertex::ms_decl) ) + { + bgfx::TransientVertexBuffer tvb; + bgfx::allocTransientVertexBuffer(&tvb, numVertices, PosColorVertex::ms_decl); + uint32_t trans = _abgr&0xffffff; + + PosColorVertex* vertex = (PosColorVertex*)tvb.data; + for (uint32_t ii = 0, jj = _numCoords-1; ii < _numCoords; jj = ii++) + { + vertex->m_x = _coords[ii*2+0]; + vertex->m_y = _coords[ii*2+1]; + vertex->m_abgr = _abgr; + ++vertex; + + vertex->m_x = _coords[jj*2+0]; + vertex->m_y = _coords[jj*2+1]; + vertex->m_abgr = _abgr; + ++vertex; + + vertex->m_x = m_tempCoords[jj*2+0]; + vertex->m_y = m_tempCoords[jj*2+1]; + vertex->m_abgr = trans; + ++vertex; + + vertex->m_x = m_tempCoords[jj*2+0]; + vertex->m_y = m_tempCoords[jj*2+1]; + vertex->m_abgr = trans; + ++vertex; + + vertex->m_x = m_tempCoords[ii*2+0]; + vertex->m_y = m_tempCoords[ii*2+1]; + vertex->m_abgr = trans; + ++vertex; + + vertex->m_x = _coords[ii*2+0]; + vertex->m_y = _coords[ii*2+1]; + vertex->m_abgr = _abgr; + ++vertex; + } + + for (uint32_t ii = 2; ii < _numCoords; ++ii) + { + vertex->m_x = _coords[0]; + vertex->m_y = _coords[1]; + vertex->m_abgr = _abgr; + ++vertex; + + vertex->m_x = _coords[(ii-1)*2+0]; + vertex->m_y = _coords[(ii-1)*2+1]; + vertex->m_abgr = _abgr; + ++vertex; + + vertex->m_x = _coords[ii*2+0]; + vertex->m_y = _coords[ii*2+1]; + vertex->m_abgr = _abgr; + ++vertex; + } + + bgfx::setVertexBuffer(&tvb); + bgfx::setState(0 + | BGFX_STATE_RGB_WRITE + | BGFX_STATE_ALPHA_WRITE + | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA) + ); + bgfx::setProgram(m_colorProgram); + bgfx::submit(m_view); + } + } + + void drawRect(float _x, float _y, float w, float h, uint32_t _argb, float _fth = 1.0f) + { + float verts[4 * 2] = + { + _x + 0.5f, _y + 0.5f, + _x + w - 0.5f, _y + 0.5f, + _x + w - 0.5f, _y + h - 0.5f, + _x + 0.5f, _y + h - 0.5f, + }; + + drawPolygon(verts, 4, _fth, _argb); + } + + void drawRoundedRect(float _x, float _y, float w, float h, float r, uint32_t _argb, float _fth = 1.0f) + { + const uint32_t num = NUM_CIRCLE_VERTS / 4; + const float* cverts = m_circleVerts; + float verts[(num + 1) * 4 * 2]; + float* vv = verts; + + for (uint32_t ii = 0; ii <= num; ++ii) + { + *vv++ = _x + w - r + cverts[ii * 2] * r; + *vv++ = _y + h - r + cverts[ii * 2 + 1] * r; + } + + for (uint32_t ii = num; ii <= num * 2; ++ii) + { + *vv++ = _x + r + cverts[ii * 2] * r; + *vv++ = _y + h - r + cverts[ii * 2 + 1] * r; + } + + for (uint32_t ii = num * 2; ii <= num * 3; ++ii) + { + *vv++ = _x + r + cverts[ii * 2] * r; + *vv++ = _y + r + cverts[ii * 2 + 1] * r; + } + + for (uint32_t ii = num * 3; ii < num * 4; ++ii) + { + *vv++ = _x + w - r + cverts[ii * 2] * r; + *vv++ = _y + r + cverts[ii * 2 + 1] * r; + } + + *vv++ = _x + w - r + cverts[0] * r; + *vv++ = _y + r + cverts[1] * r; + + drawPolygon(verts, (num + 1) * 4, _fth, _argb); + } + + void drawLine(float _x0, float _y0, float _x1, float _y1, float _r, uint32_t _abgr, float _fth = 1.0f) + { + float dx = _x1 - _x0; + float dy = _y1 - _y0; + float d = sqrtf(dx * dx + dy * dy); + if (d > 0.0001f) + { + d = 1.0f / d; + dx *= d; + dy *= d; + } + + float nx = dy; + float ny = -dx; + float verts[4 * 2]; + _r -= _fth; + _r *= 0.5f; + if (_r < 0.01f) + { + _r = 0.01f; + } + + dx *= _r; + dy *= _r; + nx *= _r; + ny *= _r; + + verts[0] = _x0 - dx - nx; + verts[1] = _y0 - dy - ny; + + verts[2] = _x0 - dx + nx; + verts[3] = _y0 - dy + ny; + + verts[4] = _x1 + dx + nx; + verts[5] = _y1 + dy + ny; + + verts[6] = _x1 + dx - nx; + verts[7] = _y1 + dy - ny; + + drawPolygon(verts, 4, _fth, _abgr); + } + + void drawTriangle(int32_t _x, int32_t _y, int32_t _width, int32_t _height, int32_t _flags, uint32_t _abgr) + { + if (1 == _flags) + { + const float verts[3 * 2] = + { + (float)_x + 0.5f, (float)_y + 0.5f, + (float)_x + 0.5f + (float)_width * 1.0f, (float)_y + 0.5f + (float)_height / 2.0f - 0.5f, + (float)_x + 0.5f, (float)_y + 0.5f + (float)_height - 1.0f, + }; + + drawPolygon(verts, 3, 1.0f, _abgr); + } + else + { + const float verts[3 * 2] = + { + (float)_x + 0.5f, (float)_y + 0.5f + (float)_height - 1.0f, + (float)_x + 0.5f + (float)_width / 2.0f - 0.5f, (float)_y + 0.5f, + (float)_x + 0.5f + (float)_width - 1.0f, (float)_y + 0.5f + (float)_height - 1.0f, + }; + + drawPolygon(verts, 3, 1.0f, _abgr); + } + } + + void getBakedQuad(stbtt_bakedchar* _chardata, int32_t char_index, float* _xpos, float* _ypos, stbtt_aligned_quad* _quad) + { + stbtt_bakedchar* b = _chardata + char_index; + int32_t round_x = STBTT_ifloor(*_xpos + b->xoff); + int32_t round_y = STBTT_ifloor(*_ypos + b->yoff); + + _quad->x0 = (float)round_x; + _quad->y0 = (float)round_y; + _quad->x1 = (float)round_x + b->x1 - b->x0; + _quad->y1 = (float)round_y + b->y1 - b->y0; + + _quad->s0 = (b->x0 + m_halfTexel) * m_invTextureWidth; + _quad->t0 = (b->y0 + m_halfTexel) * m_invTextureWidth; + _quad->s1 = (b->x1 + m_halfTexel) * m_invTextureHeight; + _quad->t1 = (b->y1 + m_halfTexel) * m_invTextureHeight; + + *_xpos += b->xadvance; + } + + float getTextLength(stbtt_bakedchar* _chardata, const char* _text, uint32_t& _numVertices) + { + float xpos = 0; + float len = 0; + uint32_t numVertices = 0; + + while (*_text) + { + int32_t ch = (uint8_t)*_text; + if (ch == '\t') + { + for (int32_t ii = 0; ii < 4; ++ii) + { + if (xpos < s_tabStops[ii]) + { + xpos = s_tabStops[ii]; + break; + } + } + } + else if (ch >= ' ' + && ch < 128) + { + stbtt_bakedchar* b = _chardata + ch - ' '; + int32_t round_x = STBTT_ifloor( (xpos + b->xoff) + 0.5); + len = round_x + b->x1 - b->x0 + 0.5f; + xpos += b->xadvance; + numVertices += 6; + } + + ++_text; + } + + _numVertices = numVertices; + + return len; + } + + void drawText(int32_t _x, int32_t _y, imguiTextAlign _align, const char* _text, uint32_t _abgr) + { + drawText( (float)_x, (float)_y, _text, _align, _abgr); + } + + void drawText(float _x, float _y, const char* _text, imguiTextAlign _align, uint32_t _abgr) + { + if (!_text) + { + return; + } + + uint32_t numVertices = 0; + if (_align == IMGUI_ALIGN_CENTER) + { + _x -= getTextLength(m_cdata, _text, numVertices) / 2; + } + else if (_align == IMGUI_ALIGN_RIGHT) + { + _x -= getTextLength(m_cdata, _text, numVertices); + } + else // just count vertices + { + getTextLength(m_cdata, _text, numVertices); + } + + if (bgfx::checkAvailTransientVertexBuffer(numVertices, PosColorUvVertex::ms_decl) ) + { + bgfx::TransientVertexBuffer tvb; + bgfx::allocTransientVertexBuffer(&tvb, numVertices, PosColorUvVertex::ms_decl); + + PosColorUvVertex* vertex = (PosColorUvVertex*)tvb.data; + + const float ox = _x; + + while (*_text) + { + int32_t ch = (uint8_t)*_text; + if (ch == '\t') + { + for (int32_t i = 0; i < 4; ++i) + { + if (_x < s_tabStops[i] + ox) + { + _x = s_tabStops[i] + ox; + break; + } + } + } + else if (ch >= ' ' + && ch < 128) + { + stbtt_aligned_quad quad; + getBakedQuad(m_cdata, ch - 32, &_x, &_y, &quad); + + vertex->m_x = quad.x0; + vertex->m_y = quad.y0; + vertex->m_u = quad.s0; + vertex->m_v = quad.t0; + vertex->m_abgr = _abgr; + ++vertex; + + vertex->m_x = quad.x1; + vertex->m_y = quad.y1; + vertex->m_u = quad.s1; + vertex->m_v = quad.t1; + vertex->m_abgr = _abgr; + ++vertex; + + vertex->m_x = quad.x1; + vertex->m_y = quad.y0; + vertex->m_u = quad.s1; + vertex->m_v = quad.t0; + vertex->m_abgr = _abgr; + ++vertex; + + vertex->m_x = quad.x0; + vertex->m_y = quad.y0; + vertex->m_u = quad.s0; + vertex->m_v = quad.t0; + vertex->m_abgr = _abgr; + ++vertex; + + vertex->m_x = quad.x0; + vertex->m_y = quad.y1; + vertex->m_u = quad.s0; + vertex->m_v = quad.t1; + vertex->m_abgr = _abgr; + ++vertex; + + vertex->m_x = quad.x1; + vertex->m_y = quad.y1; + vertex->m_u = quad.s1; + vertex->m_v = quad.t1; + vertex->m_abgr = _abgr; + ++vertex; + } + + ++_text; + } + + bgfx::setTexture(0, u_texColor, m_fontTexture); + bgfx::setVertexBuffer(&tvb); + bgfx::setState(0 + | BGFX_STATE_RGB_WRITE + | BGFX_STATE_ALPHA_WRITE + | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA) + ); + bgfx::setProgram(m_textureProgram); + bgfx::submit(m_view); + } + } + + int32_t m_mx; + int32_t m_my; + int32_t m_scroll; + uint32_t m_active; + uint32_t m_hot; + uint32_t m_hotToBe; + int32_t m_dragX; + int32_t m_dragY; + float m_dragOrig; + int32_t m_widgetX; + int32_t m_widgetY; + int32_t m_widgetW; + bool m_left; + bool m_leftPressed; + bool m_leftReleased; + bool m_isHot; + bool m_isActive; + bool m_wentActive; + bool m_insideCurrentScroll; + + uint32_t m_areaId; + uint32_t m_widgetId; + + float m_tempCoords[MAX_TEMP_COORDS * 2]; + float m_tempNormals[MAX_TEMP_COORDS * 2]; + + float m_circleVerts[NUM_CIRCLE_VERTS * 2]; + + int32_t m_scrollTop; + int32_t m_scrollBottom; + int32_t m_scrollRight; + int32_t m_scrollAreaTop; + int32_t* m_scrollVal; + int32_t m_focusTop; + int32_t m_focusBottom; + uint32_t m_scrollId; + bool m_insideScrollArea; + + stbtt_bakedchar m_cdata[96]; // ASCII 32..126 is 95 glyphs + + uint16_t m_textureWidth; + uint16_t m_textureHeight; + float m_invTextureWidth; + float m_invTextureHeight; + float m_halfTexel; + + uint8_t m_view; + bgfx::UniformHandle u_texColor; + bgfx::TextureHandle m_fontTexture; + bgfx::ProgramHandle m_colorProgram; + bgfx::ProgramHandle m_textureProgram; +}; + +static Imgui s_imgui; + +bool imguiCreate(void* _data, uint32_t _size) +{ + return s_imgui.create(_data, _size); +} + +void imguiDestroy() +{ + s_imgui.destroy(); +} + +void imguiBeginFrame(int32_t _mx, int32_t _my, uint8_t _button, int32_t _scroll, uint16_t _width, uint16_t _height, uint8_t _view) +{ + s_imgui.beginFrame(_mx, _my, _button, _scroll, _width, _height, _view); +} + +void imguiEndFrame() +{ + s_imgui.endFrame(); +} + +bool imguiBeginScrollArea(const char* _name, int32_t _x, int32_t _y, int32_t _width, int32_t _height, int32_t* _scroll) +{ + return s_imgui.beginScrollArea(_name, _x, _y, _width, _height, _scroll); +} + +void imguiEndScrollArea() +{ + return s_imgui.endScrollArea(); +} + +void imguiIndent() +{ + s_imgui.indent(); +} + +void imguiUnindent() +{ + s_imgui.unindent(); +} + +void imguiSeparator() +{ + s_imgui.separator(); +} + +void imguiSeparatorLine() +{ + s_imgui.separatorLine(); +} + +bool imguiButton(const char* _text, bool _enabled) +{ + return s_imgui.button(_text, _enabled); +} + +bool imguiItem(const char* _text, bool _enabled) +{ + return s_imgui.item(_text, _enabled); +} + +bool imguiCheck(const char* _text, bool _checked, bool _enabled) +{ + return s_imgui.check(_text, _checked, _enabled); +} + +bool imguiCollapse(const char* _text, const char* _subtext, bool _checked, bool _enabled) +{ + return s_imgui.collapse(_text, _subtext, _checked, _enabled); +} + +void imguiLabel(const char* _format, ...) +{ + va_list argList; + va_start(argList, _format); + s_imgui.labelVargs(_format, argList); + va_end(argList); +} + +void imguiValue(const char* _text) +{ + s_imgui.value(_text); +} + +bool imguiSlider(const char* _text, float* _val, float _vmin, float _vmax, float _vinc, bool _enabled) +{ + return s_imgui.slider(_text, _val, _vmin, _vmax, _vinc, _enabled); +} + +void imguiDrawText(int32_t _x, int32_t _y, imguiTextAlign _align, const char* _text, uint32_t _argb) +{ + s_imgui.drawText(_x, _y, _align, _text, _argb); +} + +void imguiDrawLine(float _x0, float _y0, float _x1, float _y1, float _r, uint32_t _argb) +{ + s_imgui.drawLine(_x0, _y0, _x1, _y1, _r, _argb); +} + +void imguiDrawRoundedRect(float _x, float _y, float _width, float _height, float _r, uint32_t _argb) +{ + s_imgui.drawRoundedRect(_x, _y, _width, _height, _r, _argb); +} + +void imguiDrawRect(float _x, float _y, float _width, float _height, uint32_t _argb) +{ + s_imgui.drawRect(_x, _y, _width, _height, _argb); +} diff --git a/examples/common/imgui/imgui.h b/examples/common/imgui/imgui.h new file mode 100644 index 00000000..2cb49a10 --- /dev/null +++ b/examples/common/imgui/imgui.h @@ -0,0 +1,79 @@ +/* + * Copyright 2011-2013 Branimir Karadzic. All rights reserved. + * License: http://www.opensource.org/licenses/BSD-2-Clause + */ + +// This code is based on: +// +// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. +// +// Source altered and distributed from https://github.com/AdrienHerubel/imgui + +#ifndef __IMGUI_H__ +#define __IMGUI_H__ + +enum imguiMouseButton +{ + IMGUI_MBUT_LEFT = 0x01, + IMGUI_MBUT_RIGHT = 0x02, +}; + +enum imguiTextAlign +{ + IMGUI_ALIGN_LEFT, + IMGUI_ALIGN_CENTER, + IMGUI_ALIGN_RIGHT, +}; + +inline uint32_t imguiRGBA(uint8_t _r, uint8_t _g, uint8_t _b, uint8_t _a = 255) +{ + return 0 + | (uint32_t(_r) << 0) + | (uint32_t(_g) << 8) + | (uint32_t(_b) << 16) + | (uint32_t(_a) << 24) + ; +} + +bool imguiCreate(void* _data, uint32_t _size); +void imguiDestroy(); + +void imguiBeginFrame(int32_t _mx, int32_t _my, uint8_t _button, int32_t _scroll, uint16_t _width, uint16_t _height, uint8_t _view = 31); +void imguiEndFrame(); + +bool imguiBeginScrollArea(const char* _name, int _x, int _y, int _width, int _height, int* _scroll); +void imguiEndScrollArea(); + +void imguiIndent(); +void imguiUnindent(); +void imguiSeparator(); +void imguiSeparatorLine(); + +bool imguiButton(const char* _text, bool _enabled = true); +bool imguiItem(const char* _text, bool _enabled = true); +bool imguiCheck(const char* _text, bool _checked, bool _enabled = true); +bool imguiCollapse(const char* _text, const char* _subtext, bool _checked, bool _enabled = true); +void imguiLabel(const char* _format, ...); +void imguiValue(const char* _text); +bool imguiSlider(const char* _text, float* val, float vmin, float vmax, float vinc, bool _enabled = true); + +void imguiDrawText(int _x, int _y, imguiTextAlign _align, const char* _text, uint32_t _argb); +void imguiDrawLine(float _x0, float _y0, float _x1, float _y1, float _r, uint32_t _argb); +void imguiDrawRoundedRect(float _x, float _y, float _w, float _h, float _r, uint32_t _argb); +void imguiDrawRect(float _x, float _y, float _w, float _h, uint32_t _argb); + +#endif // __IMGUI_H__ diff --git a/examples/common/imgui/makefile b/examples/common/imgui/makefile new file mode 100644 index 00000000..61c359c4 --- /dev/null +++ b/examples/common/imgui/makefile @@ -0,0 +1,9 @@ +# +# Copyright 2011-2013 Branimir Karadzic. All rights reserved. +# License: http://www.opensource.org/licenses/BSD-2-Clause +# + +include ../../../premake/shader-embeded.mk + +rebuild: + @make -s --no-print-directory clean all diff --git a/examples/common/imgui/varying.def.sc b/examples/common/imgui/varying.def.sc new file mode 100644 index 00000000..5f4c47ac --- /dev/null +++ b/examples/common/imgui/varying.def.sc @@ -0,0 +1,6 @@ +vec4 v_color0 : COLOR0 = vec4(1.0, 0.0, 0.0, 1.0); +vec2 v_texcoord0 : TEXCOORD0 = vec2(0.0, 0.0); + +vec2 a_position : POSITION; +vec4 a_color0 : COLOR0; +vec2 a_texcoord0 : TEXCOORD0; diff --git a/examples/common/imgui/vs_imgui_color.bin.h b/examples/common/imgui/vs_imgui_color.bin.h new file mode 100644 index 00000000..121ee071 --- /dev/null +++ b/examples/common/imgui/vs_imgui_color.bin.h @@ -0,0 +1,124 @@ +static const uint8_t vs_imgui_color_dx9[290] = +{ + 0x56, 0x53, 0x48, 0x01, 0xa4, 0x8b, 0xef, 0x49, 0x01, 0x00, 0x0a, 0x75, 0x5f, 0x76, 0x69, 0x65, // VSH....I...u_vie + 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x09, 0x01, 0x00, 0x00, 0x04, 0x00, 0x04, 0x01, 0x00, 0x03, 0xfe, // wProj........... + 0xff, 0xfe, 0xff, 0x22, 0x00, 0x43, 0x54, 0x41, 0x42, 0x1c, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, // ...".CTAB....S.. + 0x00, 0x00, 0x03, 0xfe, 0xff, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, // ................ + 0x00, 0x4c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, // .L...0.......... + 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x5f, 0x76, 0x69, 0x65, 0x77, 0x50, // .<.......u_viewP + 0x72, 0x6f, 0x6a, 0x00, 0xab, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, // roj............. + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x73, 0x5f, 0x33, 0x5f, 0x30, 0x00, 0x4d, 0x69, 0x63, 0x72, // .....vs_3_0.Micr + 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x28, 0x52, 0x29, 0x20, 0x48, 0x4c, 0x53, 0x4c, 0x20, 0x53, // osoft (R) HLSL S + 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x39, // hader Compiler 9 + 0x2e, 0x32, 0x39, 0x2e, 0x39, 0x35, 0x32, 0x2e, 0x33, 0x31, 0x31, 0x31, 0x00, 0x1f, 0x00, 0x00, // .29.952.3111.... + 0x02, 0x0a, 0x00, 0x00, 0x80, 0x00, 0x00, 0x0f, 0x90, 0x1f, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, // ................ + 0x80, 0x01, 0x00, 0x0f, 0x90, 0x1f, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x0f, // ................ + 0xe0, 0x1f, 0x00, 0x00, 0x02, 0x0a, 0x00, 0x00, 0x80, 0x01, 0x00, 0x0f, 0xe0, 0x05, 0x00, 0x00, // ................ + 0x03, 0x00, 0x00, 0x0f, 0x80, 0x01, 0x00, 0xe4, 0xa0, 0x01, 0x00, 0x55, 0x90, 0x04, 0x00, 0x00, // ...........U.... + 0x04, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0xe4, 0xa0, 0x01, 0x00, 0x00, 0x90, 0x00, 0x00, 0xe4, // ................ + 0x80, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x0f, 0xe0, 0x00, 0x00, 0xe4, 0x80, 0x03, 0x00, 0xe4, // ................ + 0xa0, 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x0f, 0xe0, 0x00, 0x00, 0xe4, 0x90, 0xff, 0xff, 0x00, // ................ + 0x00, 0x00, // .. +}; +static const uint8_t vs_imgui_color_dx11[1187] = +{ + 0x56, 0x53, 0x48, 0x01, 0xa4, 0x8b, 0xef, 0x49, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, // VSH....I........ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb0, 0x09, 0x0a, 0x75, 0x5f, 0x76, 0x69, // ............u_vi + 0x65, 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x09, 0x00, 0x60, 0x00, 0x04, 0x00, 0x74, 0x04, 0x44, 0x58, // ewProj..`...t.DX + 0x42, 0x43, 0xe3, 0x22, 0x0f, 0xd1, 0xff, 0x88, 0xa2, 0x22, 0x16, 0xe2, 0x07, 0x99, 0x95, 0xfb, // BC."....."...... + 0x1a, 0x5b, 0x01, 0x00, 0x00, 0x00, 0x74, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0x00, // .[....t.......4. + 0x00, 0x00, 0x78, 0x02, 0x00, 0x00, 0xc8, 0x02, 0x00, 0x00, 0x1c, 0x03, 0x00, 0x00, 0xf8, 0x03, // ..x............. + 0x00, 0x00, 0x52, 0x44, 0x45, 0x46, 0x3c, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, // ..RDEF<.......H. + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x04, 0xfe, 0xff, 0x00, 0x91, // ................ + 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ......<......... + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, // ................ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x00, 0xab, // ......$Globals.. + 0xab, 0xab, 0x3c, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xb0, 0x09, // ..<.......`..... + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x01, 0x00, 0x00, 0x00, 0x00, // ..........P..... + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x01, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, 0x6c, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, // ..l............. + 0x00, 0x00, 0x5c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0x20, 0x00, // ..........x... . + 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, // ..@............. + 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, // ......`...@..... + 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9b, 0x01, 0x00, 0x00, 0xa0, 0x00, // ................ + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x01, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, 0xb4, 0x01, 0x00, 0x00, 0xa0, 0x08, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, // ..........@..... + 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xe0, 0x08, // ................ + 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, // ..@............. + 0x00, 0x00, 0xd0, 0x01, 0x00, 0x00, 0x20, 0x09, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, // ...... ...@..... + 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x01, 0x00, 0x00, 0x60, 0x09, // ..............`. + 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, // ..@............. + 0x00, 0x00, 0xed, 0x01, 0x00, 0x00, 0xa0, 0x09, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x5f, 0x76, 0x69, 0x65, 0x77, // ..........u_view + 0x52, 0x65, 0x63, 0x74, 0x00, 0xab, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, // Rect............ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x5f, 0x76, 0x69, 0x65, 0x77, 0x54, 0x65, 0x78, 0x65, // ......u_viewTexe + 0x6c, 0x00, 0x75, 0x5f, 0x76, 0x69, 0x65, 0x77, 0x00, 0xab, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, // l.u_view........ + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x5f, 0x76, 0x69, 0x65, 0x77, // ..........u_view + 0x50, 0x72, 0x6f, 0x6a, 0x00, 0x75, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x00, 0xab, 0x03, 0x00, // Proj.u_model.... + 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x5f, // ...... .......u_ + 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x56, 0x69, 0x65, 0x77, 0x00, 0x75, 0x5f, 0x6d, 0x6f, 0x64, 0x65, // modelView.u_mode + 0x6c, 0x56, 0x69, 0x65, 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x00, 0x75, 0x5f, 0x6d, 0x6f, 0x64, 0x65, // lViewProj.u_mode + 0x6c, 0x56, 0x69, 0x65, 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x58, 0x00, 0x75, 0x5f, 0x76, 0x69, 0x65, // lViewProjX.u_vie + 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x58, 0x00, 0x75, 0x5f, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x52, 0x65, // wProjX.u_alphaRe + 0x66, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // f............... + 0x00, 0x00, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x28, 0x52, 0x29, 0x20, // ..Microsoft (R) + 0x48, 0x4c, 0x53, 0x4c, 0x20, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x43, 0x6f, 0x6d, 0x70, // HLSL Shader Comp + 0x69, 0x6c, 0x65, 0x72, 0x20, 0x39, 0x2e, 0x32, 0x39, 0x2e, 0x39, 0x35, 0x32, 0x2e, 0x33, 0x31, // iler 9.29.952.31 + 0x31, 0x31, 0x00, 0xab, 0xab, 0xab, 0x49, 0x53, 0x47, 0x4e, 0x48, 0x00, 0x00, 0x00, 0x02, 0x00, // 11....ISGNH..... + 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ......8......... + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x3e, 0x00, // ..............>. + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, // ................ + 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x43, 0x4f, 0x4c, 0x4f, 0x52, 0x00, 0x50, 0x4f, 0x53, 0x49, // ......COLOR.POSI + 0x54, 0x49, 0x4f, 0x4e, 0x00, 0xab, 0x4f, 0x53, 0x47, 0x4e, 0x4c, 0x00, 0x00, 0x00, 0x02, 0x00, // TION..OSGNL..... + 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, // ......8......... + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x44, 0x00, // ..............D. + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, // ................ + 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x53, 0x56, 0x5f, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, // ......SV_POSITIO + 0x4e, 0x00, 0x43, 0x4f, 0x4c, 0x4f, 0x52, 0x00, 0xab, 0xab, 0x53, 0x48, 0x44, 0x52, 0xd4, 0x00, // N.COLOR...SHDR.. + 0x00, 0x00, 0x40, 0x00, 0x01, 0x00, 0x35, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x04, 0x46, 0x8e, // ..@...5...Y...F. + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x03, 0xf2, 0x10, // ........._..... + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x03, 0x32, 0x10, 0x10, 0x00, 0x01, 0x00, // ......_...2..... + 0x00, 0x00, 0x67, 0x00, 0x00, 0x04, 0xf2, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, // ..g.... ........ + 0x00, 0x00, 0x65, 0x00, 0x00, 0x03, 0xf2, 0x20, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x68, 0x00, // ..e.... ......h. + 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x08, 0xf2, 0x00, 0x10, 0x00, 0x00, 0x00, // ......8......... + 0x00, 0x00, 0x56, 0x15, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x8e, 0x20, 0x00, 0x00, 0x00, // ..V.......F. ... + 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x0a, 0xf2, 0x00, 0x10, 0x00, 0x00, 0x00, // ......2......... + 0x00, 0x00, 0x46, 0x8e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x10, // ..F. ........... + 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ......F......... + 0x00, 0x08, 0xf2, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, 0x00, 0x00, // ... ......F..... + 0x00, 0x00, 0x46, 0x8e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x36, 0x00, // ..F. .........6. + 0x00, 0x05, 0xf2, 0x20, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x1e, 0x10, 0x00, 0x00, 0x00, // ... ......F..... + 0x00, 0x00, 0x3e, 0x00, 0x00, 0x01, 0x53, 0x54, 0x41, 0x54, 0x74, 0x00, 0x00, 0x00, 0x05, 0x00, // ..>...STATt..... + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, // ................ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, 0x00, // ... +}; +static const uint8_t vs_imgui_color_glsl[321] = +{ + 0x56, 0x53, 0x48, 0x01, 0xa4, 0x8b, 0xef, 0x49, 0x23, 0x69, 0x66, 0x64, 0x65, 0x66, 0x20, 0x47, // VSH....I#ifdef G + 0x4c, 0x5f, 0x45, 0x53, 0x0a, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x68, // L_ES.precision h + 0x69, 0x67, 0x68, 0x70, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x3b, 0x0a, 0x23, 0x65, 0x6e, 0x64, // ighp float;.#end + 0x69, 0x66, 0x20, 0x2f, 0x2f, 0x20, 0x47, 0x4c, 0x5f, 0x45, 0x53, 0x0a, 0x0a, 0x75, 0x6e, 0x69, // if // GL_ES..uni + 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x6d, 0x61, 0x74, 0x34, 0x20, 0x75, 0x5f, 0x76, 0x69, 0x65, 0x77, // form mat4 u_view + 0x50, 0x72, 0x6f, 0x6a, 0x3b, 0x0a, 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, // Proj;.varying ve + 0x63, 0x34, 0x20, 0x76, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x30, 0x3b, 0x0a, 0x61, 0x74, 0x74, // c4 v_color0;.att + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, 0x61, 0x5f, 0x70, 0x6f, // ribute vec2 a_po + 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3b, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, // sition;.attribut + 0x65, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x61, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x30, 0x3b, // e vec4 a_color0; + 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x20, 0x28, 0x29, 0x0a, 0x7b, 0x0a, // .void main ().{. + 0x20, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x31, 0x3b, // vec4 tmpvar_1; + 0x0a, 0x20, 0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x31, 0x2e, 0x7a, 0x77, 0x20, 0x3d, // . tmpvar_1.zw = + 0x20, 0x76, 0x65, 0x63, 0x32, 0x28, 0x30, 0x2e, 0x30, 0x2c, 0x20, 0x31, 0x2e, 0x30, 0x29, 0x3b, // vec2(0.0, 1.0); + 0x0a, 0x20, 0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x31, 0x2e, 0x78, 0x79, 0x20, 0x3d, // . tmpvar_1.xy = + 0x20, 0x61, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3b, 0x0a, 0x20, 0x20, 0x67, // a_position;. g + 0x6c, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x28, 0x75, 0x5f, // l_Position = (u_ + 0x76, 0x69, 0x65, 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x20, 0x2a, 0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, // viewProj * tmpva + 0x72, 0x5f, 0x31, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x76, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x30, // r_1);. v_color0 + 0x20, 0x3d, 0x20, 0x61, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x30, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, // = a_color0;.}.. + 0x00, // . +}; diff --git a/examples/common/imgui/vs_imgui_color.sc b/examples/common/imgui/vs_imgui_color.sc new file mode 100644 index 00000000..4ddb8d84 --- /dev/null +++ b/examples/common/imgui/vs_imgui_color.sc @@ -0,0 +1,15 @@ +$input a_position, a_color0 +$output v_color0 + +/* + * Copyright 2011-2013 Branimir Karadzic. All rights reserved. + * License: http://www.opensource.org/licenses/BSD-2-Clause + */ + +#include + +void main() +{ + gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0) ); + v_color0 = a_color0; +} diff --git a/examples/common/imgui/vs_imgui_texture.bin.h b/examples/common/imgui/vs_imgui_texture.bin.h new file mode 100644 index 00000000..a542e821 --- /dev/null +++ b/examples/common/imgui/vs_imgui_texture.bin.h @@ -0,0 +1,137 @@ +static const uint8_t vs_imgui_texture_dx9[326] = +{ + 0x56, 0x53, 0x48, 0x01, 0x01, 0x83, 0xf2, 0xe1, 0x01, 0x00, 0x0a, 0x75, 0x5f, 0x76, 0x69, 0x65, // VSH........u_vie + 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x09, 0x01, 0x00, 0x00, 0x04, 0x00, 0x28, 0x01, 0x00, 0x03, 0xfe, // wProj......(.... + 0xff, 0xfe, 0xff, 0x22, 0x00, 0x43, 0x54, 0x41, 0x42, 0x1c, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, // ...".CTAB....S.. + 0x00, 0x00, 0x03, 0xfe, 0xff, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, // ................ + 0x00, 0x4c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, // .L...0.......... + 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x5f, 0x76, 0x69, 0x65, 0x77, 0x50, // .<.......u_viewP + 0x72, 0x6f, 0x6a, 0x00, 0xab, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, // roj............. + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x73, 0x5f, 0x33, 0x5f, 0x30, 0x00, 0x4d, 0x69, 0x63, 0x72, // .....vs_3_0.Micr + 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x28, 0x52, 0x29, 0x20, 0x48, 0x4c, 0x53, 0x4c, 0x20, 0x53, // osoft (R) HLSL S + 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x39, // hader Compiler 9 + 0x2e, 0x32, 0x39, 0x2e, 0x39, 0x35, 0x32, 0x2e, 0x33, 0x31, 0x31, 0x31, 0x00, 0x1f, 0x00, 0x00, // .29.952.3111.... + 0x02, 0x0a, 0x00, 0x00, 0x80, 0x00, 0x00, 0x0f, 0x90, 0x1f, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, // ................ + 0x80, 0x01, 0x00, 0x0f, 0x90, 0x1f, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x80, 0x02, 0x00, 0x0f, // ................ + 0x90, 0x1f, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x0f, 0xe0, 0x1f, 0x00, 0x00, // ................ + 0x02, 0x0a, 0x00, 0x00, 0x80, 0x01, 0x00, 0x0f, 0xe0, 0x1f, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, // ................ + 0x80, 0x02, 0x00, 0x03, 0xe0, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x0f, 0x80, 0x01, 0x00, 0xe4, // ................ + 0xa0, 0x01, 0x00, 0x55, 0x90, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0xe4, // ...U............ + 0xa0, 0x01, 0x00, 0x00, 0x90, 0x00, 0x00, 0xe4, 0x80, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x0f, // ................ + 0xe0, 0x00, 0x00, 0xe4, 0x80, 0x03, 0x00, 0xe4, 0xa0, 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x0f, // ................ + 0xe0, 0x00, 0x00, 0xe4, 0x90, 0x01, 0x00, 0x00, 0x02, 0x02, 0x00, 0x03, 0xe0, 0x02, 0x00, 0xe4, // ................ + 0x90, 0xff, 0xff, 0x00, 0x00, 0x00, // ...... +}; +static const uint8_t vs_imgui_texture_dx11[1295] = +{ + 0x56, 0x53, 0x48, 0x01, 0x01, 0x83, 0xf2, 0xe1, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, // VSH............. + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb0, 0x09, 0x0a, 0x75, 0x5f, 0x76, 0x69, // ............u_vi + 0x65, 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x09, 0x00, 0x60, 0x00, 0x04, 0x00, 0xe0, 0x04, 0x44, 0x58, // ewProj..`.....DX + 0x42, 0x43, 0xba, 0x64, 0x76, 0xcf, 0xca, 0x9d, 0xf4, 0xd5, 0x85, 0xc5, 0x48, 0xa7, 0x92, 0xde, // BC.dv.......H... + 0x73, 0x7f, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0x00, // s.............4. + 0x00, 0x00, 0x78, 0x02, 0x00, 0x00, 0xe8, 0x02, 0x00, 0x00, 0x5c, 0x03, 0x00, 0x00, 0x64, 0x04, // ..x...........d. + 0x00, 0x00, 0x52, 0x44, 0x45, 0x46, 0x3c, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, // ..RDEF<.......H. + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x04, 0xfe, 0xff, 0x00, 0x91, // ................ + 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ......<......... + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, // ................ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x00, 0xab, // ......$Globals.. + 0xab, 0xab, 0x3c, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xb0, 0x09, // ..<.......`..... + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x01, 0x00, 0x00, 0x00, 0x00, // ..........P..... + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x01, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, 0x6c, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, // ..l............. + 0x00, 0x00, 0x5c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0x20, 0x00, // ..........x... . + 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, // ..@............. + 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, // ......`...@..... + 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9b, 0x01, 0x00, 0x00, 0xa0, 0x00, // ................ + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x01, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, 0xb4, 0x01, 0x00, 0x00, 0xa0, 0x08, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, // ..........@..... + 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xe0, 0x08, // ................ + 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, // ..@............. + 0x00, 0x00, 0xd0, 0x01, 0x00, 0x00, 0x20, 0x09, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, // ...... ...@..... + 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x01, 0x00, 0x00, 0x60, 0x09, // ..............`. + 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, // ..@............. + 0x00, 0x00, 0xed, 0x01, 0x00, 0x00, 0xa0, 0x09, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x5f, 0x76, 0x69, 0x65, 0x77, // ..........u_view + 0x52, 0x65, 0x63, 0x74, 0x00, 0xab, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, // Rect............ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x5f, 0x76, 0x69, 0x65, 0x77, 0x54, 0x65, 0x78, 0x65, // ......u_viewTexe + 0x6c, 0x00, 0x75, 0x5f, 0x76, 0x69, 0x65, 0x77, 0x00, 0xab, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, // l.u_view........ + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x5f, 0x76, 0x69, 0x65, 0x77, // ..........u_view + 0x50, 0x72, 0x6f, 0x6a, 0x00, 0x75, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x00, 0xab, 0x03, 0x00, // Proj.u_model.... + 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x5f, // ...... .......u_ + 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x56, 0x69, 0x65, 0x77, 0x00, 0x75, 0x5f, 0x6d, 0x6f, 0x64, 0x65, // modelView.u_mode + 0x6c, 0x56, 0x69, 0x65, 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x00, 0x75, 0x5f, 0x6d, 0x6f, 0x64, 0x65, // lViewProj.u_mode + 0x6c, 0x56, 0x69, 0x65, 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x58, 0x00, 0x75, 0x5f, 0x76, 0x69, 0x65, // lViewProjX.u_vie + 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x58, 0x00, 0x75, 0x5f, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x52, 0x65, // wProjX.u_alphaRe + 0x66, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // f............... + 0x00, 0x00, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x28, 0x52, 0x29, 0x20, // ..Microsoft (R) + 0x48, 0x4c, 0x53, 0x4c, 0x20, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x43, 0x6f, 0x6d, 0x70, // HLSL Shader Comp + 0x69, 0x6c, 0x65, 0x72, 0x20, 0x39, 0x2e, 0x32, 0x39, 0x2e, 0x39, 0x35, 0x32, 0x2e, 0x33, 0x31, // iler 9.29.952.31 + 0x31, 0x31, 0x00, 0xab, 0xab, 0xab, 0x49, 0x53, 0x47, 0x4e, 0x68, 0x00, 0x00, 0x00, 0x03, 0x00, // 11....ISGNh..... + 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ......P......... + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x56, 0x00, // ..............V. + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, // ................ + 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ......_......... + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x43, 0x4f, // ..............CO + 0x4c, 0x4f, 0x52, 0x00, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x00, 0x54, 0x45, 0x58, // LOR.POSITION.TEX + 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, 0x4f, 0x53, 0x47, 0x4e, 0x6c, 0x00, 0x00, 0x00, 0x03, 0x00, // COORD.OSGNl..... + 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, // ......P......... + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x5c, 0x00, // ................ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, // ................ + 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ......b......... + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x0c, 0x00, 0x00, 0x53, 0x56, // ..............SV + 0x5f, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x00, 0x43, 0x4f, 0x4c, 0x4f, 0x52, 0x00, // _POSITION.COLOR. + 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, 0xab, 0x53, 0x48, 0x44, 0x52, 0x00, 0x01, // TEXCOORD..SHDR.. + 0x00, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x04, 0x46, 0x8e, // ..@...@...Y...F. + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x03, 0xf2, 0x10, // ........._..... + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x03, 0x32, 0x10, 0x10, 0x00, 0x01, 0x00, // ......_...2..... + 0x00, 0x00, 0x5f, 0x00, 0x00, 0x03, 0x32, 0x10, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x67, 0x00, // .._...2.......g. + 0x00, 0x04, 0xf2, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x65, 0x00, // ... ..........e. + 0x00, 0x03, 0xf2, 0x20, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x03, 0x32, 0x20, // ... ......e...2 + 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x38, 0x00, // ......h.......8. + 0x00, 0x08, 0xf2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x15, 0x10, 0x00, 0x01, 0x00, // ..........V..... + 0x00, 0x00, 0x46, 0x8e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x32, 0x00, // ..F. .........2. + 0x00, 0x0a, 0xf2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x8e, 0x20, 0x00, 0x00, 0x00, // ..........F. ... + 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x0e, // ..............F. + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xf2, 0x20, 0x10, 0x00, 0x00, 0x00, // ........... .... + 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x8e, 0x20, 0x00, 0x00, 0x00, // ..F.......F. ... + 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0xf2, 0x20, 0x10, 0x00, 0x01, 0x00, // ......6.... .... + 0x00, 0x00, 0x46, 0x1e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0x32, 0x20, // ..F.......6...2 + 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x46, 0x10, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x3e, 0x00, // ......F.......>. + 0x00, 0x01, 0x53, 0x54, 0x41, 0x54, 0x74, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, // ..STATt......... + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ............... +}; +static const uint8_t vs_imgui_texture_glsl[404] = +{ + 0x56, 0x53, 0x48, 0x01, 0x01, 0x83, 0xf2, 0xe1, 0x23, 0x69, 0x66, 0x64, 0x65, 0x66, 0x20, 0x47, // VSH.....#ifdef G + 0x4c, 0x5f, 0x45, 0x53, 0x0a, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x68, // L_ES.precision h + 0x69, 0x67, 0x68, 0x70, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x3b, 0x0a, 0x23, 0x65, 0x6e, 0x64, // ighp float;.#end + 0x69, 0x66, 0x20, 0x2f, 0x2f, 0x20, 0x47, 0x4c, 0x5f, 0x45, 0x53, 0x0a, 0x0a, 0x75, 0x6e, 0x69, // if // GL_ES..uni + 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x6d, 0x61, 0x74, 0x34, 0x20, 0x75, 0x5f, 0x76, 0x69, 0x65, 0x77, // form mat4 u_view + 0x50, 0x72, 0x6f, 0x6a, 0x3b, 0x0a, 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, // Proj;.varying ve + 0x63, 0x32, 0x20, 0x76, 0x5f, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x30, 0x3b, 0x0a, // c2 v_texcoord0;. + 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x76, 0x5f, 0x63, // varying vec4 v_c + 0x6f, 0x6c, 0x6f, 0x72, 0x30, 0x3b, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, // olor0;.attribute + 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, 0x61, 0x5f, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, // vec2 a_texcoord + 0x30, 0x3b, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x76, 0x65, 0x63, // 0;.attribute vec + 0x32, 0x20, 0x61, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3b, 0x0a, 0x61, 0x74, // 2 a_position;.at + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x61, 0x5f, 0x63, // tribute vec4 a_c + 0x6f, 0x6c, 0x6f, 0x72, 0x30, 0x3b, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6d, 0x61, 0x69, 0x6e, // olor0;.void main + 0x20, 0x28, 0x29, 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x74, 0x6d, 0x70, // ().{. vec4 tmp + 0x76, 0x61, 0x72, 0x5f, 0x31, 0x3b, 0x0a, 0x20, 0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, // var_1;. tmpvar_ + 0x31, 0x2e, 0x7a, 0x77, 0x20, 0x3d, 0x20, 0x76, 0x65, 0x63, 0x32, 0x28, 0x30, 0x2e, 0x30, 0x2c, // 1.zw = vec2(0.0, + 0x20, 0x31, 0x2e, 0x30, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, // 1.0);. tmpvar_ + 0x31, 0x2e, 0x78, 0x79, 0x20, 0x3d, 0x20, 0x61, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, // 1.xy = a_positio + 0x6e, 0x3b, 0x0a, 0x20, 0x20, 0x67, 0x6c, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, // n;. gl_Position + 0x20, 0x3d, 0x20, 0x28, 0x75, 0x5f, 0x76, 0x69, 0x65, 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x20, 0x2a, // = (u_viewProj * + 0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x31, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x76, 0x5f, // tmpvar_1);. v_ + 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x30, 0x20, 0x3d, 0x20, 0x61, 0x5f, 0x74, 0x65, // texcoord0 = a_te + 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x30, 0x3b, 0x0a, 0x20, 0x20, 0x76, 0x5f, 0x63, 0x6f, 0x6c, // xcoord0;. v_col + 0x6f, 0x72, 0x30, 0x20, 0x3d, 0x20, 0x61, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x30, 0x3b, 0x0a, // or0 = a_color0;. + 0x7d, 0x0a, 0x0a, 0x00, // }... +}; diff --git a/examples/common/imgui/vs_imgui_texture.sc b/examples/common/imgui/vs_imgui_texture.sc new file mode 100644 index 00000000..193f6db7 --- /dev/null +++ b/examples/common/imgui/vs_imgui_texture.sc @@ -0,0 +1,16 @@ +$input a_position, a_texcoord0, a_color0 +$output v_texcoord0, v_color0 + +/* + * Copyright 2011-2013 Branimir Karadzic. All rights reserved. + * License: http://www.opensource.org/licenses/BSD-2-Clause + */ + +#include + +void main() +{ + gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0) ); + v_texcoord0 = a_texcoord0; + v_color0 = a_color0; +} diff --git a/examples/common/processevents.h b/examples/common/processevents.h index 183f6f72..c1eca843 100644 --- a/examples/common/processevents.h +++ b/examples/common/processevents.h @@ -6,7 +6,24 @@ #ifndef __PROCESS_EVENTS_H__ #define __PROCESS_EVENTS_H__ -inline bool processEvents(uint32_t& _width, uint32_t& _height, uint32_t& _debug, uint32_t& _reset) +struct MouseState +{ + MouseState() + : m_mx(0) + , m_my(0) + { + for (uint32_t ii = 0; ii < entry::MouseButton::Count; ++ii) + { + m_buttons[ii] = entry::MouseButton::None; + } + } + + uint32_t m_mx; + uint32_t m_my; + uint8_t m_buttons[entry::MouseButton::Count]; +}; + +inline bool processEvents(uint32_t& _width, uint32_t& _height, uint32_t& _debug, uint32_t& _reset, MouseState* _mouse = NULL) { using namespace entry; @@ -26,11 +43,18 @@ inline bool processEvents(uint32_t& _width, uint32_t& _height, uint32_t& _debug, return true; case Event::Mouse: + if (NULL != _mouse) { -// const MouseEvent* mouse = static_cast(ev); -// if (mouse->m_move) -// { -// } + const MouseEvent* mouse = static_cast(ev); + if (mouse->m_move) + { + _mouse->m_mx = mouse->m_mx; + _mouse->m_my = mouse->m_my; + } + else + { + _mouse->m_buttons[mouse->m_button] = mouse->m_down; + } } break; @@ -50,6 +74,11 @@ inline bool processEvents(uint32_t& _width, uint32_t& _height, uint32_t& _debug, bgfx::setDebug(_debug); return false; } + else if (key->m_key == Key::F7) + { + _reset ^= BGFX_RESET_VSYNC; + reset = true; + } else if (key->m_key == Key::F8) { _reset ^= BGFX_RESET_MSAA_X16; diff --git a/examples/runtime/font/droidsans.ttf b/examples/runtime/font/droidsans.ttf new file mode 100644 index 00000000..767c63ad Binary files /dev/null and b/examples/runtime/font/droidsans.ttf differ diff --git a/include/bgfx.h b/include/bgfx.h index 369e8972..805c9005 100644 --- a/include/bgfx.h +++ b/include/bgfx.h @@ -223,7 +223,8 @@ namespace bgfx { enum Enum { - MinimumRequiredSpecs = 1, + DebugCheck, + MinimumRequiredSpecs, InvalidShader, UnableToInitialize, UnableToCreateRenderTarget, @@ -350,11 +351,13 @@ namespace bgfx /// NOTE: /// 'fatal' callback can be called from any thread. Other callbacks /// are called from the render thread. + /// struct CallbackI { virtual ~CallbackI() = 0; - /// Called on unrecoverable error. It's not safe to continue, inform + /// If fatal code code is not Fatal::DebugCheck this callback is + /// called on unrecoverable error. It's not safe to continue, inform /// user and terminate application from this call. virtual void fatal(Fatal::Enum _code, const char* _str) = 0; @@ -454,6 +457,7 @@ namespace bgfx /// /// NOTE: /// Must be called between begin/end. + /// void add(Attrib::Enum _attrib, uint8_t _num, AttribType::Enum _type, bool _normalized = false, bool _asInt = false); /// Decode attribute. @@ -579,21 +583,38 @@ namespace bgfx /// Update dynamic vertex buffer. void updateDynamicVertexBuffer(DynamicVertexBufferHandle _handle, const Memory* _mem); - /// Destory dynamic vertex buffer. + /// Destroy dynamic vertex buffer. void destroyDynamicVertexBuffer(DynamicVertexBufferHandle _handle); /// Returns true if internal transient index buffer has enough space. - bool checkAvailTransientIndexBuffer(uint16_t _num); + /// + /// @param _num Number of indices. + /// + bool checkAvailTransientIndexBuffer(uint32_t _num); + + /// Returns true if internal transient vertex buffer has enough space. + /// + /// @param _num Number of vertices. + /// @param _decl Vertex declaration. + /// + bool checkAvailTransientVertexBuffer(uint32_t _num, const VertexDecl& _decl); + + /// Returns true if both internal transient index and vertex buffer have + /// enough space. + /// + /// @param _numVertices Number of vertices. + /// @param _decl Vertex declaration. + /// @param _numIndices Number of indices. + /// + bool checkAvailTransientBuffers(uint32_t _numVertices, const VertexDecl& _decl, uint32_t _numIndices); /// Allocate transient index buffer. /// /// @param[out] _tib is valid for the duration of frame, and it can be /// reused for multiple draw calls. /// @param _num number of indices to allocate. - void allocTransientIndexBuffer(TransientIndexBuffer* _tib, uint16_t _num); - - /// Returns true if internal transient vertex buffer has enough space. - bool checkAvailTransientVertexBuffer(uint16_t _num, const VertexDecl& _decl); + /// + void allocTransientIndexBuffer(TransientIndexBuffer* _tib, uint32_t _num); /// Allocate transient vertex buffer. /// @@ -601,10 +622,11 @@ namespace bgfx /// reused for multiple draw calls. /// @param _num number of vertices to allocate. /// @param _decl vertex declaration. - void allocTransientVertexBuffer(TransientVertexBuffer* _tvb, uint16_t _num, const VertexDecl& _decl); + /// + void allocTransientVertexBuffer(TransientVertexBuffer* _tvb, uint32_t _num, const VertexDecl& _decl); /// Allocate instance data buffer. - const InstanceDataBuffer* allocInstanceDataBuffer(uint16_t _num, uint16_t _stride); + const InstanceDataBuffer* allocInstanceDataBuffer(uint32_t _num, uint16_t _stride); /// Create vertex shader from memory buffer. VertexShaderHandle createVertexShader(const Memory* _mem); @@ -626,6 +648,7 @@ namespace bgfx /// @param _fsh fragment shader. /// @returns Program handle if vertex shader output and fragment shader /// input are matching, otherwise returns invalid program handle. + /// ProgramHandle createProgram(VertexShaderHandle _vsh, FragmentShaderHandle _fsh); /// Destroy program. @@ -635,6 +658,7 @@ namespace bgfx void calcTextureSize(TextureInfo& _info, uint16_t _width, uint16_t _height, uint16_t _depth, uint8_t _numMips, TextureFormat::Enum _format); /// Create texture from memory buffer. + /// /// @param _mem DDS texture data. /// @param _flags Default texture sampling mode is linear, and wrap mode /// is repeat. @@ -649,6 +673,7 @@ namespace bgfx /// /// @param _info Returns parsed DDS texture information. /// @returns Texture handle. + /// TextureHandle createTexture(const Memory* _mem, uint32_t _flags = BGFX_TEXTURE_NONE, TextureInfo* _info = NULL); /// Create 2D texture. @@ -699,6 +724,7 @@ namespace bgfx /// @param _rgba color clear value. /// @param _depth depth clear value. /// @param _stencil stencil clear value. + /// void setViewClear(uint8_t _id, uint8_t _flags, uint32_t _rgba = 0x000000ff, float _depth = 1.0f, uint8_t _stencil = 0); /// Set view clear flags for multiple views. @@ -726,6 +752,7 @@ namespace bgfx void setViewTransformMask(uint32_t _viewMask, const void* _view, const void* _proj, uint8_t _other = 0xff); /// Set render states for draw primitive. + /// /// @param _state State flags. Default state for primitive type is /// triangles. See: BGFX_STATE_DEFAULT. /// @@ -745,6 +772,7 @@ namespace bgfx /// NOTE: /// Use BGFX_STATE_ALPHA_REF, BGFX_STATE_POINT_SIZE and /// BGFX_STATE_BLEND_FUNC macros to setup more complex states. + /// void setState(uint64_t _state, uint32_t _rgba = UINT32_MAX); /// Set stencil test state. @@ -752,6 +780,7 @@ namespace bgfx /// @param _fstencil Front stencil state. /// @param _bstencil Back stencil state. If back is set to BGFX_STENCIL_NONE /// _fstencil is applied to both front and back facing primitives. + /// void setStencil(uint32_t _fstencil, uint32_t _bstencil = BGFX_STENCIL_NONE); /// Set model matrix for draw primitive. If it is not called model will @@ -761,12 +790,14 @@ namespace bgfx /// @param _num number of matrices in array. /// @returns index into matrix cache in case the same model matrix has /// to be used for other draw primitive call. + /// uint32_t setTransform(const void* _mtx, uint16_t _num = 1); /// Set model matrix from matrix cache for draw primitive. /// /// @param _cache index in matrix cache. /// @param _num number of matrices from cache. + /// void setTransform(uint32_t _cache, uint16_t _num = 1); /// Set shader uniform parameter for draw primitive. @@ -806,12 +837,14 @@ namespace bgfx /// /// @param _id View id. /// @param _depth depth for sorting. + /// void submit(uint8_t _id, int32_t _depth = 0); /// Submit primitive for rendering into multiple views. /// /// @param _viewMask mask to which views to submit draw primitive calls. /// @param _depth depth for sorting. + /// void submitMask(uint32_t _viewMask, int32_t _depth = 0); /// Request screen shot. diff --git a/makefile b/makefile index 1d1ae251..e852410f 100755 --- a/makefile +++ b/makefile @@ -102,6 +102,7 @@ rebuild-shaders: make -R -C examples rebuild docs: + doxygen premake/bgfx.doxygen markdown README.md > .build/docs/readme.html clean: diff --git a/premake/bgfx.doxygen b/premake/bgfx.doxygen index c3c90a79..a78861fd 100644 --- a/premake/bgfx.doxygen +++ b/premake/bgfx.doxygen @@ -661,7 +661,7 @@ WARN_LOGFILE = # directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = include/bgfx.h +INPUT = include/bgfx.h README.md # 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 diff --git a/premake/bgfx.lua b/premake/bgfx.lua index 14484943..5b7cbc91 100755 --- a/premake/bgfx.lua +++ b/premake/bgfx.lua @@ -30,7 +30,7 @@ project "bgfx" BGFX_DIR .. "src/**.mm", } - configuration { "vs* or linux" } + configuration { "vs* or linux or mingw or osx" } includedirs { --nacl has GLES2 headers modified... BGFX_DIR .. "3rdparty/glext", diff --git a/premake/geometryc.lua b/premake/geometryc.lua index 3444273f..f5950b89 100644 --- a/premake/geometryc.lua +++ b/premake/geometryc.lua @@ -15,3 +15,5 @@ project "geometryc" BGFX_DIR .. "tools/geometryc/**.cpp", BGFX_DIR .. "tools/geometryc/**.h", } + + strip() diff --git a/premake/premake4.lua b/premake/premake4.lua index 9e53ad56..df3ccea0 100644 --- a/premake/premake4.lua +++ b/premake/premake4.lua @@ -46,6 +46,7 @@ function exampleProject(_name, _uuid) includedirs { BX_DIR .. "include", BGFX_DIR .. "include", + BGFX_DIR .. "3rdparty", } files { @@ -80,6 +81,7 @@ function exampleProject(_name, _uuid) configuration { "linux" } links { + "X11", "GL", "pthread", } diff --git a/premake/shaderc.lua b/premake/shaderc.lua index 44ffaaad..6d2e20a2 100644 --- a/premake/shaderc.lua +++ b/premake/shaderc.lua @@ -91,3 +91,5 @@ project "shaderc" GLSL_OPTIMIZER .. "src/glsl/main.cpp", GLSL_OPTIMIZER .. "src/glsl/builtin_stubs.cpp", } + + strip() diff --git a/src/bgfx.cpp b/src/bgfx.cpp index 266834fa..922e6298 100755 --- a/src/bgfx.cpp +++ b/src/bgfx.cpp @@ -63,9 +63,16 @@ namespace bgfx virtual void fatal(Fatal::Enum _code, const char* _str) BX_OVERRIDE { - BX_TRACE("0x%08x: %s", _code, _str); - BX_UNUSED(_code, _str); - abort(); + if (Fatal::DebugCheck == _code) + { + bx::debugBreak(); + } + else + { + BX_TRACE("0x%08x: %s", _code, _str); + BX_UNUSED(_code, _str); + abort(); + } } virtual uint32_t cacheReadSize(uint64_t /*_id*/) BX_OVERRIDE @@ -130,7 +137,7 @@ namespace bgfx va_list argList; va_start(argList, _format); - vsnprintf(temp, sizeof(temp), _format, argList); + bx::vsnprintf(temp, sizeof(temp), _format, argList); va_end(argList); temp[sizeof(temp)-1] = '\0'; @@ -917,14 +924,28 @@ namespace bgfx s_ctx.destroyDynamicVertexBuffer(_handle); } - bool checkAvailTransientIndexBuffer(uint16_t _num) + bool checkAvailTransientIndexBuffer(uint32_t _num) { BGFX_CHECK_MAIN_THREAD(); BX_CHECK(0 < _num, "Requesting 0 indices."); return s_ctx.m_submit->checkAvailTransientIndexBuffer(_num); } - void allocTransientIndexBuffer(TransientIndexBuffer* _tib, uint16_t _num) + bool checkAvailTransientVertexBuffer(uint32_t _num, const VertexDecl& _decl) + { + BGFX_CHECK_MAIN_THREAD(); + BX_CHECK(0 < _num, "Requesting 0 vertices."); + return s_ctx.m_submit->checkAvailTransientVertexBuffer(_num, _decl.m_stride); + } + + bool checkAvailTransientBuffers(uint32_t _numVertices, const VertexDecl& _decl, uint32_t _numIndices) + { + return checkAvailTransientVertexBuffer(_numVertices, _decl) + && checkAvailTransientIndexBuffer(_numIndices) + ; + } + + void allocTransientIndexBuffer(TransientIndexBuffer* _tib, uint32_t _num) { BGFX_CHECK_MAIN_THREAD(); BX_CHECK(NULL != _tib, "_tib can't be NULL"); @@ -932,22 +953,16 @@ namespace bgfx return s_ctx.allocTransientIndexBuffer(_tib, _num); } - bool checkAvailTransientVertexBuffer(uint16_t _num, const VertexDecl& _decl) - { - BGFX_CHECK_MAIN_THREAD(); - BX_CHECK(0 < _num, "Requesting 0 vertices."); - return s_ctx.m_submit->checkAvailTransientVertexBuffer(_num, _decl.m_stride); - } - - void allocTransientVertexBuffer(TransientVertexBuffer* _tvb, uint16_t _num, const VertexDecl& _decl) + void allocTransientVertexBuffer(TransientVertexBuffer* _tvb, uint32_t _num, const VertexDecl& _decl) { BGFX_CHECK_MAIN_THREAD(); BX_CHECK(NULL != _tvb, "_tvb can't be NULL"); BX_CHECK(0 < _num, "Requesting 0 vertices."); + BX_CHECK(UINT16_MAX >= _num, "Requesting %d vertices (max: %d).", _num, UINT16_MAX); return s_ctx.allocTransientVertexBuffer(_tvb, _num, _decl); } - const InstanceDataBuffer* allocInstanceDataBuffer(uint16_t _num, uint16_t _stride) + const InstanceDataBuffer* allocInstanceDataBuffer(uint32_t _num, uint16_t _stride) { BGFX_CHECK_MAIN_THREAD(); BX_CHECK(0 < _num, "Requesting 0 instanced data vertices."); @@ -1264,14 +1279,12 @@ namespace bgfx void setViewClear(uint8_t _id, uint8_t _flags, uint32_t _rgba, float _depth, uint8_t _stencil) { BGFX_CHECK_MAIN_THREAD(); - BX_CHECK(_flags != BGFX_CLEAR_NONE, "At least one clear bit flag must be used."); s_ctx.setViewClear(_id, _flags, _rgba, _depth, _stencil); } void setViewClearMask(uint32_t _viewMask, uint8_t _flags, uint32_t _rgba, float _depth, uint8_t _stencil) { BGFX_CHECK_MAIN_THREAD(); - BX_CHECK(_flags != BGFX_CLEAR_NONE, "At least one clear bit flag must be used."); s_ctx.setViewClearMask(_viewMask, _flags, _rgba, _depth, _stencil); } diff --git a/src/bgfx_p.h b/src/bgfx_p.h index 225a1362..b6602ceb 100755 --- a/src/bgfx_p.h +++ b/src/bgfx_p.h @@ -7,6 +7,8 @@ #define __BGFX_P_H__ #include "bgfx.h" +#include "config.h" + #include #include // va_list #include @@ -14,17 +16,16 @@ #include #include -extern void dbgPrintf(const char* _format, ...); -extern void dbgPrintfData(const void* _data, uint32_t _size, const char* _format, ...); - -#ifndef BGFX_CONFIG_DEBUG -# define BGFX_CONFIG_DEBUG 0 -#endif // BGFX_CONFIG_DEBUG +namespace bgfx +{ + void fatal(Fatal::Enum _code, const char* _format, ...); + void dbgPrintf(const char* _format, ...); +} #if BGFX_CONFIG_DEBUG # define BX_TRACE(_format, ...) \ do { \ - dbgPrintf(BX_FILE_LINE_LITERAL "BGFX " _format "\n", ##__VA_ARGS__); \ + bgfx::dbgPrintf(BX_FILE_LINE_LITERAL "BGFX " _format "\n", ##__VA_ARGS__); \ } while(0) # define BX_WARN(_condition, _format, ...) \ @@ -40,7 +41,7 @@ extern void dbgPrintfData(const void* _data, uint32_t _size, const char* _format if (!(_condition) ) \ { \ BX_TRACE("CHECK " _format, ##__VA_ARGS__); \ - bx::debugBreak(); \ + bgfx::fatal(bgfx::Fatal::DebugCheck, _format, ##__VA_ARGS__); \ } \ } while(0) #endif // 0 @@ -65,6 +66,7 @@ extern void dbgPrintfData(const void* _data, uint32_t _size, const char* _format #include #include #include +#include #include "dds.h" @@ -109,8 +111,6 @@ namespace stl { # include #endif // BX_PLATFORM_* -#include "config.h" - #include #include #include @@ -196,7 +196,6 @@ namespace bgfx extern ReallocFn g_realloc; extern FreeFn g_free; - void fatal(Fatal::Enum _code, const char* _format, ...); void release(const Memory* _mem); void saveTga(const char* _filePath, uint32_t _width, uint32_t _height, uint32_t _srcPitch, const void* _src, bool _grayscale = false, bool _yflip = false); const char* getAttribName(Attrib::Enum _attr); @@ -323,7 +322,7 @@ namespace bgfx { char* temp = (char*)alloca(m_width); - uint32_t num = vsnprintf(temp, m_width, _format, _argList); + uint32_t num = bx::vsnprintf(temp, m_width, _format, _argList); uint8_t* mem = &m_mem[(_y*m_width+_x)*2]; for (uint32_t ii = 0, xx = _x; ii < num && xx < m_width; ++ii, ++xx) @@ -986,7 +985,11 @@ namespace bgfx if (0 < m_numDropped) { - BX_TRACE("Too many draw calls: %d, dropped %d (max: %d)", m_num+m_numDropped, m_numDropped, BGFX_CONFIG_MAX_DRAW_CALLS); + BX_TRACE("Too many draw calls: %d, dropped %d (max: %d)" + , m_num+m_numDropped + , m_numDropped + , BGFX_CONFIG_MAX_DRAW_CALLS + ); } } @@ -1104,7 +1107,7 @@ namespace bgfx void submitMask(uint32_t _viewMask, int32_t _depth); void sort(); - bool checkAvailTransientIndexBuffer(uint16_t _num) + bool checkAvailTransientIndexBuffer(uint32_t _num) { uint32_t offset = m_iboffset; uint32_t iboffset = offset + _num*sizeof(uint16_t); @@ -1113,16 +1116,16 @@ namespace bgfx return num == _num; } - uint32_t allocTransientIndexBuffer(uint16_t& _num) + uint32_t allocTransientIndexBuffer(uint32_t& _num) { uint32_t offset = m_iboffset; m_iboffset = offset + _num*sizeof(uint16_t); m_iboffset = uint32_min(m_iboffset, BGFX_CONFIG_TRANSIENT_INDEX_BUFFER_SIZE); - _num = uint16_t( (m_iboffset-offset)/sizeof(uint16_t) ); + _num = (m_iboffset-offset)/sizeof(uint16_t); return offset; } - bool checkAvailTransientVertexBuffer(uint16_t _num, uint16_t _stride) + bool checkAvailTransientVertexBuffer(uint32_t _num, uint16_t _stride) { uint32_t offset = strideAlign(m_vboffset, _stride); uint32_t vboffset = offset + _num * _stride; @@ -1131,12 +1134,12 @@ namespace bgfx return num == _num; } - uint32_t allocTransientVertexBuffer(uint16_t& _num, uint16_t _stride) + uint32_t allocTransientVertexBuffer(uint32_t& _num, uint16_t _stride) { uint32_t offset = strideAlign(m_vboffset, _stride); m_vboffset = offset + _num * _stride; m_vboffset = uint32_min(m_vboffset, BGFX_CONFIG_TRANSIENT_VERTEX_BUFFER_SIZE); - _num = uint16_t( (m_vboffset-offset)/_stride); + _num = (m_vboffset-offset)/_stride; return offset; } @@ -1778,7 +1781,7 @@ namespace bgfx g_free(const_cast(_ib) ); } - void allocTransientIndexBuffer(TransientIndexBuffer* _tib, uint16_t _num) + void allocTransientIndexBuffer(TransientIndexBuffer* _tib, uint32_t _num) { uint32_t offset = m_submit->allocTransientIndexBuffer(_num); @@ -1835,7 +1838,7 @@ namespace bgfx g_free(const_cast(_vb) ); } - void allocTransientVertexBuffer(TransientVertexBuffer* _tvb, uint16_t _num, const VertexDecl& _decl) + void allocTransientVertexBuffer(TransientVertexBuffer* _tvb, uint32_t _num, const VertexDecl& _decl) { VertexDeclHandle declHandle = m_declRef.find(_decl.m_hash); @@ -1861,7 +1864,7 @@ namespace bgfx _tvb->decl = declHandle; } - const InstanceDataBuffer* allocInstanceDataBuffer(uint16_t _num, uint16_t _stride) + const InstanceDataBuffer* allocInstanceDataBuffer(uint32_t _num, uint16_t _stride) { uint16_t stride = BX_ALIGN_16(_stride); uint32_t offset = m_submit->allocTransientVertexBuffer(_num, stride); @@ -2290,7 +2293,7 @@ namespace bgfx } else { - m_view[_id].setIdentity(); + m_proj[_id].setIdentity(); } } diff --git a/src/config.h b/src/config.h index 7767cce0..3d1d64a5 100644 --- a/src/config.h +++ b/src/config.h @@ -6,6 +6,10 @@ #ifndef __CONFIG_H__ #define __CONFIG_H__ +#ifndef BGFX_CONFIG_DEBUG +# define BGFX_CONFIG_DEBUG 0 +#endif // BGFX_CONFIG_DEBUG + #if !defined(BGFX_CONFIG_RENDERER_DIRECT3D9) \ && !defined(BGFX_CONFIG_RENDERER_DIRECT3D11) \ && !defined(BGFX_CONFIG_RENDERER_OPENGL) \ diff --git a/src/glcontext_egl.cpp b/src/glcontext_egl.cpp index 92c93d55..a66b23ab 100644 --- a/src/glcontext_egl.cpp +++ b/src/glcontext_egl.cpp @@ -77,6 +77,8 @@ namespace bgfx success = eglMakeCurrent(m_display, m_surface, m_surface, m_context); BGFX_FATAL(success, Fatal::UnableToInitialize, "Failed to set context."); + eglSwapInterval(m_display, 0); + # if BX_PLATFORM_EMSCRIPTEN emscripten_set_canvas_size(_width, _height); # endif // BX_PLATFORM_EMSCRIPTEN @@ -93,8 +95,9 @@ namespace bgfx m_context = NULL; } - void GlContext::resize(uint32_t /*_width*/, uint32_t /*_height*/) + void GlContext::resize(uint32_t /*_width*/, uint32_t /*_height*/, bool _vsync) { + eglSwapInterval(m_display, _vsync ? 1 : 0); } void GlContext::swap() diff --git a/src/glcontext_egl.h b/src/glcontext_egl.h index 1fe35748..73cc0337 100644 --- a/src/glcontext_egl.h +++ b/src/glcontext_egl.h @@ -23,7 +23,7 @@ namespace bgfx void create(uint32_t _width, uint32_t _height); void destroy(); - void resize(uint32_t _width, uint32_t _height); + void resize(uint32_t _width, uint32_t _height, bool _vsync); void swap(); void import(); diff --git a/src/glcontext_glx.cpp b/src/glcontext_glx.cpp index ab1b68cd..f7df1404 100644 --- a/src/glcontext_glx.cpp +++ b/src/glcontext_glx.cpp @@ -5,13 +5,20 @@ #include "bgfx_p.h" -#if (BGFX_CONFIG_RENDERER_OPENGLES2|BGFX_CONFIG_RENDERER_OPENGLES3|BGFX_CONFIG_RENDERER_OPENGL) +#if BX_PLATFORM_LINUX & (BGFX_CONFIG_RENDERER_OPENGLES2|BGFX_CONFIG_RENDERER_OPENGLES3|BGFX_CONFIG_RENDERER_OPENGL) # include "renderer_gl.h" - -# if BX_PLATFORM_LINUX +# define GLX_GLXEXT_PROTOTYPES +# include namespace bgfx { + typedef int (*PFNGLXSWAPINTERVALMESAPROC)(uint32_t _interval); + + PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB; + PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT; + PFNGLXSWAPINTERVALMESAPROC glXSwapIntervalMESA; + PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalSGI; + # define GL_IMPORT(_optional, _proto, _func) _proto _func # include "glimports.h" # undef GL_IMPORT @@ -39,6 +46,12 @@ namespace bgfx , minor ); + int32_t screen = DefaultScreen(s_display); + + const char* extensions = glXQueryExtensionsString(s_display, screen); + BX_TRACE("GLX extensions:"); + dumpExtensions(extensions); + const int attrsGlx[] = { GLX_RENDER_TYPE, GLX_RGBA_BIT, @@ -57,7 +70,7 @@ namespace bgfx GLXFBConfig bestConfig = NULL; int numConfigs; - GLXFBConfig* configs = glXChooseFBConfig(s_display, DefaultScreen(s_display), attrsGlx, &numConfigs); + GLXFBConfig* configs = glXChooseFBConfig(s_display, screen, attrsGlx, &numConfigs); BX_TRACE("glX num configs %d", numConfigs); @@ -113,8 +126,7 @@ namespace bgfx XFree(visualInfo); #if BGFX_CONFIG_RENDERER_OPENGL >= 31 - typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*); - glXCreateContextAttribsARBProc glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)glXGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB"); + glXCreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddress( (const GLubyte*)"glXCreateContextAttribsARB"); if (NULL != glXCreateContextAttribsARB) { BX_TRACE("Create GL 3.1 context."); @@ -142,7 +154,33 @@ namespace bgfx import(); + glXSwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC)glXGetProcAddress( (const GLubyte*)"glXSwapIntervalEXT"); + if (NULL != glXSwapIntervalEXT) + { + BX_TRACE("Using glXSwapIntervalEXT."); + glXSwapIntervalEXT(s_display, s_window, 0); + } + else + { + glXSwapIntervalMESA = (PFNGLXSWAPINTERVALMESAPROC)glXGetProcAddress( (const GLubyte*)"glXSwapIntervalMESA"); + if (NULL != glXSwapIntervalMESA) + { + BX_TRACE("Using glXSwapIntervalMESA."); + glXSwapIntervalMESA(0); + } + else + { + glXSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)glXGetProcAddress( (const GLubyte*)"glXSwapIntervalSGI"); + if (NULL != glXSwapIntervalSGI) + { + BX_TRACE("Using glXSwapIntervalSGI."); + glXSwapIntervalSGI(0); + } + } + } + glXMakeCurrent(s_display, s_window, m_context); + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glXSwapBuffers(s_display, s_window); @@ -154,8 +192,22 @@ namespace bgfx glXDestroyContext(s_display, m_context); } - void GlContext::resize(uint32_t _width, uint32_t _height) + void GlContext::resize(uint32_t /*_width*/, uint32_t /*_height*/, bool _vsync) { + int32_t interval = _vsync ? 1 : 0; + + if (NULL != glXSwapIntervalEXT) + { + glXSwapIntervalEXT(s_display, s_window, interval); + } + else if (NULL != glXSwapIntervalMESA) + { + glXSwapIntervalMESA(interval); + } + else if (NULL != glXSwapIntervalSGI) + { + glXSwapIntervalSGI(interval); + } } void GlContext::swap() @@ -177,6 +229,4 @@ namespace bgfx } // namespace bgfx -# endif // BX_PLATFORM_LINUX -#endif // (BGFX_CONFIG_RENDERER_OPENGLES2|BGFX_CONFIG_RENDERER_OPENGLES3|BGFX_CONFIG_RENDERER_OPENGL) - +#endif // BX_PLATFORM_LINUX & (BGFX_CONFIG_RENDERER_OPENGLES2|BGFX_CONFIG_RENDERER_OPENGLES3|BGFX_CONFIG_RENDERER_OPENGL) diff --git a/src/glcontext_glx.h b/src/glcontext_glx.h index ff9e09e5..2c2e6167 100644 --- a/src/glcontext_glx.h +++ b/src/glcontext_glx.h @@ -22,7 +22,7 @@ namespace bgfx void create(uint32_t _width, uint32_t _height); void destroy(); - void resize(uint32_t _width, uint32_t _height); + void resize(uint32_t _width, uint32_t _height, bool _vsync); void swap(); void import(); diff --git a/src/glcontext_nsgl.h b/src/glcontext_nsgl.h index e779c834..b8e7c1b9 100755 --- a/src/glcontext_nsgl.h +++ b/src/glcontext_nsgl.h @@ -19,7 +19,7 @@ namespace bgfx void create(uint32_t _width, uint32_t _height); void destroy(); - void resize(uint32_t _width, uint32_t _height); + void resize(uint32_t _width, uint32_t _height, bool _vsync); void swap(); void import(); diff --git a/src/glcontext_nsgl.mm b/src/glcontext_nsgl.mm index 316ab517..9236b44e 100755 --- a/src/glcontext_nsgl.mm +++ b/src/glcontext_nsgl.mm @@ -80,7 +80,7 @@ namespace bgfx [glView release]; } - void GlContext::resize(uint32_t _width, uint32_t _height) + void GlContext::resize(uint32_t _width, uint32_t _height, bool _vsync) { } diff --git a/src/glcontext_ppapi.cpp b/src/glcontext_ppapi.cpp index e5c61027..3ba6a622 100644 --- a/src/glcontext_ppapi.cpp +++ b/src/glcontext_ppapi.cpp @@ -5,11 +5,9 @@ #include "bgfx_p.h" -#if (BGFX_CONFIG_RENDERER_OPENGLES2|BGFX_CONFIG_RENDERER_OPENGLES3|BGFX_CONFIG_RENDERER_OPENGL) +#if BX_PLATFORM_NACL & (BGFX_CONFIG_RENDERER_OPENGLES2|BGFX_CONFIG_RENDERER_OPENGLES3|BGFX_CONFIG_RENDERER_OPENGL) # include "renderer_gl.h" -# if BX_PLATFORM_NACL - namespace bgfx { # define GL_IMPORT(_optional, _proto, _func) _proto _func @@ -49,7 +47,7 @@ namespace bgfx { } - void GlContext::resize(uint32_t _width, uint32_t _height) + void GlContext::resize(uint32_t _width, uint32_t _height, bool /*_vsync*/) { m_graphicsInterface->ResizeBuffers(m_context, _width, _height); } @@ -65,5 +63,4 @@ namespace bgfx } } // namespace bgfx -# endif // BX_PLATFORM_NACL -#endif // (BGFX_CONFIG_RENDERER_OPENGLES2|BGFX_CONFIG_RENDERER_OPENGLES3|BGFX_CONFIG_RENDERER_OPENGL) +#endif // BX_PLATFORM_NACL & (BGFX_CONFIG_RENDERER_OPENGLES2|BGFX_CONFIG_RENDERER_OPENGLES3|BGFX_CONFIG_RENDERER_OPENGL) diff --git a/src/glcontext_ppapi.h b/src/glcontext_ppapi.h index 222d86fc..053fde2e 100644 --- a/src/glcontext_ppapi.h +++ b/src/glcontext_ppapi.h @@ -28,7 +28,7 @@ namespace bgfx void create(uint32_t _width, uint32_t _height); void destroy(); - void resize(uint32_t _width, uint32_t _height); + void resize(uint32_t _width, uint32_t _height, bool _vsync); void swap(); void import(); diff --git a/src/glcontext_wgl.cpp b/src/glcontext_wgl.cpp index 30cddd95..b0b57b13 100644 --- a/src/glcontext_wgl.cpp +++ b/src/glcontext_wgl.cpp @@ -120,34 +120,9 @@ namespace bgfx if (NULL != wglGetExtensionsStringARB) { - BX_TRACE("WGL extensions:"); const char* extensions = (const char*)wglGetExtensionsStringARB(hdc); - if (NULL != extensions) - { - char name[1024]; - const char* pos = extensions; - const char* end = extensions + strlen(extensions); - while (pos < end) - { - uint32_t len; - const char* space = strchr(pos, ' '); - if (NULL != space) - { - len = uint32_min(sizeof(name), (uint32_t)(space - pos) ); - } - else - { - len = uint32_min(sizeof(name), (uint32_t)strlen(pos) ); - } - - strncpy(name, pos, len); - name[len] = '\0'; - - BX_TRACE("\t%s", name); - - pos += len+1; - } - } + BX_TRACE("WGL extensions:"); + dumpExtensions(extensions); } if (NULL != wglChoosePixelFormatARB @@ -203,7 +178,7 @@ namespace bgfx uint32_t flags = BGFX_CONFIG_DEBUG ? WGL_CONTEXT_DEBUG_BIT_ARB : 0; BX_UNUSED(flags); - int32_t contextAttrs[] = + int32_t contextAttrs[9] = { #if BGFX_CONFIG_RENDERER_OPENGL >= 31 WGL_CONTEXT_MAJOR_VERSION_ARB, 3, @@ -213,6 +188,8 @@ namespace bgfx #else WGL_CONTEXT_MAJOR_VERSION_ARB, 2, WGL_CONTEXT_MINOR_VERSION_ARB, 1, + 0, 0, + 0, 0, #endif // BGFX_CONFIG_RENDERER_OPENGL >= 31 0 }; @@ -261,8 +238,12 @@ namespace bgfx m_opengl32dll = NULL; } - void GlContext::resize(uint32_t /*_width*/, uint32_t /*_height*/) + void GlContext::resize(uint32_t /*_width*/, uint32_t /*_height*/, bool _vsync) { + if (NULL != wglSwapIntervalEXT) + { + wglSwapIntervalEXT(_vsync ? 1 : 0); + } } void GlContext::swap() diff --git a/src/glcontext_wgl.h b/src/glcontext_wgl.h index 8aee18fb..44044681 100644 --- a/src/glcontext_wgl.h +++ b/src/glcontext_wgl.h @@ -66,7 +66,7 @@ namespace bgfx void create(uint32_t _width, uint32_t _height); void destroy(); - void resize(uint32_t _width, uint32_t _height); + void resize(uint32_t _width, uint32_t _height, bool _vsync); void swap(); void import(); diff --git a/src/renderer_d3d11.cpp b/src/renderer_d3d11.cpp index 7e812a89..3f39189d 100644 --- a/src/renderer_d3d11.cpp +++ b/src/renderer_d3d11.cpp @@ -10,6 +10,8 @@ namespace bgfx { + typedef HRESULT (WINAPI * PFN_CREATEDXGIFACTORY)(REFIID _riid, void** _factory); + static const D3D11_PRIMITIVE_TOPOLOGY s_primType[] = { D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST, @@ -322,8 +324,58 @@ namespace bgfx PFN_D3D11_CREATE_DEVICE d3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(m_d3d11dll, "D3D11CreateDevice"); BGFX_FATAL(NULL != d3D11CreateDevice, Fatal::UnableToInitialize, "Function D3D11CreateDevice not found."); + m_dxgidll = LoadLibrary("dxgi.dll"); + BGFX_FATAL(NULL != m_dxgidll, Fatal::UnableToInitialize, "Failed to load dxgi.dll."); + + PFN_CREATEDXGIFACTORY dxgiCreateDXGIFactory = (PFN_CREATEDXGIFACTORY)GetProcAddress(m_dxgidll, "CreateDXGIFactory"); + BGFX_FATAL(NULL != dxgiCreateDXGIFactory, Fatal::UnableToInitialize, "Function CreateDXGIFactory not found."); + HRESULT hr; + IDXGIFactory* factory; + hr = dxgiCreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&factory); + BGFX_FATAL(SUCCEEDED(hr), Fatal::UnableToInitialize, "Unable to create DXGI factory."); + + m_adapter = NULL; + m_driverType = D3D_DRIVER_TYPE_HARDWARE; + + IDXGIAdapter* adapter; + for (uint32_t ii = 0; DXGI_ERROR_NOT_FOUND != factory->EnumAdapters(ii, &adapter); ++ii) + { + DXGI_ADAPTER_DESC desc; + hr = adapter->GetDesc(&desc); + if (SUCCEEDED(hr) ) + { + BX_TRACE("Adapter #%d", ii); + + char description[countof(desc.Description)]; + wcstombs(description, desc.Description, countof(desc.Description) ); + BX_TRACE("\tDescription: %s", description); + BX_TRACE("\tVendorId: 0x%08x, DeviceId: 0x%08x, SubSysId: 0x%08x, Revision: 0x%08x" + , desc.VendorId + , desc.DeviceId + , desc.SubSysId + , desc.Revision + ); + BX_TRACE("\tMemory: %" PRIi64 " (video), %" PRIi64 " (system), %" PRIi64 " (shared)" + , desc.DedicatedVideoMemory + , desc.DedicatedSystemMemory + , desc.SharedSystemMemory + ); + +#if BGFX_CONFIG_DEBUG_PERFHUD + if (0 != strstr(description, "PerfHUD") ) + { + m_adapter = adapter; + m_driverType = D3D_DRIVER_TYPE_REFERENCE; + } +#endif // BGFX_CONFIG_DEBUG_PERFHUD + } + + DX_RELEASE(adapter, adapter == m_adapter ? 1 : 0); + } + DX_RELEASE(factory, NULL != m_adapter ? 1 : 0); + D3D_FEATURE_LEVEL features[] = { D3D_FEATURE_LEVEL_11_0, @@ -350,8 +402,8 @@ namespace bgfx D3D_FEATURE_LEVEL featureLevel; - hr = d3D11CreateDevice(NULL - , D3D_DRIVER_TYPE_HARDWARE + hr = d3D11CreateDevice(m_adapter + , m_driverType , NULL , flags , features @@ -367,11 +419,13 @@ namespace bgfx hr = m_device->QueryInterface(__uuidof(IDXGIDevice), (void**)&device); BGFX_FATAL(SUCCEEDED(hr), Fatal::UnableToInitialize, "Unable to create Direct3D11 device."); - IDXGIAdapter* adapter; hr = device->GetParent(__uuidof(IDXGIAdapter), (void**)&adapter); BGFX_FATAL(SUCCEEDED(hr), Fatal::UnableToInitialize, "Unable to create Direct3D11 device."); DX_RELEASE(device, 2); + hr = adapter->GetDesc(&m_adapterDesc); + BGFX_FATAL(SUCCEEDED(hr), Fatal::UnableToInitialize, "Unable to create Direct3D11 device."); + hr = adapter->GetParent(__uuidof(IDXGIFactory), (void**)&m_factory); BGFX_FATAL(SUCCEEDED(hr), Fatal::UnableToInitialize, "Unable to create Direct3D11 device."); DX_RELEASE(adapter, 2); @@ -444,6 +498,7 @@ namespace bgfx DX_RELEASE(m_device, 0); DX_RELEASE(m_factory, 0); + FreeLibrary(m_dxgidll); FreeLibrary(m_d3d11dll); } @@ -1032,6 +1087,10 @@ namespace bgfx } HMODULE m_d3d11dll; + HMODULE m_dxgidll; + D3D_DRIVER_TYPE m_driverType; + IDXGIAdapter* m_adapter; + DXGI_ADAPTER_DESC m_adapterDesc; IDXGIFactory* m_factory; IDXGISwapChain* m_swapChain; ID3D11Device* m_device; @@ -2675,8 +2734,20 @@ namespace bgfx double toMs = 1000.0/freq; tvm.clear(); - uint16_t pos = 10; - tvm.printf(0, 0, BGFX_CONFIG_DEBUG ? 0x89 : 0x8f, " " BGFX_RENDERER_NAME " "); + uint16_t pos = 0; + tvm.printf(0, pos++, BGFX_CONFIG_DEBUG ? 0x89 : 0x8f, " " BGFX_RENDERER_NAME " "); + + const DXGI_ADAPTER_DESC& desc = s_renderCtx.m_adapterDesc; + char description[countof(desc.Description)]; + wcstombs(description, desc.Description, countof(desc.Description) ); + tvm.printf(0, pos++, 0x0f, " Device: %s", description); + tvm.printf(0, pos++, 0x0f, " Memory: %" PRIi64 " (video), %" PRIi64 " (system), %" PRIi64 " (shared)" + , desc.DedicatedVideoMemory + , desc.DedicatedSystemMemory + , desc.SharedSystemMemory + ); + + pos = 10; tvm.printf(10, pos++, 0x8e, " Frame: %7.3f, % 7.3f \x1f, % 7.3f \x1e [ms] / % 6.2f FPS" , double(frameTime)*toMs , double(min)*toMs diff --git a/src/renderer_d3d9.cpp b/src/renderer_d3d9.cpp index 11272203..3a8f80e8 100644 --- a/src/renderer_d3d9.cpp +++ b/src/renderer_d3d9.cpp @@ -273,13 +273,14 @@ namespace bgfx for (uint32_t ii = 0; ii < adapterCount; ++ii) { D3DADAPTER_IDENTIFIER9 identifier; - DX_CHECK(m_d3d9->GetAdapterIdentifier(ii, 0, &identifier) ); - - BX_TRACE("Adapter #%d", ii); - BX_TRACE("\tDriver: %s", identifier.Driver); - BX_TRACE("\tDescription: %s", identifier.Description); - BX_TRACE("\tDeviceName: %s", identifier.DeviceName); - BX_TRACE("\tVendorId: 0x%08x, DeviceId: 0x%08x, SubSysId: 0x%08x, Revision: 0x%08x" + HRESULT hr = m_d3d9->GetAdapterIdentifier(ii, 0, &identifier); + if (SUCCEEDED(hr) ) + { + BX_TRACE("Adapter #%d", ii); + BX_TRACE("\tDriver: %s", identifier.Driver); + BX_TRACE("\tDescription: %s", identifier.Description); + BX_TRACE("\tDeviceName: %s", identifier.DeviceName); + BX_TRACE("\tVendorId: 0x%08x, DeviceId: 0x%08x, SubSysId: 0x%08x, Revision: 0x%08x" , identifier.VendorId , identifier.DeviceId , identifier.SubSysId @@ -287,18 +288,18 @@ namespace bgfx ); #if BGFX_CONFIG_DEBUG_PERFHUD - if (0 != strstr(identifier.Description, "PerfHUD") ) - { - m_adapter = ii; - m_deviceType = D3DDEVTYPE_REF; - } + if (0 != strstr(identifier.Description, "PerfHUD") ) + { + m_adapter = ii; + m_deviceType = D3DDEVTYPE_REF; + } #endif // BGFX_CONFIG_DEBUG_PERFHUD + } } - D3DADAPTER_IDENTIFIER9 identifier; - DX_CHECK(m_d3d9->GetAdapterIdentifier(m_adapter, 0, &identifier) ); - m_amd = identifier.VendorId == 0x1002; - m_nvidia = identifier.VendorId == 0x10de; + DX_CHECK(m_d3d9->GetAdapterIdentifier(m_adapter, 0, &m_identifier) ); + m_amd = m_identifier.VendorId == 0x1002; + m_nvidia = m_identifier.VendorId == 0x10de; uint32_t behaviorFlags[] = { @@ -875,6 +876,7 @@ namespace bgfx D3DDEVTYPE m_deviceType; D3DPRESENT_PARAMETERS m_params; uint32_t m_flags; + D3DADAPTER_IDENTIFIER9 m_identifier; bool m_initialized; bool m_amd; @@ -2772,8 +2774,13 @@ namespace bgfx double toMs = 1000.0/freq; tvm.clear(); - uint16_t pos = 10; - tvm.printf(0, 0, BGFX_CONFIG_DEBUG ? 0x89 : 0x8f, " " BGFX_RENDERER_NAME " "); + uint16_t pos = 0; + tvm.printf(0, pos++, BGFX_CONFIG_DEBUG ? 0x89 : 0x8f, " " BGFX_RENDERER_NAME " "); + + const D3DADAPTER_IDENTIFIER9& identifier = s_renderCtx.m_identifier; + tvm.printf(0, pos++, 0x0f, " Device: %s (%s)", identifier.Description, identifier.Driver); + + pos = 10; tvm.printf(10, pos++, 0x8e, " Frame: %7.3f, % 7.3f \x1f, % 7.3f \x1e [ms] / % 6.2f FPS" , double(frameTime)*toMs , double(min)*toMs diff --git a/src/renderer_gl.cpp b/src/renderer_gl.cpp index 68326bf8..314dff30 100644 --- a/src/renderer_gl.cpp +++ b/src/renderer_gl.cpp @@ -180,12 +180,42 @@ namespace bgfx glGetError(); // ignore error if glGetString returns NULL. if (NULL != str) { - return bx::hashMurmur2A(str, strlen(str) ); + return bx::hashMurmur2A(str, (uint32_t)strlen(str) ); } return 0; } + void dumpExtensions(const char* _extensions) + { + if (NULL != _extensions) + { + char name[1024]; + const char* pos = _extensions; + const char* end = _extensions + strlen(_extensions); + while (pos < end) + { + uint32_t len; + const char* space = strchr(pos, ' '); + if (NULL != space) + { + len = uint32_min(sizeof(name), (uint32_t)(space - pos) ); + } + else + { + len = uint32_min(sizeof(name), (uint32_t)strlen(pos) ); + } + + strncpy(name, pos, len); + name[len] = '\0'; + + BX_TRACE("\t%s", name); + + pos += len+1; + } + } + } + #if BGFX_CONFIG_RENDERER_OPENGL const char* toString(GLenum _enum) { @@ -261,7 +291,8 @@ namespace bgfx uint32_t msaa = 1<<( (m_resolution.m_flags&BGFX_RESET_MSAA_MASK)>>BGFX_RESET_MSAA_SHIFT); msaa = uint32_min(m_maxMsaa, msaa == 0 ? 0 : 1<finish(); @@ -2256,6 +2288,7 @@ namespace bgfx } BX_TRACE("GL_EXTENSION%s: %s", supported ? " (supported)" : "", name); + BX_UNUSED(supported); pos += len+1; } diff --git a/src/renderer_gl.h b/src/renderer_gl.h index b5a7d016..0fc13b2f 100755 --- a/src/renderer_gl.h +++ b/src/renderer_gl.h @@ -280,7 +280,9 @@ namespace bgfx #define GL_IMPORT(_optional, _proto, _func) extern _proto _func #include "glimports.h" #undef GL_IMPORT - + + void dumpExtensions(const char* _extensions); + class ConstantBuffer; class VaoCache diff --git a/src/vertexdecl.cpp b/src/vertexdecl.cpp index 6518520d..697eb17d 100644 --- a/src/vertexdecl.cpp +++ b/src/vertexdecl.cpp @@ -4,14 +4,14 @@ */ #include +#include #include #include +#include +#include #include "vertexdecl.h" -extern void dbgPrintf(const char* _format, ...); -extern void dbgPrintfData(const void* _data, uint32_t _size, const char* _format, ...); - namespace bgfx { static const uint8_t s_attribTypeSizeDx9[AttribType::Count][4] = @@ -56,6 +56,28 @@ namespace bgfx &s_attribTypeSizeGl, }; + void dbgPrintfVargs(const char* _format, va_list _argList) + { + char temp[8192]; + char* out = temp; + int32_t len = bx::vsnprintf(out, sizeof(temp), _format, _argList); + if ( (int32_t)sizeof(temp) < len) + { + out = (char*)alloca(len+1); + len = bx::vsnprintf(out, len, _format, _argList); + } + out[len] = '\0'; + bx::debugOutput(out); + } + + void dbgPrintf(const char* _format, ...) + { + va_list argList; + va_start(argList, _format); + dbgPrintfVargs(_format, argList); + va_end(argList); + } + void VertexDecl::begin(RendererType::Enum _renderer) { m_hash = _renderer; // use hash to store renderer type while building VertexDecl. diff --git a/tools/bin/geometryc b/tools/bin/geometryc index c8f427a5..958f7851 100755 Binary files a/tools/bin/geometryc and b/tools/bin/geometryc differ diff --git a/tools/bin/shaderc b/tools/bin/shaderc index 918e5034..c9d6cbcf 100755 Binary files a/tools/bin/shaderc and b/tools/bin/shaderc differ