Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 637434 | Differences between
and this patch

Collapse All | Expand All

(-)a/Documentation/fb/00-INDEX (+2 lines)
Lines 23-28 ep93xx-fb.txt Link Here
23
	- info on the driver for EP93xx LCD controller.
23
	- info on the driver for EP93xx LCD controller.
24
fbcon.txt
24
fbcon.txt
25
	- intro to and usage guide for the framebuffer console (fbcon).
25
	- intro to and usage guide for the framebuffer console (fbcon).
26
fbcondecor.txt
27
	- info on the Framebuffer Console Decoration
26
framebuffer.txt
28
framebuffer.txt
27
	- introduction to frame buffer devices.
29
	- introduction to frame buffer devices.
28
gxfb.txt
30
gxfb.txt
(-)a/Documentation/fb/fbcondecor.txt (+207 lines)
Line 0 Link Here
1
What is it?
2
-----------
3
4
The framebuffer decorations are a kernel feature which allows displaying a
5
background picture on selected consoles.
6
7
What do I need to get it to work?
8
---------------------------------
9
10
To get fbcondecor up-and-running you will have to:
11
 1) get a copy of splashutils [1] or a similar program
12
 2) get some fbcondecor themes
13
 3) build the kernel helper program
14
 4) build your kernel with the FB_CON_DECOR option enabled.
15
16
To get fbcondecor operational right after fbcon initialization is finished, you
17
will have to include a theme and the kernel helper into your initramfs image.
18
Please refer to splashutils documentation for instructions on how to do that.
19
20
[1] The splashutils package can be downloaded from:
21
    http://github.com/alanhaggai/fbsplash
22
23
The userspace helper
24
--------------------
25
26
The userspace fbcondecor helper (by default: /sbin/fbcondecor_helper) is called by the
27
kernel whenever an important event occurs and the kernel needs some kind of
28
job to be carried out. Important events include console switches and video
29
mode switches (the kernel requests background images and configuration
30
parameters for the current console). The fbcondecor helper must be accessible at
31
all times. If it's not, fbcondecor will be switched off automatically.
32
33
It's possible to set path to the fbcondecor helper by writing it to
34
/proc/sys/kernel/fbcondecor.
35
36
*****************************************************************************
37
38
The information below is mostly technical stuff. There's probably no need to
39
read it unless you plan to develop a userspace helper.
40
41
The fbcondecor protocol
42
-----------------------
43
44
The fbcondecor protocol defines a communication interface between the kernel and
45
the userspace fbcondecor helper.
46
47
The kernel side is responsible for:
48
49
 * rendering console text, using an image as a background (instead of a
50
   standard solid color fbcon uses),
51
 * accepting commands from the user via ioctls on the fbcondecor device,
52
 * calling the userspace helper to set things up as soon as the fb subsystem
53
   is initialized.
54
55
The userspace helper is responsible for everything else, including parsing
56
configuration files, decompressing the image files whenever the kernel needs
57
it, and communicating with the kernel if necessary.
58
59
The fbcondecor protocol specifies how communication is done in both ways:
60
kernel->userspace and userspace->helper.
61
62
Kernel -> Userspace
63
-------------------
64
65
The kernel communicates with the userspace helper by calling it and specifying
66
the task to be done in a series of arguments.
67
68
The arguments follow the pattern:
69
<fbcondecor protocol version> <command> <parameters>
70
71
All commands defined in fbcondecor protocol v2 have the following parameters:
72
 virtual console
73
 framebuffer number
74
 theme
75
76
Fbcondecor protocol v1 specified an additional 'fbcondecor mode' after the
77
framebuffer number. Fbcondecor protocol v1 is deprecated and should not be used.
78
79
Fbcondecor protocol v2 specifies the following commands:
80
81
getpic
82
------
83
 The kernel issues this command to request image data. It's up to the
84
 userspace  helper to find a background image appropriate for the specified
85
 theme and the current resolution. The userspace helper should respond by
86
 issuing the FBIOCONDECOR_SETPIC ioctl.
87
88
init
89
----
90
 The kernel issues this command after the fbcondecor device is created and
91
 the fbcondecor interface is initialized. Upon receiving 'init', the userspace
92
 helper should parse the kernel command line (/proc/cmdline) or otherwise
93
 decide whether fbcondecor is to be activated.
94
95
 To activate fbcondecor on the first console the helper should issue the
96
 FBIOCONDECOR_SETCFG, FBIOCONDECOR_SETPIC and FBIOCONDECOR_SETSTATE commands,
97
 in the above-mentioned order.
98
99
 When the userspace helper is called in an early phase of the boot process
100
 (right after the initialization of fbcon), no filesystems will be mounted.
101
 The helper program should mount sysfs and then create the appropriate
