commit 3413eed

Michael Forney  ·  2014-01-31 12:26:13 +0000 UTC
parent f5b2b47
nouveau: Implement text rendering
1 files changed,  +73, -1
+73, -1
 1@@ -124,6 +124,13 @@ static inline void nv_add_dwords_va(struct nouveau_pushbuf * push,
 2         nv_add_dword(push, va_arg(dwords, uint32_t));
 3 }
 4 
 5+static inline void nv_add_data(struct nouveau_pushbuf * push,
 6+                               void * data, uint32_t count)
 7+{
 8+    memcpy(push->cur, data, count * 4);
 9+    push->cur += count;
10+}
11+
12 static uint32_t nvc0_format(uint32_t format)
13 {
14     switch (format)
15@@ -488,7 +495,72 @@ void renderer_draw_text(struct wld_renderer * base,
16                         int32_t x, int32_t y, const char * text, int32_t length,
17                         struct wld_extents * extents)
18 {
19-    /* TODO: Implement */
20+    struct nouveau_renderer * renderer = nouveau_renderer(base);
21+    uint32_t format;
22+    int ret;
23+    struct glyph * glyph;
24+    FT_UInt glyph_index;
25+    uint32_t c, count;
26+    int32_t origin_x = x;
27+
28+    if (!ensure_space(renderer->pushbuf, 17))
29+        return;
30+
31+    format = nvc0_format(renderer->target->base.format);
32+
33+    nouveau_bufctx_reset(renderer->bufctx, 0);
34+    nvc0_2d_use_buffer(renderer, renderer->target,
35+                       NV50_2D_DST_FORMAT, format);
36+    nvc0_2d_inline(renderer->pushbuf, NV50_2D_SIFC_BITMAP_ENABLE, 1);
37+    nvc0_2d(renderer->pushbuf, NV50_2D_SIFC_BITMAP_FORMAT, 6,
38+            NV50_2D_SIFC_BITMAP_FORMAT_I1,
39+            0,          /* SIFC_FORMAT */
40+            NV50_2D_SIFC_BITMAP_LINE_PACK_MODE_ALIGN_BYTE,
41+            0, color,   /* SIFC_BITMAP_COLOR_BIT0, SIFC_BITMAP_COLOR_BIT1 */
42+            0           /* SIFC_BITMAP_WRITE_BIT0_ENABLE */
43+    );
44+    nouveau_pushbuf_bufctx(renderer->pushbuf, renderer->bufctx);
45+
46+    if (nouveau_pushbuf_validate(renderer->pushbuf) != 0)
47+        return;
48+
49+    while ((ret = FcUtf8ToUcs4((FcChar8 *) text, &c, length)) > 0 && c != '\0')
50+    {
51+        text += ret;
52+        length -= ret;
53+        glyph_index = FT_Get_Char_Index(font->face, c);
54+
55+        if (!font_ensure_glyph(font, glyph_index))
56+            continue;
57+
58+        glyph = font->glyphs[glyph_index];
59+
60+        if (glyph->bitmap.width == 0 || glyph->bitmap.rows == 0)
61+            goto advance;
62+
63+        count = (glyph->bitmap.pitch * glyph->bitmap.rows + 3) / 4;
64+
65+        if (!ensure_space(renderer->pushbuf, 12 + count))
66+            return;
67+
68+        nvc0_2d(renderer->pushbuf, NV50_2D_SIFC_WIDTH, 10,
69+                /* Use the pitch instead of width to ensure the correct
70+                 * alignment is used. */
71+                glyph->bitmap.pitch * 8, glyph->bitmap.rows,
72+                0, 1, 0, 1,
73+                0, origin_x + glyph->x, 0, y + glyph->y);
74+        nv_add_dword(renderer->pushbuf,
75+                     nvc0_command(NVC0_COMMAND_TYPE_NON_INCREASING,
76+                                  NVC0_SUBCHANNEL_2D,
77+                                  NV50_2D_SIFC_DATA, count));
78+        nv_add_data(renderer->pushbuf, glyph->bitmap.buffer, count);
79+
80+      advance:
81+        origin_x += glyph->advance;
82+    }
83+
84+    if (extents)
85+        extents->advance = origin_x - x;
86 }
87 
88 void renderer_flush(struct wld_renderer * base)