awesome!!!
This commit is contained in:
		
							
								
								
									
										94
									
								
								third-party/stb/tests/oversample/README.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								third-party/stb/tests/oversample/README.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,94 @@ | ||||
| # Font character oversampling for rendering from atlas textures | ||||
|  | ||||
| TL,DR: Run oversample.exe on a windows machine to see the | ||||
| benefits of oversampling. It will try to use arial.ttf from the | ||||
| Windows font directory unless you type the name of a .ttf file as | ||||
| a command-line argument. | ||||
|  | ||||
| ## Benefits of oversampling | ||||
|  | ||||
| Oversampling is a mechanism for improving subpixel rendering of characters. | ||||
|  | ||||
| Improving subpixel has a few benefits: | ||||
|  | ||||
| * With horizontal-oversampling, text can remain sharper while still being sub-pixel positioned for better kerning | ||||
| * Horizontally-oversampled text significantly reduces aliasing when text animates horizontally | ||||
| * Vertically-oversampled text significantly reduces aliasing when text animates vertically | ||||
| * Text oversampled in both directions significantly reduces aliasing when text rotates | ||||
|  | ||||
| ## What text oversampling is | ||||
|  | ||||
| A common strategy for rendering text is to cache character bitmaps | ||||
| and reuse them. For hinted characters, every instance of a given | ||||
| character is always identical, so this works fine. However, stb_truetype | ||||
| doesn't do hinting. | ||||
|  | ||||
| For anti-aliased characters, you can actually position the characters | ||||
| with subpixel precision, and get different bitmaps based on that positioning | ||||
| if you re-render the vector data. | ||||
|  | ||||
| However, if you simply cache a single version of the bitmap and | ||||
| draw it at different subpixel positions with a GPU, you will get | ||||
| either the exact same result (if you use point-sampling on the | ||||
| texture) or linear filtering. Linear filtering will cause a sub-pixel | ||||
| positioned bitmap to blur further, causing a visible de-sharpening | ||||
| of the character. (And, since the character wasn't hinted, it was | ||||
| already blurrier than a hinted one would be, and now it gets even | ||||
| more blurry.) | ||||
|  | ||||
| You can avoid this by caching multiple variants of a character which | ||||
| were rendered independently from the vector data. For example, you | ||||
| might cache 3 versions of a char, at 0, 1/3, and 2/3rds of a pixel | ||||
| horizontal offset, and always require characters to fall on integer | ||||
| positions vertically. | ||||
|  | ||||
| When creating a texture atlas for use on GPUs, which support bilinear | ||||
| filtering, there is a better approach than caching several independent | ||||
| positions, which is to allow lerping between the versions to allow | ||||
| finer subpixel positioning. You can achieve these by interleaving | ||||
| each of the cached bitmaps, but this turns out to be mathematically | ||||
| equivalent to a simpler operation: oversampling and prefiltering the | ||||
| characters. | ||||
|  | ||||
| So, setting oversampling of 2x2 in stb_truetype is equivalent to caching | ||||
| each character in 4 different variations, 1 for each subpixel position | ||||
| in a 2x2 set. | ||||
|  | ||||
| An advantage of this formulation is that no changes are required to | ||||
| the rendering code; the exact same quad-rendering code works, it just | ||||
| uses different texture coordinates. (Note this does potentially increase | ||||
| texture bandwidth for text rendering since we end up minifying the texture | ||||
| without using mipmapping, but you probably are not going to be fill-bound | ||||
| by your text rendering.) | ||||
|  | ||||
| ## What about gamma? | ||||
|  | ||||
| Gamma-correction for fonts just doesn't work. This doesn't seem to make | ||||
| much sense -- it's physically correct, it simulates what we'd see if you | ||||
| shrunk a font down really far, right? | ||||
|  | ||||
| But you can play with it in the oversample.exe app. If you turn it on, | ||||
| white-on-black fonts become too thick (i.e. they become too bright), and | ||||
| black-on-white fonts become too thin (i.e. they are insufficiently dark). There is | ||||
| no way to adjust the font's inherent thickness (i.e. by switching to | ||||
| bold) to fix this for both; making the font thicker will make white | ||||
| text worse, and making the font thinner will make black text worse. | ||||
| Obviously you could use different fonts for light and dark cases, but | ||||
| this doesn't seem like a very good way for fonts to work. | ||||
|  | ||||
| Multiple people who have experimented with this independently (me, | ||||
| Fabian Giesen,and Maxim Shemanarev of Anti-Grain Geometry) have all | ||||
| concluded that correct gamma-correction does not produce the best | ||||
| results for fonts. Font rendering just generally looks better without | ||||
| gamma correction (or possibly with some arbitrary power stuck in | ||||
| there, but it's not really correcting for gamma at that point). Maybe | ||||
| this is in part a product of how we're used to fonts being on screens | ||||
| which has changed how we expect them to look (e.g. perhaps hinting | ||||
| oversharpens them and prevents the real-world thinning you'd see in | ||||
| a black-on-white text). | ||||
|  | ||||
| (AGG link on text rendering, including mention of gamma: | ||||
|   http://www.antigrain.com/research/font_rasterization/ ) | ||||
|  | ||||
| Nevertheless, even if you turn on gamma-correction, you will find that | ||||
| oversampling still helps in many cases for small fonts. | ||||
							
								
								
									
										332
									
								
								third-party/stb/tests/oversample/main.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										332
									
								
								third-party/stb/tests/oversample/main.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,332 @@ | ||||
| #pragma warning(disable:4244; disable:4305; disable:4018) | ||||
| #include <assert.h> | ||||
| #include <ctype.h> | ||||
|  | ||||
| #define STB_WINMAIN | ||||
| #include "stb_wingraph.h" | ||||
|  | ||||
| #define STB_TRUETYPE_IMPLEMENTATION | ||||
| #define STB_RECT_PACK_IMPLEMENTATION | ||||
| #include "stb_rect_pack.h" | ||||
| #include "stb_truetype.h" | ||||
|  | ||||
| #ifndef WINGDIAPI | ||||
| #define CALLBACK    __stdcall | ||||
| #define WINGDIAPI   __declspec(dllimport) | ||||
| #define APIENTRY    __stdcall | ||||
| #endif | ||||
|  | ||||
| #include <gl/gl.h> | ||||
| #include <gl/glu.h> | ||||
|  | ||||
| #define GL_FRAMEBUFFER_SRGB_EXT           0x8DB9 | ||||
|  | ||||
| #define SIZE_X  1024 | ||||
| #define SIZE_Y  768 | ||||
|  | ||||
| stbtt_packedchar chardata[6][128]; | ||||
|  | ||||
| int sx=SIZE_X, sy=SIZE_Y; | ||||
|  | ||||
| #define BITMAP_W 512 | ||||
| #define BITMAP_H 512 | ||||
| unsigned char temp_bitmap[BITMAP_W][BITMAP_H]; | ||||
| unsigned char ttf_buffer[1 << 25]; | ||||
| GLuint font_tex; | ||||
|  | ||||
| float scale[2] = { 24.0f, 14.0f }; | ||||
|  | ||||
| int sf[6] = { 0,1,2, 0,1,2 }; | ||||
|  | ||||
| void load_fonts(void) | ||||
| { | ||||
|    stbtt_pack_context pc; | ||||
|    int i; | ||||
|    FILE *f; | ||||
|    char filename[256]; | ||||
|    char *win = getenv("windir"); | ||||
|    if (win == NULL) win = getenv("SystemRoot"); | ||||
|  | ||||
|    f = fopen(stb_wingraph_commandline, "rb"); | ||||
|    if (!f) { | ||||
|       if (win == NULL) | ||||
|          sprintf(filename, "arial.ttf", win); | ||||
|       else | ||||
|          sprintf(filename, "%s/fonts/arial.ttf", win); | ||||
|       f = fopen(filename, "rb"); | ||||
|       if (!f) exit(0); | ||||
|    } | ||||
|  | ||||
|    fread(ttf_buffer, 1, 1<<25, f); | ||||
|  | ||||
|    stbtt_PackBegin(&pc, temp_bitmap[0], BITMAP_W, BITMAP_H, 0, 1, NULL); | ||||
|    for (i=0; i < 2; ++i) { | ||||
|       stbtt_PackSetOversampling(&pc, 1, 1); | ||||
|       stbtt_PackFontRange(&pc, ttf_buffer, 0, scale[i], 32, 95, chardata[i*3+0]+32); | ||||
|       stbtt_PackSetOversampling(&pc, 2, 2); | ||||
|       stbtt_PackFontRange(&pc, ttf_buffer, 0, scale[i], 32, 95, chardata[i*3+1]+32); | ||||
|       stbtt_PackSetOversampling(&pc, 3, 1); | ||||
|       stbtt_PackFontRange(&pc, ttf_buffer, 0, scale[i], 32, 95, chardata[i*3+2]+32); | ||||
|    } | ||||
|    stbtt_PackEnd(&pc); | ||||
|  | ||||
|    glGenTextures(1, &font_tex); | ||||
|    glBindTexture(GL_TEXTURE_2D, font_tex); | ||||
|    glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, BITMAP_W, BITMAP_H, 0, GL_ALPHA, GL_UNSIGNED_BYTE, temp_bitmap); | ||||
|    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | ||||
|    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | ||||
| } | ||||
|  | ||||
| int black_on_white; | ||||
|  | ||||
| void draw_init(void) | ||||
| { | ||||
|    glDisable(GL_CULL_FACE); | ||||
|    glDisable(GL_TEXTURE_2D); | ||||
|    glDisable(GL_LIGHTING); | ||||
|    glDisable(GL_DEPTH_TEST); | ||||
|  | ||||
|    glViewport(0,0,sx,sy); | ||||
|    if (black_on_white) | ||||
|       glClearColor(255,255,255,0); | ||||
|    else | ||||
|       glClearColor(0,0,0,0); | ||||
|    glClear(GL_COLOR_BUFFER_BIT); | ||||
|  | ||||
|    glMatrixMode(GL_PROJECTION); | ||||
|    glLoadIdentity(); | ||||
|    gluOrtho2D(0,sx,sy,0); | ||||
|    glMatrixMode(GL_MODELVIEW); | ||||
|    glLoadIdentity(); | ||||
| } | ||||
|  | ||||
|  | ||||
| void drawBoxTC(float x0, float y0, float x1, float y1, float s0, float t0, float s1, float t1) | ||||
| { | ||||
|    glTexCoord2f(s0,t0); glVertex2f(x0,y0); | ||||
|    glTexCoord2f(s1,t0); glVertex2f(x1,y0); | ||||
|    glTexCoord2f(s1,t1); glVertex2f(x1,y1); | ||||
|    glTexCoord2f(s0,t1); glVertex2f(x0,y1); | ||||
| } | ||||
|  | ||||
| int integer_align; | ||||
|  | ||||
| void print(float x, float y, int font, char *text) | ||||
| { | ||||
|    glEnable(GL_TEXTURE_2D); | ||||
|    glBindTexture(GL_TEXTURE_2D, font_tex); | ||||
|    glBegin(GL_QUADS); | ||||
|    while (*text) { | ||||
|       stbtt_aligned_quad q; | ||||
|       stbtt_GetPackedQuad(chardata[font], BITMAP_W, BITMAP_H, *text++, &x, &y, &q, font ? 0 : integer_align); | ||||
|       drawBoxTC(q.x0,q.y0,q.x1,q.y1, q.s0,q.t0,q.s1,q.t1); | ||||
|    } | ||||
|    glEnd(); | ||||
| } | ||||
|  | ||||
| int font=3; | ||||
| int translating; | ||||
| int rotating=0; | ||||
| int srgb=0; | ||||
| float rotate_t, translate_t; | ||||
| int show_tex; | ||||
|  | ||||
| void draw_world(void) | ||||
| { | ||||
|    int sfont = sf[font]; | ||||
|    float x = 20; | ||||
|    glEnable(GL_BLEND); | ||||
|    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | ||||
|  | ||||
|    if (black_on_white) | ||||
|       glColor3f(0,0,0); | ||||
|    else | ||||
|       glColor3f(1,1,1); | ||||
|  | ||||
|  | ||||
|    print(80, 30, sfont, "Controls:"); | ||||
|    print(100, 60, sfont, "S: toggle font size"); | ||||
|    print(100, 85, sfont, "O: toggle oversampling"); | ||||
|    print(100,110, sfont, "T: toggle translation"); | ||||
|    print(100,135, sfont, "R: toggle rotation"); | ||||
|    print(100,160, sfont, "P: toggle pixel-snap (only non-oversampled)"); | ||||
|    print(100,185, sfont, "G: toggle srgb gamma-correction"); | ||||
|    if (black_on_white) | ||||
|       print(100,210, sfont, "B: toggle to white-on-black"); | ||||
|    else | ||||
|       print(100,210, sfont, "B: toggle to black-on-white"); | ||||
|    print(100,235, sfont, "V: view font texture"); | ||||
|  | ||||
|    print(80, 300, sfont, "Current font:"); | ||||
|  | ||||
|    if (!show_tex) { | ||||
|       if (font < 3) | ||||
|          print(100, 350, sfont, "Font height: 24 pixels"); | ||||
|       else | ||||
|          print(100, 350, sfont, "Font height: 14 pixels"); | ||||
|    } | ||||
|  | ||||
|    if (font%3==1) | ||||
|       print(100, 325, sfont, "2x2 oversampled text at 1:1"); | ||||
|    else if (font%3 == 2) | ||||
|       print(100, 325, sfont, "3x1 oversampled text at 1:1"); | ||||
|    else if (integer_align) | ||||
|       print(100, 325, sfont, "1:1 text, one texel = one pixel, snapped to integer coordinates"); | ||||
|    else | ||||
|       print(100, 325, sfont, "1:1 text, one texel = one pixel"); | ||||
|  | ||||
|    if (show_tex) { | ||||
|       glBegin(GL_QUADS); | ||||
|       drawBoxTC(200,400, 200+BITMAP_W,300+BITMAP_H, 0,0,1,1); | ||||
|       glEnd(); | ||||
|    } else { | ||||
|       glMatrixMode(GL_MODELVIEW); | ||||
|       glTranslatef(200,350,0); | ||||
|  | ||||
|       if (translating) | ||||
|          x += fmod(translate_t*8,30); | ||||
|  | ||||
|       if (rotating) { | ||||
|          glTranslatef(100,150,0); | ||||
|          glRotatef(rotate_t*2,0,0,1); | ||||
|          glTranslatef(-100,-150,0); | ||||
|       } | ||||
|       print(x,100, font, "This is a test"); | ||||
|       print(x,130, font, "Now is the time for all good men to come to the aid of their country."); | ||||
|       print(x,160, font, "The quick brown fox jumps over the lazy dog."); | ||||
|       print(x,190, font, "0123456789"); | ||||
|    } | ||||
| } | ||||
|  | ||||
| void draw(void) | ||||
| { | ||||
|    draw_init(); | ||||
|    draw_world(); | ||||
|    stbwingraph_SwapBuffers(NULL); | ||||
| } | ||||
|  | ||||
| static int initialized=0; | ||||
| static float last_dt; | ||||
|  | ||||
| int move[4]; | ||||
| int raw_mouse_x, raw_mouse_y; | ||||
|  | ||||
| int loopmode(float dt, int real, int in_client) | ||||
| { | ||||
|    float actual_dt = dt; | ||||
|  | ||||
|    if (!initialized) return 0; | ||||
|  | ||||
|    rotate_t += dt; | ||||
|    translate_t += dt; | ||||
|  | ||||
| //   music_sim(); | ||||
|    if (!real) | ||||
|       return 0; | ||||
|  | ||||
|    if (dt > 0.25) dt = 0.25; | ||||
|    if (dt < 0.01) dt = 0.01; | ||||
|  | ||||
|    draw(); | ||||
|  | ||||
|    return 0; | ||||
| } | ||||
|  | ||||
| int winproc(void *data, stbwingraph_event *e) | ||||
| { | ||||
|    switch (e->type) { | ||||
|       case STBWGE_create: | ||||
|          break; | ||||
|  | ||||
|       case STBWGE_char: | ||||
|          switch(e->key) { | ||||
|             case 27: | ||||
|                stbwingraph_ShowCursor(NULL,1); | ||||
|                return STBWINGRAPH_winproc_exit; | ||||
|                break; | ||||
|             case 'o': case 'O': | ||||
|                font = (font+1) % 3 + (font/3)*3; | ||||
|                break; | ||||
|             case 's': case 'S': | ||||
|                font = (font+3) % 6; | ||||
|                break; | ||||
|             case 't': case 'T': | ||||
|                translating = !translating; | ||||
|                translate_t = 0; | ||||
|                break; | ||||
|             case 'r': case 'R': | ||||
|                rotating = !rotating; | ||||
|                rotate_t = 0; | ||||
|                break; | ||||
|             case 'p': case 'P': | ||||
|                integer_align = !integer_align; | ||||
|                break; | ||||
|             case 'g': case 'G': | ||||
|                srgb = !srgb; | ||||
|                if (srgb) | ||||
|                   glEnable(GL_FRAMEBUFFER_SRGB_EXT); | ||||
|                else | ||||
|                   glDisable(GL_FRAMEBUFFER_SRGB_EXT); | ||||
|                break; | ||||
|             case 'v': case 'V': | ||||
|                show_tex = !show_tex; | ||||
|                break; | ||||
|             case 'b': case 'B': | ||||
|                black_on_white = !black_on_white; | ||||
|                break; | ||||
|          } | ||||
|          break; | ||||
|  | ||||
|       case STBWGE_mousemove: | ||||
|          raw_mouse_x = e->mx; | ||||
|          raw_mouse_y = e->my; | ||||
|          break; | ||||
|  | ||||
| #if 0 | ||||
|       case STBWGE_mousewheel:  do_mouse(e,0,0); break; | ||||
|       case STBWGE_leftdown:    do_mouse(e, 1,0); break; | ||||
|       case STBWGE_leftup:      do_mouse(e,-1,0); break; | ||||
|       case STBWGE_rightdown:   do_mouse(e,0, 1); break; | ||||
|       case STBWGE_rightup:     do_mouse(e,0,-1); break; | ||||
| #endif | ||||
|  | ||||
|       case STBWGE_keydown: | ||||
|          if (e->key == VK_RIGHT) move[0] = 1; | ||||
|          if (e->key == VK_LEFT)  move[1] = 1; | ||||
|          if (e->key == VK_UP)    move[2] = 1; | ||||
|          if (e->key == VK_DOWN)  move[3] = 1; | ||||
|          break; | ||||
|       case STBWGE_keyup: | ||||
|          if (e->key == VK_RIGHT) move[0] = 0; | ||||
|          if (e->key == VK_LEFT)  move[1] = 0; | ||||
|          if (e->key == VK_UP)    move[2] = 0; | ||||
|          if (e->key == VK_DOWN)  move[3] = 0; | ||||
|          break; | ||||
|  | ||||
|       case STBWGE_size: | ||||
|          sx = e->width; | ||||
|          sy = e->height; | ||||
|          loopmode(0,1,0); | ||||
|          break; | ||||
|  | ||||
|       case STBWGE_draw: | ||||
|          if (initialized) | ||||
|             loopmode(0,1,0); | ||||
|          break; | ||||
|  | ||||
|       default: | ||||
|          return STBWINGRAPH_unprocessed; | ||||
|    } | ||||
|    return 0; | ||||
| } | ||||
|  | ||||
| void stbwingraph_main(void) | ||||
| { | ||||
|    stbwingraph_Priority(2); | ||||
|    stbwingraph_CreateWindow(1, winproc, NULL, "tt", SIZE_X,SIZE_Y, 0, 1, 0, 0); | ||||
|    stbwingraph_ShowCursor(NULL, 0); | ||||
|    load_fonts(); | ||||
|    initialized = 1; | ||||
|    stbwingraph_MainLoop(loopmode, 0.016f);   // 30 fps = 0.33 | ||||
| } | ||||
|  | ||||
							
								
								
									
										97
									
								
								third-party/stb/tests/oversample/oversample.dsp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								third-party/stb/tests/oversample/oversample.dsp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,97 @@ | ||||
| # Microsoft Developer Studio Project File - Name="oversample" - Package Owner=<4> | ||||
| # Microsoft Developer Studio Generated Build File, Format Version 6.00 | ||||
| # ** DO NOT EDIT ** | ||||
|  | ||||
| # TARGTYPE "Win32 (x86) Application" 0x0101 | ||||
|  | ||||
| CFG=oversample - Win32 Debug | ||||
| !MESSAGE This is not a valid makefile. To build this project using NMAKE, | ||||
| !MESSAGE use the Export Makefile command and run | ||||
| !MESSAGE  | ||||
| !MESSAGE NMAKE /f "oversample.mak". | ||||
| !MESSAGE  | ||||
| !MESSAGE You can specify a configuration when running NMAKE | ||||
| !MESSAGE by defining the macro CFG on the command line. For example: | ||||
| !MESSAGE  | ||||
| !MESSAGE NMAKE /f "oversample.mak" CFG="oversample - Win32 Debug" | ||||
| !MESSAGE  | ||||
| !MESSAGE Possible choices for configuration are: | ||||
| !MESSAGE  | ||||
| !MESSAGE "oversample - Win32 Release" (based on "Win32 (x86) Application") | ||||
| !MESSAGE "oversample - Win32 Debug" (based on "Win32 (x86) Application") | ||||
| !MESSAGE  | ||||
|  | ||||
| # Begin Project | ||||
| # PROP AllowPerConfigDependencies 0 | ||||
| # PROP Scc_ProjName "" | ||||
| # PROP Scc_LocalPath "" | ||||
| CPP=cl.exe | ||||
| MTL=midl.exe | ||||
| RSC=rc.exe | ||||
|  | ||||
| !IF  "$(CFG)" == "oversample - Win32 Release" | ||||
|  | ||||
| # PROP BASE Use_MFC 0 | ||||
| # PROP BASE Use_Debug_Libraries 0 | ||||
| # PROP BASE Output_Dir "Release" | ||||
| # PROP BASE Intermediate_Dir "Release" | ||||
| # PROP BASE Target_Dir "" | ||||
| # PROP Use_MFC 0 | ||||
| # PROP Use_Debug_Libraries 0 | ||||
| # PROP Output_Dir "Release" | ||||
| # PROP Intermediate_Dir "Release" | ||||
| # PROP Ignore_Export_Lib 0 | ||||
| # PROP Target_Dir "" | ||||
| # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c | ||||
| # ADD CPP /nologo /W3 /WX /GX /O2 /I "c:\sean\prj\stb" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /FD /c | ||||
| # SUBTRACT CPP /YX | ||||
| # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 | ||||
| # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 | ||||
| # ADD BASE RSC /l 0x409 /d "NDEBUG" | ||||
| # ADD RSC /l 0x409 /d "NDEBUG" | ||||
| BSC32=bscmake.exe | ||||
| # ADD BASE BSC32 /nologo | ||||
| # ADD BSC32 /nologo | ||||
| LINK32=link.exe | ||||
| # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 | ||||
| # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 | ||||
| # SUBTRACT LINK32 /map /debug | ||||
|  | ||||
| !ELSEIF  "$(CFG)" == "oversample - Win32 Debug" | ||||
|  | ||||
| # PROP BASE Use_MFC 0 | ||||
| # PROP BASE Use_Debug_Libraries 1 | ||||
| # PROP BASE Output_Dir "Debug" | ||||
| # PROP BASE Intermediate_Dir "Debug" | ||||
| # PROP BASE Target_Dir "" | ||||
| # PROP Use_MFC 0 | ||||
| # PROP Use_Debug_Libraries 1 | ||||
| # PROP Output_Dir "Debug" | ||||
| # PROP Intermediate_Dir "Debug" | ||||
| # PROP Ignore_Export_Lib 0 | ||||
| # PROP Target_Dir "" | ||||
| # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c | ||||
| # ADD CPP /nologo /W3 /WX /Gm /GX /Zi /Od /I "c:\sean\prj\stb" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /FD /GZ /c | ||||
| # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 | ||||
| # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 | ||||
| # ADD BASE RSC /l 0x409 /d "_DEBUG" | ||||
| # ADD RSC /l 0x409 /d "_DEBUG" | ||||
| BSC32=bscmake.exe | ||||
| # ADD BASE BSC32 /nologo | ||||
| # ADD BSC32 /nologo | ||||
| LINK32=link.exe | ||||
| # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept | ||||
| # ADD LINK32 kernel32.lib user32.lib gdi32.lib advapi32.lib winspool.lib comdlg32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /incremental:no /debug /machine:I386 /pdbtype:sept | ||||
|  | ||||
| !ENDIF  | ||||
|  | ||||
| # Begin Target | ||||
|  | ||||
| # Name "oversample - Win32 Release" | ||||
| # Name "oversample - Win32 Debug" | ||||
| # Begin Source File | ||||
|  | ||||
| SOURCE=.\main.c | ||||
| # End Source File | ||||
| # End Target | ||||
| # End Project | ||||
							
								
								
									
										29
									
								
								third-party/stb/tests/oversample/oversample.dsw
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								third-party/stb/tests/oversample/oversample.dsw
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| Microsoft Developer Studio Workspace File, Format Version 6.00 | ||||
| # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! | ||||
|  | ||||
| ############################################################################### | ||||
|  | ||||
| Project: "oversample"=.\oversample.dsp - Package Owner=<4> | ||||
|  | ||||
| Package=<5> | ||||
| {{{ | ||||
| }}} | ||||
|  | ||||
| Package=<4> | ||||
| {{{ | ||||
| }}} | ||||
|  | ||||
| ############################################################################### | ||||
|  | ||||
| Global: | ||||
|  | ||||
| Package=<5> | ||||
| {{{ | ||||
| }}} | ||||
|  | ||||
| Package=<3> | ||||
| {{{ | ||||
| }}} | ||||
|  | ||||
| ############################################################################### | ||||
|  | ||||
							
								
								
									
										
											BIN
										
									
								
								third-party/stb/tests/oversample/oversample.exe
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								third-party/stb/tests/oversample/oversample.exe
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										829
									
								
								third-party/stb/tests/oversample/stb_wingraph.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										829
									
								
								third-party/stb/tests/oversample/stb_wingraph.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,829 @@ | ||||
| // stb_wingraph.h  v0.01 - public domain windows graphics programming | ||||
| // wraps WinMain, ChoosePixelFormat, ChangeDisplayResolution, etc. for | ||||
| // doing OpenGL graphics | ||||
| // | ||||
| // in ONE source file, put '#define STB_DEFINE' before including this | ||||
| // OR put '#define STB_WINMAIN' to define a WinMain that calls stbwingraph_main(void) | ||||
| // | ||||
| // @TODO: | ||||
| //    2d rendering interface (that can be done easily in software) | ||||
| //    STB_WINGRAPH_SOFTWARE -- 2d software rendering only | ||||
| //    STB_WINGRAPH_OPENGL   -- OpenGL only | ||||
|  | ||||
|  | ||||
| #ifndef INCLUDE_STB_WINGRAPH_H | ||||
| #define INCLUDE_STB_WINGRAPH_H | ||||
|  | ||||
| #ifdef STB_WINMAIN | ||||
|    #ifndef STB_DEFINE | ||||
|       #define STB_DEFINE | ||||
|       #define STB_WINGRAPH_DISABLE_DEFINE_AT_END | ||||
|    #endif | ||||
| #endif | ||||
|  | ||||
| #ifdef STB_DEFINE | ||||
|    #pragma comment(lib, "opengl32.lib") | ||||
|    #pragma comment(lib, "glu32.lib") | ||||
|    #pragma comment(lib, "winmm.lib") | ||||
|    #pragma comment(lib, "gdi32.lib") | ||||
|    #pragma comment(lib, "user32.lib") | ||||
| #endif | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| #define STB_EXTERN extern "C" | ||||
| #else | ||||
| #define STB_EXTERN | ||||
| #endif | ||||
|  | ||||
| #ifdef STB_DEFINE | ||||
| #ifndef _WINDOWS_ | ||||
|    #ifdef APIENTRY | ||||
|    #undef APIENTRY | ||||
|    #endif | ||||
|    #ifdef WINGDIAPI | ||||
|    #undef WINGDIAPI | ||||
|    #endif | ||||
|    #define _WIN32_WINNT 0x0400  // WM_MOUSEWHEEL | ||||
|    #include <windows.h> | ||||
| #endif | ||||
| #include <stdio.h> | ||||
| #include <math.h> | ||||
| #include <time.h> | ||||
| #include <string.h> | ||||
| #include <assert.h> | ||||
| #endif | ||||
|  | ||||
| typedef void * stbwingraph_hwnd; | ||||
| typedef void * stbwingraph_hinstance; | ||||
|  | ||||
| enum | ||||
| { | ||||
|    STBWINGRAPH_unprocessed = -(1 << 24), | ||||
|    STBWINGRAPH_do_not_show, | ||||
|    STBWINGRAPH_winproc_exit, | ||||
|    STBWINGRAPH_winproc_update, | ||||
|    STBWINGRAPH_update_exit, | ||||
|    STBWINGRAPH_update_pause, | ||||
| }; | ||||
|  | ||||
| typedef enum | ||||
| { | ||||
|    STBWGE__none=0, | ||||
|  | ||||
|    STBWGE_create, | ||||
|    STBWGE_create_postshow, | ||||
|    STBWGE_draw, | ||||
|    STBWGE_destroy, | ||||
|    STBWGE_char, | ||||
|    STBWGE_keydown, | ||||
|    STBWGE_syskeydown, | ||||
|    STBWGE_keyup, | ||||
|    STBWGE_syskeyup, | ||||
|    STBWGE_deactivate, | ||||
|    STBWGE_activate, | ||||
|    STBWGE_size, | ||||
|  | ||||
|    STBWGE_mousemove , | ||||
|    STBWGE_leftdown  , STBWGE_leftup  , | ||||
|    STBWGE_middledown, STBWGE_middleup, | ||||
|    STBWGE_rightdown , STBWGE_rightup , | ||||
|    STBWGE_mousewheel, | ||||
| } stbwingraph_event_type; | ||||
|  | ||||
| typedef struct | ||||
| { | ||||
|    stbwingraph_event_type type; | ||||
|  | ||||
|    // for input events (mouse, keyboard) | ||||
|    int mx,my; // mouse x & y | ||||
|    int dx,dy; | ||||
|    int shift, ctrl, alt; | ||||
|  | ||||
|    // for keyboard events | ||||
|    int key; | ||||
|  | ||||
|    // for STBWGE_size: | ||||
|    int width, height; | ||||
|  | ||||
|    // for STBWGE_crate | ||||
|    int did_share_lists;  // if true, wglShareLists succeeded | ||||
|  | ||||
|    void *handle; | ||||
|  | ||||
| } stbwingraph_event; | ||||
|  | ||||
| typedef int (*stbwingraph_window_proc)(void *data, stbwingraph_event *event); | ||||
|  | ||||
| extern stbwingraph_hinstance   stbwingraph_app; | ||||
| extern stbwingraph_hwnd        stbwingraph_primary_window; | ||||
| extern int                     stbwingraph_request_fullscreen; | ||||
| extern int                     stbwingraph_request_windowed; | ||||
|  | ||||
| STB_EXTERN void stbwingraph_ods(char *str, ...); | ||||
| STB_EXTERN int stbwingraph_MessageBox(stbwingraph_hwnd win, unsigned int type, | ||||
|                                               char *caption, char *text, ...); | ||||
| STB_EXTERN int stbwingraph_ChangeResolution(unsigned int w, unsigned int h, | ||||
|                                       unsigned int bits, int use_message_box); | ||||
| STB_EXTERN int stbwingraph_SetPixelFormat(stbwingraph_hwnd win, int color_bits, | ||||
|             int alpha_bits, int depth_bits, int stencil_bits, int accum_bits); | ||||
| STB_EXTERN int stbwingraph_DefineClass(void *hinstance, char *iconname); | ||||
| STB_EXTERN void stbwingraph_SwapBuffers(void *win); | ||||
| STB_EXTERN void stbwingraph_Priority(int n); | ||||
|  | ||||
| STB_EXTERN void stbwingraph_MakeFonts(void *window, int font_base); | ||||
| STB_EXTERN void stbwingraph_ShowWindow(void *window); | ||||
| STB_EXTERN void *stbwingraph_CreateWindow(int primary, stbwingraph_window_proc func, void *data, char *text, int width, int height, int fullscreen, int resizeable, int dest_alpha, int stencil); | ||||
| STB_EXTERN void *stbwingraph_CreateWindowSimple(stbwingraph_window_proc func, int width, int height); | ||||
| STB_EXTERN void *stbwingraph_CreateWindowSimpleFull(stbwingraph_window_proc func, int fullscreen, int ww, int wh, int fw, int fh); | ||||
| STB_EXTERN void stbwingraph_DestroyWindow(void *window); | ||||
| STB_EXTERN void stbwingraph_ShowCursor(void *window, int visible); | ||||
| STB_EXTERN float stbwingraph_GetTimestep(float minimum_time); | ||||
| STB_EXTERN void stbwingraph_SetGLWindow(void *win); | ||||
| typedef int (*stbwingraph_update)(float timestep, int real, int in_client); | ||||
| STB_EXTERN int stbwingraph_MainLoop(stbwingraph_update func, float mintime); | ||||
|  | ||||
| #ifdef STB_DEFINE | ||||
| stbwingraph_hinstance   stbwingraph_app; | ||||
| stbwingraph_hwnd        stbwingraph_primary_window; | ||||
| int stbwingraph_request_fullscreen; | ||||
| int stbwingraph_request_windowed; | ||||
|  | ||||
| void stbwingraph_ods(char *str, ...) | ||||
| { | ||||
|    char buffer[1024]; | ||||
|    va_list v; | ||||
|    va_start(v,str); | ||||
|    vsprintf(buffer, str, v); | ||||
|    va_end(v); | ||||
|    OutputDebugString(buffer); | ||||
| } | ||||
|  | ||||
| int stbwingraph_MessageBox(stbwingraph_hwnd win, unsigned int type, char *caption, char *text, ...) | ||||
| { | ||||
|    va_list v; | ||||
|    char buffer[1024]; | ||||
|    va_start(v, text); | ||||
|    vsprintf(buffer, text, v); | ||||
|    va_end(v); | ||||
|    return MessageBox(win, buffer, caption, type); | ||||
| } | ||||
|  | ||||
| void stbwingraph_Priority(int n) | ||||
| { | ||||
|    int p; | ||||
|    switch (n) { | ||||
|       case -1: p = THREAD_PRIORITY_BELOW_NORMAL; break; | ||||
|       case 0: p = THREAD_PRIORITY_NORMAL; break; | ||||
|       case 1: p = THREAD_PRIORITY_ABOVE_NORMAL; break; | ||||
|       default: | ||||
|          if (n < 0) p = THREAD_PRIORITY_LOWEST; | ||||
|          else p = THREAD_PRIORITY_HIGHEST; | ||||
|    } | ||||
|    SetThreadPriority(GetCurrentThread(), p); | ||||
| } | ||||
|  | ||||
| static void stbwingraph_ResetResolution(void) | ||||
| { | ||||
|    ChangeDisplaySettings(NULL, 0); | ||||
| } | ||||
|  | ||||
| static void stbwingraph_RegisterResetResolution(void) | ||||
| { | ||||
|    static int done=0; | ||||
|    if (!done) { | ||||
|       done = 1; | ||||
|       atexit(stbwingraph_ResetResolution); | ||||
|    } | ||||
| } | ||||
|  | ||||
| int stbwingraph_ChangeResolution(unsigned int w, unsigned int h, unsigned int bits, int use_message_box) | ||||
| { | ||||
|    DEVMODE mode; | ||||
|    int res; | ||||
|     | ||||
|    int i, tries=0; | ||||
|    for (i=0; ; ++i) { | ||||
|       int success = EnumDisplaySettings(NULL, i, &mode); | ||||
|       if (!success) break; | ||||
|       if (mode.dmBitsPerPel == bits && mode.dmPelsWidth == w && mode.dmPelsHeight == h) { | ||||
|          ++tries; | ||||
|          success = ChangeDisplaySettings(&mode, CDS_FULLSCREEN);  | ||||
|          if (success == DISP_CHANGE_SUCCESSFUL) { | ||||
|             stbwingraph_RegisterResetResolution(); | ||||
|             return TRUE; | ||||
|          } | ||||
|          break; | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    if (!tries) { | ||||
|       if (use_message_box) | ||||
|          stbwingraph_MessageBox(stbwingraph_primary_window, MB_ICONERROR, NULL, "The resolution %d x %d x %d-bits is not supported.", w, h, bits); | ||||
|       return FALSE; | ||||
|    } | ||||
|  | ||||
|    // we tried but failed, so try explicitly doing it without specifying refresh rate | ||||
|  | ||||
|    // Win95 support logic | ||||
|    mode.dmBitsPerPel = bits;  | ||||
|    mode.dmPelsWidth = w;  | ||||
|    mode.dmPelsHeight = h;  | ||||
|    mode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;  | ||||
|  | ||||
|    res = ChangeDisplaySettings(&mode, CDS_FULLSCREEN); | ||||
|  | ||||
|    switch (res) { | ||||
|       case DISP_CHANGE_SUCCESSFUL: | ||||
|          stbwingraph_RegisterResetResolution(); | ||||
|          return TRUE; | ||||
|  | ||||
|       case DISP_CHANGE_RESTART: | ||||
|          if (use_message_box) | ||||
|             stbwingraph_MessageBox(stbwingraph_primary_window, MB_ICONERROR, NULL, "Please set your desktop to %d-bit color and then try again."); | ||||
|          return FALSE; | ||||
|  | ||||
|       case DISP_CHANGE_FAILED: | ||||
|          if (use_message_box) | ||||
|             stbwingraph_MessageBox(stbwingraph_primary_window, MB_ICONERROR, NULL, "The hardware failed to change modes."); | ||||
|          return FALSE; | ||||
|  | ||||
|       case DISP_CHANGE_BADMODE: | ||||
|          if (use_message_box) | ||||
|             stbwingraph_MessageBox(stbwingraph_primary_window, MB_ICONERROR, NULL, "The resolution %d x %d x %d-bits is not supported.", w, h, bits); | ||||
|          return FALSE; | ||||
|  | ||||
|       default: | ||||
|          if (use_message_box) | ||||
|             stbwingraph_MessageBox(stbwingraph_primary_window, MB_ICONERROR, NULL, "An unknown error prevented a change to a %d x %d x %d-bit display.", w, h, bits); | ||||
|          return FALSE; | ||||
|    } | ||||
| } | ||||
|  | ||||
| int stbwingraph_SetPixelFormat(stbwingraph_hwnd win, int color_bits, int alpha_bits, int depth_bits, int stencil_bits, int accum_bits) | ||||
| { | ||||
|    HDC dc = GetDC(win); | ||||
|    PIXELFORMATDESCRIPTOR pfd = { sizeof(pfd) }; | ||||
|    int                   pixel_format; | ||||
|  | ||||
|    pfd.nVersion = 1; | ||||
|    pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER; | ||||
|    pfd.dwLayerMask = PFD_MAIN_PLANE; | ||||
|    pfd.iPixelType = PFD_TYPE_RGBA; | ||||
|    pfd.cColorBits = color_bits; | ||||
|    pfd.cAlphaBits = alpha_bits; | ||||
|    pfd.cDepthBits = depth_bits; | ||||
|    pfd.cStencilBits = stencil_bits; | ||||
|    pfd.cAccumBits = accum_bits; | ||||
|  | ||||
|    pixel_format = ChoosePixelFormat(dc, &pfd); | ||||
|    if (!pixel_format) return FALSE; | ||||
|  | ||||
|    if (!DescribePixelFormat(dc, pixel_format, sizeof(PIXELFORMATDESCRIPTOR), &pfd)) | ||||
|       return FALSE; | ||||
|    SetPixelFormat(dc, pixel_format, &pfd); | ||||
|  | ||||
|    return TRUE; | ||||
| } | ||||
|  | ||||
| typedef struct | ||||
| { | ||||
|    // app data | ||||
|    stbwingraph_window_proc func; | ||||
|    void *data; | ||||
|    // creation parameters | ||||
|    int   color, alpha, depth, stencil, accum; | ||||
|    HWND  share_window; | ||||
|    HWND  window; | ||||
|    // internal data | ||||
|    HGLRC rc; | ||||
|    HDC   dc; | ||||
|    int   hide_mouse; | ||||
|    int   in_client; | ||||
|    int   active; | ||||
|    int   did_share_lists; | ||||
|    int   mx,my; // last mouse positions | ||||
| } stbwingraph__window; | ||||
|  | ||||
| static void stbwingraph__inclient(stbwingraph__window *win, int state) | ||||
| { | ||||
|    if (state != win->in_client) { | ||||
|       win->in_client = state; | ||||
|       if (win->hide_mouse) | ||||
|          ShowCursor(!state); | ||||
|    } | ||||
| } | ||||
|  | ||||
| static void stbwingraph__key(stbwingraph_event *e, int type, int key, stbwingraph__window *z) | ||||
| { | ||||
|    e->type  = type; | ||||
|    e->key   = key; | ||||
|    e->shift = (GetKeyState(VK_SHIFT)   < 0); | ||||
|    e->ctrl  = (GetKeyState(VK_CONTROL) < 0); | ||||
|    e->alt   = (GetKeyState(VK_MENU)    < 0); | ||||
|    if  (z) { | ||||
|       e->mx    = z->mx; | ||||
|       e->my    = z->my; | ||||
|    } else { | ||||
|       e->mx = e->my = 0; | ||||
|    } | ||||
|    e->dx = e->dy = 0; | ||||
| } | ||||
|  | ||||
| static void stbwingraph__mouse(stbwingraph_event *e, int type, WPARAM wparam, LPARAM lparam, int capture, void *wnd, stbwingraph__window *z) | ||||
| { | ||||
|    static int captured = 0; | ||||
|    e->type = type; | ||||
|    e->mx = (short) LOWORD(lparam); | ||||
|    e->my = (short) HIWORD(lparam); | ||||
|    if (!z || z->mx == -(1 << 30)) { | ||||
|       e->dx = e->dy = 0; | ||||
|    } else { | ||||
|       e->dx = e->mx - z->mx; | ||||
|       e->dy = e->my - z->my; | ||||
|    } | ||||
|    e->shift = (wparam & MK_SHIFT) != 0; | ||||
|    e->ctrl  = (wparam & MK_CONTROL) != 0; | ||||
|    e->alt   = (wparam & MK_ALT) != 0; | ||||
|    if (z) { | ||||
|       z->mx = e->mx; | ||||
|       z->my = e->my; | ||||
|    } | ||||
|    if (capture) { | ||||
|       if (!captured && capture == 1) | ||||
|          SetCapture(wnd); | ||||
|       captured += capture; | ||||
|       if (!captured && capture == -1) | ||||
|          ReleaseCapture(); | ||||
|       if (captured < 0) captured = 0; | ||||
|    } | ||||
| } | ||||
|  | ||||
| static void stbwingraph__mousewheel(stbwingraph_event *e, int type, WPARAM wparam, LPARAM lparam, int capture, void *wnd, stbwingraph__window *z) | ||||
| { | ||||
|    // lparam seems bogus! | ||||
|    static int captured = 0; | ||||
|    e->type = type; | ||||
|    if (z) { | ||||
|       e->mx = z->mx; | ||||
|       e->my = z->my; | ||||
|    } | ||||
|    e->dx = e->dy = 0; | ||||
|    e->shift = (wparam & MK_SHIFT) != 0; | ||||
|    e->ctrl  = (wparam & MK_CONTROL) != 0; | ||||
|    e->alt   = (GetKeyState(VK_MENU)    < 0); | ||||
|    e->key = ((int) wparam >> 16); | ||||
| } | ||||
|  | ||||
| int stbwingraph_force_update; | ||||
| static int WINAPI stbwingraph_WinProc(HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam) | ||||
| { | ||||
|    int allow_default = TRUE; | ||||
|    stbwingraph_event e = { STBWGE__none }; | ||||
|    // the following line is wrong for 64-bit windows, but VC6 doesn't have GetWindowLongPtr | ||||
|    stbwingraph__window *z = (stbwingraph__window *) GetWindowLong(wnd, GWL_USERDATA); | ||||
|  | ||||
|    switch (msg) { | ||||
|  | ||||
|       case WM_CREATE: | ||||
|       { | ||||
|          LPCREATESTRUCT lpcs = (LPCREATESTRUCT) lparam; | ||||
|          assert(z == NULL); | ||||
|          z = (stbwingraph__window *) lpcs->lpCreateParams; | ||||
|          SetWindowLong(wnd, GWL_USERDATA, (LONG) z); | ||||
|          z->dc = GetDC(wnd); | ||||
|          if (stbwingraph_SetPixelFormat(wnd, z->color, z->alpha, z->depth, z->stencil, z->accum)) { | ||||
|             z->rc = wglCreateContext(z->dc); | ||||
|             if (z->rc) { | ||||
|                e.type = STBWGE_create; | ||||
|                z->did_share_lists = FALSE; | ||||
|                if (z->share_window) { | ||||
|                   stbwingraph__window *y = (stbwingraph__window *) GetWindowLong(z->share_window, GWL_USERDATA); | ||||
|                   if (wglShareLists(z->rc, y->rc)) | ||||
|                      z->did_share_lists = TRUE; | ||||
|                } | ||||
|                wglMakeCurrent(z->dc, z->rc); | ||||
|                return 0; | ||||
|             } | ||||
|          } | ||||
|          return -1; | ||||
|       } | ||||
|  | ||||
|       case WM_PAINT: { | ||||
|          PAINTSTRUCT ps; | ||||
|          HDC hdc = BeginPaint(wnd, &ps); | ||||
|          SelectObject(hdc, GetStockObject(NULL_BRUSH)); | ||||
|          e.type = STBWGE_draw; | ||||
|          e.handle = wnd; | ||||
|          z->func(z->data, &e); | ||||
|          EndPaint(wnd, &ps); | ||||
|          return 0; | ||||
|       } | ||||
|  | ||||
|       case WM_DESTROY: | ||||
|          e.type = STBWGE_destroy; | ||||
|          e.handle = wnd; | ||||
|          if (z && z->func) | ||||
|             z->func(z->data, &e); | ||||
|          wglMakeCurrent(NULL, NULL) ;  | ||||
|          if (z) { | ||||
|             if (z->rc) wglDeleteContext(z->rc); | ||||
|             z->dc = 0; | ||||
|             z->rc = 0; | ||||
|          } | ||||
|          if (wnd == stbwingraph_primary_window) | ||||
|             PostQuitMessage (0); | ||||
|          return 0; | ||||
|  | ||||
|       case WM_CHAR:         stbwingraph__key(&e, STBWGE_char   , wparam, z); break; | ||||
|       case WM_KEYDOWN:      stbwingraph__key(&e, STBWGE_keydown, wparam, z); break; | ||||
|       case WM_KEYUP:        stbwingraph__key(&e, STBWGE_keyup  , wparam, z); break; | ||||
|  | ||||
|       case WM_NCMOUSEMOVE:  stbwingraph__inclient(z,0); break; | ||||
|       case WM_MOUSEMOVE:    stbwingraph__inclient(z,1); stbwingraph__mouse(&e, STBWGE_mousemove,  wparam, lparam,0,wnd, z); break; | ||||
|       case WM_LBUTTONDOWN:  stbwingraph__mouse(&e, STBWGE_leftdown,   wparam, lparam,1,wnd, z); break; | ||||
|       case WM_MBUTTONDOWN:  stbwingraph__mouse(&e, STBWGE_middledown, wparam, lparam,1,wnd, z); break; | ||||
|       case WM_RBUTTONDOWN:  stbwingraph__mouse(&e, STBWGE_rightdown,  wparam, lparam,1,wnd, z); break; | ||||
|       case WM_LBUTTONUP:    stbwingraph__mouse(&e, STBWGE_leftup,     wparam, lparam,-1,wnd, z); break; | ||||
|       case WM_MBUTTONUP:    stbwingraph__mouse(&e, STBWGE_middleup,   wparam, lparam,-1,wnd, z); break; | ||||
|       case WM_RBUTTONUP:    stbwingraph__mouse(&e, STBWGE_rightup,    wparam, lparam,-1,wnd, z); break; | ||||
|       case WM_MOUSEWHEEL:   stbwingraph__mousewheel(&e, STBWGE_mousewheel, wparam, lparam,0,wnd, z); break; | ||||
|  | ||||
|       case WM_ACTIVATE: | ||||
|          allow_default = FALSE; | ||||
|          if (LOWORD(wparam)==WA_INACTIVE ) { | ||||
|             wglMakeCurrent(z->dc, NULL); | ||||
|             e.type = STBWGE_deactivate; | ||||
|             z->active = FALSE; | ||||
|          } else { | ||||
|             wglMakeCurrent(z->dc, z->rc); | ||||
|             e.type = STBWGE_activate; | ||||
|             z->active = TRUE; | ||||
|          } | ||||
|          e.handle = wnd; | ||||
|          z->func(z->data, &e); | ||||
|          return 0; | ||||
|  | ||||
|       case WM_SIZE: { | ||||
|          RECT rect; | ||||
|          allow_default = FALSE; | ||||
|          GetClientRect(wnd, &rect); | ||||
|          e.type = STBWGE_size; | ||||
|          e.width = rect.right; | ||||
|          e.height = rect.bottom; | ||||
|          e.handle = wnd; | ||||
|          z->func(z->data, &e); | ||||
|          return 0; | ||||
|       } | ||||
|  | ||||
|       default: | ||||
|          return DefWindowProc (wnd, msg, wparam, lparam); | ||||
|    } | ||||
|  | ||||
|    if (e.type != STBWGE__none) { | ||||
|       int n; | ||||
|       e.handle = wnd; | ||||
|       n = z->func(z->data, &e); | ||||
|       if (n == STBWINGRAPH_winproc_exit) { | ||||
|          PostQuitMessage(0); | ||||
|          n = 0; | ||||
|       } | ||||
|       if (n == STBWINGRAPH_winproc_update) { | ||||
|          stbwingraph_force_update = TRUE; | ||||
|          return 1; | ||||
|       } | ||||
|       if (n != STBWINGRAPH_unprocessed) | ||||
|          return n; | ||||
|    } | ||||
|    return DefWindowProc (wnd, msg, wparam, lparam); | ||||
| } | ||||
|  | ||||
| int stbwingraph_DefineClass(HINSTANCE hInstance, char *iconname) | ||||
| { | ||||
|    WNDCLASSEX  wndclass; | ||||
|  | ||||
|    stbwingraph_app = hInstance; | ||||
|  | ||||
|    wndclass.cbSize        = sizeof(wndclass); | ||||
|    wndclass.style         = CS_OWNDC; | ||||
|    wndclass.lpfnWndProc   = (WNDPROC) stbwingraph_WinProc; | ||||
|    wndclass.cbClsExtra    = 0; | ||||
|    wndclass.cbWndExtra    = 0; | ||||
|    wndclass.hInstance     = hInstance; | ||||
|    wndclass.hIcon         = LoadIcon(hInstance, iconname); | ||||
|    wndclass.hCursor       = LoadCursor(NULL,IDC_ARROW); | ||||
|    wndclass.hbrBackground = GetStockObject(NULL_BRUSH); | ||||
|    wndclass.lpszMenuName  = "zwingraph"; | ||||
|    wndclass.lpszClassName = "zwingraph"; | ||||
|    wndclass.hIconSm       = NULL; | ||||
|  | ||||
|    if (!RegisterClassEx(&wndclass)) | ||||
|       return FALSE; | ||||
|    return TRUE; | ||||
| } | ||||
|  | ||||
| void stbwingraph_ShowWindow(void *window) | ||||
| { | ||||
|    stbwingraph_event e = { STBWGE_create_postshow }; | ||||
|    stbwingraph__window *z = (stbwingraph__window *) GetWindowLong(window, GWL_USERDATA); | ||||
|    ShowWindow(window, SW_SHOWNORMAL); | ||||
|    InvalidateRect(window, NULL, TRUE); | ||||
|    UpdateWindow(window); | ||||
|    e.handle = window; | ||||
|    z->func(z->data, &e); | ||||
| } | ||||
|  | ||||
| void *stbwingraph_CreateWindow(int primary, stbwingraph_window_proc func, void *data, char *text, | ||||
|            int width, int height, int fullscreen, int resizeable, int dest_alpha, int stencil) | ||||
| { | ||||
|    HWND win; | ||||
|    DWORD dwstyle; | ||||
|    stbwingraph__window *z = (stbwingraph__window *) malloc(sizeof(*z)); | ||||
|  | ||||
|    if (z == NULL) return NULL; | ||||
|    memset(z, 0, sizeof(*z)); | ||||
|    z->color = 24; | ||||
|    z->depth = 24; | ||||
|    z->alpha = dest_alpha; | ||||
|    z->stencil = stencil; | ||||
|    z->func = func; | ||||
|    z->data = data; | ||||
|    z->mx = -(1 << 30); | ||||
|    z->my = 0; | ||||
|  | ||||
|    if (primary) { | ||||
|       if (stbwingraph_request_windowed) | ||||
|          fullscreen = FALSE; | ||||
|       else if (stbwingraph_request_fullscreen) | ||||
|          fullscreen = TRUE; | ||||
|    } | ||||
|  | ||||
|    if (fullscreen) { | ||||
|       #ifdef STB_SIMPLE | ||||
|       stbwingraph_ChangeResolution(width, height, 32, 1); | ||||
|       #else | ||||
|       if (!stbwingraph_ChangeResolution(width, height, 32, 0)) | ||||
|          return NULL; | ||||
|       #endif | ||||
|       dwstyle = WS_POPUP | WS_CLIPSIBLINGS; | ||||
|    } else { | ||||
|       RECT rect; | ||||
|       dwstyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX; | ||||
|       if (resizeable) | ||||
|          dwstyle |= WS_SIZEBOX | WS_MAXIMIZEBOX; | ||||
|       rect.top = 0; | ||||
|       rect.left = 0; | ||||
|       rect.right = width; | ||||
|       rect.bottom = height; | ||||
|       AdjustWindowRect(&rect, dwstyle, FALSE); | ||||
|       width = rect.right - rect.left; | ||||
|       height = rect.bottom - rect.top; | ||||
|    } | ||||
|  | ||||
|    win = CreateWindow("zwingraph", text ? text : "sample", dwstyle, | ||||
|                       CW_USEDEFAULT,0, width, height, | ||||
|                       NULL, NULL, stbwingraph_app, z); | ||||
|  | ||||
|    if (win == NULL) return win; | ||||
|  | ||||
|    if (primary) { | ||||
|       if (stbwingraph_primary_window) | ||||
|          stbwingraph_DestroyWindow(stbwingraph_primary_window); | ||||
|       stbwingraph_primary_window = win; | ||||
|    } | ||||
|  | ||||
|    { | ||||
|       stbwingraph_event e = { STBWGE_create }; | ||||
|       stbwingraph__window *z = (stbwingraph__window *) GetWindowLong(win, GWL_USERDATA); | ||||
|       z->window = win; | ||||
|       e.did_share_lists = z->did_share_lists; | ||||
|       e.handle = win; | ||||
|       if (z->func(z->data, &e) != STBWINGRAPH_do_not_show) | ||||
|          stbwingraph_ShowWindow(win); | ||||
|    } | ||||
|  | ||||
|    return win; | ||||
| } | ||||
|  | ||||
| void *stbwingraph_CreateWindowSimple(stbwingraph_window_proc func, int width, int height) | ||||
| { | ||||
|    int fullscreen = 0; | ||||
|    #ifndef _DEBUG | ||||
|    if (width ==  640 && height ==  480) fullscreen = 1; | ||||
|    if (width ==  800 && height ==  600) fullscreen = 1; | ||||
|    if (width == 1024 && height ==  768) fullscreen = 1; | ||||
|    if (width == 1280 && height == 1024) fullscreen = 1; | ||||
|    if (width == 1600 && height == 1200) fullscreen = 1; | ||||
|    //@TODO: widescreen widths | ||||
|    #endif | ||||
|    return stbwingraph_CreateWindow(1, func, NULL, NULL, width, height, fullscreen, 1, 0, 0); | ||||
| } | ||||
|  | ||||
| void *stbwingraph_CreateWindowSimpleFull(stbwingraph_window_proc func, int fullscreen, int ww, int wh, int fw, int fh) | ||||
| { | ||||
|    if (fullscreen == -1) { | ||||
|    #ifdef _DEBUG | ||||
|       fullscreen = 0; | ||||
|    #else | ||||
|       fullscreen = 1; | ||||
|    #endif | ||||
|    } | ||||
|  | ||||
|    if (fullscreen) { | ||||
|       if (fw) ww = fw; | ||||
|       if (fh) wh = fh; | ||||
|    } | ||||
|    return stbwingraph_CreateWindow(1, func, NULL, NULL, ww, wh, fullscreen, 1, 0, 0); | ||||
| } | ||||
|  | ||||
| void stbwingraph_DestroyWindow(void *window) | ||||
| { | ||||
|    stbwingraph__window *z = (stbwingraph__window *) GetWindowLong(window, GWL_USERDATA); | ||||
|    DestroyWindow(window); | ||||
|    free(z); | ||||
|    if (stbwingraph_primary_window == window) | ||||
|       stbwingraph_primary_window = NULL; | ||||
| } | ||||
|  | ||||
| void stbwingraph_ShowCursor(void *window, int visible) | ||||
| { | ||||
|    int hide; | ||||
|    stbwingraph__window *win; | ||||
|    if (!window) | ||||
|       window = stbwingraph_primary_window; | ||||
|    win = (stbwingraph__window *) GetWindowLong((HWND) window, GWL_USERDATA); | ||||
|    hide = !visible; | ||||
|    if (hide != win->hide_mouse) { | ||||
|       win->hide_mouse = hide; | ||||
|       if (!hide) | ||||
|          ShowCursor(TRUE); | ||||
|       else if (win->in_client) | ||||
|          ShowCursor(FALSE); | ||||
|    } | ||||
| } | ||||
|  | ||||
| float stbwingraph_GetTimestep(float minimum_time) | ||||
| { | ||||
|    float elapsedTime; | ||||
|    double thisTime; | ||||
|    static double lastTime = -1; | ||||
|     | ||||
|    if (lastTime == -1) | ||||
|       lastTime = timeGetTime() / 1000.0 - minimum_time; | ||||
|  | ||||
|    for(;;) { | ||||
|       thisTime = timeGetTime() / 1000.0; | ||||
|       elapsedTime = (float) (thisTime - lastTime); | ||||
|       if (elapsedTime >= minimum_time) { | ||||
|          lastTime = thisTime;          | ||||
|          return elapsedTime; | ||||
|       } | ||||
|       #if 1 | ||||
|       Sleep(2); | ||||
|       #endif | ||||
|    } | ||||
| } | ||||
|  | ||||
| void stbwingraph_SetGLWindow(void *win) | ||||
| { | ||||
|    stbwingraph__window *z = (stbwingraph__window *) GetWindowLong(win, GWL_USERDATA); | ||||
|    if (z) | ||||
|       wglMakeCurrent(z->dc, z->rc); | ||||
| } | ||||
|  | ||||
| void stbwingraph_MakeFonts(void *window, int font_base) | ||||
| { | ||||
|    wglUseFontBitmaps(GetDC(window ? window : stbwingraph_primary_window), 0, 256, font_base); | ||||
| } | ||||
|  | ||||
| // returns 1 if WM_QUIT, 0 if 'func' returned 0 | ||||
| int stbwingraph_MainLoop(stbwingraph_update func, float mintime) | ||||
| { | ||||
|    int needs_drawing = FALSE; | ||||
|    MSG msg; | ||||
|  | ||||
|    int is_animating = TRUE; | ||||
|    if (mintime <= 0) mintime = 0.01f; | ||||
|  | ||||
|    for(;;) { | ||||
|       int n; | ||||
|  | ||||
|       is_animating = TRUE; | ||||
|       // wait for a message if: (a) we're animating and there's already a message | ||||
|       // or (b) we're not animating | ||||
|       if (!is_animating || PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) { | ||||
|          stbwingraph_force_update = FALSE; | ||||
|          if (GetMessage(&msg, NULL, 0, 0)) { | ||||
|             TranslateMessage(&msg); | ||||
|             DispatchMessage(&msg); | ||||
|          } else { | ||||
|             return 1;   // WM_QUIT | ||||
|          } | ||||
|  | ||||
|          // only force a draw for certain messages... | ||||
|          // if I don't do this, we peg at 50% for some reason... must | ||||
|          // be a bug somewhere, because we peg at 100% when rendering... | ||||
|          // very weird... looks like NVIDIA is pumping some messages | ||||
|          // through our pipeline? well, ok, I guess if we can get | ||||
|          // non-user-generated messages we have to do this | ||||
|          if (!stbwingraph_force_update) { | ||||
|             switch (msg.message) { | ||||
|                case WM_MOUSEMOVE: | ||||
|                case WM_NCMOUSEMOVE: | ||||
|                   break; | ||||
|                case WM_CHAR:          | ||||
|                case WM_KEYDOWN:       | ||||
|                case WM_KEYUP:         | ||||
|                case WM_LBUTTONDOWN:   | ||||
|                case WM_MBUTTONDOWN:   | ||||
|                case WM_RBUTTONDOWN:   | ||||
|                case WM_LBUTTONUP:     | ||||
|                case WM_MBUTTONUP:     | ||||
|                case WM_RBUTTONUP:     | ||||
|                case WM_TIMER: | ||||
|                case WM_SIZE: | ||||
|                case WM_ACTIVATE: | ||||
|                   needs_drawing = TRUE; | ||||
|                   break; | ||||
|             } | ||||
|          } else | ||||
|             needs_drawing = TRUE; | ||||
|       } | ||||
|  | ||||
|       // if another message, process that first | ||||
|       // @TODO: i don't think this is working, because I can't key ahead | ||||
|       // in the SVT demo app | ||||
|       if (PeekMessage(&msg, NULL, 0,0, PM_NOREMOVE)) | ||||
|          continue; | ||||
|  | ||||
|       // and now call update | ||||
|       if (needs_drawing || is_animating) { | ||||
|          int real=1, in_client=1; | ||||
|          if (stbwingraph_primary_window) { | ||||
|             stbwingraph__window *z = (stbwingraph__window *) GetWindowLong(stbwingraph_primary_window, GWL_USERDATA); | ||||
|             if (z && !z->active) { | ||||
|                real = 0; | ||||
|             } | ||||
|             if (z) | ||||
|                in_client = z->in_client; | ||||
|          } | ||||
|  | ||||
|          if (stbwingraph_primary_window) | ||||
|             stbwingraph_SetGLWindow(stbwingraph_primary_window); | ||||
|          n = func(stbwingraph_GetTimestep(mintime), real, in_client); | ||||
|          if (n == STBWINGRAPH_update_exit) | ||||
|             return 0; // update_quit | ||||
|  | ||||
|          is_animating = (n != STBWINGRAPH_update_pause); | ||||
|  | ||||
|          needs_drawing = FALSE; | ||||
|       } | ||||
|    } | ||||
| } | ||||
|  | ||||
| void stbwingraph_SwapBuffers(void *win) | ||||
| { | ||||
|    stbwingraph__window *z; | ||||
|    if (win == NULL) win = stbwingraph_primary_window; | ||||
|    z = (stbwingraph__window *) GetWindowLong(win, GWL_USERDATA); | ||||
|    if (z && z->dc) | ||||
|       SwapBuffers(z->dc); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| #ifdef STB_WINMAIN     | ||||
| void stbwingraph_main(void); | ||||
|  | ||||
| char *stb_wingraph_commandline; | ||||
|  | ||||
| int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) | ||||
| { | ||||
|    { | ||||
|       char buffer[1024]; | ||||
|       // add spaces to either side of the string | ||||
|       buffer[0] = ' '; | ||||
|       strcpy(buffer+1, lpCmdLine); | ||||
|       strcat(buffer, " "); | ||||
|       if (strstr(buffer, " -reset ")) { | ||||
|          ChangeDisplaySettings(NULL, 0);  | ||||
|          exit(0); | ||||
|       } | ||||
|       if (strstr(buffer, " -window ") || strstr(buffer, " -windowed ")) | ||||
|          stbwingraph_request_windowed = TRUE; | ||||
|       else if (strstr(buffer, " -full ") || strstr(buffer, " -fullscreen ")) | ||||
|          stbwingraph_request_fullscreen = TRUE; | ||||
|    } | ||||
|    stb_wingraph_commandline = lpCmdLine; | ||||
|  | ||||
|    stbwingraph_DefineClass(hInstance, "appicon"); | ||||
|    stbwingraph_main(); | ||||
|  | ||||
|    return 0; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| #undef STB_EXTERN | ||||
| #ifdef STB_WINGRAPH_DISABLE_DEFINE_AT_END | ||||
| #undef STB_DEFINE | ||||
| #endif | ||||
|  | ||||
| #endif // INCLUDE_STB_WINGRAPH_H | ||||
		Reference in New Issue
	
	Block a user