102
 framebuffer, fbcondecor and tty0 devices (if they don't already exist) to get
103
 current display settings and to be able to communicate with the kernel side.
104
 It should probably also mount the procfs to be able to parse the kernel
105
 command line parameters.
106
107
 Note that the console sem is not held when the kernel calls fbcondecor_helper
108
 with the 'init' command. The fbcondecor helper should perform all ioctls with
109
 origin set to FBCON_DECOR_IO_ORIG_USER.
110
111
modechange
112
----------
113
 The kernel issues this command on a mode change. The helper's response should
114
 be similar to the response to the 'init' command. Note that this time the
115
 console sem is held and all ioctls must be performed with origin set to
116
 FBCON_DECOR_IO_ORIG_KERNEL.
117
118
119
Userspace -> Kernel
120
-------------------
121
122
Userspace programs can communicate with fbcondecor via ioctls on the
123
fbcondecor device. These ioctls are to be used by both the userspace helper
124
(called only by the kernel) and userspace configuration tools (run by the users).
125
126
The fbcondecor helper should set the origin field to FBCON_DECOR_IO_ORIG_KERNEL
127
when doing the appropriate ioctls. All userspace configuration tools should
128
use FBCON_DECOR_IO_ORIG_USER. Failure to set the appropriate value in the origin
129
field when performing ioctls from the kernel helper will most likely result
130
in a console deadlock.
131
132
FBCON_DECOR_IO_ORIG_KERNEL instructs fbcondecor not to try to acquire the console
133
semaphore. Not surprisingly, FBCON_DECOR_IO_ORIG_USER instructs it to acquire
134
the console sem.
135
136
The framebuffer console decoration provides the following ioctls (all defined in
137
linux/fb.h):
138
139
FBIOCONDECOR_SETPIC
140
description: loads a background picture for a virtual console
141
argument: struct fbcon_decor_iowrapper*; data: struct fb_image*
142
notes:
143
If called for consoles other than the current foreground one, the picture data
144
will be ignored.
145
146
If the current virtual console is running in a 8-bpp mode, the cmap substruct
147
of fb_image has to be filled appropriately: start should be set to 16 (first
148
16 colors are reserved for fbcon), len to a value <= 240 and red, green and
149
blue should point to valid cmap data. The transp field is ingored. The fields
150
dx, dy, bg_color, fg_color in fb_image are ignored as well.
151
152
FBIOCONDECOR_SETCFG
153
description: sets the fbcondecor config for a virtual console
154
argument: struct fbcon_decor_iowrapper*; data: struct vc_decor*
155
notes: The structure has to be filled with valid data.
156
157
FBIOCONDECOR_GETCFG
158
description: gets the fbcondecor config for a virtual console
159
argument: struct fbcon_decor_iowrapper*; data: struct vc_decor*
160
161
FBIOCONDECOR_SETSTATE
162
description: sets the fbcondecor state for a virtual console
163
argument: struct fbcon_decor_iowrapper*; data: unsigned int*
164
          values: 0 = disabled, 1 = enabled.
165
166
FBIOCONDECOR_GETSTATE
167
description: gets the fbcondecor state for a virtual console
168
argument: struct fbcon_decor_iowrapper*; data: unsigned int*
169
          values: as in FBIOCONDECOR_SETSTATE
170
171
Info on used structures:
172
173
Definition of struct vc_decor can be found in linux/console_decor.h. It's
174
heavily commented. Note that the 'theme' field should point to a string
175
no longer than FBCON_DECOR_THEME_LEN. When FBIOCONDECOR_GETCFG call is
176
performed, the theme field should point to a char buffer of length
177
FBCON_DECOR_THEME_LEN.
178
179
Definition of struct fbcon_decor_iowrapper can be found in linux/fb.h.
180
The fields in this struct have the following meaning:
181
182
vc:
183
Virtual console number.
184
185
origin:
186
Specifies if the ioctl is performed as a response to a kernel request. The
187
fbcondecor helper should set this field to FBCON_DECOR_IO_ORIG_KERNEL, userspace
188
programs should set it to FBCON_DECOR_IO_ORIG_USER. This field is necessary to
189
avoid console semaphore deadlocks.
190
191
data:
192
Pointer to a data structure appropriate for the performed ioctl. Type of
193
the data struct is specified in the ioctls description.
194
195
*****************************************************************************
196
197
Credit
198
------
199
200
Original 'bootsplash' project & implementation by:
201
  Volker Poplawski <volker@poplawski.de>, Stefan Reinauer <stepan@suse.de>,
202
  Steffen Winterfeldt <snwint@suse.de>, Michael Schroeder <mls@suse.de>,
203
  Ken Wimer <wimer@suse.de>.
204
205
Fbcondecor, fbcondecor protocol design, current implementation & docs by:
206
  Michal Januszewski <michalj+fbcondecor@gmail.com>
207
(-)a/drivers/Makefile (-5 / +4 lines)
Lines 23-28 obj-y += pci/dwc/ Link Here
23
23
24
obj-$(CONFIG_PARISC)		+= parisc/
24
obj-$(CONFIG_PARISC)		+= parisc/
25
obj-$(CONFIG_RAPIDIO)		+= rapidio/
25
obj-$(CONFIG_RAPIDIO)		+= rapidio/
26
# tty/ comes before char/ so that the VT console is the boot-time
27
# default.
28
obj-y				+= tty/
29
obj-y				+= char/
26
obj-y				+= video/
30
obj-y				+= video/
27
obj-y				+= idle/
31
obj-y				+= idle/
28
32
Lines 53-63 obj-$(CONFIG_REGULATOR) += regulator/ Link Here
53
# reset controllers early, since gpu drivers might rely on them to initialize
57
# reset controllers early, since gpu drivers might rely on them to initialize
54
obj-$(CONFIG_RESET_CONTROLLER)	+= reset/
58
obj-$(CONFIG_RESET_CONTROLLER)	+= reset/
55
59
56
# tty/ comes before char/ so that the VT console is the boot-time
57
# default.
58
obj-y				+= tty/
59
obj-y				+= char/
60
61
# iommu/ comes before gpu as gpu are using iommu controllers
60
# iommu/ comes before gpu as gpu are using iommu controllers
62
obj-$(CONFIG_IOMMU_SUPPORT)	+= iommu/
61
obj-$(CONFIG_IOMMU_SUPPORT)	+= iommu/
63
62
(-)a/drivers/video/console/Kconfig (+13 lines)
Lines 151-156 config FRAMEBUFFER_CONSOLE_ROTATION Link Here
151
         such that other users of the framebuffer will remain normally
151
         such that other users of the framebuffer will remain normally
152
         oriented.
152
         oriented.
153
153
154
config FB_CON_DECOR
155
	bool "Support for the Framebuffer Console Decorations"
156
	depends on FRAMEBUFFER_CONSOLE=y && !FB_TILEBLITTING
157
	default n
158
	---help---
159
	  This option enables support for framebuffer console decorations which
160
	  makes it possible to display images in the background of the system
161
	  consoles.  Note that userspace utilities are necessary in order to take
162
	  advantage of these features. Refer to Documentation/fb/fbcondecor.txt
163
	  for more information.
164
165
	  If unsure, say N.
166
154
config STI_CONSOLE
167
config STI_CONSOLE
155
        bool "STI text console"
168
        bool "STI text console"
156
        depends on PARISC
169
        depends on PARISC
(-)a/drivers/video/console/Makefile (+1 lines)
Lines 9-12 obj-$(CONFIG_STI_CONSOLE) += sticon.o sticore.o Link Here
9
obj-$(CONFIG_VGA_CONSOLE)         += vgacon.o
9
obj-$(CONFIG_VGA_CONSOLE)         += vgacon.o
10
obj-$(CONFIG_MDA_CONSOLE)         += mdacon.o
10
obj-$(CONFIG_MDA_CONSOLE)         += mdacon.o
11
11
12
obj-$(CONFIG_FB_CON_DECOR)     	  += fbcondecor.o cfbcondecor.o
12
obj-$(CONFIG_FB_STI)              += sticore.o
13
obj-$(CONFIG_FB_STI)              += sticore.o
(-)a/drivers/video/console/cfbcondecor.c (+473 lines)
Line 0 Link Here
1
/*
2
 *  linux/drivers/video/cfbcon_decor.c -- Framebuffer decor render functions
3
 *
4
 *  Copyright (C) 2004 Michal Januszewski <michalj+fbcondecor@gmail.com>
5
 *
6
 *  Code based upon "Bootdecor" (C) 2001-2003
7
 *       Volker Poplawski <volker@poplawski.de>,
8
 *       Stefan Reinauer <stepan@suse.de>,
9
 *       Steffen Winterfeldt <snwint@suse.de>,
10
 *       Michael Schroeder <mls@suse.de>,
11
 *       Ken Wimer <wimer@suse.de>.
12
 *
13
 *  This file is subject to the terms and conditions of the GNU General Public
14
 *  License.  See the file COPYING in the main directory of this archive for
15
 *  more details.
16
 */
17
#include <linux/module.h>
18
#include <linux/types.h>
19
#include <linux/fb.h>
20
#include <linux/selection.h>
21
#include <linux/slab.h>
22
#include <linux/vt_kern.h>
23
#include <asm/irq.h>
24
25
#include "../fbdev/core/fbcon.h"
26
#include "fbcondecor.h"
27
28
#define parse_pixel(shift, bpp, type)						\
29
	do {									\
30
		if (d & (0x80 >> (shift)))					\
31
			dd2[(shift)] = fgx;					\
32
		else								\
33
			dd2[(shift)] = transparent ? *(type *)decor_src : bgx;	\
34
		decor_src += (bpp);						\
35
	} while (0)								\
36
37
extern int get_color(struct vc_data *vc, struct fb_info *info,
38
		     u16 c, int is_fg);
39
40
void fbcon_decor_fix_pseudo_pal(struct fb_info *info, struct vc_data *vc)
41
{
42
	int i, j, k;
43
	int minlen = min(min(info->var.red.length, info->var.green.length),
44
			     info->var.blue.length);
45
	u32 col;
46
47
	for (j = i = 0; i < 16; i++) {
48
		k = color_table[i];
49
50
		col = ((vc->vc_palette[j++]  >> (8-minlen))
51
			<< info->var.red.offset);
52
		col |= ((vc->vc_palette[j++] >> (8-minlen))
53
			<< info->var.green.offset);
54
		col |= ((vc->vc_palette[j++] >> (8-minlen))
55
			<< info->var.blue.offset);
56
			((u32 *)info->pseudo_palette)[k] = col;
57
	}
58
}
59
60
void fbcon_decor_renderc(struct fb_info *info, int ypos, int xpos, int height,
61
		      int width, u8 *src, u32 fgx, u32 bgx, u8 transparent)
62
{
63
	unsigned int x, y;
64
	u32 dd;
65
	int bytespp = ((info->var.bits_per_pixel + 7) >> 3);
66
	unsigned int d = ypos * info->fix.line_length + xpos * bytespp;
67
	unsigned int ds = (ypos * info->var.xres + xpos) * bytespp;
68
	u16 dd2[4];
69
70
	u8 *decor_src = (u8 *)(info->bgdecor.data + ds);
71
	u8 *dst = (u8 *)(info->screen_base + d);
72
73
	if ((ypos + height) > info->var.yres || (xpos + width) > info->var.xres)
74
		return;
75
76
	for (y = 0; y < height; y++) {
77
		switch (info->var.bits_per_pixel) {
78
79
		case 32:
80
			for (x = 0; x < width; x++) {
81
82
				if ((x & 7) == 0)
83
					d = *src++;
84
				if (d & 0x80)
85
					dd = fgx;
86
				else
87
					dd = transparent ?
88
					     *(u32 *)decor_src : bgx;
89
90
				d <<= 1;
91
				decor_src += 4;
92
				fb_writel(dd, dst);
93
				dst += 4;
94
			}
95
			break;
96
		case 24:
97
			for (x = 0; x < width; x++) {
98
99
				if ((x & 7) == 0)
100
					d = *src++;
101
				if (d & 0x80)
102
					dd = fgx;
103
				else
104
					dd = transparent ?
105
					     (*(u32 *)decor_src & 0xffffff) : bgx;
106
107
				d <<= 1;
108
				decor_src += 3;
109
#ifdef __LITTLE_ENDIAN
110
				fb_writew(dd & 0xffff, dst);
111
				dst += 2;
112
				fb_writeb((dd >> 16), dst);
113
#else
114
				fb_writew(dd >> 8, dst);
115
				dst += 2;
116
				fb_writeb(dd & 0xff, dst);
117
#endif
118
				dst++;
119
			}
120
			break;
121
		case 16:
122
			for (x = 0; x < width; x += 2) {
123
				if ((x & 7) == 0)
124
					d = *src++;
125
126
				parse_pixel(0, 2, u16);
127
				parse_pixel(1, 2, u16);
128
#ifdef __LITTLE_ENDIAN
129
				dd = dd2[0] | (dd2[1] << 16);
130
#else
131
				dd = dd2[1] | (dd2[0] << 16);
132
#endif
133
				d <<= 2;
134
				fb_writel(dd, dst);
135
				dst += 4;
136
			}
137
			break;
138
139
		case 8:
140
			for (x = 0; x < width; x += 4) {
141
				if ((x & 7) == 0)
142
					d = *src++;
143
144
				parse_pixel(0, 1, u8);
145
				parse_pixel(1, 1, u8);
146
				parse_pixel(2, 1, u8);
147
				parse_pixel(3, 1, u8);
148
149
#ifdef __LITTLE_ENDIAN
150
				dd = dd2[0] | (dd2[1] << 8) | (dd2[2] << 16) | (dd2[3] << 24);
151
#else
152
				dd = dd2[3] | (dd2[2] << 8) | (dd2[1] << 16) | (dd2[0] << 24);
153
#endif
154
				d <<= 4;
155
				fb_writel(dd, dst);
156
				dst += 4;
157
			}
158
		}
159
160
		dst += info->fix.line_length - width * bytespp;
161
		decor_src += (info->var.xres - width) * bytespp;
162
	}
163
}
164
165
#define cc2cx(a)						\
166
	((info->fix.visual == FB_VISUAL_TRUECOLOR ||		\
167
		info->fix.visual == FB_VISUAL_DIRECTCOLOR) ?	\
168
			((u32 *)info->pseudo_palette)[a] : a)
169
170
void fbcon_decor_putcs(struct vc_data *vc, struct fb_info *info,
171
		   const unsigned short *s, int count, int yy, int xx)
172
{
173
	unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
174
	struct fbcon_ops *ops = info->fbcon_par;
175
	int fg_color, bg_color, transparent;
176
	u8 *src;
177
	u32 bgx, fgx;
178
	u16 c = scr_readw(s);
179
180
	fg_color = get_color(vc, info, c, 1);
181
	bg_color = get_color(vc, info, c, 0);
182
183
	/* Don't paint the background image if console is blanked */
184
	transparent = ops->blank_state ? 0 :
185
		(vc->vc_decor.bg_color == bg_color);
186
187
	xx = xx * vc->vc_font.width + vc->vc_decor.tx;
188
	yy = yy * vc->vc_font.height + vc->vc_decor.ty;
189
190
	fgx = cc2cx(fg_color);
191
	bgx = cc2cx(bg_color);
192
193
	while (count--) {
194
		c = scr_readw(s++);
195
		src = vc->vc_font.data + (c & charmask) * vc->vc_font.height *
196
		      ((vc->vc_font.width + 7) >> 3);
197
198
		fbcon_decor_renderc(info, yy, xx, vc->vc_font.height,
199
			       vc->vc_font.width, src, fgx, bgx, transparent);
200
		xx += vc->vc_font.width;
201
	}
202
}
203
204
void fbcon_decor_cursor(struct fb_info *info, struct fb_cursor *cursor)
205
{
206
	int i;
207
	unsigned int dsize, s_pitch;
208
	struct fbcon_ops *ops = info->fbcon_par;
209
	struct vc_data *vc;
210
	u8 *src;
211
212
	/* we really don't need any cursors while the console is blanked */
213
	if (info->state != FBINFO_STATE_RUNNING || ops->blank_state)
214
		return;
215
216
	vc = vc_cons[ops->currcon].d;
217
218
	src = kmalloc(64 + sizeof(struct fb_image), GFP_ATOMIC);
219
	if (!src)
220
		return;
221
222
	s_pitch = (cursor->image.width + 7) >> 3;
223
	dsize = s_pitch * cursor->image.height;
224
	if (cursor->enable) {
225
		switch (cursor->rop) {
226
		case ROP_XOR:
227
			for (i = 0; i < dsize; i++)
228
				src[i] = cursor->image.data[i] ^ cursor->mask[i];
229
			break;
230
		case ROP_COPY:
231
		default:
232
			for (i = 0; i < dsize; i++)
233
				src[i] = cursor->image.data[i] & cursor->mask[i];
234
			break;
235
		}
236
	} else
237
		memcpy(src, cursor->image.data, dsize);
238
239
	fbcon_decor_renderc(info,
240
			cursor->image.dy + vc->vc_decor.ty,
241
			cursor->image.dx + vc->vc_decor.tx,
242
			cursor->image.height,
243
			cursor->image.width,
244
			(u8 *)src,
245
			cc2cx(cursor->image.fg_color),
246
			cc2cx(cursor->image.bg_color),
247
			cursor->image.bg_color == vc->vc_decor.bg_color);
248
249
	kfree(src);
250
}
251
252
static void decorset(u8 *dst, int height, int width, int dstbytes,
253
				u32 bgx, int bpp)
254
{
255
	int i;
256
257
	if (bpp == 8)
258
		bgx |= bgx << 8;
259
	if (bpp == 16 || bpp == 8)
260
		bgx |= bgx << 16;
261
262
	while (height-- > 0) {
263
		u8 *p = dst;
264
265
		switch (bpp) {
266
267
		case 32:
268
			for (i = 0; i < width; i++) {
269
				fb_writel(bgx, p); p += 4;
270
			}
271
			break;
272
		case 24:
273
			for (i = 0; i < width; i++) {
274
#ifdef __LITTLE_ENDIAN
275
				fb_writew((bgx & 0xffff), (u16 *)p); p += 2;
276
				fb_writeb((bgx >> 16), p++);
277
#else
278
				fb_writew((bgx >> 8), (u16 *)p); p += 2;
279
				fb_writeb((bgx & 0xff), p++);
280
#endif
281
			}
282
			break;
283
		case 16:
284
			for (i = 0; i < width/4; i++) {
285
				fb_writel(bgx, p); p += 4;
286
				fb_writel(bgx, p); p += 4;
287
			}
288
			if (width & 2) {
289
				fb_writel(bgx, p); p += 4;
290
			}
291
			if (width & 1)
292
				fb_writew(bgx, (u16 *)p);
293
			break;
294
		case 8:
295
			for (i = 0; i < width/4; i++) {
296
				fb_writel(bgx, p); p += 4;
297
			}
298
299
			if (width & 2) {
300
				fb_writew(bgx, p); p += 2;
301
			}
302
			if (width & 1)
303
				fb_writeb(bgx, (u8 *)p);
304
			break;
305
306
		}
307
		dst += dstbytes;
308
	}
309
}
310
311
void fbcon_decor_copy(u8 *dst, u8 *src, int height, int width, int linebytes,
312
		   int srclinebytes, int bpp)
313
{
314
	int i;
315
316
	while (height-- > 0) {
317
		u32 *p = (u32 *)dst;
318
		u32 *q = (u32 *)src;
319
320
		switch (bpp) {
321
322
		case 32:
323
			for (i = 0; i < width; i++)
324
				fb_writel(*q++, p++);
325
			break;
326
		case 24:
327
			for (i = 0; i < (width * 3 / 4); i++)
328
				fb_writel(*q++, p++);
329
			if ((width * 3) % 4) {
330
				if (width & 2) {
331
					fb_writeb(*(u8 *)q, (u8 *)p);
332
				} else if (width & 1) {
333
					fb_writew(*(u16 *)q, (u16 *)p);
334
					fb_writeb(*(u8 *)((u16 *)q + 1),
335
							(u8 *)((u16 *)p + 2));
336
				}
337
			}
338
			break;
339
		case 16:
340
			for (i = 0; i < width/4; i++) {
341
				fb_writel(*q++, p++);
342
				fb_writel(*q++, p++);
343
			}
344
			if (width & 2)
345
				fb_writel(*q++, p++);
346
			if (width & 1)
347
				fb_writew(*(u16 *)q, (u16 *)p);
348
			break;
349
		case 8:
350
			for (i = 0; i < width/4; i++)
351
				fb_writel(*q++, p++);
352
353
			if (width & 2) {
354
				fb_writew(*(u16 *)q, (u16 *)p);
355
				q = (u32 *) ((u16 *)q + 1);
356
				p = (u32 *) ((u16 *)p + 1);
357
			}
358
			if (width & 1)
359
				fb_writeb(*(u8 *)q, (u8 *)p);
360
			break;
361
		}
362
363
		dst += linebytes;
364
		src += srclinebytes;
365
	}
366
}
367
368
static void decorfill(struct fb_info *info, int sy, int sx, int height,
369
		       int width)
370
{
371
	int bytespp = ((info->var.bits_per_pixel + 7) >> 3);
372
	int d  = sy * info->fix.line_length + sx * bytespp;
373
	int ds = (sy * info->var.xres + sx) * bytespp;
374
375
	fbcon_decor_copy((u8 *)(info->screen_base + d), (u8 *)(info->bgdecor.data + ds),
376
		    height, width, info->fix.line_length, info->var.xres * bytespp,
377
		    info->var.bits_per_pixel);
378
}
379
380
void fbcon_decor_clear(struct vc_data *vc, struct fb_info *info, int sy, int sx,
381
		    int height, int width)
382
{
383
	int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
384
	struct fbcon_ops *ops = info->fbcon_par;
385
	u8 *dst;
386
	int transparent, bg_color = attr_bgcol_ec(bgshift, vc, info);
387
388
	transparent = (vc->vc_decor.bg_color == bg_color);
389
	sy = sy * vc->vc_font.height + vc->vc_decor.ty;
390
	sx = sx * vc->vc_font.width + vc->vc_decor.tx;
391
	height *= vc->vc_font.height;
392
	width *= vc->vc_font.width;
393
394
	/* Don't paint the background image if console is blanked */
395
	if (transparent && !ops->blank_state) {
396
		decorfill(info, sy, sx, height, width);
397
	} else {
398
		dst = (u8 *)(info->screen_base + sy * info->fix.line_length +
399
			     sx * ((info->var.bits_per_pixel + 7) >> 3));
400
		decorset(dst, height, width, info->fix.line_length, cc2cx(bg_color),
401
			  info->var.bits_per_pixel);
402
	}
403
}
404
405
void fbcon_decor_clear_margins(struct vc_data *vc, struct fb_info *info,
406
			    int bottom_only)
407
{
408
	unsigned int tw = vc->vc_cols*vc->vc_font.width;
409
	unsigned int th = vc->vc_rows*vc->vc_font.height;
410
411
	if (!bottom_only) {
412
		/* top margin */
413
		decorfill(info, 0, 0, vc->vc_decor.ty, info->var.xres);
414
		/* left margin */
415
		decorfill(info, vc->vc_decor.ty, 0, th, vc->vc_decor.tx);
416
		/* right margin */
417
		decorfill(info, vc->vc_decor.ty, vc->vc_decor.tx + tw, th,
418
			   info->var.xres - vc->vc_decor.tx - tw);
419
	}
420
	decorfill(info, vc->vc_decor.ty + th, 0,
421
		   info->var.yres - vc->vc_decor.ty - th, info->var.xres);
422
}
423
424
void fbcon_decor_bmove_redraw(struct vc_data *vc, struct fb_info *info, int y,
425
			   int sx, int dx, int width)
426
{
427
	u16 *d = (u16 *) (vc->vc_origin + vc->vc_size_row * y + dx * 2);
428
	u16 *s = d + (dx - sx);
429
	u16 *start = d;
430
	u16 *ls = d;
431
	u16 *le = d + width;
432
	u16 c;
433
	int x = dx;
434
	u16 attr = 1;
435
436
	do {
437
		c = scr_readw(d);
438
		if (attr != (c & 0xff00)) {
439
			attr = c & 0xff00;
440
			if (d > start) {
441
				fbcon_decor_putcs(vc, info, start, d - start, y, x);
442
				x += d - start;
443
				start = d;
444
			}
445
		}
446
		if (s >= ls && s < le && c == scr_readw(s)) {
447
			if (d > start) {
448
				fbcon_decor_putcs(vc, info, start, d - start, y, x);
449
				x += d - start + 1;
450
				start = d + 1;
451
			} else {
452
				x++;
453
				start++;
454
			}
455
		}
456
		s++;
457
		d++;
458
	} while (d < le);
459
	if (d > start)
460
		fbcon_decor_putcs(vc, info, start, d - start, y, x);
461
}
462
463
void fbcon_decor_blank(struct vc_data *vc, struct fb_info *info, int blank)
464
{
465
	if (blank) {
466
		decorset((u8 *)info->screen_base, info->var.yres, info->var.xres,
467
			  info->fix.line_length, 0, info->var.bits_per_pixel);
468
	} else {
469
		update_screen(vc);
470
		fbcon_decor_clear_margins(vc, info, 0);
471
	}
472
}
473
(-)a/drivers/video/console/fbcondecor.c (+549 lines)
Line 0 Link Here
1
/*
2
 *  linux/drivers/video/console/fbcondecor.c -- Framebuffer console decorations
3
 *
4
 *  Copyright (C) 2004-2009 Michal Januszewski <michalj+fbcondecor@gmail.com>
5
 *
6
 *  Code based upon "Bootsplash" (C) 2001-2003
7
 *       Volker Poplawski <volker@poplawski.de>,
8
 *       Stefan Reinauer <stepan@suse.de>,
9
 *       Steffen Winterfeldt <snwint@suse.de>,
10
 *       Michael Schroeder <mls@suse.de>,
11
 *       Ken Wimer <wimer@suse.de>.
12
 *
13
 *  Compat ioctl support by Thorsten Klein <TK@Thorsten-Klein.de>.
14
 *
15
 *  This file is subject to the terms and conditions of the GNU General Public
16
 *  License.  See the file COPYING in the main directory of this archive for
17
 *  more details.
18
 *
19
 */
20
#include <linux/module.h>
21
#include <linux/kernel.h>
22
#include <linux/string.h>
23
#include <linux/types.h>
24
#include <linux/fb.h>
25
#include <linux/vt_kern.h>
26
#include <linux/vmalloc.h>
27
#include <linux/unistd.h>
28
#include <linux/syscalls.h>
29
#include <linux/init.h>
30
#include <linux/proc_fs.h>
31
#include <linux/workqueue.h>
32
#include <linux/kmod.h>
33
#include <linux/miscdevice.h>
34
#include <linux/device.h>
35
#include <linux/fs.h>
36
#include <linux/compat.h>
37
#include <linux/console.h>
38
#include <linux/binfmts.h>
39
#include <linux/uaccess.h>
40
#include <asm/irq.h>
41
42
#include "../fbdev/core/fbcon.h"
43
#include "fbcondecor.h"
44
45
extern signed char con2fb_map[];
46
static int fbcon_decor_enable(struct vc_data *vc);
47
48
static int initialized;
49
50
char fbcon_decor_path[KMOD_PATH_LEN] = "/sbin/fbcondecor_helper";
51
EXPORT_SYMBOL(fbcon_decor_path);
52
53
int fbcon_decor_call_helper(char *cmd, unsigned short vc)
54
{
55
	char *envp[] = {
56
		"HOME=/",
57
		"PATH=/sbin:/bin",
58
		NULL
59
	};
60
61
	char tfb[5];
62
	char tcons[5];
63
	unsigned char fb = (int) con2fb_map[vc];
64
65
	char *argv[] = {
66
		fbcon_decor_path,
67
		"2",
68
		cmd,
69
		tcons,
70
		tfb,
71
		vc_cons[vc].d->vc_decor.theme,
72
		NULL
73
	};
74
75
	snprintf(tfb, 5, "%d", fb);
76
	snprintf(tcons, 5, "%d", vc);
77
78
	return call_usermodehelper(fbcon_decor_path, argv, envp, UMH_WAIT_EXEC);
79
}
80
81
/* Disables fbcondecor on a virtual console; called with console sem held. */
82
int fbcon_decor_disable(struct vc_data *vc, unsigned char redraw)
83
{
84
	struct fb_info *info;
85
86
	if (!vc->vc_decor.state)
87
		return -EINVAL;
88
89
	info = registered_fb[(int) con2fb_map[vc->vc_num]];
90
91
	if (info == NULL)
92
		return -EINVAL;
93
94
	vc->vc_decor.state = 0;
95
	vc_resize(vc, info->var.xres / vc->vc_font.width,
96
		  info->var.yres / vc->vc_font.height);
97
98
	if (fg_console == vc->vc_num && redraw) {
99
		redraw_screen(vc, 0);
100
		update_region(vc, vc->vc_origin +
101
			      vc->vc_size_row * vc->vc_top,
102
			      vc->vc_size_row * (vc->vc_bottom - vc->vc_top) / 2);
103
	}
104
105
	printk(KERN_INFO "fbcondecor: switched decor state to 'off' on console %d\n",
106
			 vc->vc_num);
107
108
	return 0;
109
}
110
111
/* Enables fbcondecor on a virtual console; called with console sem held. */
112
static int fbcon_decor_enable(struct vc_data *vc)
113
{
114
	struct fb_info *info;
115
116
	info = registered_fb[(int) con2fb_map[vc->vc_num]];
117
118
	if (vc->vc_decor.twidth == 0 || vc->vc_decor.theight == 0 ||
119
	    info == NULL || vc->vc_decor.state || (!info->bgdecor.data &&
120
	    vc->vc_num == fg_console))
121
		return -EINVAL;
122
123
	vc->vc_decor.state = 1;
124
	vc_resize(vc, vc->vc_decor.twidth / vc->vc_font.width,
125
		  vc->vc_decor.theight / vc->vc_font.height);
126
127
	if (fg_console == vc->vc_num) {
128
		redraw_screen(vc, 0);
129
		update_region(vc, vc->vc_origin +
130
			      vc->vc_size_row * vc->vc_top,
131
			      vc->vc_size_row * (vc->vc_bottom - vc->vc_top) / 2);
132
		fbcon_decor_clear_margins(vc, info, 0);
133
	}
134
135
	printk(KERN_INFO "fbcondecor: switched decor state to 'on' on console %d\n",
136
			 vc->vc_num);
137
138
	return 0;
139
}
140
141
static inline int fbcon_decor_ioctl_dosetstate(struct vc_data *vc, unsigned int state, unsigned char origin)
142
{
143
	int ret;
144
145
	console_lock();
146
	if (!state)
147
		ret = fbcon_decor_disable(vc, 1);
148
	else
149
		ret = fbcon_decor_enable(vc);
150
	console_unlock();
151
152
	return ret;
153
}
154
155
static inline void fbcon_decor_ioctl_dogetstate(struct vc_data *vc, unsigned int *state)
156
{
157
	*state = vc->vc_decor.state;
158
}
159
160
static int fbcon_decor_ioctl_dosetcfg(struct vc_data *vc, struct vc_decor *cfg, unsigned char origin)
161
{
162
	struct fb_info *info;
163
	int len;
164
	char *tmp;
165
166
	info = registered_fb[(int) con2fb_map[vc->vc_num]];
167
168
	if (info == NULL || !cfg->twidth || !cfg->theight ||
169
	    cfg->tx + cfg->twidth  > info->var.xres ||
170
	    cfg->ty + cfg->theight > info->var.yres)
171
		return -EINVAL;
172
173
	len = strnlen_user(cfg->theme, MAX_ARG_STRLEN);
174
	if (!len || len > FBCON_DECOR_THEME_LEN)
175
		return -EINVAL;
176
	tmp = kmalloc(len, GFP_KERNEL);
177
	if (!tmp)
178
		return -ENOMEM;
179
	if (copy_from_user(tmp, (void __user *)cfg->theme, len))
180
		return -EFAULT;
181
	cfg->theme = tmp;
182
	cfg->state = 0;
183
184
	console_lock();
185
	if (vc->vc_decor.state)
186
		fbcon_decor_disable(vc, 1);
187
	kfree(vc->vc_decor.theme);
188
	vc->vc_decor = *cfg;
189
	console_unlock();
190
191
	printk(KERN_INFO "fbcondecor: console %d using theme '%s'\n",
192
			 vc->vc_num, vc->vc_decor.theme);
193
	return 0;
194
}
195
196
static int fbcon_decor_ioctl_dogetcfg(struct vc_data *vc,
197
					struct vc_decor *decor)
198
{
199
	char __user *tmp;
200
201
	tmp = decor->theme;
202
	*decor = vc->vc_decor;
203
	decor->theme = tmp;
204
205
	if (vc->vc_decor.theme) {
206
		if (copy_to_user(tmp, vc->vc_decor.theme,
207
					strlen(vc->vc_decor.theme) + 1))
208
			return -EFAULT;
209
	} else
210
		if (put_user(0, tmp))
211
			return -EFAULT;
212
213
	return 0;
214
}
215
216
static int fbcon_decor_ioctl_dosetpic(struct vc_data *vc, struct fb_image *img,
217
						unsigned char origin)
218
{
219
	struct fb_info *info;
220
	int len;
221
	u8 *tmp;
222
223
	if (vc->vc_num != fg_console)
224
		return -EINVAL;
225
226
	info = registered_fb[(int) con2fb_map[vc->vc_num]];
227
228
	if (info == NULL)
229
		return -EINVAL;
230
231
	if (img->width != info->var.xres || img->height != info->var.yres) {
232
		printk(KERN_ERR "fbcondecor: picture dimensions mismatch\n");
233
		printk(KERN_ERR "%dx%d vs %dx%d\n", img->width, img->height,
234
				info->var.xres, info->var.yres);
235
		return -EINVAL;
236
	}
237
238
	if (img->depth != info->var.bits_per_pixel) {
239
		printk(KERN_ERR "fbcondecor: picture depth mismatch\n");
240
		return -EINVAL;
241
	}
242
243
	if (img->depth == 8) {
244
		if (!img->cmap.len || !img->cmap.red || !img->cmap.green ||
245
		    !img->cmap.blue)
246
			return -EINVAL;
247
248
		tmp = vmalloc(img->cmap.len * 3 * 2);
249
		if (!tmp)
250
			return -ENOMEM;
251
252
		if (copy_from_user(tmp,
253
				(void __user *)img->cmap.red,
254
						(img->cmap.len << 1)) ||
255
			copy_from_user(tmp + (img->cmap.len << 1),
256
				(void __user *)img->cmap.green,
257
						(img->cmap.len << 1)) ||
258
			copy_from_user(tmp + (img->cmap.len << 2),
259
				(void __user *)img->cmap.blue,
260
						(img->cmap.len << 1))) {
261
			vfree(tmp);
262
			return -EFAULT;
263
		}
264
265
		img->cmap.transp = NULL;
266
		img->cmap.red = (u16 *)tmp;
267
		img->cmap.green = img->cmap.red + img->cmap.len;
268
		img->cmap.blue = img->cmap.green + img->cmap.len;
269
	} else {
270
		img->cmap.red = NULL;
271
	}
272
273
	len = ((img->depth + 7) >> 3) * img->width * img->height;
274
275
	/*
276
	 * Allocate an additional byte so that we never go outside of the
277
	 * buffer boundaries in the rendering functions in a 24 bpp mode.
278
	 */
279
	tmp = vmalloc(len + 1);
280
281
	if (!tmp)
282
		goto out;
283
284
	if (copy_from_user(tmp, (void __user *)img->data, len))
285
		goto out;
286
287
	img->data = tmp;
288
289
	console_lock();
290
291
	if (info->bgdecor.data)
292
		vfree((u8 *)info->bgdecor.data);
293
	if (info->bgdecor.cmap.red)
294
		vfree(info->bgdecor.cmap.red);
295
296
	info->bgdecor = *img;
297
298
	if (fbcon_decor_active_vc(vc) && fg_console == vc->vc_num) {
299
		redraw_screen(vc, 0);
300
		update_region(vc, vc->vc_origin +
301
			      vc->vc_size_row * vc->vc_top,
302
			      vc->vc_size_row * (vc->vc_bottom - vc->vc_top) / 2);
303
		fbcon_decor_clear_margins(vc, info, 0);
304
	}
305
306
	console_unlock();
307
308
	return 0;
309
310
out:
311
	if (img->cmap.red)
312
		vfree(img->cmap.red);
313
314
	if (tmp)
315
		vfree(tmp);
316
	return -ENOMEM;
317
}
318
319
static long fbcon_decor_ioctl(struct file *filp, u_int cmd, u_long arg)
320
{
321
	struct fbcon_decor_iowrapper __user *wrapper = (void __user *) arg;
322
	struct vc_data *vc = NULL;
323
	unsigned short vc_num = 0;
324
	unsigned char origin = 0;
325
	void __user *data = NULL;
326
327
	if (!access_ok(VERIFY_READ, wrapper,
328
			sizeof(struct fbcon_decor_iowrapper)))
329
		return -EFAULT;
330
331
	__get_user(vc_num, &wrapper->vc);
332
	__get_user(origin, &wrapper->origin);
333
	__get_user(data, &wrapper->data);
334
335
	if (!vc_cons_allocated(vc_num))
336
		return -EINVAL;
337
338
	vc = vc_cons[vc_num].d;
339
340
	switch (cmd) {
341
	case FBIOCONDECOR_SETPIC:
342
	{
343
		struct fb_image img;
344
345
		if (copy_from_user(&img, (struct fb_image __user *)data, sizeof(struct fb_image)))
346
			return -EFAULT;
347
348
		return fbcon_decor_ioctl_dosetpic(vc, &img, origin);
349
	}
350
	case FBIOCONDECOR_SETCFG:
351
	{
352
		struct vc_decor cfg;
353
354
		if (copy_from_user(&cfg, (struct vc_decor __user *)data, sizeof(struct vc_decor)))
355
			return -EFAULT;
356
357
		return fbcon_decor_ioctl_dosetcfg(vc, &cfg, origin);
358
	}
359
	case FBIOCONDECOR_GETCFG:
360
	{
361
		int rval;
362
		struct vc_decor cfg;
363
364
		if (copy_from_user(&cfg, (struct vc_decor __user *)data, sizeof(struct vc_decor)))
365
			return -EFAULT;
366
367
		rval = fbcon_decor_ioctl_dogetcfg(vc, &cfg);
368
369
		if (copy_to_user(data, &cfg, sizeof(struct vc_decor)))
370
			return -EFAULT;
371
		return rval;
372
	}
373
	case FBIOCONDECOR_SETSTATE:
374
	{
375
		unsigned int state = 0;
376
377
		if (get_user(state, (unsigned int __user *)data))
378
			return -EFAULT;
379
		return fbcon_decor_ioctl_dosetstate(vc, state, origin);
380
	}
381
	case FBIOCONDECOR_GETSTATE:
382
	{
383
		unsigned int state = 0;
384
385
		fbcon_decor_ioctl_dogetstate(vc, &state);
386
		return put_user(state, (unsigned int __user *)data);
387
	}
388
389
	default:
390
		return -ENOIOCTLCMD;
391
	}
392
}
393
394
#ifdef CONFIG_COMPAT
395
396
static long fbcon_decor_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
397
{
398
	struct fbcon_decor_iowrapper32 __user *wrapper = (void __user *)arg;
399
	struct vc_data *vc = NULL;
400
	unsigned short vc_num = 0;
401
	unsigned char origin = 0;
402
	compat_uptr_t data_compat = 0;
403
	void __user *data = NULL;
404
405
	if (!access_ok(VERIFY_READ, wrapper,
406
			sizeof(struct fbcon_decor_iowrapper32)))
407
		return -EFAULT;
408
409
	__get_user(vc_num, &wrapper->vc);
410
	__get_user(origin, &wrapper->origin);
411
	__get_user(data_compat, &wrapper->data);
412
	data = compat_ptr(data_compat);
413
414
	if (!vc_cons_allocated(vc_num))
415
		return -EINVAL;
416
417
	vc = vc_cons[vc_num].d;
418
419
	switch (cmd) {
420
	case FBIOCONDECOR_SETPIC32:
421
	{
422
		struct fb_image32 img_compat;
423
		struct fb_image img;
424
425
		if (copy_from_user(&img_compat, (struct fb_image32 __user *)data, sizeof(struct fb_image32)))
426
			return -EFAULT;
427
428
		fb_image_from_compat(img, img_compat);
429
430
		return fbcon_decor_ioctl_dosetpic(vc, &img, origin);
431
	}
432
433
	case FBIOCONDECOR_SETCFG32:
434
	{
435
		struct vc_decor32 cfg_compat;
436
		struct vc_decor cfg;
437
438
		if (copy_from_user(&cfg_compat, (struct vc_decor32 __user *)data, sizeof(struct vc_decor32)))
439
			return -EFAULT;
440
441
		vc_decor_from_compat(cfg, cfg_compat);
442
443
		return fbcon_decor_ioctl_dosetcfg(vc, &cfg, origin);
444
	}
445
446
	case FBIOCONDECOR_GETCFG32:
447
	{
448
		int rval;
449
		struct vc_decor32 cfg_compat;
450
		struct vc_decor cfg;
451
452
		if (copy_from_user(&cfg_compat, (struct vc_decor32 __user *)data, sizeof(struct vc_decor32)))
453
			return -EFAULT;
454
		cfg.theme = compat_ptr(cfg_compat.theme);
455
456
		rval = fbcon_decor_ioctl_dogetcfg(vc, &cfg);
457
458
		vc_decor_to_compat(cfg_compat, cfg);
459
460
		if (copy_to_user((struct vc_decor32 __user *)data, &cfg_compat, sizeof(struct vc_decor32)))
461
			return -EFAULT;
462
		return rval;
463
	}
464
465
	case FBIOCONDECOR_SETSTATE32:
466
	{
467
		compat_uint_t state_compat = 0;
468
		unsigned int state = 0;
469
470
		if (get_user(state_compat, (compat_uint_t __user *)data))
471
			return -EFAULT;
472
473
		state = (unsigned int)state_compat;
474
475
		return fbcon_decor_ioctl_dosetstate(vc, state, origin);
476
	}
477
478
	case FBIOCONDECOR_GETSTATE32:
479
	{
480
		compat_uint_t state_compat = 0;
481
		unsigned int state = 0;
482
483
		fbcon_decor_ioctl_dogetstate(vc, &state);
484
		state_compat = (compat_uint_t)state;
485
486
		return put_user(state_compat, (compat_uint_t __user *)data);
487
	}
488
489
	default:
490
		return -ENOIOCTLCMD;
491
	}
492
}
493
#else
494
  #define fbcon_decor_compat_ioctl NULL
495
#endif
496
497
static struct file_operations fbcon_decor_ops = {
498
	.owner = THIS_MODULE,
499
	.unlocked_ioctl = fbcon_decor_ioctl,
500
	.compat_ioctl = fbcon_decor_compat_ioctl
501
};
502
503
static struct miscdevice fbcon_decor_dev = {
504
	.minor = MISC_DYNAMIC_MINOR,
505
	.name = "fbcondecor",
506
	.fops = &fbcon_decor_ops
507
};
508
509
void fbcon_decor_reset(void)
510
{
511
	int i;
512
513
	for (i = 0; i < num_registered_fb; i++) {
514
		registered_fb[i]->bgdecor.data = NULL;
515
		registered_fb[i]->bgdecor.cmap.red = NULL;
516
	}
517
518
	for (i = 0; i < MAX_NR_CONSOLES && vc_cons[i].d; i++) {
519
		vc_cons[i].d->vc_decor.state = vc_cons[i].d->vc_decor.twidth =
520
						vc_cons[i].d->vc_decor.theight = 0;
521
		vc_cons[i].d->vc_decor.theme = NULL;
522
	}
523
}
524
525
int fbcon_decor_init(void)
526
{
527
	int i;
528
529
	fbcon_decor_reset();
530
531
	if (initialized)
532
		return 0;
533
534
	i = misc_register(&fbcon_decor_dev);
535
	if (i) {
536
		printk(KERN_ERR "fbcondecor: failed to register device\n");
537
		return i;
538
	}
539
540
	fbcon_decor_call_helper("init", 0);
541
	initialized = 1;
542
	return 0;
543
}
544
545
int fbcon_decor_exit(void)
546
{
547
	fbcon_decor_reset();
548
	return 0;
549
}
(-)a/drivers/video/console/fbcondecor.h (+77 lines)
Line 0 Link Here
1
/*
2
 *  linux/drivers/video/console/fbcondecor.h -- Framebuffer Console Decoration headers
3
 *
4
 *  Copyright (C) 2004 Michal Januszewski <michalj+fbcondecor@gmail.com>
5
 *
6
 */
7
8
#ifndef __FBCON_DECOR_H
9
#define __FBCON_DECOR_H
10
11
#ifndef _LINUX_FB_H
12
#include <linux/fb.h>
13
#endif
14
15
/* This is needed for vc_cons in fbcmap.c */
16
#include <linux/vt_kern.h>
17
18
struct fb_cursor;
19
struct fb_info;
20
struct vc_data;
21
22
#ifdef CONFIG_FB_CON_DECOR
23
/* fbcondecor.c */
24
int fbcon_decor_init(void);
25
int fbcon_decor_exit(void);
26
int fbcon_decor_call_helper(char *cmd, unsigned short cons);
27
int fbcon_decor_disable(struct vc_data *vc, unsigned char redraw);
28
29
/* cfbcondecor.c */
30
void fbcon_decor_putcs(struct vc_data *vc, struct fb_info *info, const unsigned short *s, int count, int yy, int xx);
31
void fbcon_decor_cursor(struct fb_info *info, struct fb_cursor *cursor);
32
void fbcon_decor_clear(struct vc_data *vc, struct fb_info *info, int sy, int sx, int height, int width);
33
void fbcon_decor_clear_margins(struct vc_data *vc, struct fb_info *info, int bottom_only);
34
void fbcon_decor_blank(struct vc_data *vc, struct fb_info *info, int blank);
35
void fbcon_decor_bmove_redraw(struct vc_data *vc, struct fb_info *info, int y, int sx, int dx, int width);
36
void fbcon_decor_copy(u8 *dst, u8 *src, int height, int width, int linebytes, int srclinesbytes, int bpp);
37
void fbcon_decor_fix_pseudo_pal(struct fb_info *info, struct vc_data *vc);
38
39
/* vt.c */
40
void acquire_console_sem(void);
41
void release_console_sem(void);
42
void do_unblank_screen(int entering_gfx);
43
44
/* struct vc_data *y */
45
#define fbcon_decor_active_vc(y) (y->vc_decor.state && y->vc_decor.theme)
46
47
/* struct fb_info *x, struct vc_data *y */
48
#define fbcon_decor_active_nores(x, y) (x->bgdecor.data && fbcon_decor_active_vc(y))
49
50
/* struct fb_info *x, struct vc_data *y */
51
#define fbcon_decor_active(x, y) (fbcon_decor_active_nores(x, y) &&	\
52
				x->bgdecor.width == x->var.xres &&	\
53
				x->bgdecor.height == x->var.yres &&	\
54
				x->bgdecor.depth == x->var.bits_per_pixel)
