1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File: font_CharWriter.cpp
4
5 Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Revision: 23030 $
14 *---------------------------------------------------------------------------*/
15
16 #include "precompiled.h"
17
18 #include <GLES2/gl2.h>
19 #include <GLES2/gl2ext.h>
20 #include <nn/types.h>
21 #include <nn/assert.h>
22 #include <nn/gx.h>
23
24 #include <nw/config.h>
25 #include <nw/font/font_CharWriter.h>
26 #include <nw/font/font_DispStringBuffer.h>
27 #include <cstdarg>
28 #include <cstdio>
29
30 #include <nw/assert.h> // NW_GL_ASSERT用
31
32 namespace nw {
33 namespace font {
34
35 namespace {
36
37
38 /*!--------------------------------------------------------------------------*
39 @brief カラーにアルファ値を掛けます。
40 *---------------------------------------------------------------------------*/
41 void
MultiplyAlpha(ut::FloatColor * pDst,const ut::Color8 src,u8 alpha)42 MultiplyAlpha(
43 ut::FloatColor* pDst,
44 const ut::Color8 src,
45 u8 alpha
46 )
47 {
48 const f32 floatAlphaMax = ut::Color8::ALPHA_MAX;
49
50 pDst->r = src.r / floatAlphaMax;
51 pDst->g = src.g / floatAlphaMax;
52 pDst->b = src.b / floatAlphaMax;
53 pDst->a = (src.a / floatAlphaMax) * (alpha / floatAlphaMax);
54 }
55
56 } // namespace
57
58 void
SetupGXCommon()59 CharWriter::SetupGXCommon()
60 {
61 const int *const locations = m_pTextWriterResource->GetUniformLocations();
62
63 // フラグメントライティングの無効化
64 glUniform1i(locations[internal::LOC_FRAGMENTLIGHTING_ENABLED], GL_FALSE);
65
66 // テクスチャユニット0を2次元テクスチャに設定
67 glUniform1i(locations[internal::LOC_TEXTURE0_SAMPLERTYPE], GL_TEXTURE_2D);
68
69 // テクスチャユニット0をアクティブに設定
70 glActiveTexture(GL_TEXTURE0);
71
72 // フォグの無効化
73 glUniform1i(locations[internal::LOC_FOG_MODE], GL_FALSE);
74
75 // アルファテストの無効化 (常にパス)
76 glUniform1i(locations[internal::LOC_FRAGOPERATION_ENABLEALPHATEST], GL_FALSE);
77
78 // ソースアルファでブレンド
79 glEnable(GL_BLEND);
80 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
81 glBlendEquation(GL_FUNC_ADD);
82
83 // 論理演算を無効
84 glDisable(GL_COLOR_LOGIC_OP);
85
86 NW_GL_ASSERT();
87 }
88
89
90 /* =======================================================================
91 public
92 ======================================================================== */
93
94 /* ------------------------------------------------------------------------
95 コンストラクタ/デストラクタ
96 ------------------------------------------------------------------------ */
97
CharWriter()98 CharWriter::CharWriter()
99 : m_FixedWidth(0),
100 m_pFont(NULL),
101 m_pTextWriterResource(NULL),
102 m_pDispStringBuffer(NULL),
103 m_IsWidthFixed(false),
104 m_Alpha(ut::Color8::ALPHA_MAX)
105 {
106 ResetColorMapping(); // m_ColorMapping
107 SetGradationMode(GRADMODE_NONE); // m_TextColor, mVertexColor
108 SetTextColor(ut::Color8::WHITE); // m_TextColor, mVertexColor
109 SetScale(1, 1); // m_Scale
110 SetCursor(0, 0, 0); // m_CursorPos
111
112 #if defined(NW_FONT_PROFILE)
113 m_LoadTextureCount = 0;
114 m_PrintCharCount = 0;
115 m_DispCharCount = 0;
116 #endif
117 }
118
~CharWriter()119 CharWriter::~CharWriter()
120 {
121 }
122
123
124 /* ------------------------------------------------------------------------
125 描画準備
126 ------------------------------------------------------------------------ */
127
128 void
SetupGX()129 CharWriter::SetupGX()
130 {
131 NN_NULL_ASSERT(m_pTextWriterResource);
132
133 m_pTextWriterResource->ResetLoadingTexture();
134 SetupGXCommon();
135
136 bool bAlphaTex = false;
137 if (m_pFont)
138 {
139 switch (m_pFont->GetTextureFormat())
140 {
141 case FONT_SHEET_FORMAT_A4:
142 case FONT_SHEET_FORMAT_A8:
143 bAlphaTex = true;
144 break;
145 }
146 }
147
148 if ( m_Alpha != ut::Color8::ALPHA_MAX
149 || m_ColorMapping.min != DEFAULT_COLOR_MAPPING_MIN
150 || m_ColorMapping.max != DEFAULT_COLOR_MAPPING_MAX
151 )
152 {
153 SetupGXWithColorMapping(bAlphaTex);
154 }
155 else
156 {
157
158 SetupGXDefault(bAlphaTex);
159 }
160
161 SetupVertexFormat();
162 }
163
164 /* ------------------------------------------------------------------------
165 文字サイズ
166 ------------------------------------------------------------------------ */
167
168 void
SetFontSize(f32 width,f32 height)169 CharWriter::SetFontSize(
170 f32 width,
171 f32 height
172 )
173 {
174 NN_POINTER_ASSERT(m_pFont);
175 NW_FONT_MIN_ASSERT(m_pFont->GetWidth(), 1);
176 NW_FONT_MIN_ASSERT(m_pFont->GetHeight(), 1);
177 SetScale(
178 width / m_pFont->GetWidth(),
179 height / m_pFont->GetHeight()
180 );
181 }
182
183 void
SetFontSize(f32 height)184 CharWriter::SetFontSize(f32 height)
185 {
186 NN_POINTER_ASSERT(m_pFont);
187 NW_FONT_MIN_ASSERT(m_pFont->GetHeight(), 1);
188 const f32 scale = height / m_pFont->GetHeight();
189 SetScale(scale);
190 }
191
192 f32
GetFontWidth() const193 CharWriter::GetFontWidth() const
194 {
195 NN_POINTER_ASSERT(m_pFont);
196 return m_pFont->GetWidth() * m_Scale.x;
197 }
198
199 f32
GetFontHeight() const200 CharWriter::GetFontHeight() const
201 {
202 NN_POINTER_ASSERT(m_pFont);
203 return m_pFont->GetHeight() * m_Scale.y;
204 }
205
206 f32
GetFontAscent() const207 CharWriter::GetFontAscent() const
208 {
209 NN_POINTER_ASSERT(m_pFont);
210 return m_pFont->GetAscent() * m_Scale.y;
211 }
212
213 f32
GetFontDescent() const214 CharWriter::GetFontDescent() const
215 {
216 NN_POINTER_ASSERT(m_pFont);
217 return m_pFont->GetDescent() * m_Scale.y;
218 }
219
220 /* ------------------------------------------------------------------------
221 文字描画
222 ------------------------------------------------------------------------ */
223
224 f32
Print(CharCode code)225 CharWriter::Print(CharCode code)
226 {
227 NN_POINTER_ASSERT(m_pFont);
228 NN_ASSERT(code != Font::INVALID_CHARACTER_CODE);
229
230 NW_FONT_COUNTUP(m_PrintCharCount);
231 NW_FONT_STOPWATCH_START(m_PrintCharSw);
232
233 Glyph glyph;
234 m_pFont->GetGlyph(&glyph, code);
235
236 CharWidths &widths = glyph.widths;
237
238 f32 width;
239 f32 left;
240 if (m_IsWidthFixed)
241 {
242 f32 margin = (m_FixedWidth - widths.charWidth * m_Scale.x) / 2;
243
244 width = m_FixedWidth;
245 left = margin + widths.left * m_Scale.x;
246 }
247 else
248 {
249 width = widths.charWidth * m_Scale.x;
250 left = widths.left * m_Scale.x;
251 }
252
253 PrintGlyph(m_CursorPos.x + left, glyph);
254
255 m_CursorPos.x += width;
256
257 NW_FONT_STOPWATCH_STOP(m_PrintCharSw);
258
259 return width;
260 }
261
262 void
DrawGlyph(const Glyph & glyph)263 CharWriter::DrawGlyph(const Glyph& glyph)
264 {
265 NN_POINTER_ASSERT(&glyph);
266 PrintGlyph(m_CursorPos.x, glyph);
267 m_CursorPos.x += glyph.widths.glyphWidth * m_Scale.x;
268 }
269
270
271 /* =======================================================================
272 private
273 ======================================================================== */
274
275
276 void
PrintGlyph(f32 x,const Glyph & glyph)277 CharWriter::PrintGlyph(
278 f32 x,
279 const Glyph& glyph
280 )
281 {
282 NN_POINTER_ASSERT(&glyph);
283 NW_FONT_MIN_ASSERT(glyph.texWidth, 1);
284 NW_FONT_MIN_ASSERT(glyph.texHeight, 1);
285
286 const f32 y = m_CursorPos.y;
287
288 const f32 texLeft = 1.0f * glyph.cellX / glyph.texWidth;
289 const f32 texRight = 1.0f * (glyph.cellX + glyph.widths.glyphWidth)
290 / glyph.texWidth;
291
292 // cellYは左上原点の値が入っているので、これをOpenGLの左下原点の
293 // テクスチャ座標に変換してセットする。
294 const f32 texTop = 1.0f * (glyph.texHeight - glyph.cellY) / glyph.texHeight;
295 const f32 texBottom = 1.0f * (glyph.texHeight - (glyph.cellY + glyph.height))
296 / glyph.texHeight;
297
298 if (NULL != m_pDispStringBuffer)
299 {
300 const f32 width = glyph.widths.glyphWidth * m_Scale.x;
301 const f32 height = - glyph.height * m_Scale.y;
302
303 const u32 charIdx = m_pDispStringBuffer->charCount;
304
305 if (charIdx >= m_pDispStringBuffer->charCountMax)
306 {
307 NN_LOG("nw::font::CharWriter : Vertex Buffer Over.\n");
308 return;
309 }
310
311 m_pDispStringBuffer->charCount++;
312
313 internal::CharAttribute* pCharAttrs =
314 &m_pDispStringBuffer->GetCharAttrs()[charIdx];
315
316 // ポジションのセット
317 pCharAttrs->pos.Set(
318 width,
319 height,
320 x,
321 y);
322
323 // カラーのセット
324 for (int i = 0; i < internal::TEXTCOLOR_MAX; ++i)
325 {
326 pCharAttrs->color[i] = m_TextColors[i];
327 }
328
329 // テクスチャ座標のセット
330 pCharAttrs->tex.Set(
331 texLeft,
332 texTop,
333 texRight,
334 texBottom);
335
336 // テクスチャオブジェクトへのポインタのセット
337 NN_NULL_ASSERT(glyph.pTextureObject);
338 pCharAttrs->pTexObj = glyph.pTextureObject;
339 }
340 else
341 {
342 const f32 posLeft = x;
343 const f32 posRight = posLeft + glyph.widths.glyphWidth * m_Scale.x;
344 #if defined(COORDINATE_LT)
345 const f32 posTop = y;
346 const f32 posBottom = y + glyph.height * m_Scale.y;
347 #else
348 const f32 posTop = y + glyph.height * m_Scale.y;
349 const f32 posBottom = y;
350 #endif
351
352 internal::VertexAttribute *const pVtxAttrs =
353 m_pTextWriterResource->GetVertexAttributeArray();
354
355 // ポジションのセット
356 {
357 GLfloat* attrs = pVtxAttrs[internal::TRIFAN_VTX_RT].pos;
358 attrs[internal::POS_X] = posRight;
359 attrs[internal::POS_Y] = posTop;
360
361 attrs = pVtxAttrs[internal::TRIFAN_VTX_LT].pos;
362 attrs[internal::POS_X] = posLeft;
363 attrs[internal::POS_Y] = posTop;
364
365 attrs = pVtxAttrs[internal::TRIFAN_VTX_LB].pos;
366 attrs[internal::POS_X] = posLeft;
367 attrs[internal::POS_Y] = posBottom;
368
369 attrs = pVtxAttrs[internal::TRIFAN_VTX_RB].pos;
370 attrs[internal::POS_X] = posRight;
371 attrs[internal::POS_Y] = posBottom;
372 }
373
374 // カラーのセット
375 for (int i = 0; i < internal::TRIFAN_VTX_MAX; ++i)
376 {
377 pVtxAttrs[i].color = m_VertexColors[i];
378 }
379
380 // テクスチャ座標のセット
381 {
382 GLfloat* attrs = pVtxAttrs[internal::TRIFAN_VTX_RT].tex;
383 attrs[internal::TEXCOORD_X] = texRight;
384 attrs[internal::TEXCOORD_Y] = texTop;
385
386 attrs = pVtxAttrs[internal::TRIFAN_VTX_LT].tex;
387 attrs[internal::TEXCOORD_X] = texLeft;
388 attrs[internal::TEXCOORD_Y] = texTop;
389
390 attrs = pVtxAttrs[internal::TRIFAN_VTX_LB].tex;
391 attrs[internal::TEXCOORD_X] = texLeft;
392 attrs[internal::TEXCOORD_Y] = texBottom;
393
394 attrs = pVtxAttrs[internal::TRIFAN_VTX_RB].tex;
395 attrs[internal::TEXCOORD_X] = texRight;
396 attrs[internal::TEXCOORD_Y] = texBottom;
397 }
398
399 LoadTexture(glyph);
400 m_pTextWriterResource->UpdatePosZ(m_CursorPos.z);
401
402 glDrawArrays(GL_TRIANGLE_FAN, 0, internal::TRIFAN_VTX_MAX);
403
404 NW_GL_ASSERT();
405 }
406 }
407
408 void
StartPrint()409 CharWriter::StartPrint()
410 {
411 NN_NULL_ASSERT(m_pDispStringBuffer);
412
413 m_pDispStringBuffer->charCount = 0;
414 m_pDispStringBuffer->ClearCommand();
415 }
416
417 void
EndPrint()418 CharWriter::EndPrint()
419 {
420 NN_NULL_ASSERT(m_pDispStringBuffer);
421 }
422
423
424 /* ------------------------------------------------------------------------
425 内部処理
426 ------------------------------------------------------------------------ */
427
428 void
LoadTexture(const Glyph & glyph)429 CharWriter::LoadTexture(const Glyph& glyph)
430 {
431 NN_POINTER_ASSERT(&glyph);
432
433 bool doLoad = false;
434 GLuint texName = 0;
435
436 if (NULL == glyph.pTextureObject)
437 {
438 texName = m_pTextWriterResource->GetTextureID();
439 doLoad = m_pTextWriterResource->SetLoadingTexture(glyph.pTexture);
440 }
441 else
442 {
443 texName = glyph.pTextureObject->GetName();
444 if (texName == 0)
445 {
446 glGenTextures(1, &texName);
447 const_cast<internal::TextureObject*>(glyph.pTextureObject)->SetName(texName);
448 doLoad = true;
449 }
450 else
451 {
452 doLoad = 0 != glyph.isSheetUpdated; // 強制ロード
453 }
454 }
455
456 glBindTexture(GL_TEXTURE_2D, texName);
457
458 if (doLoad)
459 {
460 NW_FONT_COUNTUP(m_LoadTextureCount);
461 NW_FONT_STOPWATCH_START(m_LoadTextureSw);
462
463 internal::LoadTexture(
464 glyph.texWidth,
465 glyph.texHeight,
466 glyph.texFormat,
467 glyph.pTexture,
468 m_pFont->IsLinearFilterEnableAtSmall(),
469 m_pFont->IsLinearFilterEnableAtLarge());
470
471 NW_FONT_STOPWATCH_STOP(m_LoadTextureSw);
472 }
473 }
474
475 void
UpdateVertexColor()476 CharWriter::UpdateVertexColor()
477 {
478 m_VertexColors[internal::TRIFAN_VTX_LT] = m_TextColors[internal::TEXTCOLOR_START];
479 m_VertexColors[internal::TRIFAN_VTX_RT] = m_TextColors[
480 m_GradationMode != GRADMODE_H ? internal::TEXTCOLOR_START: internal::TEXTCOLOR_END];
481 m_VertexColors[internal::TRIFAN_VTX_LB] = m_TextColors[
482 m_GradationMode != GRADMODE_V ? internal::TEXTCOLOR_START: internal::TEXTCOLOR_END];
483 m_VertexColors[internal::TRIFAN_VTX_RB] = m_TextColors[
484 m_GradationMode == GRADMODE_NONE ? internal::TEXTCOLOR_START: internal::TEXTCOLOR_END];
485 }
486
487
488
489 /* ------------------------------------------------------------------------
490 static
491 ------------------------------------------------------------------------ */
492 /* ------------------------------------------------------------------------
493 描画準備
494 ------------------------------------------------------------------------ */
495
496 void
SetupVertexFormat()497 CharWriter::SetupVertexFormat()
498 {
499 NN_ASSERT(NULL == m_pDispStringBuffer);
500
501 // バッファオブジェクトを無効化
502 glBindBuffer(GL_ARRAY_BUFFER, 0);
503 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
504
505 const u8* basePtr = reinterpret_cast<u8*>(m_pTextWriterResource->GetVertexAttributeArray()[0].pos);
506 const GLsizei stride = sizeof(internal::VertexAttribute);
507
508 glEnableVertexAttribArray(internal::VERTEX_ATTR_POS);
509 glVertexAttribPointer(
510 internal::VERTEX_ATTR_POS,
511 internal::POS_NUM,
512 GL_FLOAT,
513 GL_FALSE,
514 stride,
515 basePtr);
516
517 glDisableVertexAttribArray(internal::VERTEX_ATTR_POS_Z);
518 m_pTextWriterResource->SetPosZ(m_CursorPos.z);
519
520 glEnableVertexAttribArray(internal::VERTEX_ATTR_COLOR);
521 glVertexAttribPointer(
522 internal::VERTEX_ATTR_COLOR,
523 internal::COLOR_NUM,
524 GL_UNSIGNED_BYTE,
525 GL_FALSE,
526 stride,
527 basePtr + offsetof(internal::VertexAttribute, color));
528
529 glEnableVertexAttribArray(internal::VERTEX_ATTR_TEXCOORD);
530 glVertexAttribPointer(
531 internal::VERTEX_ATTR_TEXCOORD,
532 internal::TEXCOORD_NUM,
533 GL_FLOAT,
534 GL_FALSE,
535 stride,
536 basePtr + offsetof(internal::VertexAttribute, tex));
537
538 NW_GL_ASSERT();
539 }
540
541 u32
GetDispStringBufferSize(u32 charNum)542 CharWriter::GetDispStringBufferSize(u32 charNum)
543 {
544 const u32 drawFlagBytes = math::RoundUp(charNum, 8) / 8;
545 return sizeof(DispStringBuffer)
546 + sizeof(internal::CharAttribute) * charNum
547 + math::RoundUp(drawFlagBytes, sizeof(u32))
548 + sizeof(u32) * DispStringBuffer::CalcCommandBufferCapacity(charNum)
549 ;
550 }
551
552 DispStringBuffer*
InitDispStringBuffer(void * drawBuffer,u32 charNum)553 CharWriter::InitDispStringBuffer(
554 void* drawBuffer,
555 u32 charNum
556 )
557 {
558 NN_NULL_ASSERT(drawBuffer);
559
560 return new (drawBuffer) DispStringBuffer(charNum);
561 }
562
563 void
SetupGXDefault(bool bAlphaTex)564 CharWriter::SetupGXDefault(bool bAlphaTex)
565 {
566 const int (*locations)[internal::TCLOC_MAX] =
567 m_pTextWriterResource->GetTexEnvUniformLocations();
568
569 // テクスチャコンバイナ設定
570 static const GLint src[] = { GL_PRIMARY_COLOR, GL_TEXTURE0, GL_CONSTANT };
571 static const GLint operandRgb[] = { GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR };
572 static const GLint operandAlp[] = { GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA };
573 const GLint combineMode = bAlphaTex ? GL_REPLACE: GL_MODULATE;
574
575 glUniform3iv(locations[internal::TEXENV_5][internal::TCLOC_SRCRGB ], 1, src);
576 glUniform3iv(locations[internal::TEXENV_5][internal::TCLOC_SRCALPHA ], 1, src);
577 glUniform3iv(locations[internal::TEXENV_5][internal::TCLOC_OPERANDRGB ], 1, operandRgb);
578 glUniform3iv(locations[internal::TEXENV_5][internal::TCLOC_OPERANDALPHA], 1, operandAlp);
579 glUniform1i (locations[internal::TEXENV_5][internal::TCLOC_COMBINERGB ], combineMode);
580 glUniform1i (locations[internal::TEXENV_5][internal::TCLOC_COMBINEALPHA], GL_MODULATE);
581 glUniform1f (locations[internal::TEXENV_5][internal::TCLOC_SCALERGB ], 1.0);
582 glUniform1f (locations[internal::TEXENV_5][internal::TCLOC_SCALEALPHA ], 1.0);
583 }
584
585 void
SetupGXWithColorMapping(bool bAlphaTex)586 CharWriter::SetupGXWithColorMapping(bool bAlphaTex)
587 {
588 const int (*locations)[internal::TCLOC_MAX] =
589 m_pTextWriterResource->GetTexEnvUniformLocations();
590
591 // テクスチャコンバイナ設定
592 static const GLint Src0[] = { GL_TEXTURE0, GL_CONSTANT, GL_CONSTANT };
593 static const GLint OpRgb0[] = { GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR };
594 static const GLint OpRgb1[] = { GL_ONE_MINUS_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR };
595 static const GLint OpAlp0[] = { GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA };
596 glUniform3iv(locations[internal::TEXENV_3][internal::TCLOC_SRCRGB ], 1, Src0);
597 glUniform3iv(locations[internal::TEXENV_3][internal::TCLOC_SRCALPHA ], 1, Src0);
598 glUniform3iv(locations[internal::TEXENV_3][internal::TCLOC_OPERANDRGB ], 1, bAlphaTex ? OpRgb1: OpRgb0);
599 glUniform3iv(locations[internal::TEXENV_3][internal::TCLOC_OPERANDALPHA], 1, OpAlp0);
600 glUniform1i (locations[internal::TEXENV_3][internal::TCLOC_COMBINERGB ], GL_MODULATE);
601 glUniform1i (locations[internal::TEXENV_3][internal::TCLOC_COMBINEALPHA], GL_MODULATE);
602 glUniform1f (locations[internal::TEXENV_3][internal::TCLOC_SCALERGB ], 1.0);
603 glUniform1f (locations[internal::TEXENV_3][internal::TCLOC_SCALEALPHA ], 1.0);
604 ut::FloatColor maxCol;
605 MultiplyAlpha(&maxCol, m_ColorMapping.max, m_Alpha);
606 glUniform4fv(locations[internal::TEXENV_3][internal::TCLOC_CONSTRGBA ], 1, maxCol.ToArray());
607
608 static const GLint Src1[] = { GL_TEXTURE0, GL_CONSTANT, GL_PREVIOUS };
609 static const GLint OpAlp1[] = { GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA };
610 glUniform3iv(locations[internal::TEXENV_4][internal::TCLOC_SRCRGB ], 1, Src1);
611 glUniform3iv(locations[internal::TEXENV_4][internal::TCLOC_SRCALPHA ], 1, Src1);
612 glUniform3iv(locations[internal::TEXENV_4][internal::TCLOC_OPERANDRGB ], 1, bAlphaTex ? OpRgb0: OpRgb1);
613 glUniform3iv(locations[internal::TEXENV_4][internal::TCLOC_OPERANDALPHA], 1, OpAlp1);
614 glUniform1i (locations[internal::TEXENV_4][internal::TCLOC_COMBINERGB ], GL_MULT_ADD_DMP);
615 glUniform1i (locations[internal::TEXENV_4][internal::TCLOC_COMBINEALPHA], GL_MULT_ADD_DMP);
616 glUniform1f (locations[internal::TEXENV_4][internal::TCLOC_SCALERGB ], 1.0);
617 glUniform1f (locations[internal::TEXENV_4][internal::TCLOC_SCALEALPHA ], 1.0);
618 ut::FloatColor minCol;
619 MultiplyAlpha(&minCol, m_ColorMapping.min, m_Alpha);
620 glUniform4fv(locations[internal::TEXENV_4][internal::TCLOC_CONSTRGBA ], 1, minCol.ToArray());
621
622 static const GLint Src2[] = { GL_PRIMARY_COLOR, GL_PREVIOUS, GL_PREVIOUS };
623 glUniform3iv(locations[internal::TEXENV_5][internal::TCLOC_SRCRGB ], 1, Src2);
624 glUniform3iv(locations[internal::TEXENV_5][internal::TCLOC_SRCALPHA ], 1, Src2);
625 glUniform3iv(locations[internal::TEXENV_5][internal::TCLOC_OPERANDRGB ], 1, OpRgb0);
626 glUniform3iv(locations[internal::TEXENV_5][internal::TCLOC_OPERANDALPHA], 1, OpAlp0);
627 glUniform1i (locations[internal::TEXENV_5][internal::TCLOC_COMBINERGB ], GL_MODULATE);
628 glUniform1i (locations[internal::TEXENV_5][internal::TCLOC_COMBINEALPHA], GL_MODULATE);
629 glUniform1f (locations[internal::TEXENV_5][internal::TCLOC_SCALERGB ], 1.0);
630 glUniform1f (locations[internal::TEXENV_5][internal::TCLOC_SCALEALPHA ], 1.0);
631 }
632
633 #if defined(NW_FONT_PROFILE)
634 void
PrintProfile()635 CharWriter::PrintProfile()
636 {
637 using namespace nn::fnd;
638
639 TimeSpan timeSpan = m_LoadTextureSw.GetElapsedTime();
640 NN_LOG("CharWriter Load Texture time %d micros, count %d.\n", (int)timeSpan.GetMilliSeconds(), m_LoadTextureCount);
641 timeSpan = m_PrintCharSw.GetElapsedTime();
642 NN_LOG("CharWriter Print time %d micros, count %d.\n", (int)timeSpan.GetMilliSeconds(), m_PrintCharCount);
643 timeSpan = m_DispCharSw.GetElapsedTime();
644 NN_LOG("CharWriter Disp time %d micros, count %d.\n", (int)timeSpan.GetMilliSeconds(), m_DispCharCount);
645 }
646
647 void
CopyProfileData(const CharWriter & other) const648 CharWriter::CopyProfileData(const CharWriter& other) const
649 {
650 m_LoadTextureSw = other.m_LoadTextureSw;
651 m_PrintCharSw = other.m_PrintCharSw;
652 m_LoadTextureCount = other.m_LoadTextureCount;
653 m_PrintCharCount = other.m_PrintCharCount;
654 }
655 #endif
656
657 } // namespace font
658 } // namespace nw
659