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