55
56
#else /* CONFIG_FB_CON_DECOR */
57
58
static inline void fbcon_decor_putcs(struct vc_data *vc, struct fb_info *info, const unsigned short *s, int count, int yy, int xx) {}
59
static inline void fbcon_decor_putc(struct vc_data *vc, struct fb_info *info, int c, int ypos, int xpos) {}
60
static inline void fbcon_decor_cursor(struct fb_info *info, struct fb_cursor *cursor) {}
61
static inline void fbcon_decor_clear(struct vc_data *vc, struct fb_info *info, int sy, int sx, int height, int width) {}
62
static inline void fbcon_decor_clear_margins(struct vc_data *vc, struct fb_info *info, int bottom_only) {}
63
static inline void fbcon_decor_blank(struct vc_data *vc, struct fb_info *info, int blank) {}
64
static inline void fbcon_decor_bmove_redraw(struct vc_data *vc, struct fb_info *info, int y, int sx, int dx, int width) {}
65
static inline void fbcon_decor_fix_pseudo_pal(struct fb_info *info, struct vc_data *vc) {}
66
static inline int fbcon_decor_call_helper(char *cmd, unsigned short cons) { return 0; }
67
static inline int fbcon_decor_init(void) { return 0; }
68
static inline int fbcon_decor_exit(void) { return 0; }
69
static inline int fbcon_decor_disable(struct vc_data *vc, unsigned char redraw) { return 0; }
70
71
#define fbcon_decor_active_vc(y) (0)
72
#define fbcon_decor_active_nores(x, y) (0)
73
#define fbcon_decor_active(x, y) (0)
74
75
#endif /* CONFIG_FB_CON_DECOR */
76
77
#endif /* __FBCON_DECOR_H */
(-)a/drivers/video/fbdev/Kconfig (-1 lines)
Lines 1226-1232 config FB_MATROX Link Here
1226
	select FB_CFB_FILLRECT
