diff -r 000000000000 -r 6474c204b198 gfx/skia/trunk/src/views/SkEvent.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gfx/skia/trunk/src/views/SkEvent.cpp Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,508 @@ + +/* + * Copyright 2006 The Android Open Source Project + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + + +#include "SkEvent.h" + +void SkEvent::initialize(const char* type, size_t typeLen, + SkEventSinkID targetID) { + fType = NULL; + setType(type, typeLen); + f32 = 0; + fTargetID = targetID; + fTargetProc = NULL; +#ifdef SK_DEBUG + fTime = 0; + fNextEvent = NULL; +#endif +} + +SkEvent::SkEvent() +{ + initialize("", 0, 0); +} + +SkEvent::SkEvent(const SkEvent& src) +{ + *this = src; + if (((size_t) fType & 1) == 0) + setType(src.fType); +} + +SkEvent::SkEvent(const SkString& type, SkEventSinkID targetID) +{ + initialize(type.c_str(), type.size(), targetID); +} + +SkEvent::SkEvent(const char type[], SkEventSinkID targetID) +{ + SkASSERT(type); + initialize(type, strlen(type), targetID); +} + +SkEvent::~SkEvent() +{ + if (((size_t) fType & 1) == 0) + sk_free((void*) fType); +} + +static size_t makeCharArray(char* buffer, size_t compact) +{ + size_t bits = (size_t) compact >> 1; + memcpy(buffer, &bits, sizeof(compact)); + buffer[sizeof(compact)] = 0; + return strlen(buffer); +} + +void SkEvent::getType(SkString* str) const +{ + if (str) + { + if ((size_t) fType & 1) // not a pointer + { + char chars[sizeof(size_t) + 1]; + size_t len = makeCharArray(chars, (size_t) fType); + str->set(chars, len); + } + else + str->set(fType); + } +} + +bool SkEvent::isType(const SkString& str) const +{ + return this->isType(str.c_str(), str.size()); +} + +bool SkEvent::isType(const char type[], size_t typeLen) const +{ + if (typeLen == 0) + typeLen = strlen(type); + if ((size_t) fType & 1) { // not a pointer + char chars[sizeof(size_t) + 1]; + size_t len = makeCharArray(chars, (size_t) fType); + return len == typeLen && strncmp(chars, type, typeLen) == 0; + } + return strncmp(fType, type, typeLen) == 0 && fType[typeLen] == 0; +} + +void SkEvent::setType(const char type[], size_t typeLen) +{ + if (typeLen == 0) + typeLen = strlen(type); + if (typeLen <= sizeof(fType)) { + size_t slot = 0; + memcpy(&slot, type, typeLen); + if (slot << 1 >> 1 != slot) + goto useCharStar; + slot <<= 1; + slot |= 1; + fType = (char*) slot; + } else { +useCharStar: + fType = (char*) sk_malloc_throw(typeLen + 1); + SkASSERT(((size_t) fType & 1) == 0); + memcpy(fType, type, typeLen); + fType[typeLen] = 0; + } +} + +void SkEvent::setType(const SkString& type) +{ + setType(type.c_str()); +} + +//////////////////////////////////////////////////////////////////////////// + +#include "SkParse.h" + +void SkEvent::inflate(const SkDOM& dom, const SkDOM::Node* node) +{ + const char* name = dom.findAttr(node, "type"); + if (name) + this->setType(name); + + const char* value; + if ((value = dom.findAttr(node, "fast32")) != NULL) + { + int32_t n; + if (SkParse::FindS32(value, &n)) + this->setFast32(n); + } + + for (node = dom.getFirstChild(node); node; node = dom.getNextSibling(node)) + { + if (strcmp(dom.getName(node), "data")) + { + SkDEBUGCODE(SkDebugf("SkEvent::inflate unrecognized subelement <%s>\n", dom.getName(node));) + continue; + } + + name = dom.findAttr(node, "name"); + if (name == NULL) + { + SkDEBUGCODE(SkDebugf("SkEvent::inflate missing required \"name\" attribute in subelement\n");) + continue; + } + + if ((value = dom.findAttr(node, "s32")) != NULL) + { + int32_t n; + if (SkParse::FindS32(value, &n)) + this->setS32(name, n); + } + else if ((value = dom.findAttr(node, "scalar")) != NULL) + { + SkScalar x; + if (SkParse::FindScalar(value, &x)) + this->setScalar(name, x); + } + else if ((value = dom.findAttr(node, "string")) != NULL) + this->setString(name, value); +#ifdef SK_DEBUG + else + { + SkDebugf("SkEvent::inflate subelement missing required type attribute [S32 | scalar | string]\n", name); + } +#endif + } +} + +#ifdef SK_DEBUG + + #ifndef SkScalarToFloat + #define SkScalarToFloat(x) ((x) / 65536.f) + #endif + + void SkEvent::dump(const char title[]) + { + if (title) + SkDebugf("%s ", title); + + SkString etype; + this->getType(&etype); + SkDebugf("event<%s> fast32=%d", etype.c_str(), this->getFast32()); + + const SkMetaData& md = this->getMetaData(); + SkMetaData::Iter iter(md); + SkMetaData::Type mtype; + int count; + const char* name; + + while ((name = iter.next(&mtype, &count)) != NULL) + { + SkASSERT(count > 0); + + SkDebugf(" <%s>=", name); + switch (mtype) { + case SkMetaData::kS32_Type: // vector version??? + { + int32_t value; + md.findS32(name, &value); + SkDebugf("%d ", value); + } + break; + case SkMetaData::kScalar_Type: + { + const SkScalar* values = md.findScalars(name, &count, NULL); + SkDebugf("%f", SkScalarToFloat(values[0])); + for (int i = 1; i < count; i++) + SkDebugf(", %f", SkScalarToFloat(values[i])); + SkDebugf(" "); + } + break; + case SkMetaData::kString_Type: + { + const char* value = md.findString(name); + SkASSERT(value); + SkDebugf("<%s> ", value); + } + break; + case SkMetaData::kPtr_Type: // vector version??? + { + void* value; + md.findPtr(name, &value); + SkDebugf("%p ", value); + } + break; + case SkMetaData::kBool_Type: // vector version??? + { + bool value; + md.findBool(name, &value); + SkDebugf("%s ", value ? "true" : "false"); + } + break; + default: + SkDEBUGFAIL("unknown metadata type returned from iterator"); + break; + } + } + SkDebugf("\n"); + } +#endif + +/////////////////////////////////////////////////////////////////////////////////////// + +#ifdef SK_DEBUG +// #define SK_TRACE_EVENTSx +#endif + +#ifdef SK_TRACE_EVENTS + static void event_log(const char s[]) + { + SkDEBUGF(("%s\n", s)); + } + + #define EVENT_LOG(s) event_log(s) + #define EVENT_LOGN(s, n) do { SkString str(s); str.append(" "); str.appendS32(n); event_log(str.c_str()); } while (0) +#else + #define EVENT_LOG(s) + #define EVENT_LOGN(s, n) +#endif + +#include "SkThread.h" +#include "SkTime.h" + +class SkEvent_Globals { +public: + SkEvent_Globals() { + fEventQHead = NULL; + fEventQTail = NULL; + fDelayQHead = NULL; + SkDEBUGCODE(fEventCounter = 0;) + } + + SkMutex fEventMutex; + SkEvent* fEventQHead, *fEventQTail; + SkEvent* fDelayQHead; + SkDEBUGCODE(int fEventCounter;) +}; + +static SkEvent_Globals& getGlobals() { + // leak this, so we don't incure any shutdown perf hit + static SkEvent_Globals* gGlobals = new SkEvent_Globals; + return *gGlobals; +} + +/////////////////////////////////////////////////////////////////////////////// + +void SkEvent::postDelay(SkMSec delay) { + if (!fTargetID && !fTargetProc) { + delete this; + return; + } + + if (delay) { + this->postTime(SkTime::GetMSecs() + delay); + return; + } + + SkEvent_Globals& globals = getGlobals(); + + globals.fEventMutex.acquire(); + bool wasEmpty = SkEvent::Enqueue(this); + globals.fEventMutex.release(); + + // call outside of us holding the mutex + if (wasEmpty) { + SkEvent::SignalNonEmptyQueue(); + } +} + +void SkEvent::postTime(SkMSec time) { + if (!fTargetID && !fTargetProc) { + delete this; + return; + } + + SkEvent_Globals& globals = getGlobals(); + + globals.fEventMutex.acquire(); + SkMSec queueDelay = SkEvent::EnqueueTime(this, time); + globals.fEventMutex.release(); + + // call outside of us holding the mutex + if ((int32_t)queueDelay != ~0) { + SkEvent::SignalQueueTimer(queueDelay); + } +} + +bool SkEvent::Enqueue(SkEvent* evt) { + SkEvent_Globals& globals = getGlobals(); + // gEventMutex acquired by caller + + SkASSERT(evt); + + bool wasEmpty = globals.fEventQHead == NULL; + + if (globals.fEventQTail) + globals.fEventQTail->fNextEvent = evt; + globals.fEventQTail = evt; + if (globals.fEventQHead == NULL) + globals.fEventQHead = evt; + evt->fNextEvent = NULL; + + SkDEBUGCODE(++globals.fEventCounter); + + return wasEmpty; +} + +SkEvent* SkEvent::Dequeue() { + SkEvent_Globals& globals = getGlobals(); + globals.fEventMutex.acquire(); + + SkEvent* evt = globals.fEventQHead; + if (evt) { + SkDEBUGCODE(--globals.fEventCounter); + + globals.fEventQHead = evt->fNextEvent; + if (globals.fEventQHead == NULL) { + globals.fEventQTail = NULL; + } + } + globals.fEventMutex.release(); + + return evt; +} + +bool SkEvent::QHasEvents() { + SkEvent_Globals& globals = getGlobals(); + + // this is not thread accurate, need a semaphore for that + return globals.fEventQHead != NULL; +} + +#ifdef SK_TRACE_EVENTS + static int gDelayDepth; +#endif + +SkMSec SkEvent::EnqueueTime(SkEvent* evt, SkMSec time) { + SkEvent_Globals& globals = getGlobals(); + // gEventMutex acquired by caller + + SkEvent* curr = globals.fDelayQHead; + SkEvent* prev = NULL; + + while (curr) { + if (SkMSec_LT(time, curr->fTime)) { + break; + } + prev = curr; + curr = curr->fNextEvent; + } + + evt->fTime = time; + evt->fNextEvent = curr; + if (prev == NULL) { + globals.fDelayQHead = evt; + } else { + prev->fNextEvent = evt; + } + + SkMSec delay = globals.fDelayQHead->fTime - SkTime::GetMSecs(); + if ((int32_t)delay <= 0) { + delay = 1; + } + return delay; +} + +/////////////////////////////////////////////////////////////////////////////// + +#include "SkEventSink.h" + +bool SkEvent::ProcessEvent() { + SkEvent* evt = SkEvent::Dequeue(); + SkAutoTDelete autoDelete(evt); + bool again = false; + + EVENT_LOGN("ProcessEvent", (int32_t)evt); + + if (evt) { + (void)SkEventSink::DoEvent(*evt); + again = SkEvent::QHasEvents(); + } + return again; +} + +void SkEvent::ServiceQueueTimer() +{ + SkEvent_Globals& globals = getGlobals(); + + globals.fEventMutex.acquire(); + + bool wasEmpty = false; + SkMSec now = SkTime::GetMSecs(); + SkEvent* evt = globals.fDelayQHead; + + while (evt) + { + if (SkMSec_LT(now, evt->fTime)) + break; + +#ifdef SK_TRACE_EVENTS + --gDelayDepth; + SkDebugf("dequeue-delay %s (%d)", evt->getType(), gDelayDepth); + const char* idStr = evt->findString("id"); + if (idStr) + SkDebugf(" (%s)", idStr); + SkDebugf("\n"); +#endif + + SkEvent* next = evt->fNextEvent; + if (SkEvent::Enqueue(evt)) + wasEmpty = true; + evt = next; + } + globals.fDelayQHead = evt; + + SkMSec time = evt ? evt->fTime - now : 0; + + globals.fEventMutex.release(); + + if (wasEmpty) + SkEvent::SignalNonEmptyQueue(); + + SkEvent::SignalQueueTimer(time); +} + +int SkEvent::CountEventsOnQueue() { + SkEvent_Globals& globals = getGlobals(); + globals.fEventMutex.acquire(); + + int count = 0; + const SkEvent* evt = globals.fEventQHead; + while (evt) { + count += 1; + evt = evt->fNextEvent; + } + globals.fEventMutex.release(); + + return count; +} + +/////////////////////////////////////////////////////////////////////////////// + +void SkEvent::Init() {} + +void SkEvent::Term() { + SkEvent_Globals& globals = getGlobals(); + + SkEvent* evt = globals.fEventQHead; + while (evt) { + SkEvent* next = evt->fNextEvent; + delete evt; + evt = next; + } + + evt = globals.fDelayQHead; + while (evt) { + SkEvent* next = evt->fNextEvent; + delete evt; + evt = next; + } +}