dc_hw.c 9.5 KB
Newer Older
B
bernard.xiong 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/*
 * File      : dc_hw.c
 * This file is part of RT-Thread RTOS
 * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
 *
 * The license and distribution terms for this file may be
 * found in the file LICENSE in this distribution or at
 * http://www.rt-thread.org/license/LICENSE
 *
 * Change Logs:
 * Date           Author       Notes
 * 2009-10-16     Bernard      first version
 */
#include <rtgui/dc.h>
15
#include <rtgui/dc_hw.h>
B
bernard.xiong 已提交
16
#include <rtgui/driver.h>
B
bernard.xiong 已提交
17
#include <rtgui/rtgui_system.h>
18
#include <rtgui/rtgui_app.h>
19 20 21
#include <rtgui/rtgui_server.h>

#include <rtgui/widgets/container.h>
B
bernard.xiong 已提交
22 23 24
#include <rtgui/widgets/window.h>
#include <rtgui/widgets/title.h>

25 26
#define _int_swap(x, y)			do {x ^= y; y ^= x; x ^= y;} while (0)

B
bernard.xiong 已提交
27
static void rtgui_dc_hw_draw_point(struct rtgui_dc* dc, int x, int y);
28
static void rtgui_dc_hw_draw_color_point(struct rtgui_dc* dc, int x, int y, rtgui_color_t color);
B
bernard.xiong 已提交
29 30 31
static void rtgui_dc_hw_draw_hline(struct rtgui_dc* dc, int x1, int x2, int y);
static void rtgui_dc_hw_draw_vline(struct rtgui_dc* dc, int x, int y1, int y2);
static void rtgui_dc_hw_fill_rect (struct rtgui_dc* dc, rtgui_rect_t* rect);
B
bernard.xiong 已提交
32
static void rtgui_dc_hw_blit_line (struct rtgui_dc* self, int x1, int x2, int y, rt_uint8_t* line_data);
B
bernard.xiong 已提交
33
static void rtgui_dc_hw_blit	  (struct rtgui_dc* dc, struct rtgui_point* dc_point, struct rtgui_dc* dest, rtgui_rect_t* rect);
34 35
static void rtgui_dc_hw_set_gc (struct rtgui_dc* dc, rtgui_gc_t *gc);
static rtgui_gc_t *rtgui_dc_hw_get_gc (struct rtgui_dc* dc);
B
bernard.xiong 已提交
36 37 38 39
static rt_bool_t rtgui_dc_hw_fini(struct rtgui_dc* dc);
static rt_bool_t rtgui_dc_hw_get_visible(struct rtgui_dc* dc);
static void rtgui_dc_hw_get_rect(struct rtgui_dc* dc, rtgui_rect_t* rect);

B
bernard.xiong@gmail.com 已提交
40 41 42 43 44 45
struct rtgui_dc_hw
{
	struct rtgui_dc parent;
	rtgui_widget_t *owner;
	const struct rtgui_graphic_driver* hw_driver;
};
46 47

const struct rtgui_dc_engine dc_hw_engine = 
B
bernard.xiong 已提交
48
{
49 50 51 52 53
	rtgui_dc_hw_draw_point,
	rtgui_dc_hw_draw_color_point,
	rtgui_dc_hw_draw_vline,
	rtgui_dc_hw_draw_hline,
	rtgui_dc_hw_fill_rect,
B
bernard.xiong 已提交
54
	rtgui_dc_hw_blit_line,
55
	rtgui_dc_hw_blit,
B
bernard.xiong 已提交
56

57 58
	rtgui_dc_hw_set_gc,
	rtgui_dc_hw_get_gc,
B
bernard.xiong 已提交
59

60 61
	rtgui_dc_hw_get_visible,
	rtgui_dc_hw_get_rect,
B
bernard.xiong 已提交
62

63 64
	rtgui_dc_hw_fini,
};
B
bernard.xiong 已提交
65 66 67 68 69 70

extern struct rt_mutex cursor_mutex;
extern void rtgui_mouse_show_cursor(void);
extern void rtgui_mouse_hide_cursor(void);
struct rtgui_dc* rtgui_dc_hw_create(rtgui_widget_t* owner)
{
B
bernard.xiong@gmail.com 已提交
71
	struct rtgui_dc_hw* dc;
B
bernard.xiong 已提交
72 73 74 75 76 77
	rtgui_widget_t* widget;