1226
	select FB_CFB_FILLRECT
1227
	select FB_CFB_COPYAREA
1227
	select FB_CFB_COPYAREA
1228
	select FB_CFB_IMAGEBLIT
1228
	select FB_CFB_IMAGEBLIT
1229
	select FB_TILEBLITTING
1230
	select FB_MACMODES if PPC_PMAC
1229
	select FB_MACMODES if PPC_PMAC
1231
	---help---
1230
	---help---
1232
	  Say Y here if you have a Matrox Millennium, Matrox Millennium II,
1231
	  Say Y here if you have a Matrox Millennium, Matrox Millennium II,
(-)a/drivers/video/fbdev/core/bitblit.c (-4 / +16 lines)
Lines 18-23 Link Here
18
#include <linux/console.h>
18
#include <linux/console.h>
19
#include <asm/types.h>
19
#include <asm/types.h>
20
#include "fbcon.h"
20
#include "fbcon.h"
21
#include "../../console/fbcondecor.h"
21
22
22
/*
23
/*
23
 * Accelerated handlers.
24
 * Accelerated handlers.
Lines 55-60 static void bit_bmove(struct vc_data *vc, struct fb_info *info, int sy, Link Here
55
	area.height = height * vc->vc_font.height;
56
	area.height = height * vc->vc_font.height;
56
	area.width = width * vc->vc_font.width;
57
	area.width = width * vc->vc_font.width;
57
58
59
	if (fbcon_decor_active(info, vc)) {
60
		area.sx += vc->vc_decor.tx;
61
		area.sy += vc->vc_decor.ty;
62
		area.dx += vc->vc_decor.tx;
63
		area.dy += vc->vc_decor.ty;
64
	}
65
58
	info->fbops->fb_copyarea(info, &area);
66
	info->fbops->fb_copyarea(info, &area);
59
}
67
}
60
68
Lines 379-389 static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode, Link Here
379
	cursor.image.depth = 1;
387
	cursor.image.depth = 1;
380
	cursor.rop = ROP_XOR;
388
	cursor.rop = ROP_XOR;
381
389
382
	if (info->fbops->fb_cursor)
390
	if (fbcon_decor_active(info, vc)) {
383
		err = info->fbops->fb_cursor(info, &cursor);
391
		fbcon_decor_cursor(info, &cursor);
392
	} else {
393
		if (info->fbops->fb_cursor)
394
			err = info->fbops->fb_cursor(info, &cursor);
384
395
385
	if (err)
396
		if (err)
386
		soft_cursor(info, &cursor);
397
			soft_cursor(info, &cursor);
398
	}
387
399
388
	ops->cursor_reset = 0;
400
	ops->cursor_reset = 0;
389
}
401
}
(-)a/drivers/video/fbdev/core/fbcmap.c (-2 / +7 lines)
Lines 17-22 Link Here
17
#include <linux/slab.h>
17
#include <linux/slab.h>
18
#include <linux/uaccess.h>
18
#include <linux/uaccess.h>
19
19
20
#include "../../console/fbcondecor.h"
21
20
static u16 red2[] __read_mostly = {
22
static u16 red2[] __read_mostly = {
21
    0x0000, 0xaaaa
23
    0x0000, 0xaaaa
22
};
24
};
Lines 256-264 int fb_set_cmap(struct fb_cmap *cmap, struct fb_info *info) Link Here
256
				break;
258
				break;
257
		}
259
		}
258
	}
260
	}
259
	if (rc == 0)
261
	if (rc == 0) {
260
		fb_copy_cmap(cmap, &info->cmap);
262
		fb_copy_cmap(cmap, &info->cmap);
261
263
		if (fbcon_decor_active(info, vc_cons[fg_console].d) &&
264
		    info->fix.visual == FB_VISUAL_DIRECTCOLOR)
265
			fbcon_decor_fix_pseudo_pal(info, vc_cons[fg_console].d);
266
	}
262
	return rc;
267
	return rc;
263
}
268
}
264
269
(-)a/drivers/video/fbdev/core/fbcon.c (-23 / +148 lines)
Lines 80-85 Link Here
80
#include <asm/irq.h>
80
#include <asm/irq.h>
81
81
82
#include "fbcon.h"
82
#include "fbcon.h"
83
#include "../../console/fbcondecor.h"
83
84
84
#ifdef FBCONDEBUG
85
#ifdef FBCONDEBUG
85
#  define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args)
86
#  define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args)
Lines 95-101 enum { Link Here
95
96
96
static struct display fb_display[MAX_NR_CONSOLES];
97
static struct display fb_display[MAX_NR_CONSOLES];
97
98
98
static signed char con2fb_map[MAX_NR_CONSOLES];
99
signed char con2fb_map[MAX_NR_CONSOLES];
99
static signed char con2fb_map_boot[MAX_NR_CONSOLES];
100
static signed char con2fb_map_boot[MAX_NR_CONSOLES];
100
101
101
static int logo_lines;
102
static int logo_lines;
Lines 282-288 static inline int fbcon_is_inactive(struct vc_data *vc, struct fb_info *info) Link Here
282
		!vt_force_oops_output(vc);
283
		!vt_force_oops_output(vc);
283
}
284
}
284
285
285
static int get_color(struct vc_data *vc, struct fb_info *info,
286
int get_color(struct vc_data *vc, struct fb_info *info,
286
	      u16 c, int is_fg)
287
	      u16 c, int is_fg)
287
{
288
{
288
	int depth = fb_get_color_depth(&info->var, &info->fix);
289
	int depth = fb_get_color_depth(&info->var, &info->fix);
Lines 551-556 static int do_fbcon_takeover(int show_logo) Link Here
551
		info_idx = -1;
552
		info_idx = -1;
552
	} else {
553
	} else {
553
		fbcon_has_console_bind = 1;
554
		fbcon_has_console_bind = 1;
555
#ifdef CONFIG_FB_CON_DECOR
556
		fbcon_decor_init();
557
#endif
554
	}
558
	}
555
559
556
	return err;
560
	return err;
Lines 1013-1018 static const char *fbcon_startup(void) Link Here
1013
	rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
1017
	rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
1014
	cols /= vc->vc_font.width;
1018
	cols /= vc->vc_font.width;
1015
	rows /= vc->vc_font.height;
1019
	rows /= vc->vc_font.height;
1020
1021
	if (fbcon_decor_active(info, vc)) {
1022
		cols = vc->vc_decor.twidth / vc->vc_font.width;
1023
		rows = vc->vc_decor.theight / vc->vc_font.height;
1024
	}
1025
1016
	vc_resize(vc, cols, rows);
1026
	vc_resize(vc, cols, rows);
1017
1027
1018
	DPRINTK("mode:   %s\n", info->fix.id);
1028
	DPRINTK("mode:   %s\n", info->fix.id);
Lines 1042-1048 static void fbcon_init(struct vc_data *vc, int init) Link Here
1042
	cap = info->flags;
1052
	cap = info->flags;
1043
1053
1044
	if (vc != svc || logo_shown == FBCON_LOGO_DONTSHOW ||
1054
	if (vc != svc || logo_shown == FBCON_LOGO_DONTSHOW ||
1045
	    (info->fix.type == FB_TYPE_TEXT))
1055
	    (info->fix.type == FB_TYPE_TEXT) || fbcon_decor_active(info, vc))
1046
		logo = 0;
1056
		logo = 0;
1047
1057
1048
	if (var_to_display(p, &info->var, info))
1058
	if (var_to_display(p, &info->var, info))
Lines 1275-1280 static void fbcon_clear(struct vc_data *vc, int sy, int sx, int height, Link Here
1275
		fbcon_clear_margins(vc, 0);
1285
		fbcon_clear_margins(vc, 0);
1276
	}
1286
	}
1277
1287
1288
	if (fbcon_decor_active(info, vc)) {
1289
		fbcon_decor_clear(vc, info, sy, sx, height, width);
1290
		return;
1291
	}
1292
1278
	/* Split blits that cross physical y_wrap boundary */
