dc_hw.c 9.3 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
	x = x + dc->owner->extent.x1;
I
iamyhw@gmail.com 已提交
230
	if(x < dc->owner->extent.x1 || x >= dc->owner->extent.x2) return;
B
bernard.xiong@gmail.com 已提交
231
	y = y + dc->owner->extent.y1;
I
iamyhw@gmail.com 已提交
232
	if(y < dc->owner->extent.y1 || y >= dc->owner->extent.y2) return;
233

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

B
bernard.xiong 已提交
311 312 313 314 315 316 317 318 319 320 321 322
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;

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

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

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

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

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

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

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

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

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

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

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

362
	return RT_TRUE;
B
bernard.xiong 已提交
363 364 365 366
}

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

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

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