	/* adjudge owner */
	if (owner == RT_NULL || owner->toplevel == RT_NULL) return RT_NULL;
	if (!RTGUI_IS_TOPLEVEL(owner->toplevel)) return RT_NULL;

78 79
	/* set init visible as true */
	RTGUI_WIDGET_DC_SET_VISIBLE(owner);
B
bernard.xiong 已提交
80

81
	/* check widget visible */
B
bernard.xiong 已提交
82 83 84 85 86
	widget = owner;
	while (widget != RT_NULL)
	{
		if (RTGUI_WIDGET_IS_HIDE(widget))
		{
87
			RTGUI_WIDGET_DC_SET_UNVISIBLE(owner);
88
			return RT_NULL;
B
bernard.xiong 已提交
89 90 91 92 93
		}

		widget = widget->parent;
	}

B
bernard.xiong@gmail.com 已提交
94 95 96 97 98 99 100 101 102
	if (!RTGUI_WIDGET_IS_DC_VISIBLE(owner)) return RT_NULL;

	/* create DC */
	dc = (struct rtgui_dc_hw*) rtgui_malloc(sizeof(struct rtgui_dc_hw));
	dc->parent.type = RTGUI_DC_HW;
	dc->parent.engine = &dc_hw_engine;
	dc->owner = owner;
	dc->hw_driver = rtgui_graphic_driver_get_default();

103
	if (RTGUI_IS_WINTITLE(owner->toplevel))
B
bernard.xiong 已提交
104
	{
105
		rtgui_toplevel_t* top = RTGUI_TOPLEVEL(owner->toplevel);
B
bernard.xiong 已提交
106 107 108 109 110
		top->drawing ++;

		if (top->drawing == 1)
		{
#ifdef RTGUI_USING_MOUSE_CURSOR
111
#ifdef _WIN32
B
bernard.xiong 已提交
112 113 114 115 116 117 118 119 120 121
			rt_mutex_take(&cursor_mutex, RT_WAITING_FOREVER);
			rt_kprintf("hide cursor\n");
			rtgui_mouse_hide_cursor();
#else
			/* hide cursor */
			rtgui_mouse_hide_cursor();
#endif
#endif
		}
	}
122
	else if (RTGUI_IS_APP(owner->toplevel) ||
123
		RTGUI_IS_WIN(owner->toplevel))
B
bernard.xiong 已提交
124
	{
125
		rtgui_toplevel_t* top = RTGUI_TOPLEVEL(owner->toplevel);
B
bernard.xiong 已提交
126 127 128 129
		top->drawing ++;

		if (top->drawing == 1)
		{
130
#ifdef _WIN32
B
bernard.xiong 已提交
131 132 133 134 135 136 137 138 139 140 141
#ifdef RTGUI_USING_MOUSE_CURSOR
			rt_mutex_take(&cursor_mutex, RT_WAITING_FOREVER);
			rt_kprintf("hide cursor\n");
			rtgui_mouse_hide_cursor();
#endif
#else
			/* send draw begin to server */
			struct rtgui_event_update_begin eupdate;
			RTGUI_EVENT_UPDATE_BEGIN_INIT(&(eupdate));
			eupdate.rect = RTGUI_WIDGET(top)->extent;

142
			rtgui_server_post_event((struct rtgui_event*)&eupdate, sizeof(eupdate));
B
bernard.xiong 已提交
143 144 145 146
#endif
		}
	}

B
bernard.xiong@gmail.com 已提交
147
	return &(dc->parent);
B
bernard.xiong 已提交
148 149 150 151
}

