dc_hw.c 9.2 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>
B
bernard.xiong 已提交
18 19 20 21 22 23
#include <rtgui/widgets/view.h>
#include <rtgui/widgets/window.h>
#include <rtgui/widgets/workbench.h>
#include <rtgui/widgets/title.h>

static void rtgui_dc_hw_draw_point(struct rtgui_dc* dc, int x, int y);
24
static void rtgui_dc_hw_draw_color_point(struct rtgui_dc* dc, int x, int y, rtgui_color_t color);
B
bernard.xiong 已提交
25 26 27
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 已提交
28
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 已提交
29
static void rtgui_dc_hw_blit	  (struct rtgui_dc* dc, struct rtgui_point* dc_point, struct rtgui_dc* dest, rtgui_rect_t* rect);
30 31
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 已提交
32 33 34 35
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 已提交
36 37 38 39 40 41
struct rtgui_dc_hw
{
	struct rtgui_dc parent;
	rtgui_widget_t *owner;
	const struct rtgui_graphic_driver* hw_driver;
};
42 43

const struct rtgui_dc_engine dc_hw_engine = 
B
bernard.xiong 已提交
44
{
45 46 47 48 49
	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 已提交
50
	rtgui_dc_hw_blit_line,
51
	rtgui_dc_hw_blit,
B
bernard.xiong 已提交
52

53 54
	rtgui_dc_hw_set_gc,
	rtgui_dc_hw_get_gc,
B
bernard.xiong 已提交
55

56 57
	rtgui_dc_hw_get_visible,
	rtgui_dc_hw_get_rect,
B
bernard.xiong 已提交
58

59 60
	rtgui_dc_hw_fini,
};
B
bernard.xiong 已提交
61 62 63 64 65 66

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 已提交
67
	struct rtgui_dc_hw* dc;
B
bernard.xiong 已提交
68 69 70 71 72 73
	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;

74 75
	/* set init visible as true */
	RTGUI_WIDGET_DC_SET_VISIBLE(owner);
B
bernard.xiong 已提交
76

77
	/* check widget visible */
B
bernard.xiong 已提交
78 79 80 81 82
	widget = owner;
	while (widget != RT_NULL)
	{
		if (RTGUI_WIDGET_IS_HIDE(widget))
		{
83
			RTGUI_WIDGET_DC_SET_UNVISIBLE(owner);
B
bernard.xiong 已提交
84 85 86 87 88 89
			break;
		}

		widget = widget->parent;
	}

B
bernard.xiong@gmail.com 已提交
90 91 92 93 94 95 96 97 98
	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();

99
	if (RTGUI_IS_WINTITLE(owner->toplevel))
B
bernard.xiong 已提交
100
	{
101
		rtgui_toplevel_t* top = RTGUI_TOPLEVEL(owner->toplevel);
B
bernard.xiong 已提交
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
		top->drawing ++;

		if (top->drawing == 1)
		{
#ifdef RTGUI_USING_MOUSE_CURSOR
#ifdef __WIN32__
			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
		}
	}
118 119
	else if (RTGUI_IS_WORKBENCH(owner->toplevel) ||
		RTGUI_IS_WIN(owner->toplevel))
B
bernard.xiong 已提交
120
	{
121
		rtgui_toplevel_t* top = RTGUI_TOPLEVEL(owner->toplevel);
B
bernard.xiong 已提交
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
		top->drawing ++;

		if (top->drawing == 1)
		{
#ifdef __WIN32__
#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;

			rtgui_thread_send(top->server, (struct rtgui_event*)&eupdate, sizeof(eupdate));
#endif
		}
	}

B
bernard.xiong@gmail.com 已提交
143
	return &(dc->parent);
B
bernard.xiong 已提交
144 145 146 147
}

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

151 152
	if (dc == RT_NULL || dc->type != RTGUI_DC_HW) return RT_FALSE;

B
bernard.xiong@gmail.com 已提交
153
	self = (struct rtgui_dc_hw*)dc;
154
	/* get owner */
B
bernard.xiong@gmail.com 已提交
155
	owner = self->owner;
B
bernard.xiong 已提交
156

157
	if (RTGUI_IS_WINTITLE(owner->toplevel))
B
bernard.xiong 已提交
158 159
	{
		/* update title extent */
160
		rtgui_toplevel_t* top = RTGUI_TOPLEVEL(owner->toplevel);
B
bernard.xiong 已提交
161 162

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

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

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

			rtgui_thread_send(top->server, (struct rtgui_event*)&eupdate, sizeof(eupdate));
#endif
		}
	}

B
bernard.xiong@gmail.com 已提交
213 214 215
	/* release hardware dc */
	rtgui_free(self);

B
bernard.xiong 已提交
216 217 218 219 220 221 222 223
	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 已提交
224
	struct rtgui_dc_hw* dc;
B
bernard.xiong 已提交
225

B
bernard.xiong@gmail.com 已提交
226 227
	RT_ASSERT(self != RT_NULL);
	dc = (struct rtgui_dc_hw*) self;
B
bernard.xiong 已提交
228

B
bernard.xiong@gmail.com 已提交
229 230
	x = x + dc->owner->extent.x1;
	y = y + dc->owner->extent.y1;
231

232
	/* draw this point */