1293
	/* Split blits that cross physical y_wrap boundary */
1279
1294
1280
	y_break = p->vrows - p->yscroll;
1295
	y_break = p->vrows - p->yscroll;
Lines 1294-1303 static void fbcon_putcs(struct vc_data *vc, const unsigned short *s, Link Here
1294
	struct display *p = &fb_display[vc->vc_num];
1309
	struct display *p = &fb_display[vc->vc_num];
1295
	struct fbcon_ops *ops = info->fbcon_par;
1310
	struct fbcon_ops *ops = info->fbcon_par;
1296
1311
1297
	if (!fbcon_is_inactive(vc, info))
1312
	if (!fbcon_is_inactive(vc, info)) {
1298
		ops->putcs(vc, info, s, count, real_y(p, ypos), xpos,
1313
1299
			   get_color(vc, info, scr_readw(s), 1),
1314
		if (fbcon_decor_active(info, vc))
1300
			   get_color(vc, info, scr_readw(s), 0));
1315
			fbcon_decor_putcs(vc, info, s, count, ypos, xpos);
1316
		else
1317
			ops->putcs(vc, info, s, count, real_y(p, ypos), xpos,
1318
				   get_color(vc, info, scr_readw(s), 1),
1319
				   get_color(vc, info, scr_readw(s), 0));
1320
	}
1301
}
1321
}
1302
1322
1303
static void fbcon_putc(struct vc_data *vc, int c, int ypos, int xpos)
1323
static void fbcon_putc(struct vc_data *vc, int c, int ypos, int xpos)
Lines 1313-1320 static void fbcon_clear_margins(struct vc_data *vc, int bottom_only) Link Here
1313
	struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
