xref: /netbsd-src/sys/dev/wscons/wsdisplay_glyphcache.c (revision b757af438b42b93f8c6571f026d8b8ef3eaf5fc9)
1 /*	$NetBSD: wsdisplay_glyphcache.c,v 1.1 2012/02/16 17:29:21 macallan Exp $	*/
2 
3 /*
4  * Copyright (c) 2012 Michael Lorenz
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 /*
29  * a simple glyph cache in offscreen memory
30  * For now it only caches glyphs with the default attribute ( assuming they're
31  * the most commonly used glyphs ) but the API should at least not prevent
32  * more sophisticated caching algorithms
33  */
34 
35 #include <sys/atomic.h>
36 #include <sys/errno.h>
37 #include <dev/wscons/wsdisplay_glyphcachevar.h>
38 
39 /* first line, lines, width, attr */
40 int
41 glyphcache_init(glyphcache *gc, int first, int lines, int width,
42     int cellwidth, int cellheight, long attr)
43 {
44 	int cache_lines;
45 
46 	gc->gc_cellwidth = cellwidth;
47 	gc->gc_cellheight = cellheight;
48 	gc->gc_firstline = first;
49 	gc->gc_cellsperline = width / cellwidth;
50 	cache_lines = lines / cellheight;
51 	gc->gc_numcells = cache_lines * gc->gc_cellsperline;
52 	if (gc->gc_numcells > 256)
53 		gc->gc_numcells = 256;
54 	gc->gc_attr = attr;
55 	glyphcache_wipe(gc);
56 	return 0;
57 }
58 
59 void
60 glyphcache_wipe(glyphcache *gc)
61 {
62 	int i;
63 
64 	gc->gc_usedcells = 0;
65 	for (i = 0; i < 256; i++)
66 		gc->gc_map[i] = -1;
67 }
68 
69 /*
70  * add a glyph drawn at (x,y) to the cache as (c)
71  * call this only if glyphcache_try() returned GC_ADD
72  * caller or gc_bitblt must make sure the glyph is actually completely drawn
73  */
74 int
75 glyphcache_add(glyphcache *gc, int c, int x, int y)
76 {
77 	int cell;
78 	int cx, cy;
79 
80 	if (gc->gc_map[c] != -1)
81 		return EINVAL;
82 	if (gc->gc_usedcells >= gc->gc_numcells)
83 		return ENOMEM;
84 	cell = atomic_add_int_nv(&gc->gc_usedcells, 1) - 1;
85 	gc->gc_map[c] = cell;
86 	cy = gc->gc_firstline +
87 	    (cell / gc->gc_cellsperline) * gc->gc_cellheight;
88 	cx = (cell % gc->gc_cellsperline) * gc->gc_cellwidth;
89 	gc->gc_bitblt(gc->gc_blitcookie, x, y, cx, cy,
90 	    gc->gc_cellwidth, gc->gc_cellheight, gc->gc_rop);
91 	return 0;
92 }
93 
94 /*
95  * check if (c) is in the cache, if so draw it at (x,y)
96  * return:
97  * - GC_OK when the glyph was found
98  * - GC_ADD when the glyph wasn't found but can be added
99  * - GC_NOPE when the glyph can't be cached
100  */
101 int
102 glyphcache_try(glyphcache *gc, int c, int x, int y, long attr)
103 {
104 	int cell, cx, cy;
105 	if ((c < 0) || (c > 255) || (attr != gc->gc_attr))
106 		return GC_NOPE;
107 	if (gc->gc_usedcells >= gc->gc_numcells)
108 		return GC_NOPE;
109 	cell = gc->gc_map[c];
110 	if (cell == -1)
111 		return GC_ADD;
112 	cy = gc->gc_firstline +
113 	    (cell / gc->gc_cellsperline) * gc->gc_cellheight;
114 	cx = (cell % gc->gc_cellsperline) * gc->gc_cellwidth;
115 	gc->gc_bitblt(gc->gc_blitcookie, cx, cy, x, y,
116 	    gc->gc_cellwidth, gc->gc_cellheight, gc->gc_rop);
117 	return GC_OK;
118 }
119