static rt_bool_t rtgui_dc_hw_fini(struct rtgui_dc* dc)
{
152
	rtgui_widget_t* owner;
B
bernard.xiong@gmail.com 已提交
153 154
	struct rtgui_dc_hw* self;

155 156
	if (dc == RT_NULL || dc->type != RTGUI_DC_HW) return RT_FALSE;

B
bernard.xiong@gmail.com 已提交
157
	self = (struct rtgui_dc_hw*)dc;
158
	/* get owner */
B
bernard.xiong@gmail.com 已提交
159
	owner = self->owner;
B
bernard.xiong 已提交
160

161
	if (RTGUI_IS_WINTITLE(owner->toplevel))
B
bernard.xiong 已提交
162 163
	{
		/* update title extent */
164
		rtgui_toplevel_t* top = RTGUI_TOPLEVEL(owner->toplevel);
B
bernard.xiong 已提交
165 166

		top->drawing --;
167
		if ((top->drawing == 0) && RTGUI_WIDGET_IS_DC_VISIBLE(owner))
B
bernard.xiong 已提交
168
		{
169
#ifdef _WIN32
B
bernard.xiong 已提交
170 171 172 173 174 175 176
#ifdef RTGUI_USING_MOUSE_CURSOR
			rt_mutex_release(&cursor_mutex);
			/* show cursor */
			rtgui_mouse_show_cursor();
			rt_kprintf("show cursor\n");
#endif
			/* update screen */
177
			rtgui_graphic_driver_screen_update(self->hw_driver, &(owner->extent));
B
bernard.xiong 已提交
178 179 180 181 182 183 184
#else
#ifdef RTGUI_USING_MOUSE_CURSOR
			/* show cursor */
			rtgui_mouse_show_cursor();
#endif

			/* update screen */
185
			rtgui_graphic_driver_screen_update(self->hw_driver, &(owner->extent));
B
bernard.xiong 已提交
186 187 188
#endif
		}
	}
189
	else if (RTGUI_IS_APP(owner->toplevel) ||
190
		RTGUI_IS_WIN(owner->toplevel))
B
bernard.xiong 已提交
191
	{
192
		rtgui_toplevel_t* top = RTGUI_TOPLEVEL(owner->toplevel);
B
bernard.xiong 已提交
193 194
		top->drawing --;

195
		if ((top->drawing == 0) && RTGUI_WIDGET_IS_DC_VISIBLE(owner))
B
bernard.xiong 已提交
196
		{
197
#ifdef _WIN32
B
bernard.xiong 已提交
198 199 200 201 202 203 204
#ifdef RTGUI_USING_MOUSE_CURSOR
			rt_mutex_release(&cursor_mutex);
			/* show cursor */
			rtgui_mouse_show_cursor();
			rt_kprintf("show cursor\n");
#endif
			/* update screen */
205
			rtgui_graphic_driver_screen_update(self->hw_driver, &(owner->extent));
B
bernard.xiong 已提交
206 207 208 209
#else
			/* send to server to end drawing */
			struct rtgui_event_update_end eupdate;
			RTGUI_EVENT_UPDATE_END_INIT(&(eupdate));
210
			eupdate.rect = owner->extent;
B
bernard.xiong 已提交
211

212
			rtgui_server_post_event((struct rtgui_event*)&eupdate, sizeof(eupdate));
B
bernard.xiong 已提交
213 214 215 216
#endif
		}
	}

B
bernard.xiong@gmail.com 已提交
217 218 219
	/* release hardware dc */
	rtgui_free(self);

B
bernard.xiong 已提交
220 221 222 223 224 225 226 227
	return RT_TRUE;
}

/*
 * draw a logic point on device
 */
static void rtgui_dc_hw_draw_point(struct rtgui_dc* self, int x, int y)
{
B
bernard.xiong@gmail.com 已提交
228
	struct rtgui_dc_hw* dc;
B
bernard.xiong 已提交
229

B
bernard.xiong@gmail.com 已提交
230 231
	RT_ASSERT(self != RT_NULL);
	dc = (struct rtgui_dc_hw*) self;
B
bernard.xiong 已提交
232

B
bernard.xiong@gmail.com 已提交
233
	x = x + dc->owner->extent.x1;
I
 
iamyhw@gmail.com 已提交
234
#if (0) /* Please yourself to decide whether to use it*/
I
iamyhw@gmail.com 已提交
235
	if(x < dc->owner->extent.x1 || x >= dc->owner->extent.x2) return;
I
 
iamyhw@gmail.com 已提交
236
#endif
B
bernard.xiong@gmail.com 已提交
237
	y = y + dc->owner->extent.y1;
I
 
iamyhw@gmail.com 已提交
238
#if (0)
I
iamyhw@gmail.com 已提交
239
	if(y < dc->owner->extent.y1 || y >= dc->owner->extent.y2) return;
I
 
iamyhw@gmail.com 已提交
240
#endif
241
	/* draw this point */
242
	dc->hw_driver->ops->set_pixel(&(dc->owner->gc.foreground), x, y);
B
bernard.xiong 已提交
243 244
}