1333
	struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
1314
	struct fbcon_ops *ops = info->fbcon_par;
1334
	struct fbcon_ops *ops = info->fbcon_par;
1315
1335
1316
	if (!fbcon_is_inactive(vc, info))
1336
	if (!fbcon_is_inactive(vc, info)) {
1317
		ops->clear_margins(vc, info, margin_color, bottom_only);
1337
		if (fbcon_decor_active(info, vc))
1338
			fbcon_decor_clear_margins(vc, info, bottom_only);
1339
		else
1340
			ops->clear_margins(vc, info, margin_color, bottom_only);
1341
	}
1318
}
1342
}
1319
1343
1320
static void fbcon_cursor(struct vc_data *vc, int mode)
1344
static void fbcon_cursor(struct vc_data *vc, int mode)
Lines 1835-1841 static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b, Link Here
1835
			count = vc->vc_rows;
1859
			count = vc->vc_rows;
1836
		if (softback_top)
1860
		if (softback_top)
1837
			fbcon_softback_note(vc, t, count);
1861
			fbcon_softback_note(vc, t, count);
1838
		if (logo_shown >= 0)
1862
		if (logo_shown >= 0 || fbcon_decor_active(info, vc))
1839
			goto redraw_up;
1863
			goto redraw_up;
1840
		switch (p->scrollmode) {
1864
		switch (p->scrollmode) {
1841
		case SCROLL_MOVE:
1865
		case SCROLL_MOVE:
Lines 1928-1933 static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b, Link Here
1928
			count = vc->vc_rows;
1952
			count = vc->vc_rows;
1929
		if (logo_shown >= 0)
1953
		if (logo_shown >= 0)
1930
			goto redraw_down;
1954
			goto redraw_down;
1955
		if (fbcon_decor_active(info, vc))
1956
			goto redraw_down;
1931
		switch (p->scrollmode) {
1957
		switch (p->scrollmode) {
1932
		case SCROLL_MOVE:
1958
		case SCROLL_MOVE:
1933
			fbcon_redraw_blit(vc, info, p, b - 1, b - t - count,
1959
			fbcon_redraw_blit(vc, info, p, b - 1, b - t - count,
Lines 2076-2081 static void fbcon_bmove_rec(struct vc_data *vc, struct display *p, int sy, int s Link Here
2076
		}
2102
		}
2077
		return;
2103
		return;
2078
	}
2104
	}
2105
2106
	if (fbcon_decor_active(info, vc) && sy == dy && height == 1) {
2107
		/* must use slower redraw bmove to keep background pic intact */
2108
		fbcon_decor_bmove_redraw(vc, info, sy, sx, dx, width);
2109
		return;
2110
	}
2111
2079
	ops->bmove(vc, info, real_y(p, sy), sx, real_y(p, dy), dx,
2112
	ops->bmove(vc, info, real_y(p, sy), sx, real_y(p, dy), dx,
2080
		   height, width);
2113
		   height, width);
2081
}
2114
}
Lines 2146-2153 static int fbcon_resize(struct vc_data *vc, unsigned int width, Link Here
2146
	var.yres = virt_h * virt_fh;
2179
	var.yres = virt_h * virt_fh;
2147
	x_diff = info->var.xres - var.xres;
2180
	x_diff = info->var.xres - var.xres;
2148
	y_diff = info->var.yres - var.yres;
2181
	y_diff = info->var.yres - var.yres;
2149
	if (x_diff < 0 || x_diff > virt_fw ||
2182
	if ((x_diff < 0 || x_diff > virt_fw ||
2150
	    y_diff < 0 || y_diff > virt_fh) {
2183
		y_diff < 0 || y_diff > virt_fh) && !vc->vc_decor.state) {
2151
		const struct fb_videomode *mode;
2184
		const struct fb_videomode *mode;
2152
2185
2153
		DPRINTK("attempting resize %ix%i\n", var.xres, var.yres);
2186
		DPRINTK("attempting resize %ix%i\n", var.xres, var.yres);
Lines 2183-2188 static int fbcon_switch(struct vc_data *vc) Link Here
2183
2216
2184
	info = registered_fb[con2fb_map[vc->vc_num]];
2217
	info = registered_fb[con2fb_map[vc->vc_num]];
2185
	ops = info->fbcon_par;
2218
	ops = info->fbcon_par;
2219
	prev_console = ops->currcon;
2220
	if (prev_console != -1)
2221
		old_info = registered_fb[con2fb_map[prev_console]];
2222
2223
#ifdef CONFIG_FB_CON_DECOR
2224
	if (!fbcon_decor_active_vc(vc) && info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
2225
		struct vc_data *vc_curr = vc_cons[prev_console].d;
2226
2227
		if (vc_curr && fbcon_decor_active_vc(vc_curr)) {
2228
			// Clear the screen to avoid displaying funky colors
2229
			// during palette updates.
2230
			memset((u8 *)info->screen_base + info->fix.line_length * info->var.yoffset,
2231
			       0, info->var.yres * info->fix.line_length);
2232
		}
2233
	}
2234
#endif
2186
2235
2187
	if (softback_top) {
2236
	if (softback_top) {
2188
		if (softback_lines)
2237
		if (softback_lines)
Lines 2201-2209 static int fbcon_switch(struct vc_data *vc) Link Here
2201
		logo_shown = FBCON_LOGO_CANSHOW;
2250
		logo_shown = FBCON_LOGO_CANSHOW;
2202
	}
2251
	}
2203
2252
2204
	prev_console = ops->currcon;
2205
	if (prev_console != -1)
2206
		old_info = registered_fb[con2fb_map[prev_console]];
2207
	/*
2253
	/*
2208
	 * FIXME: If we have multiple fbdev's loaded, we need to
2254
	 * FIXME: If we have multiple fbdev's loaded, we need to
2209
	 * update all info->currcon.  Perhaps, we can place this
2255
	 * update all info->currcon.  Perhaps, we can place this
Lines 2247-2252 static int fbcon_switch(struct vc_data *vc) Link Here
2247
			fbcon_del_cursor_timer(old_info);
2293
			fbcon_del_cursor_timer(old_info);
2248
	}
2294
	}
2249
2295
2296
	if (fbcon_decor_active_vc(vc)) {
2297
		struct vc_data *vc_curr = vc_cons[prev_console].d;
2298
2299
		if (!vc_curr->vc_decor.theme ||
2300
			strcmp(vc->vc_decor.theme, vc_curr->vc_decor.theme) ||
2301
			(fbcon_decor_active_nores(info, vc_curr) &&
2302
			 !fbcon_decor_active(info, vc_curr))) {
2303
			fbcon_decor_disable(vc, 0);
2304
			fbcon_decor_call_helper("modechange", vc->vc_num);
2305
		}
2306
	}
2307
2250
	if (fbcon_is_inactive(vc, info) ||
2308
	if (fbcon_is_inactive(vc, info) ||
2251
	    ops->blank_state != FB_BLANK_UNBLANK)
2309
	    ops->blank_state != FB_BLANK_UNBLANK)
2252
		fbcon_del_cursor_timer(info);
2310
		fbcon_del_cursor_timer(info);
Lines 2355-2369 static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch) Link Here
2355
		}
2413
		}
2356
	}
2414
	}
2357
2415
2358
 	if (!fbcon_is_inactive(vc, info)) {
2416
	if (!fbcon_is_inactive(vc, info)) {
2359
		if (ops->blank_state != blank) {
2417
		if (ops->blank_state != blank) {
2360
			ops->blank_state = blank;
2418
			ops->blank_state = blank;
2361
			fbcon_cursor(vc, blank ? CM_ERASE : CM_DRAW);
2419
			fbcon_cursor(vc, blank ? CM_ERASE : CM_DRAW);
2362
			ops->cursor_flash = (!blank);
2420
			ops->cursor_flash = (!blank);
2363
2421
2364
			if (!(info->flags & FBINFO_MISC_USEREVENT))
2422
			if (!(info->flags & FBINFO_MISC_USEREVENT)) {
2365
				if (fb_blank(info, blank))
2423
				if (fb_blank(info, blank)) {
2366
					fbcon_generic_blank(vc, info, blank);
2424
					if (fbcon_decor_active(info, vc))
2425
						fbcon_decor_blank(vc, info, blank);
2426
					else
2427
						fbcon_generic_blank(vc, info, blank);
2428
				}
2429
			}
2367
		}
2430
		}
2368
2431
2369
		if (!blank)
2432
		if (!blank)
Lines 2546-2558 static int fbcon_do_set_font(struct vc_data *vc, int w, int h, Link Here
2546
		set_vc_hi_font(vc, true);
2609
		set_vc_hi_font(vc, true);
2547
2610
2548
	if (resize) {
2611
	if (resize) {
2612
		/* reset wrap/pan */
2549
		int cols, rows;
2613
		int cols, rows;
2550
2614
2551
		cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres);
2615
		cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres);
2552
		rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
2616
		rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
2617
2618
		if (fbcon_decor_active(info, vc)) {
2619
			info->var.xoffset = info->var.yoffset = p->yscroll = 0;
2620
			cols = vc->vc_decor.twidth;
2621
			rows = vc->vc_decor.theight;
2622
		}
2553
		cols /= w;
2623
		cols /= w;
2554
		rows /= h;
2624
		rows /= h;
2625
2555
		vc_resize(vc, cols, rows);
2626
		vc_resize(vc, cols, rows);
2627
2556
		if (con_is_visible(vc) && softback_buf)
2628
		if (con_is_visible(vc) && softback_buf)
2557
			fbcon_update_softback(vc);
2629
			fbcon_update_softback(vc);
2558
	} else if (con_is_visible(vc)
2630
	} else if (con_is_visible(vc)
Lines 2681-2687 static void fbcon_set_palette(struct vc_data *vc, const unsigned char *table) Link Here
2681
	int i, j, k, depth;
2753
	int i, j, k, depth;
2682
	u8 val;
2754
	u8 val;
2683
2755
2684
	if (fbcon_is_inactive(vc, info))
2756
	if (fbcon_is_inactive(vc, info)
2757
#ifdef CONFIG_FB_CON_DECOR
2758
			|| vc->vc_num != fg_console
2759
#endif
2760
		)
2685
		return;
2761
		return;
2686
2762
2687
	if (!con_is_visible(vc))
2763
	if (!con_is_visible(vc))
Lines 2707-2713 static void fbcon_set_palette(struct vc_data *vc, const unsigned char *table) Link Here
2707
	} else
2783
	} else