233
	dc->hw_driver->ops->set_pixel(&(dc->owner->gc.foreground), x, y);
B
bernard.xiong 已提交
234 235
}

236 237
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 已提交
238
	struct rtgui_dc_hw* dc;
239

B
bernard.xiong@gmail.com 已提交
240 241
	RT_ASSERT(self != RT_NULL);
	dc = (struct rtgui_dc_hw*) self;
242

B
bernard.xiong@gmail.com 已提交
243 244
	x = x + dc->owner->extent.x1;
	y = y + dc->owner->extent.y1;
245

246
	/* draw this point */
247
	dc->hw_driver->ops->set_pixel(&color, x, y);
248 249
}

B
bernard.xiong 已提交
250 251 252 253 254
/*
 * 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 已提交
255
	struct rtgui_dc_hw* dc;
B
bernard.xiong 已提交
256

B
bernard.xiong@gmail.com 已提交
257 258
	RT_ASSERT(self != RT_NULL);
	dc = (struct rtgui_dc_hw*) self;
B
bernard.xiong 已提交
259

B
bernard.xiong@gmail.com 已提交
260 261 262
	x = x + dc->owner->extent.x1;
	y1 = y1 + dc->owner->extent.y1;
	y2 = y2 + dc->owner->extent.y1;
B
bernard.xiong 已提交
263

264
	/* draw vline */
265
	dc->hw_driver->ops->draw_vline(&(dc->owner->gc.foreground), x, y1, y2);
B
bernard.xiong 已提交
266 267 268 269 270 271 272
}

/*
 * 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 已提交
273
	struct rtgui_dc_hw* dc;
B
bernard.xiong 已提交
274

B
bernard.xiong@gmail.com 已提交
275 276
	RT_ASSERT(self != RT_NULL);
	dc = (struct rtgui_dc_hw*) self;
B
bernard.xiong 已提交
277 278

	/* convert logic to device */
B
bernard.xiong@gmail.com 已提交
279 280 281
	x1 = x1 + dc->owner->extent.x1;
	x2 = x2 + dc->owner->extent.x1;
	y  = y + dc->owner->extent.y1;
B
bernard.xiong 已提交
282

283
	/* draw hline */
284
	dc->hw_driver->ops->draw_hline(&(dc->owner->gc.foreground), x1, x2, y);
B
bernard.xiong 已提交
285 286 287 288
}

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

B
bernard.xiong@gmail.com 已提交
293 294
	RT_ASSERT(self != RT_NULL);
	dc = (struct rtgui_dc_hw*) self;
B
bernard.xiong 已提交
295

296
	/* get background color */
B
bernard.xiong@gmail.com 已提交
297
	color = dc->owner->gc.background;
298
	/* convert logic to device */
B
bernard.xiong@gmail.com 已提交
299 300
	x1 = rect->x1 + dc->owner->extent.x1;
	x2 = rect->x2 + dc->owner->extent.x1;
B
bernard.xiong 已提交
301 302

	/* fill rect */
B
bernard.xiong@gmail.com 已提交
303
	for (index = dc->owner->extent.y1 + rect->y1; index < dc->owner->extent.y1 + rect->y2; index ++)
B
bernard.xiong 已提交
304
	{
305
		dc->hw_driver->ops->draw_hline(&color, x1, x2, index);
B
bernard.xiong 已提交
306 307 308
	}
}

B
bernard.xiong 已提交
309 310 311 312 313 314 315 316 317 318 319 320
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;
	y  = y + dc->owner->extent.y1;

321
	dc->hw_driver->ops->draw_raw_hline(line_data, x1, x2, y);
B
bernard.xiong 已提交
322 323
}

B
bernard.xiong 已提交
324 325 326 327 328 329
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 ;
}

330
static void rtgui_dc_hw_set_gc(struct rtgui_dc* self, rtgui_gc_t *gc)
B
bernard.xiong 已提交
331
{
B
bernard.xiong@gmail.com 已提交
332
	struct rtgui_dc_hw* dc;
B
bernard.xiong 已提交
333

B
bernard.xiong@gmail.com 已提交
334 335 336 337 338
	RT_ASSERT(self != RT_NULL);
	dc = (struct rtgui_dc_hw*) self;

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

341
static rtgui_gc_t* rtgui_dc_hw_get_gc(struct rtgui_dc* self)
B
bernard.xiong 已提交
342
{
B
bernard.xiong@gmail.com 已提交
343
	struct rtgui_dc_hw* dc;
B
bernard.xiong 已提交
344

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

B
bernard.xiong@gmail.com 已提交
348
	return &(dc->owner->gc);
B
bernard.xiong 已提交
349 350
}

351
static rt_bool_t rtgui_dc_hw_get_visible(struct rtgui_dc* self)
B
bernard.xiong 已提交
352
{
B
bernard.xiong@gmail.com 已提交
353
	struct rtgui_dc_hw* dc;
354

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

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

360
	return RT_TRUE;
B
bernard.xiong 已提交
361 362 363 364
}

static void rtgui_dc_hw_get_rect(struct rtgui_dc* self, rtgui_rect_t* rect)
{
B
bernard.xiong@gmail.com 已提交
365 366 367 368
	struct rtgui_dc_hw* dc;

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

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