OLD | NEW |
| (Empty) |
1 /* libs/graphics/views/SkEvent.cpp | |
2 ** | |
3 ** Copyright 2006, The Android Open Source Project | |
4 ** | |
5 ** Licensed under the Apache License, Version 2.0 (the "License"); | |
6 ** you may not use this file except in compliance with the License. | |
7 ** You may obtain a copy of the License at | |
8 ** | |
9 ** http://www.apache.org/licenses/LICENSE-2.0 | |
10 ** | |
11 ** Unless required by applicable law or agreed to in writing, software | |
12 ** distributed under the License is distributed on an "AS IS" BASIS, | |
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 ** See the License for the specific language governing permissions and | |
15 ** limitations under the License. | |
16 */ | |
17 | |
18 #include "SkEvent.h" | |
19 | |
20 void SkEvent::initialize(const char* type, size_t typeLen) { | |
21 fType = NULL; | |
22 setType(type, typeLen); | |
23 f32 = 0; | |
24 #ifdef SK_DEBUG | |
25 fTargetID = 0; | |
26 fTime = 0; | |
27 fNextEvent = NULL; | |
28 #endif | |
29 SkDEBUGCODE(fDebugTrace = false;) | |
30 } | |
31 | |
32 SkEvent::SkEvent() | |
33 { | |
34 initialize("", 0); | |
35 } | |
36 | |
37 SkEvent::SkEvent(const SkEvent& src) | |
38 { | |
39 *this = src; | |
40 if (((size_t) fType & 1) == 0) | |
41 setType(src.fType); | |
42 } | |
43 | |
44 SkEvent::SkEvent(const SkString& type) | |
45 { | |
46 initialize(type.c_str(), type.size()); | |
47 } | |
48 | |
49 SkEvent::SkEvent(const char type[]) | |
50 { | |
51 SkASSERT(type); | |
52 initialize(type, strlen(type)); | |
53 } | |
54 | |
55 SkEvent::~SkEvent() | |
56 { | |
57 if (((size_t) fType & 1) == 0) | |
58 sk_free((void*) fType); | |
59 } | |
60 | |
61 static size_t makeCharArray(char* buffer, size_t compact) | |
62 { | |
63 size_t bits = (size_t) compact >> 1; | |
64 memcpy(buffer, &bits, sizeof(compact)); | |
65 buffer[sizeof(compact)] = 0; | |
66 return strlen(buffer); | |
67 } | |
68 | |
69 #if 0 | |
70 const char* SkEvent::getType() const | |
71 { | |
72 if ((size_t) fType & 1) { // not a pointer | |
73 char chars[sizeof(size_t) + 1]; | |
74 size_t len = makeCharArray(chars, (size_t) fType); | |
75 fType = (char*) sk_malloc_throw(len); | |
76 SkASSERT(((size_t) fType & 1) == 0); | |
77 memcpy(fType, chars, len); | |
78 } | |
79 return fType; | |
80 } | |
81 #endif | |
82 | |
83 void SkEvent::getType(SkString* str) const | |
84 { | |
85 if (str) | |
86 { | |
87 if ((size_t) fType & 1) // not a pointer | |
88 { | |
89 char chars[sizeof(size_t) + 1]; | |
90 size_t len = makeCharArray(chars, (size_t) fType); | |
91 str->set(chars, len); | |
92 } | |
93 else | |
94 str->set(fType); | |
95 } | |
96 } | |
97 | |
98 bool SkEvent::isType(const SkString& str) const | |
99 { | |
100 return this->isType(str.c_str(), str.size()); | |
101 } | |
102 | |
103 bool SkEvent::isType(const char type[], size_t typeLen) const | |
104 { | |
105 if (typeLen == 0) | |
106 typeLen = strlen(type); | |
107 if ((size_t) fType & 1) { // not a pointer | |
108 char chars[sizeof(size_t) + 1]; | |
109 size_t len = makeCharArray(chars, (size_t) fType); | |
110 return len == typeLen && strncmp(chars, type, typeLen) == 0; | |
111 } | |
112 return strncmp(fType, type, typeLen) == 0 && fType[typeLen] == 0; | |
113 } | |
114 | |
115 void SkEvent::setType(const char type[], size_t typeLen) | |
116 { | |
117 if (typeLen == 0) | |
118 typeLen = strlen(type); | |
119 if (typeLen <= sizeof(fType)) { | |
120 size_t slot = 0; | |
121 memcpy(&slot, type, typeLen); | |
122 if (slot << 1 >> 1 != slot) | |
123 goto useCharStar; | |
124 slot <<= 1; | |
125 slot |= 1; | |
126 fType = (char*) slot; | |
127 } else { | |
128 useCharStar: | |
129 fType = (char*) sk_malloc_throw(typeLen + 1); | |
130 SkASSERT(((size_t) fType & 1) == 0); | |
131 memcpy(fType, type, typeLen); | |
132 fType[typeLen] = 0; | |
133 } | |
134 } | |
135 | |
136 void SkEvent::setType(const SkString& type) | |
137 { | |
138 setType(type.c_str()); | |
139 } | |
140 | |
141 //////////////////////////////////////////////////////////////////////////// | |
142 | |
143 #include "SkParse.h" | |
144 | |
145 void SkEvent::inflate(const SkDOM& dom, const SkDOM::Node* node) | |
146 { | |
147 const char* name = dom.findAttr(node, "type"); | |
148 if (name) | |
149 this->setType(name); | |
150 | |
151 const char* value; | |
152 if ((value = dom.findAttr(node, "fast32")) != NULL) | |
153 { | |
154 int32_t n; | |
155 if (SkParse::FindS32(value, &n)) | |
156 this->setFast32(n); | |
157 } | |
158 | |
159 for (node = dom.getFirstChild(node); node; node = dom.getNextSibling(node)) | |
160 { | |
161 if (strcmp(dom.getName(node), "data")) | |
162 { | |
163 SkDEBUGCODE(SkDebugf("SkEvent::inflate unrecognized subelement <%s>\
n", dom.getName(node));) | |
164 continue; | |
165 } | |
166 | |
167 name = dom.findAttr(node, "name"); | |
168 if (name == NULL) | |
169 { | |
170 SkDEBUGCODE(SkDebugf("SkEvent::inflate missing required \"name\" att
ribute in <data> subelement\n");) | |
171 continue; | |
172 } | |
173 | |
174 if ((value = dom.findAttr(node, "s32")) != NULL) | |
175 { | |
176 int32_t n; | |
177 if (SkParse::FindS32(value, &n)) | |
178 this->setS32(name, n); | |
179 } | |
180 else if ((value = dom.findAttr(node, "scalar")) != NULL) | |
181 { | |
182 SkScalar x; | |
183 if (SkParse::FindScalar(value, &x)) | |
184 this->setScalar(name, x); | |
185 } | |
186 else if ((value = dom.findAttr(node, "string")) != NULL) | |
187 this->setString(name, value); | |
188 #ifdef SK_DEBUG | |
189 else | |
190 { | |
191 SkDebugf("SkEvent::inflate <data name=\"%s\"> subelement missing req
uired type attribute [S32 | scalar | string]\n", name); | |
192 } | |
193 #endif | |
194 } | |
195 } | |
196 | |
197 #ifdef SK_DEBUG | |
198 | |
199 #ifndef SkScalarToFloat | |
200 #define SkScalarToFloat(x) ((x) / 65536.f) | |
201 #endif | |
202 | |
203 void SkEvent::dump(const char title[]) | |
204 { | |
205 if (title) | |
206 SkDebugf("%s ", title); | |
207 | |
208 SkString etype; | |
209 this->getType(&etype); | |
210 SkDebugf("event<%s> fast32=%d", etype.c_str(), this->getFast32()); | |
211 | |
212 const SkMetaData& md = this->getMetaData(); | |
213 SkMetaData::Iter iter(md); | |
214 SkMetaData::Type mtype; | |
215 int count; | |
216 const char* name; | |
217 | |
218 while ((name = iter.next(&mtype, &count)) != NULL) | |
219 { | |
220 SkASSERT(count > 0); | |
221 | |
222 SkDebugf(" <%s>=", name); | |
223 switch (mtype) { | |
224 case SkMetaData::kS32_Type: // vector version??? | |
225 { | |
226 int32_t value; | |
227 md.findS32(name, &value); | |
228 SkDebugf("%d ", value); | |
229 } | |
230 break; | |
231 case SkMetaData::kScalar_Type: | |
232 { | |
233 const SkScalar* values = md.findScalars(name, &count, NULL); | |
234 SkDebugf("%f", SkScalarToFloat(values[0])); | |
235 for (int i = 1; i < count; i++) | |
236 SkDebugf(", %f", SkScalarToFloat(values[i])); | |
237 SkDebugf(" "); | |
238 } | |
239 break; | |
240 case SkMetaData::kString_Type: | |
241 { | |
242 const char* value = md.findString(name); | |
243 SkASSERT(value); | |
244 SkDebugf("<%s> ", value); | |
245 } | |
246 break; | |
247 case SkMetaData::kPtr_Type: // vector version??? | |
248 { | |
249 void* value; | |
250 md.findPtr(name, &value); | |
251 SkDebugf("%p ", value); | |
252 } | |
253 break; | |
254 case SkMetaData::kBool_Type: // vector version??? | |
255 { | |
256 bool value; | |
257 md.findBool(name, &value); | |
258 SkDebugf("%s ", value ? "true" : "false"); | |
259 } | |
260 break; | |
261 default: | |
262 SkASSERT(!"unknown metadata type returned from iterator"); | |
263 break; | |
264 } | |
265 } | |
266 SkDebugf("\n"); | |
267 } | |
268 #endif | |
269 | |
270 ////////////////////////////////////////////////////////////////////////////////
/////// | |
271 | |
272 #ifdef SK_DEBUG | |
273 // #define SK_TRACE_EVENTSx | |
274 #endif | |
275 | |
276 #ifdef SK_TRACE_EVENTS | |
277 static void event_log(const char s[]) | |
278 { | |
279 SkDEBUGF(("%s\n", s)); | |
280 } | |
281 | |
282 #define EVENT_LOG(s) event_log(s) | |
283 #define EVENT_LOGN(s, n) do { SkString str(s); str.append(" "); str.appen
dS32(n); event_log(str.c_str()); } while (0) | |
284 #else | |
285 #define EVENT_LOG(s) | |
286 #define EVENT_LOGN(s, n) | |
287 #endif | |
288 | |
289 #include "SkGlobals.h" | |
290 #include "SkThread.h" | |
291 #include "SkTime.h" | |
292 | |
293 #define SK_Event_GlobalsTag SkSetFourByteTag('e', 'v', 'n', 't') | |
294 | |
295 class SkEvent_Globals : public SkGlobals::Rec { | |
296 public: | |
297 SkMutex fEventMutex; | |
298 SkEvent* fEventQHead, *fEventQTail; | |
299 SkEvent* fDelayQHead; | |
300 SkDEBUGCODE(int fEventCounter;) | |
301 }; | |
302 | |
303 static SkGlobals::Rec* create_globals() | |
304 { | |
305 SkEvent_Globals* rec = new SkEvent_Globals; | |
306 rec->fEventQHead = NULL; | |
307 rec->fEventQTail = NULL; | |
308 rec->fDelayQHead = NULL; | |
309 SkDEBUGCODE(rec->fEventCounter = 0;) | |
310 return rec; | |
311 } | |
312 | |
313 bool SkEvent::Post(SkEvent* evt, SkEventSinkID sinkID, SkMSec delay) | |
314 { | |
315 if (delay) | |
316 return SkEvent::PostTime(evt, sinkID, SkTime::GetMSecs() + delay); | |
317 | |
318 SkEvent_Globals& globals = *(SkEvent_Globals*)SkGlobals::Find(SK_Event_Globa
lsTag, create_globals); | |
319 | |
320 evt->fTargetID = sinkID; | |
321 | |
322 #ifdef SK_TRACE_EVENTS | |
323 { | |
324 SkString str("SkEvent::Post("); | |
325 str.append(evt->getType()); | |
326 str.append(", 0x"); | |
327 str.appendHex(sinkID); | |
328 str.append(", "); | |
329 str.appendS32(delay); | |
330 str.append(")"); | |
331 event_log(str.c_str()); | |
332 } | |
333 #endif | |
334 | |
335 globals.fEventMutex.acquire(); | |
336 bool wasEmpty = SkEvent::Enqueue(evt); | |
337 globals.fEventMutex.release(); | |
338 | |
339 // call outside of us holding the mutex | |
340 if (wasEmpty) | |
341 SkEvent::SignalNonEmptyQueue(); | |
342 return true; | |
343 } | |
344 | |
345 #if defined(SK_SIMULATE_FAILED_MALLOC) && defined(SK_FIND_MEMORY_LEAKS) | |
346 SkMSec gMaxDrawTime; | |
347 #endif | |
348 | |
349 bool SkEvent::PostTime(SkEvent* evt, SkEventSinkID sinkID, SkMSec time) | |
350 { | |
351 #if defined(SK_SIMULATE_FAILED_MALLOC) && defined(SK_FIND_MEMORY_LEAKS) | |
352 gMaxDrawTime = time; | |
353 #endif | |
354 SkEvent_Globals& globals = *(SkEvent_Globals*)SkGlobals::Find(SK_Event_Globa
lsTag, create_globals); | |
355 | |
356 evt->fTargetID = sinkID; | |
357 | |
358 #ifdef SK_TRACE_EVENTS | |
359 { | |
360 SkString str("SkEvent::Post("); | |
361 str.append(evt->getType()); | |
362 str.append(", 0x"); | |
363 str.appendHex(sinkID); | |
364 str.append(", "); | |
365 str.appendS32(time); | |
366 str.append(")"); | |
367 event_log(str.c_str()); | |
368 } | |
369 #endif | |
370 | |
371 globals.fEventMutex.acquire(); | |
372 SkMSec queueDelay = SkEvent::EnqueueTime(evt, time); | |
373 globals.fEventMutex.release(); | |
374 | |
375 // call outside of us holding the mutex | |
376 if ((int32_t)queueDelay != ~0) | |
377 SkEvent::SignalQueueTimer(queueDelay); | |
378 return true; | |
379 } | |
380 | |
381 bool SkEvent::Enqueue(SkEvent* evt) | |
382 { | |
383 SkEvent_Globals& globals = *(SkEvent_Globals*)SkGlobals::Find(SK_Event_Globa
lsTag, create_globals); | |
384 // gEventMutex acquired by caller | |
385 | |
386 SkASSERT(evt); | |
387 | |
388 bool wasEmpty = globals.fEventQHead == NULL; | |
389 | |
390 if (globals.fEventQTail) | |
391 globals.fEventQTail->fNextEvent = evt; | |
392 globals.fEventQTail = evt; | |
393 if (globals.fEventQHead == NULL) | |
394 globals.fEventQHead = evt; | |
395 evt->fNextEvent = NULL; | |
396 | |
397 SkDEBUGCODE(++globals.fEventCounter); | |
398 // SkDebugf("Enqueue: count=%d\n", gEventCounter); | |
399 | |
400 return wasEmpty; | |
401 } | |
402 | |
403 SkEvent* SkEvent::Dequeue(SkEventSinkID* sinkID) | |
404 { | |
405 SkEvent_Globals& globals = *(SkEvent_Globals*)SkGlobals::Find(SK_Event_Globa
lsTag, create_globals); | |
406 globals.fEventMutex.acquire(); | |
407 | |
408 SkEvent* evt = globals.fEventQHead; | |
409 if (evt) | |
410 { | |
411 SkDEBUGCODE(--globals.fEventCounter); | |
412 | |
413 if (sinkID) | |
414 *sinkID = evt->fTargetID; | |
415 | |
416 globals.fEventQHead = evt->fNextEvent; | |
417 if (globals.fEventQHead == NULL) | |
418 globals.fEventQTail = NULL; | |
419 } | |
420 globals.fEventMutex.release(); | |
421 | |
422 // SkDebugf("Dequeue: count=%d\n", gEventCounter); | |
423 | |
424 return evt; | |
425 } | |
426 | |
427 bool SkEvent::QHasEvents() | |
428 { | |
429 SkEvent_Globals& globals = *(SkEvent_Globals*)SkGlobals::Find(SK_Event_Globa
lsTag, create_globals); | |
430 | |
431 // this is not thread accurate, need a semaphore for that | |
432 return globals.fEventQHead != NULL; | |
433 } | |
434 | |
435 #ifdef SK_TRACE_EVENTS | |
436 static int gDelayDepth; | |
437 #endif | |
438 | |
439 SkMSec SkEvent::EnqueueTime(SkEvent* evt, SkMSec time) | |
440 { | |
441 #ifdef SK_TRACE_EVENTS | |
442 SkDebugf("enqueue-delay %s %d (%d)", evt->getType(), time, gDelayDepth); | |
443 const char* idStr = evt->findString("id"); | |
444 if (idStr) | |
445 SkDebugf(" (%s)", idStr); | |
446 SkDebugf("\n"); | |
447 ++gDelayDepth; | |
448 #endif | |
449 | |
450 SkEvent_Globals& globals = *(SkEvent_Globals*)SkGlobals::Find(SK_Event_Globa
lsTag, create_globals); | |
451 // gEventMutex acquired by caller | |
452 | |
453 SkEvent* curr = globals.fDelayQHead; | |
454 SkEvent* prev = NULL; | |
455 | |
456 while (curr) | |
457 { | |
458 if (SkMSec_LT(time, curr->fTime)) | |
459 break; | |
460 prev = curr; | |
461 curr = curr->fNextEvent; | |
462 } | |
463 | |
464 evt->fTime = time; | |
465 evt->fNextEvent = curr; | |
466 if (prev == NULL) | |
467 globals.fDelayQHead = evt; | |
468 else | |
469 prev->fNextEvent = evt; | |
470 | |
471 SkMSec delay = globals.fDelayQHead->fTime - SkTime::GetMSecs(); | |
472 if ((int32_t)delay <= 0) | |
473 delay = 1; | |
474 return delay; | |
475 } | |
476 | |
477 ////////////////////////////////////////////////////////////////////////////// | |
478 | |
479 #include "SkEventSink.h" | |
480 | |
481 bool SkEvent::ProcessEvent() | |
482 { | |
483 SkEventSinkID sinkID; | |
484 SkEvent* evt = SkEvent::Dequeue(&sinkID); | |
485 SkAutoTDelete<SkEvent> autoDelete(evt); | |
486 bool again = false; | |
487 | |
488 EVENT_LOGN("ProcessEvent", (int32_t)evt); | |
489 | |
490 if (evt) | |
491 { | |
492 (void)SkEventSink::DoEvent(*evt, sinkID); | |
493 again = SkEvent::QHasEvents(); | |
494 } | |
495 return again; | |
496 } | |
497 | |
498 void SkEvent::ServiceQueueTimer() | |
499 { | |
500 SkEvent_Globals& globals = *(SkEvent_Globals*)SkGlobals::Find(SK_Event_Globa
lsTag, create_globals); | |
501 | |
502 globals.fEventMutex.acquire(); | |
503 | |
504 bool wasEmpty = false; | |
505 SkMSec now = SkTime::GetMSecs(); | |
506 SkEvent* evt = globals.fDelayQHead; | |
507 | |
508 while (evt) | |
509 { | |
510 if (SkMSec_LT(now, evt->fTime)) | |
511 break; | |
512 | |
513 #ifdef SK_TRACE_EVENTS | |
514 --gDelayDepth; | |
515 SkDebugf("dequeue-delay %s (%d)", evt->getType(), gDelayDepth); | |
516 const char* idStr = evt->findString("id"); | |
517 if (idStr) | |
518 SkDebugf(" (%s)", idStr); | |
519 SkDebugf("\n"); | |
520 #endif | |
521 | |
522 SkEvent* next = evt->fNextEvent; | |
523 if (SkEvent::Enqueue(evt)) | |
524 wasEmpty = true; | |
525 evt = next; | |
526 } | |
527 globals.fDelayQHead = evt; | |
528 | |
529 SkMSec time = evt ? evt->fTime - now : 0; | |
530 | |
531 globals.fEventMutex.release(); | |
532 | |
533 if (wasEmpty) | |
534 SkEvent::SignalNonEmptyQueue(); | |
535 | |
536 SkEvent::SignalQueueTimer(time); | |
537 } | |
538 | |
539 //////////////////////////////////////////////////////////////// | |
540 | |
541 void SkEvent::Init() | |
542 { | |
543 } | |
544 | |
545 void SkEvent::Term() | |
546 { | |
547 SkEvent_Globals& globals = *(SkEvent_Globals*)SkGlobals::Find(SK_Event_Globa
lsTag, create_globals); | |
548 | |
549 SkEvent* evt = globals.fEventQHead; | |
550 while (evt) | |
551 { | |
552 SkEvent* next = evt->fNextEvent; | |
553 delete evt; | |
554 evt = next; | |
555 } | |
556 | |
557 evt = globals.fDelayQHead; | |
558 while (evt) | |
559 { | |
560 SkEvent* next = evt->fNextEvent; | |
561 delete evt; | |
562 evt = next; | |
563 } | |
564 } | |
565 | |
OLD | NEW |