2708
		fb_copy_cmap(fb_default_cmap(1 << depth), &palette_cmap);
2784
		fb_copy_cmap(fb_default_cmap(1 << depth), &palette_cmap);
2709
2785
2710
	fb_set_cmap(&palette_cmap, info);
2786
	if (fbcon_decor_active(info, vc_cons[fg_console].d) &&
2787
	    info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
2788
2789
		u16 *red, *green, *blue;
2790
		int minlen = min(min(info->var.red.length, info->var.green.length),
2791
				     info->var.blue.length);
2792
2793
		struct fb_cmap cmap = {
2794
			.start = 0,
2795
			.len = (1 << minlen),
2796
			.red = NULL,
2797
			.green = NULL,
2798
			.blue = NULL,
2799
			.transp = NULL
2800
		};
2801
2802
		red = kmalloc(256 * sizeof(u16) * 3, GFP_KERNEL);
2803
2804
		if (!red)
2805
			goto out;
2806
2807
		green = red + 256;
2808
		blue = green + 256;
2809
		cmap.red = red;
2810
		cmap.green = green;
2811
		cmap.blue = blue;
2812
2813
		for (i = 0; i < cmap.len; i++)
2814
			red[i] = green[i] = blue[i] = (0xffff * i)/(cmap.len-1);
2815
2816
		fb_set_cmap(&cmap, info);
2817
		fbcon_decor_fix_pseudo_pal(info, vc_cons[fg_console].d);
2818
		kfree(red);
2819
2820
		return;
2821
2822
	} else if (fbcon_decor_active(info, vc_cons[fg_console].d) &&
2823
		   info->var.bits_per_pixel == 8 && info->bgdecor.cmap.red != NULL)
2824
		fb_set_cmap(&info->bgdecor.cmap, info);
2825
2826
out:	fb_set_cmap(&palette_cmap, info);
2711
}
2827
}
2712
2828
2713
static u16 *fbcon_screen_pos(struct vc_data *vc, int offset)
2829
static u16 *fbcon_screen_pos(struct vc_data *vc, int offset)
Lines 2932-2938 static void fbcon_modechanged(struct fb_info *info) Link Here
2932
		rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
3048
		rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
2933
		cols /= vc->vc_font.width;
3049
		cols /= vc->vc_font.width;
2934
		rows /= vc->vc_font.height;
3050
		rows /= vc->vc_font.height;
2935
		vc_resize(vc, cols, rows);
3051
3052
		if (!fbcon_decor_active_nores(info, vc)) {
3053
			vc_resize(vc, cols, rows);
3054
		} else {
3055
			fbcon_decor_disable(vc, 0);
3056
			fbcon_decor_call_helper("modechange", vc->vc_num);
3057
		}
3058
2936
		updatescrollmode(p, info, vc);
3059
		updatescrollmode(p, info, vc);
2937
		scrollback_max = 0;
3060
		scrollback_max = 0;
2938
		scrollback_current = 0;
3061
		scrollback_current = 0;
Lines 2977-2983 static void fbcon_set_all_vcs(struct fb_info *info) Link Here
2977
		rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
3100
		rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
2978
		cols /= vc->vc_font.width;
3101
		cols /= vc->vc_font.width;
2979
		rows /= vc->vc_font.height;
3102
		rows /= vc->vc_font.height;
2980
		vc_resize(vc, cols, rows);
3103
		if (!fbcon_decor_active_nores(info, vc))
3104
			vc_resize(vc, cols, rows);
2981
	}
3105
	}
2982
3106
2983
	if (fg != -1)
3107
	if (fg != -1)
Lines 3618-3623 static void fbcon_exit(void) Link Here
3618
		}
3742
		}
3619
	}
3743
	}
3620
3744
3745
	fbcon_decor_exit();
3621
	fbcon_has_exited = 1;
3746
	fbcon_has_exited = 1;
3622
}
3747
}
3623
3748
(-)a/drivers/video/fbdev/core/fbmem.c (-9 lines)
Lines 1253-1267 struct fb_fix_screeninfo32 { Link Here
1253
	u16			reserved[3];
1253
	u16			reserved[3];
1254
};
1254
};
1255
1255
1256
struct fb_cmap32 {
1257
	u32			start;
1258
	u32			len;
1259
	compat_caddr_t	red;
1260
	compat_caddr_t	green;
1261
	compat_caddr_t	blue;
1262
	compat_caddr_t	transp;
1263
};
1264
1265
static int fb_getput_cmap(struct fb_info *info, unsigned int cmd,
1256
static int fb_getput_cmap(struct fb_info *info, unsigned int cmd,
1266
			  unsigned long arg)
1257
			  unsigned long arg)
