1 /*---------------------------------------------------------------------------*
2 
3   Copyright (C) Nintendo.  All rights reserved.
4 
5   These coded instructions, statements, and computer programs contain
6   proprietary information of Nintendo of America Inc. and/or Nintendo
7   Company Ltd., and are protected by Federal copyright law.  They may
8   not be disclosed to third parties or copied or duplicated in any form,
9   in whole or in part, without the prior written consent of Nintendo.
10 
11  *---------------------------------------------------------------------------*/
12 ////===========================================================================
13 ///  demoFont.c
14 ///
15 ///     This is font code for the demo library.
16 ///
17 ////===========================================================================
18 #include <stdarg.h>
19 #include <stdio.h>
20 
21 #include <cafe/demo.h>
22 #include <cafe/demo/demoFontData.h> // Font Data
23 #include <cafe/gfd.h>
24 
25 //---------------------------------------------------------------------------
26 //  Shader Data
27 //---------------------------------------------------------------------------
28 static const char * const FONT_GSH_SHADER_FILE = "shaders/lib_demo/cafe/demoFont.gsh";
29 
30 // --------------------------------------------------------------------------
31 //  Macro definitions
32 // --------------------------------------------------------------------------
33 // Max Buffer Size for vsnprintf_s
34 #define FONT_MAX_BUFSIZ 512
35 
36 
37 // Simple structure that contains all the data
38 // we need to know about characters in the font texture
39 typedef struct
40 {
41     u32   id;
42     s32 minS;
43     s32 minT;
44     s32 maxS;
45     s32 maxT;
46     s32 minX;
47     s32 minY;
48     s32 maxX;
49     s32 maxY;
50     s32 xAdvance;
51 } CharContainer_t;
52 
53 typedef struct
54 {
55     // Contains all the data we need to render each character
56     CharContainer_t* pCharDataBuffer;
57 
58     // Font texture height
59     f32 fontTextureWidth;
60 
61     // Font texture width
62     f32 fontTextureHeight;
63 
64     // The number of characters stored in the raw char data
65     u32 numCharData;
66 
67     // The offset height of grid
68     f32 gridOffsetY;
69 
70     // The offset width of grid
71     f32 gridOffsetX;
72 
73     // Pointer to Font Image Data
74     u8* pFontImageData;
75 
76     // --- GPU MEM ---
77     // includes pointer to buffer containing the Texture image Data
78     GX2Texture TexData;
79 } FontData_t;
80 
81 // DEMO Font Context State
82 static GX2ContextState *DEMOFontContextState;
83 
84 // P: Proportional, F: Fixed mono_space
85 static FontData_t s_FontP, s_FontF;
86 static GX2Sampler s_sampler = {0};
87 static DEMOGfxShader s_Shader = {0};
88 static BOOL s_enabled=TRUE;
89 
90 // Max number of unique characters defined in each font
91 #define MAX_NUM_CHARS 100
92 static CharContainer_t s_CharDataBufferP[MAX_NUM_CHARS];
93 static CharContainer_t s_CharDataBufferF[MAX_NUM_CHARS];
94 
95 // Instance
96 static DEMOFontInstance* gDemoFontCurInstance = NULL;
97 
98 //--------------------------------------------------------------------------
99 //   Forward references
100 //--------------------------------------------------------------------------
101 static FontData_t* GetCurrentFont(void);
102 static void UpdateScale(DEMOFontFontData* pFont, f32 scaleX, f32 scaleY);
103 static void SetFontTexture(DEMOGfxShader* pShader, FontData_t* pFont);
104 static void GetFontCharData(FontData_t* pFont,
105                             const u32* pFontHeader,
106                             const u32* pCharData,
107                             const u8* pFontImageData);
108 static void InitFontTexture(DEMOGfxShader* pShader, FontData_t* pFont);
109 static void InitShader(DEMOGfxShader* pShader);
110 static u32  BSearchIndex(FontData_t* pFont, u32 id);
111 
112 // --------------------------------------------------------------------------
113 //  Init
114 // --------------------------------------------------------------------------
DEMOFontInit()115 DEMOFontInstance* DEMOFontInit()
116 {
117     // Get Font char data
118     GetFontCharData(&s_FontF,
119                     s_FontHeaderF, (u32*)s_CharDataF, s_FontImageDataF);
120 
121     GetFontCharData(&s_FontP,
122                     s_FontHeaderP, (u32*)s_CharDataP, s_FontImageDataP);
123 
124     // Initialise Shader
125     InitShader(&s_Shader);
126 
127     // Initialize Font Texture
128     InitFontTexture(&s_Shader, &s_FontP);
129     InitFontTexture(&s_Shader, &s_FontF);
130 
131     DEMOFontAddInstance();
132 
133     // Restore state
134     DEMOGfxSetContextState();
135 
136     return gDemoFontCurInstance;
137 }
138 
139 // --------------------------------------------------------------------------
140 //  ShutDown
141 // --------------------------------------------------------------------------
DEMOFontShutdown(void)142 void DEMOFontShutdown(void)
143 {
144     // Delete the instance
145     DEMOFontDeleteInstance(gDemoFontCurInstance);
146 
147     // Free shaders
148     DEMOGfxFreeShaders(&s_Shader);
149 
150     // Free texture
151     if (s_FontP.TexData.surface.imagePtr) {
152         DEMOGfxFreeMEM2(s_FontP.TexData.surface.imagePtr);
153     }
154     if (s_FontF.TexData.surface.imagePtr) {
155         DEMOGfxFreeMEM2(s_FontF.TexData.surface.imagePtr);
156     }
157 }
158 
159 // --------------------------------------------------------------------------
160 //  Context State
161 // --------------------------------------------------------------------------
DEMOFontSetContextState(void)162 void DEMOFontSetContextState(void)
163 {
164     GX2UTDebugTagIndent("DEMOFontSetContextState()");
165     GX2SetContextState(DEMOFontContextState);
166     GX2UTDebugTagUndent();
167 }
168 
169 // --------------------------------------------------------------------------
170 //  Enable
171 // --------------------------------------------------------------------------
DEMOFontDrawEnable(BOOL enable)172 void DEMOFontDrawEnable(BOOL enable)
173 {
174     s_enabled = enable;
175 
176         // MUST verify the instance exists before setting it!
177     if (gDemoFontCurInstance)
178         gDemoFontCurInstance->enabled = enable;
179 }
180 
181 // --------------------------------------------------------------------------
182 //  Printf
183 // --------------------------------------------------------------------------
DEMOFontPrintf(f32 column,f32 line,const char * pFmt,...)184 void DEMOFontPrintf(f32 column, f32 line, const char* pFmt, ... )
185 {
186     char str[FONT_MAX_BUFSIZ];
187     va_list args;
188     s32 stringSize;
189 
190     // Don't draw if fonts are disabled
191     if (!gDemoFontCurInstance->enabled) return;
192 
193     // Get string
194     va_start(args, pFmt);
195     stringSize = vsnprintf( str, FONT_MAX_BUFSIZ, pFmt, args );
196 
197     // Assert for over string size
198     if ( stringSize < 0 )
199     {
200         DEMOAssert(!"String is too long\n");
201     }
202 
203     va_end(args);
204 
205     DEMOFontPuts( column, line, str );
206 }
207 
DEMOFontPuts(f32 column,f32 line,const char * pStr)208 void DEMOFontPuts(f32 column, f32 line, const char* pStr)
209 {
210     u32 stringLength;
211     s32 offsetX;
212     s32 offsetY;
213     FontData_t* pFont = GetCurrentFont();
214     DEMOFontFontData* pFontData = &gDemoFontCurInstance->font;
215     f32 basePos[3];
216     u32 advanceX = 0;
217     u32 indices[FONT_MAX_BUFSIZ*4];
218     u32 indCount;
219     u32 cIn = 0;
220 
221     // Don't draw if fonts are disabled
222     if (!gDemoFontCurInstance->enabled) return;
223 
224     // Check the initialize
225     DEMOAssert(pStr &&
226         "Need to initialize pStr.\n");
227     DEMOAssert(pFont->pCharDataBuffer &&
228         "Need to call DEMOFontInit(). Before this function.\n");
229 
230     stringLength = (u32)(strlen((const char *)pStr));
231 
232     // Calc offsets
233     offsetX = (s32)(column * pFont->gridOffsetX);
234     offsetY = -(s32)((line + 1) * pFont->gridOffsetY);
235 
236     // Set up rendering state
237     SetFontTexture(&s_Shader, pFont);
238 
239     // Update scale
240     GX2SetVertexUniformReg(s_Shader.uniformsVS.location[1], 1*4, &pFontData->charMagScale[0]);
241 
242     // Update color uniform
243     GX2SetPixelUniformReg(s_Shader.uniformsPS.location[0], 1*4, &pFontData->color);
244 
245     basePos[2] = pFontData->depth;
246 
247     while (cIn < stringLength) {
248 
249         basePos[0] = (f32) offsetX;
250         basePos[1] = (f32) offsetY;
251 
252         indCount = 0;
253 
254         for(; cIn < stringLength; cIn++) {
255 
256             u32 id = (u32) pStr[cIn];
257             u32 index = 0;
258             u32 px1, px2, py1, py2;
259             u32 ps1, ps2, pt1, pt2;
260 
261             if(id == 10)
262             {
263                 advanceX = 0;
264                 offsetY -= pFont->gridOffsetY;
265                 cIn++;
266                 break;
267             }
268             else if(id >= 32 && id <= 127)
269             {
270                 // Get index of character id
271                 index = BSearchIndex(pFont,id);
272             }
273 
274             px1 = (u32)(pFont->pCharDataBuffer[index].minX + advanceX);
275             px2 = (u32)(pFont->pCharDataBuffer[index].maxX + advanceX);
276             py1 = (u32)(pFont->pCharDataBuffer[index].minY);
277             py2 = (u32)(pFont->pCharDataBuffer[index].maxY);
278 
279             // If we exceed the bitfield for advanceX, reset base
280             if (px2 > 0xfff) {
281                 offsetX += advanceX;
282                 advanceX = 0;
283                 break;
284             }
285 
286             ps1 = (u32)pFont->pCharDataBuffer[index].minS;
287             ps2 = (u32)pFont->pCharDataBuffer[index].maxS;
288             pt1 = (u32)pFont->pCharDataBuffer[index].minT;
289             pt2 = (u32)pFont->pCharDataBuffer[index].maxT;
290 
291 #define CHECK(px, py, tx, ty) \
292     DEMOAssert(!((px)&~0xfff)&&!((py)&~0x1f)&&!((tx)&~0xff)&&!((ty)&~0x7f))
293 #define PACK(px, py, tx, ty) (((px)<<20)|((py)<<15)|((tx)<<7)|(ty))
294 
295             CHECK(px1, py1, ps1, pt1);
296             CHECK(px2, py2, ps2, pt2);
297 
298             indices[indCount++] = PACK(px1, py1, ps1, pt1);
299             indices[indCount++] = PACK(px1, py2, ps1, pt2);
300             indices[indCount++] = PACK(px2, py2, ps2, pt2);
301             indices[indCount++] = PACK(px2, py1, ps2, pt1);
302 
303             advanceX += pFont->pCharDataBuffer[index].xAdvance;
304         }
305 
306         // Skip blank lines
307         if (indCount == 0) continue;
308 
309         // Set base position
310         GX2SetVertexUniformReg(s_Shader.uniformsVS.location[0], 1*4, &basePos);
311 
312         // Draw the characters
313         GX2DrawIndexedImmediate(GX2_PRIMITIVE_QUADS,
314                                    indCount,
315                                    GX2_INDEX_FORMAT_U32,
316                                    indices);
317     }
318 }
319 
320 // --------------------------------------------------------------------------
321 //  Update
322 // --------------------------------------------------------------------------
DEMOFontSetSpacing(BOOL proportional)323 void DEMOFontSetSpacing(BOOL proportional)
324 {
325     // Check the initialize
326     DEMOAssert(s_FontP.pCharDataBuffer &&
327         "Need to call DEMOFontInit(). Before this function.\n");
328 
329     // Update proportional boolean
330     gDemoFontCurInstance->proportional = proportional;
331 
332     // Switch which scale we use
333     if (proportional)
334         gDemoFontCurInstance->font.charMagScale = gDemoFontCurInstance->font.charMagScaleP;
335     else
336         gDemoFontCurInstance->font.charMagScale = gDemoFontCurInstance->font.charMagScaleF;
337 }
338 
DEMOFontSetGridSize(f32 xGrid,f32 yGrid)339 void DEMOFontSetGridSize(f32 xGrid, f32 yGrid)
340 {
341     // Check the initialize
342     DEMOAssert(s_FontP.pCharDataBuffer &&
343         "Need to call DEMOFontInit(). Before this function.\n");
344 
345     // Update scale
346     UpdateScale(&gDemoFontCurInstance->font, xGrid, yGrid);
347 }
348 
DEMOFontSetColor(f32 r,f32 g,f32 b,f32 a)349 void DEMOFontSetColor(f32 r, f32 g, f32 b, f32 a)
350 {
351     // Check the initialize
352     DEMOAssert(s_FontP.pCharDataBuffer &&
353         "Need to call DEMOFontInit(). Before this function.\n");
354 
355     // Update color
356     gDemoFontCurInstance->font.color[0] = r;
357     gDemoFontCurInstance->font.color[1] = g;
358     gDemoFontCurInstance->font.color[2] = b;
359     gDemoFontCurInstance->font.color[3] = a;
360 }
361 
DEMOFontSetZValue(f32 zValue)362 void DEMOFontSetZValue(f32 zValue)
363 {
364     // Check the initialize
365     DEMOAssert(s_FontP.pCharDataBuffer &&
366         "Need to call DEMOFontInit(). Before this function.\n");
367 
368     // Update depth value
369     gDemoFontCurInstance->font.depth = zValue;
370 }
371 
372 // --------------------------------------------------------------------------
373 //  Getter
374 // --------------------------------------------------------------------------
375 
DEMOFontGetCharSize(f32 * pCharWidth,f32 * pCharHeight)376 void DEMOFontGetCharSize(f32 *pCharWidth, f32 *pCharHeight)
377 {
378     FontData_t* pFont = GetCurrentFont();
379 
380     // Get size of font
381     *pCharWidth   = pFont->gridOffsetX;
382     *pCharHeight  = pFont->gridOffsetY;
383 }
384 
385 // --------------------------------------------------------------------------
386 //  Private Functions
387 // --------------------------------------------------------------------------
388 /// Check Proportional boolean and return Font handle
GetCurrentFont(void)389 static FontData_t* GetCurrentFont(void)
390 {
391     if(gDemoFontCurInstance->proportional)
392     {
393         return &s_FontP;
394     }
395     else
396     {
397         return &s_FontF;
398     }
399 }
400 
401 /// Update scale
UpdateScale(DEMOFontFontData * pFont,f32 scaleX,f32 scaleY)402 static void UpdateScale(DEMOFontFontData* pFont, f32 scaleX, f32 scaleY)
403 {
404     // Calculate char scale
405     pFont->charMagScaleF[0] = 2.0f/(scaleX * s_FontF.gridOffsetX);
406     pFont->charMagScaleF[1] = 2.0f/(scaleY * s_FontF.gridOffsetY);
407 
408     pFont->charMagScaleP[0] = 2.0f/(scaleX * s_FontP.gridOffsetX);
409     pFont->charMagScaleP[1] = 2.0f/(scaleY * s_FontP.gridOffsetY);
410 }
411 
412 /// Get Font char data from demoFontData.h
GetFontCharData(FontData_t * pFont,const u32 * pFontHeader,const u32 * pCharData,const u8 * pFontImageData)413 static void GetFontCharData(FontData_t* pFont,
414                             const u32* pFontHeader,
415                             const u32* pCharData,
416                             const u8* pFontImageData)
417 {
418     u32 i;
419     f32 lineHeight;
420     f32 maxCharWidth = 0.0f;
421     f32 maxCharHeight = 0.0f;
422 
423     // Check Font Texture Data
424     DEMOAssert(pFontHeader != NULL && pCharData != NULL &&
425         pFontImageData != NULL && "No texture data.\n");
426 
427     // Check char data buffer
428     if (pFont->pCharDataBuffer)
429     {
430         // Skip Data Initialization
431         return;
432     }
433 
434     // Set Font Texture Data Information
435     pFont->fontTextureWidth  = (f32)pFontHeader[0];
436     pFont->fontTextureHeight = (f32)pFontHeader[1];
437     lineHeight               = (f32)pFontHeader[4];
438     pFont->numCharData       = pFontHeader[5];
439     pFont->gridOffsetX       = 0;
440     pFont->gridOffsetY       = 0;
441 
442     if(pFont == &s_FontP)
443     {
444         pFont->pCharDataBuffer = s_CharDataBufferP;
445     }
446     else
447     {
448         pFont->pCharDataBuffer = s_CharDataBufferF;
449     }
450 
451     // Check the max number
452     DEMOAssert(pFont->numCharData <= MAX_NUM_CHARS &&
453         "Font has over the max number of characters.\n");
454 
455     // Format of data is: id, x, y, width, height, xOffset, yOffset, xAdvance
456     for(i = 0; i < pFont->numCharData; ++i)
457     {
458         u32 id         = pCharData[i*8 + 0];
459         u32 x          = pCharData[i*8 + 1];
460         u32 y          = pCharData[i*8 + 2];
461         u32 w          = pCharData[i*8 + 3];
462         u32 h          = pCharData[i*8 + 4];
463                          // +3 below is a hack to deal with negative offsets
464         s32 xOffset    = (s32)pCharData[i*8 + 5] + 3;
465         s32 yOffset    = (s32)pCharData[i*8 + 6];
466         u32 xAdvance   = pCharData[i*8 + 7];
467         f32 charHeight = (f32)(h + yOffset);
468 
469         pFont->pCharDataBuffer[i].id       = id;
470         pFont->pCharDataBuffer[i].minS     = (s32)x;
471         pFont->pCharDataBuffer[i].minT     = (s32)(pFont->fontTextureHeight - h - y - 1);
472         pFont->pCharDataBuffer[i].maxS     = (s32)(x + w);
473         pFont->pCharDataBuffer[i].maxT     = (s32)(pFont->fontTextureHeight - y - 1);
474         pFont->pCharDataBuffer[i].minX     = (s32)xOffset;
475         pFont->pCharDataBuffer[i].minY     = (s32)(lineHeight - yOffset - h);
476         pFont->pCharDataBuffer[i].maxX     = (s32)(xOffset + w);
477         pFont->pCharDataBuffer[i].maxY     = (s32)(lineHeight - yOffset);
478         pFont->pCharDataBuffer[i].xAdvance = (s32)xAdvance;
479 
480         // Set max height of char in GL cordinate space
481         if(charHeight > maxCharHeight)
482         {
483             maxCharHeight = charHeight;
484         }
485 
486         if(pFont->pCharDataBuffer[i].xAdvance > maxCharWidth)
487         {
488             maxCharWidth = (f32)pFont->pCharDataBuffer[i].xAdvance;
489         }
490     }
491 
492     // Set grid offsetX
493     pFont->gridOffsetX = maxCharWidth;
494 
495     // Set grid offsetY
496     pFont->gridOffsetY = maxCharHeight;
497 
498     // Set pointer of Font Image Data
499     pFont->pFontImageData = (u8*)pFontImageData;
500 }
501 
502 /// Init Font Texture
InitFontTexture(DEMOGfxShader * pShader,FontData_t * pFont)503 static void InitFontTexture(DEMOGfxShader* pShader, FontData_t* pFont)
504 {
505     // Texture setup
506     u32 width =(u32)pFont->fontTextureWidth;
507     u32 height=(u32)pFont->fontTextureHeight;
508 
509     GX2InitTexture(&pFont->TexData,
510               width,    // width
511               height,   // height
512               1,        // depth
513               0,        // num mips
514               GX2_SURFACE_FORMAT_TC_R8_UNORM,
515               GX2_SURFACE_DIM_2D);
516 
517     // Allocate from graphics memory
518     GX2InitTexturePtrs(&pFont->TexData,
519                  DEMOGfxAllocMEM2(pFont->TexData.surface.imageSize,
520                                    pFont->TexData.surface.alignment), 0);
521 
522     // add dummy alloc notify because invalidate inside GX2TileTexture creates orphaned upload otherwise
523     GX2NotifyMemAlloc(pFont->pFontImageData, width*height, 32);
524     // Then we retile the image
525     // This function calls Invalidate for us
526     GX2TileTexture(&pFont->TexData,     // dst
527                    pFont->pFontImageData); // src
528     GX2NotifyMemFree(pFont->pFontImageData);
529 
530     // Set up the sampler object
531     GX2InitSampler(&s_sampler,
532              GX2_TEX_CLAMP_WRAP,
533              GX2_TEX_XY_FILTER_BILINEAR);
534 }
535 
536 // Set Font Texture
SetFontTexture(DEMOGfxShader * pShader,FontData_t * pFont)537 static void SetFontTexture(DEMOGfxShader* pShader, FontData_t* pFont)
538 {
539     // Set Texture
540     GX2SetPixelTexture(&pFont->TexData, pShader->samplersPS.location[0]);
541 }
542 
543 
544 /// Initialize Font shader
InitShader(DEMOGfxShader * pShader)545 static void InitShader(DEMOGfxShader* pShader)
546 {
547     void * gshBuf;
548     u32 gshLen;
549 
550     // Load shader binary to memory
551     gshBuf = DEMOGfxLoadAssetFile(FONT_GSH_SHADER_FILE, &gshLen);
552 
553     // Load demoFont shader
554     DEMOGfxLoadShaders(pShader, 0, gshBuf);
555 
556     GX2RSetBufferName(&pShader->pVertexShader->shaderProgram, "demoFont VS");
557     GX2RSetBufferName(&pShader->pPixelShader->shaderProgram, "demoFont PS");
558 
559     // Free memory used to load the shader file
560     DEMOFree(gshBuf);
561 
562     // Init attribute to shader
563     DEMOGfxGetVertexShaderUniformLocation(pShader, "u_BasePosition");
564     DEMOGfxGetVertexShaderUniformLocation(pShader, "u_Scale");
565     DEMOGfxGetPixelShaderUniformLocation(pShader, "u_Color");
566     DEMOGfxGetPixelShaderSamplerLocation(pShader, "u_CharTex");
567 
568     // Set fetch Shader buffer
569     DEMOGfxInitFetchShader(pShader);
570 }
571 
572 // Search index of character id
BSearchIndex(FontData_t * pFont,u32 id)573 static u32 BSearchIndex(FontData_t* pFont, u32 id)
574 {
575     u32 first;
576     u32 last;
577     u32 index = 0;
578 
579     // quick check for sanely-ordered fonts
580     if (id >= 32 && id < 32+pFont->numCharData &&
581         pFont->pCharDataBuffer[id-32].id == id )
582         return id-32;
583 
584     first = 0;
585     last  = pFont->numCharData-1;
586 
587     while(first <= last)
588     {
589         u32 mid = first + (last - first) / 2;
590 
591         if( pFont->pCharDataBuffer[mid].id < id )
592         {
593             first = mid + 1;
594         }
595         else if( id < pFont->pCharDataBuffer[mid].id )
596         {
597             last = mid - 1;
598         }
599         else
600         {
601             index = mid;
602             break;
603         }
604     }
605     return index;
606 }
607 
608 
DEMOFontAddInstance(void)609 DEMOFontInstance* DEMOFontAddInstance(void)
610 {
611     // Setup Context State buffer
612     DEMOFontContextState = DEMOGfxAllocMEM2(sizeof(GX2ContextState), GX2_CONTEXT_STATE_ALIGNMENT);
613 
614     // Create a state context with profiling disabled
615     // GX2SetupContextState will invalidate CPU cache for us
616     GX2SetupContextStateEx(DEMOFontContextState, GX2_DISABLE);
617 
618     // Setup default render buffers to be used now
619     DEMOFontSetTarget(&DEMOColorBuffer);
620 
621     // Set Depth Control
622     GX2SetDepthOnlyControl(GX2_DISABLE,
623                            GX2_DISABLE,
624                            GX2_COMPARE_LESS);
625 
626     // Set Blend Enable
627     GX2SetColorControl(GX2_LOGIC_OP_COPY,
628                        GX2_ENABLE,
629                        GX2_DISABLE,
630                        GX2_ENABLE);
631 
632     // Set Blend Function & Combine Mode
633     GX2SetBlendControl(GX2_RENDER_TARGET_0,
634                         GX2_BLEND_SRC_ALPHA,
635                         GX2_BLEND_ONE_MINUS_SRC_ALPHA,
636                         GX2_BLEND_COMBINE_ADD,
637                         GX2_ENABLE,
638                         GX2_BLEND_SRC_ALPHA,
639                         GX2_BLEND_ONE_MINUS_SRC_ALPHA,
640                         GX2_BLEND_COMBINE_ADD
641                       );
642 
643 /////////////////////////////////////////////////////////////////////////////
644     // Create the new instance
645     gDemoFontCurInstance = DEMOAlloc(sizeof(DEMOFontInstance));
646     memset(gDemoFontCurInstance, 0, sizeof(DEMOFontInstance));
647     gDemoFontCurInstance->contextState = DEMOFontContextState;
648 
649 /////////////////////////////////////////////////////////////////////////////
650     // Set shaders
651     GX2SetShaders(&s_Shader.fetchShader,
652                    s_Shader.pVertexShader,
653                    s_Shader.pPixelShader);
654 
655     // Set up sampler
656     GX2SetPixelSampler(&s_sampler, s_Shader.samplersPS.location[0]);
657 
658     // Initialize Proportional Font
659     DEMOFontSetSpacing(1);
660     DEMOFontSetGridSize(60, 24);
661     DEMOFontSetColor(1.0f, 1.0f, 1.0f, 1.0f);
662     DEMOFontSetZValue(-1.0f);
663 
664     gDemoFontCurInstance->enabled = s_enabled;
665     s_enabled = TRUE;
666 
667     return gDemoFontCurInstance;
668 }
669 
DEMOFontDeleteInstance(DEMOFontInstance * instance)670 void DEMOFontDeleteInstance(DEMOFontInstance *instance)
671 {
672     DEMOGfxFreeMEM2(instance->contextState);
673     DEMOFree(instance);
674 
675     // Edge case:  delete current
676     if (gDemoFontCurInstance == instance) {
677         gDemoFontCurInstance = NULL;
678         DEMOFontContextState = NULL;
679     }
680 }
681 
682 
DEMOFontSetInstance(DEMOFontInstance * instance)683 void DEMOFontSetInstance(DEMOFontInstance *instance)
684 {
685     gDemoFontCurInstance = instance;
686 
687     DEMOFontContextState = instance->contextState;
688     GX2SetContextState(DEMOFontContextState);
689 }
690 
DEMOFontGetInstance(void)691 DEMOFontInstance* DEMOFontGetInstance(void)
692 {
693     return gDemoFontCurInstance;
694 }
695 
696