text: add bbulk renderer
[platform/upstream/kmscon.git] / src / text_bbulk.c
1 /*
2  * kmscon - Bit-Blitting Bulk Text Renderer Backend
3  *
4  * Copyright (c) 2012 David Herrmann <dh.herrmann@googlemail.com>
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files
8  * (the "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sublicense, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included
15  * in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  */
25
26 /**
27  * SECTION:text_bbulk.c
28  * @short_description: Bit-Blitting Bulk Text Renderer Backend
29  * @include: text.h
30  *
31  * Similar to the bblit renderer but assembles an array of blit-requests and
32  * pushes all of them at once to the video device.
33  */
34
35 #include <errno.h>
36 #include <stdbool.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include "log.h"
40 #include "static_misc.h"
41 #include "text.h"
42 #include "unicode.h"
43 #include "uterm.h"
44
45 #define LOG_SUBSYSTEM "text_bbulk"
46
47 struct bbulk {
48         struct uterm_video_blend_req *reqs;
49 };
50
51 #define FONT_WIDTH(txt) ((txt)->font->attr.width)
52 #define FONT_HEIGHT(txt) ((txt)->font->attr.height)
53
54 #define SCREEN_WIDTH(txt) uterm_screen_width((txt)->screen)
55 #define SCREEN_HEIGHT(txt) uterm_screen_height((txt)->screen)
56
57 static int bbulk_init(struct kmscon_text *txt)
58 {
59         struct bbulk *bb;
60
61         bb = malloc(sizeof(*bb));
62         if (!bb)
63                 return -ENOMEM;
64
65         txt->data = bb;
66         return 0;
67 }
68
69 static void bbulk_destroy(struct kmscon_text *txt)
70 {
71         struct bbulk *bb = txt->data;
72
73         free(bb);
74 }
75
76 static int bbulk_set(struct kmscon_text *txt)
77 {
78         struct bbulk *bb = txt->data;
79         unsigned int sw, sh, i, j;
80         struct uterm_video_blend_req *req;
81
82         memset(bb, 0, sizeof(*bb));
83
84         sw = SCREEN_WIDTH(txt);
85         sh = SCREEN_HEIGHT(txt);
86
87         txt->cols = sw / FONT_WIDTH(txt);
88         txt->rows = sh / FONT_HEIGHT(txt);
89
90         bb->reqs = malloc(sizeof(*bb->reqs) * txt->cols * txt->rows);
91         if (!bb->reqs)
92                 return -ENOMEM;
93         memset(bb->reqs, 0, sizeof(*bb->reqs) * txt->cols * txt->rows);
94
95         for (i = 0; i < txt->rows; ++i) {
96                 for (j = 0; j < txt->cols; ++j) {
97                         req = &bb->reqs[i * txt->cols + j];
98                         req->x = j * FONT_WIDTH(txt);
99                         req->y = i * FONT_HEIGHT(txt);
100                 }
101         }
102
103         return 0;
104 }
105
106 static void bbulk_unset(struct kmscon_text *txt)
107 {
108         struct bbulk *bb = txt->data;
109
110         free(bb->reqs);
111         bb->reqs = NULL;
112 }
113
114 static int bbulk_draw(struct kmscon_text *txt, kmscon_symbol_t ch,
115                       unsigned int posx, unsigned int posy,
116                       const struct font_char_attr *attr)
117 {
118         struct bbulk *bb = txt->data;
119         const struct kmscon_glyph *glyph;
120         int ret;
121         struct uterm_video_blend_req *req;
122
123         if (ch == 0 || ch == ' ') {
124                 ret = kmscon_font_render_empty(txt->font, &glyph);
125         } else {
126                 ret = kmscon_font_render(txt->font, ch, &glyph);
127         }
128
129         if (ret) {
130                 ret = kmscon_font_render_inval(txt->font, &glyph);
131                 if (ret)
132                         return ret;
133         }
134
135         req = &bb->reqs[posy * txt->cols + posx];
136         req->buf = &glyph->buf;
137         if (attr->inverse) {
138                 req->fr = attr->br;
139                 req->fg = attr->bg;
140                 req->fb = attr->bb;
141                 req->br = attr->fr;
142                 req->bg = attr->fg;
143                 req->bb = attr->fb;
144         } else {
145                 req->fr = attr->fr;
146                 req->fg = attr->fg;
147                 req->fb = attr->fb;
148                 req->br = attr->br;
149                 req->bg = attr->bg;
150                 req->bb = attr->bb;
151         }
152
153         return 0;
154 }
155
156 static int bbulk_render(struct kmscon_text *txt)
157 {
158         struct bbulk *bb = txt->data;
159
160         return uterm_screen_blendv(txt->screen, bb->reqs,
161                                    txt->cols * txt->rows);
162 }
163
164 static const struct kmscon_text_ops kmscon_text_bbulk_ops = {
165         .name = "bbulk",
166         .init = bbulk_init,
167         .destroy = bbulk_destroy,
168         .set = bbulk_set,
169         .unset = bbulk_unset,
170         .prepare = NULL,
171         .draw = bbulk_draw,
172         .render = bbulk_render,
173         .abort = NULL,
174 };
175
176 int kmscon_text_bbulk_load(void)
177 {
178         int ret;
179
180         ret = kmscon_text_register(&kmscon_text_bbulk_ops);
181         if (ret) {
182                 log_error("cannot register bbulk renderer");
183                 return ret;
184         }
185
186         return 0;
187 }
188
189 void kmscon_text_bbulk_unload(void)
190 {
191         kmscon_text_unregister(kmscon_text_bbulk_ops.name);
192 }