1267
{
1258
{
(-)a/include/linux/console_decor.h (+46 lines)
Line 0 Link Here
1
#ifndef _LINUX_CONSOLE_DECOR_H_
2
#define _LINUX_CONSOLE_DECOR_H_ 1
3
4
/* A structure used by the framebuffer console decorations (drivers/video/console/fbcondecor.c) */
5
struct vc_decor {
6
	__u8 bg_color;				/* The color that is to be treated as transparent */
7
	__u8 state;				/* Current decor state: 0 = off, 1 = on */
8
	__u16 tx, ty;				/* Top left corner coordinates of the text field */
9
	__u16 twidth, theight;			/* Width and height of the text field */
10
	char *theme;
11
};
12
13
#ifdef __KERNEL__
14
#ifdef CONFIG_COMPAT
15
#include <linux/compat.h>
16
17
struct vc_decor32 {
18
	__u8 bg_color;				/* The color that is to be treated as transparent */
19
	__u8 state;				/* Current decor state: 0 = off, 1 = on */
20
	__u16 tx, ty;				/* Top left corner coordinates of the text field */
21
	__u16 twidth, theight;			/* Width and height of the text field */
22
	compat_uptr_t theme;
23
};
24
25
#define vc_decor_from_compat(to, from) \
26
	(to).bg_color = (from).bg_color; \
27
	(to).state    = (from).state; \
28
	(to).tx       = (from).tx; \
29
	(to).ty       = (from).ty; \
30
	(to).twidth   = (from).twidth; \
31
	(to).theight  = (from).theight; \
32
	(to).theme    = compat_ptr((from).theme)
33
34
#define vc_decor_to_compat(to, from) \
35
	(to).bg_color = (from).bg_color; \
36
	(to).state    = (from).state; \
37
	(to).tx       = (from).tx; \
38
	(to).ty       = (from).ty; \
39
	(to).twidth   = (from).twidth; \
40
	(to).theight  = (from).theight; \
41
	(to).theme    = ptr_to_compat((from).theme)
42
43
#endif /* CONFIG_COMPAT */
44
#endif /* __KERNEL__ */
45
46
#endif
(-)a/include/linux/console_struct.h (+3 lines)
Lines 21-26 struct vt_struct; Link Here
21
struct uni_pagedir;
21
struct uni_pagedir;
22
22
23
#define NPAR 16
23
#define NPAR 16
24
#include <linux/console_decor.h>
24
25
25
/*
26
/*
26
 * Example: vc_data of a console that was scrolled 3 lines down.
27
 * Example: vc_data of a console that was scrolled 3 lines down.
Lines 141-146 struct vc_data { Link Here
141
	struct uni_pagedir *vc_uni_pagedir;
142
	struct uni_pagedir *vc_uni_pagedir;
142
	struct uni_pagedir **vc_uni_pagedir_loc; /* [!] Location of uni_pagedir variable for this console */
143
	struct uni_pagedir **vc_uni_pagedir_loc; /* [!] Location of uni_pagedir variable for this console */
143
	bool vc_panic_force_write; /* when oops/panic this VC can accept forced output/blanking */
144
	bool vc_panic_force_write; /* when oops/panic this VC can accept forced output/blanking */
145
146
	struct vc_decor vc_decor;
144
	/* additional information is in vt_kern.h */
147
	/* additional information is in vt_kern.h */
145
};
148
};
146
149
(-)a/include/linux/fb.h (+31 lines)
Lines 239-244 struct fb_deferred_io { Link Here
239
};
239
};
240
#endif
240
#endif
241
241
242
#ifdef __KERNEL__
243
#ifdef CONFIG_COMPAT
244
struct fb_image32 {
245
	__u32 dx;			/* Where to place image */
246
	__u32 dy;
247
	__u32 width;			/* Size of image */
248
	__u32 height;
249
	__u32 fg_color;			/* Only used when a mono bitmap */
250
	__u32 bg_color;
251
	__u8  depth;			/* Depth of the image */
252
	const compat_uptr_t data;	/* Pointer to image data */
253
	struct fb_cmap32 cmap;		/* color map info */
254
};
255
256
#define fb_image_from_compat(to, from) \
257
	(to).dx       = (from).dx; \
258
	(to).dy       = (from).dy; \
259
	(to).width    = (from).width; \
260
	(to).height   = (from).height; \
261
	(to).fg_color = (from).fg_color; \
262
	(to).bg_color = (from).bg_color; \
263
	(to).depth    = (from).depth; \
264
	(to).data     = compat_ptr((from).data); \
265
	fb_cmap_from_compat((to).cmap, (from).cmap)
266
267
#endif /* CONFIG_COMPAT */
268
#endif /* __KERNEL__ */
269
242
/*
270
/*
243
 * Frame buffer operations
271
 * Frame buffer operations
244
 *
272
 *
Lines 509-514 struct fb_info { Link Here
509
#define FBINFO_STATE_SUSPENDED	1
537
#define FBINFO_STATE_SUSPENDED	1
510
	u32 state;			/* Hardware state i.e suspend */
538
	u32 state;			/* Hardware state i.e suspend */
511
	void *fbcon_par;                /* fbcon use-only private area */
539
	void *fbcon_par;                /* fbcon use-only private area */
540
541
	struct fb_image bgdecor;
542
512
	/* From here on everything is device dependent */
543
	/* From here on everything is device dependent */
513
	void *par;
544
	void *par;
514
	/* we need the PCI or similar aperture base/size not
545
	/* we need the PCI or similar aperture base/size not
(-)a/include/uapi/linux/fb.h (+59 lines)
Lines 9-14 Link Here
9
9
10
#define FB_MAX			32	/* sufficient for now */
10
#define FB_MAX			32	/* sufficient for now */
11
11
12
struct fbcon_decor_iowrapper {
13
	unsigned short vc;		/* Virtual console */
14
	unsigned char origin;		/* Point of origin of the request */
15
	void *data;
16
};
17
18
#ifdef __KERNEL__
19
#ifdef CONFIG_COMPAT
20
#include <linux/compat.h>
21
struct fbcon_decor_iowrapper32 {
22
	unsigned short vc;		/* Virtual console */
23
	unsigned char origin;		/* Point of origin of the request */
24
	compat_uptr_t data;
25
};
26
#endif /* CONFIG_COMPAT */
27
#endif /* __KERNEL__ */
28
12
/* ioctls
29
/* ioctls
13
   0x46 is 'F'								*/
30
   0x46 is 'F'								*/
14
#define FBIOGET_VSCREENINFO	0x4600
31
#define FBIOGET_VSCREENINFO	0x4600
Lines 36-41 Link Here
36
#define FBIOGET_DISPINFO        0x4618
53
#define FBIOGET_DISPINFO        0x4618
37
#define FBIO_WAITFORVSYNC	_IOW('F', 0x20, __u32)
54
#define FBIO_WAITFORVSYNC	_IOW('F', 0x20, __u32)
38
55
56
#define FBIOCONDECOR_SETCFG	_IOWR('F', 0x19, struct fbcon_decor_iowrapper)
57
#define FBIOCONDECOR_GETCFG	_IOR('F', 0x1A, struct fbcon_decor_iowrapper)
58
#define FBIOCONDECOR_SETSTATE	_IOWR('F', 0x1B, struct fbcon_decor_iowrapper)
59
#define FBIOCONDECOR_GETSTATE	_IOR('F', 0x1C, struct fbcon_decor_iowrapper)
60
#define FBIOCONDECOR_SETPIC	_IOWR('F', 0x1D, struct fbcon_decor_iowrapper)
61
#ifdef __KERNEL__
62
#ifdef CONFIG_COMPAT
63
#define FBIOCONDECOR_SETCFG32	_IOWR('F', 0x19, struct fbcon_decor_iowrapper32)
64
#define FBIOCONDECOR_GETCFG32	_IOR('F', 0x1A, struct fbcon_decor_iowrapper32)
65
#define FBIOCONDECOR_SETSTATE32	_IOWR('F', 0x1B, struct fbcon_decor_iowrapper32)
66
#define FBIOCONDECOR_GETSTATE32	_IOR('F', 0x1C, struct fbcon_decor_iowrapper32)
67
#define FBIOCONDECOR_SETPIC32	_IOWR('F', 0x1D, struct fbcon_decor_iowrapper32)
68
#endif /* CONFIG_COMPAT */
69
#endif /* __KERNEL__ */
70
71
#define FBCON_DECOR_THEME_LEN		128	/* Maximum length of a theme name */
72
#define FBCON_DECOR_IO_ORIG_KERNEL	0	/* Kernel ioctl origin */
73
#define FBCON_DECOR_IO_ORIG_USER	1	/* User ioctl origin */
74
39
#define FB_TYPE_PACKED_PIXELS		0	/* Packed Pixels	*/
75
#define FB_TYPE_PACKED_PIXELS		0	/* Packed Pixels	*/
40
#define FB_TYPE_PLANES			1	/* Non interleaved planes */
76
#define FB_TYPE_PLANES			1	/* Non interleaved planes */
41
#define FB_TYPE_INTERLEAVED_PLANES	2	/* Interleaved planes	*/
77
#define FB_TYPE_INTERLEAVED_PLANES	2	/* Interleaved planes	*/
Lines 278-283 struct fb_var_screeninfo { Link Here
278
	__u32 reserved[4];		/* Reserved for future compatibility */
314
	__u32 reserved[4];		/* Reserved for future compatibility */
279
};
315
};
280
316
317
#ifdef __KERNEL__
318
#ifdef CONFIG_COMPAT
319
struct fb_cmap32 {
320
	__u32 start;
321
	__u32 len;			/* Number of entries */
322
	compat_uptr_t red;		/* Red values	*/
323
	compat_uptr_t green;
324
	compat_uptr_t blue;
325
	compat_uptr_t transp;		/* transparency, can be NULL */
326
};
327
328
#define fb_cmap_from_compat(to, from) \
329
	(to).start  = (from).start; \
330
	(to).len    = (from).len; \
331
	(to).red    = compat_ptr((from).red); \
332
	(to).green  = compat_ptr((from).green); \
333
	(to).blue   = compat_ptr((from).blue); \
334
	(to).transp = compat_ptr((from).transp)
335
336
#endif /* CONFIG_COMPAT */
337
#endif /* __KERNEL__ */
338
339
281
struct fb_cmap {
340
struct fb_cmap {
282
	__u32 start;			/* First entry	*/
341
	__u32 start;			/* First entry	*/
283
	__u32 len;			/* Number of entries */
342
	__u32 len;			/* Number of entries */
(-)a/kernel/sysctl.c (+13 lines)
Lines 150-155 static const int cap_last_cap = CAP_LAST_CAP; Link Here
150
static unsigned long hung_task_timeout_max = (LONG_MAX/HZ);
150
static unsigned long hung_task_timeout_max = (LONG_MAX/HZ);
151
#endif
151
#endif
152
152
153
#ifdef CONFIG_FB_CON_DECOR
154
extern char fbcon_decor_path[];
155
#endif
156
153
#ifdef CONFIG_INOTIFY_USER
157
#ifdef CONFIG_INOTIFY_USER
154
#include <linux/inotify.h>
158
#include <linux/inotify.h>
155
#endif
159
#endif
Lines 283-288 static struct ctl_table sysctl_base_table[] = { Link Here
283
		.mode		= 0555,
287
		.mode		= 0555,
284
		.child		= dev_table,
288
		.child		= dev_table,
285
	},
289
	},
290
#ifdef CONFIG_FB_CON_DECOR
291
	{
292
		.procname	= "fbcondecor",
293
		.data		= &fbcon_decor_path,
294
		.maxlen		= KMOD_PATH_LEN,
295
		.mode		= 0644,
296
		.proc_handler	= &proc_dostring,
297
	},
298
#endif
286
	{ }
299
	{ }
287
};
300
};
288
301

Return to bug 637434