245 246
static void rtgui_dc_hw_draw_color_point(struct rtgui_dc* self, int x, int y, rtgui_color_t color)
{
B
bernard.xiong@gmail.com 已提交
247
	struct rtgui_dc_hw* dc;
248

B
bernard.xiong@gmail.com 已提交
249 250
	RT_ASSERT(self != RT_NULL);
	dc = (struct rtgui_dc_hw*) self;
251

B
bernard.xiong@gmail.com 已提交
252 253
	x = x + dc->owner->extent.x1;
	y = y + dc->owner->extent.y1;
254

255
	/* draw this point */
256
	dc->hw_driver->ops->set_pixel(&color, x, y);
257 258
}

B
bernard.xiong 已提交
259 260 261 262 263
/*
 * draw a logic vertical line on device
 */
static void rtgui_dc_hw_draw_vline(struct rtgui_dc* self, int x, int y1, int y2)
{
B
bernard.xiong@gmail.com 已提交
264
	struct rtgui_dc_hw* dc;
B
bernard.xiong 已提交
265

B
bernard.xiong@gmail.com 已提交
266 267
	RT_ASSERT(self != RT_NULL);
	dc = (struct rtgui_dc_hw*) self;
B
bernard.xiong 已提交
268

B
bernard.xiong@gmail.com 已提交
269 270 271
	x = x + dc->owner->extent.x1;
	y1 = y1 + dc->owner->extent.y1;
	y2 = y2 + dc->owner->extent.y1;
272
	if (y1 > y2) _int_swap(y1, y2);
B
bernard.xiong 已提交
273

274
	/* draw vline */
275
	dc->hw_driver->ops->draw_vline(&(dc->owner->gc.foreground), x, y1, y2);
B
bernard.xiong 已提交
276 277 278 279 280 281 282
}

/*
 * draw a logic horizontal line on device
 */
static void rtgui_dc_hw_draw_hline(struct rtgui_dc* self, int x1, int x2, int y)
{
B
bernard.xiong@gmail.com 已提交
283
	struct rtgui_dc_hw* dc;
B
bernard.xiong 已提交
284

B
bernard.xiong@gmail.com 已提交
285 286
	RT_ASSERT(self != RT_NULL);
	dc = (struct rtgui_dc_hw*) self;
B
bernard.xiong 已提交
287 288

	/* convert logic to device */
B
bernard.xiong@gmail.com 已提交
289 290
	x1 = x1 + dc->owner->extent.x1;
	x2 = x2 + dc->owner->extent.x1;
291
	if (x1 > x2) _int_swap(x1, x2);	
B
bernard.xiong@gmail.com 已提交
292
	y  = y + dc->owner->extent.y1;
B
bernard.xiong 已提交
293

294
	/* draw hline */
295
	dc->hw_driver->ops->draw_hline(&(dc->owner->gc.foreground), x1, x2, y);
B
bernard.xiong 已提交
296 297 298 299
}

static void rtgui_dc_hw_fill_rect (struct rtgui_dc* self, struct rtgui_rect* rect)
{
300 301
	rtgui_color_t color;
	register rt_base_t index, x1, x2;
B
bernard.xiong@gmail.com 已提交
302
	struct rtgui_dc_hw* dc;
B
bernard.xiong 已提交
303

B
bernard.xiong@gmail.com 已提交
304 305
	RT_ASSERT(self != RT_NULL);
	dc = (struct rtgui_dc_hw*) self;
B
bernard.xiong 已提交
306

307
	/* get background color */
B
bernard.xiong@gmail.com 已提交
308
	color = dc->owner->gc.background;
309
	/* convert logic to device */
B
bernard.xiong@gmail.com 已提交
310 311
	x1 = rect->x1 + dc->owner->extent.x1;
	x2 = rect->x2 + dc->owner->extent.x1;
B
bernard.xiong 已提交
312 313

	/* fill rect */
B
bernard.xiong@gmail.com 已提交
314
	for (index = dc->owner->extent.y1 + rect->y1; index < dc->owner->extent.y1 + rect->y2; index ++)
B
bernard.xiong 已提交
315
	{
316
		dc->hw_driver->ops->draw_hline(&color, x1, x2, index);
B
bernard.xiong 已提交
317 318 319
	}
}

B
bernard.xiong 已提交
320 321 322 323 324 325 326 327 328 329
static void rtgui_dc_hw_blit_line (struct rtgui_dc* self, int x1, int x2, int y, rt_uint8_t* line_data)
{
	struct rtgui_dc_hw* dc;

	RT_ASSERT(self != RT_NULL);
	dc = (struct rtgui_dc_hw*) self;

	/* convert logic to device */
	x1 = x1 + dc->owner->extent.x1;
	x2 = x2 + dc->owner->extent.x1;
330
	if (x1 > x2) _int_swap(x1, x2);	
B
bernard.xiong 已提交
331 332
	y  = y + dc->owner->extent.y1;

333
	dc->hw_driver->ops->draw_raw_hline(line_data, x1, x2, y);
B
bernard.xiong 已提交
334 335
}

B
bernard.xiong 已提交
336 337 338 339 340 341
static void rtgui_dc_hw_blit(struct rtgui_dc* dc, struct rtgui_point* dc_point, struct rtgui_dc* dest, rtgui_rect_t* rect)
{
	/* not blit in hardware dc */
	return ;
}

342
static void rtgui_dc_hw_set_gc(struct rtgui_dc* self, rtgui_gc_t *gc)
B
bernard.xiong 已提交
343
{
B
bernard.xiong@gmail.com 已提交
344
	struct rtgui_dc_hw* dc;
B
bernard.xiong 已提交
345

B
bernard.xiong@gmail.com 已提交
346 347 348 349 350
	RT_ASSERT(self != RT_NULL);
	dc = (struct rtgui_dc_hw*) self;

	/* set gc */
	dc->owner->gc = *gc;
B
bernard.xiong 已提交
351 352
}

353
static rtgui_gc_t* rtgui_dc_hw_get_gc(struct rtgui_dc* self)
B
bernard.xiong 已提交
354
{
B
bernard.xiong@gmail.com 已提交
355
	struct rtgui_dc_hw* dc;
B
bernard.xiong 已提交
356

B
bernard.xiong@gmail.com 已提交
357 358
	RT_ASSERT(self != RT_NULL);
	dc = (struct rtgui_dc_hw*) self;
359

B
bernard.xiong@gmail.com 已提交
360
	return &(dc->owner->gc);
B
bernard.xiong 已提交
361 362
}

363
static rt_bool_t rtgui_dc_hw_get_visible(struct rtgui_dc* self)
B
bernard.xiong 已提交
364
{
B
bernard.xiong@gmail.com 已提交
365
	struct rtgui_dc_hw* dc;
366

B
bernard.xiong@gmail.com 已提交
367 368 369 370
	RT_ASSERT(self != RT_NULL);
	dc = (struct rtgui_dc_hw*) self;

	if (!RTGUI_WIDGET_IS_DC_VISIBLE(dc->owner)) return RT_FALSE;
371

372
	return RT_TRUE;
B
bernard.xiong 已提交
373 374 375 376
}

static void rtgui_dc_hw_get_rect(struct rtgui_dc* self, rtgui_rect_t* rect)
{
B
bernard.xiong@gmail.com 已提交
377 378 379 380
	struct rtgui_dc_hw* dc;

	RT_ASSERT(self != RT_NULL);
	dc = (struct rtgui_dc_hw*) self;
B
bernard.xiong 已提交
381

382
	/* get owner */
B
bernard.xiong@gmail.com 已提交
383
	rtgui_widget_get_rect(dc->owner, rect);
B
bernard.xiong 已提交
384
}