Beispiel #1
0
static void pollScaling()
{
    // Check the event queue.
    if (gEventQueueMutex == NULL)
    {
        return;
    }

    loom_mutex_lock(gEventQueueMutex);

    while (gEventQueue.size() > 0)
    {
        RescaleEventStatus curItem = gEventQueue.front();

        gImageScaleProgressDelegate.pushArgument(curItem.path.c_str());
        gImageScaleProgressDelegate.pushArgument(curItem.progress);
        gImageScaleProgressDelegate.invoke();

        // Flush the asset (only works on main thread atm)
        if (curItem.progress == 1.0f)
        {
            loom_asset_flush(curItem.path.c_str());
        }

        gEventQueue.pop_front();
    }

    loom_mutex_unlock(gEventQueueMutex);
}
Beispiel #2
0
    // removes all breakpoints
    static void removeAllBreakpoints()
    {
        for (UTsize i = 0; i < breakpoints.size(); i++)
        {
            delete breakpoints.at(i);
        }

        breakpoints.clear();

        regenerateSourceBreakpoints();
    }
Beispiel #3
0
    // removes the breakpoint at the given index
    static void removeBreakpointAtIndex(int index)
    {
        if ((index < 0) || (index >= (int)breakpoints.size()))
        {
            return;
        }

        Breakpoint *bp = breakpoints.at(index);
        breakpoints.erase(bp);
        delete bp;

        regenerateSourceBreakpoints();
    }
Beispiel #4
0
    // removes a breakpoint at the given source and line
    static void removeBreakpoint(const char *source, int line)
    {
        for (UTsize i = 0; i < breakpoints.size(); i++)
        {
            Breakpoint *bp = breakpoints.at(i);
            if ((bp->source == source) && (bp->line == line))
            {
                breakpoints.erase(bp);
                delete bp;
            }
        }

        regenerateSourceBreakpoints();
    }
Beispiel #5
0
    // retrieves a Vector of system.Breakpoints corresponding
    // to the current breakpoints
    static int getBreakpoints(lua_State *L)
    {
        Type *vectorType = LSLuaState::getLuaState(L)->getType("system.Vector");
        Type *bpType     = LSLuaState::getLuaState(L)->getType("system.Breakpoint");

        int sourceOrdinal = bpType->getMemberOrdinal("source");
        int lineOrdinal   = bpType->getMemberOrdinal("line");

        // create the vector instance
        lsr_createinstance(L, vectorType);

        // store the length
        lsr_vector_set_length(L, -1, breakpoints.size());

        lua_rawgeti(L, -1, LSINDEXVECTOR);

        int vidx = lua_gettop(L);

        // loop through the current breakpoints and setup
        // data
        for (UTsize i = 0; i < breakpoints.size(); i++)
        {
            Breakpoint *bp = breakpoints.at(i);

            lsr_createinstance(L, bpType);

            int bpIdx = lua_gettop(L);

            lua_pushnumber(L, sourceOrdinal);
            lua_pushstring(L, bp->source.c_str());
            lua_rawset(L, bpIdx);

            lua_pushnumber(L, lineOrdinal);
            lua_pushnumber(L, bp->line);
            lua_rawset(L, bpIdx);

            lua_rawseti(L, vidx, i);
        }

        lua_pop(L, 1); // pop vector table

        // return Vector
        return 1;
    }
Beispiel #6
0
    static void regenerateSourceBreakpoints()
    {
        sourceBreakpoints.clear();

        for (UTsize i = 0; i < breakpoints.size(); i++)
        {
            Breakpoint *bp = breakpoints.at(i);

            utFastStringHash fhash(bp->source);

            if (sourceBreakpoints.find(fhash) == UT_NPOS)
            {
                utArray<Breakpoint *> bps;
                sourceBreakpoints.insert(fhash, bps);
            }

            sourceBreakpoints.get(fhash)->push_back(bp);
        }
    }
Beispiel #7
0
static CallbackQueueNote *dequeueCallback()
{
    CallbackQueueNote *cqn = NULL;

    loom_mutex_lock(gCallbackLock);

    if (gCallbackQueue.begin() == NULL)
    {
        cqn = NULL;
    }
    else
    {
        cqn = gCallbackQueue.front();
        gCallbackQueue.pop_front();
    }

    loom_mutex_unlock(gCallbackLock);

    return cqn;
}
Beispiel #8
0
static void enqueueFileChangeCallback(const char *path)
{
    CallbackQueueNote *cqn = lmNew(NULL) CallbackQueueNote();

    cqn->type = QNT_Change;
    cqn->text = utString(path);

    loom_mutex_lock(gCallbackLock);
    gCallbackQueue.push_back(cqn);
    loom_mutex_unlock(gCallbackLock);
}
Beispiel #9
0
static void enqueueLogCallback(const char *msg)
{
    CallbackQueueNote *cqn = lmNew(NULL) CallbackQueueNote();

    cqn->type = QNT_Log;
    cqn->text = utString(msg);

    loom_mutex_lock(gCallbackLock);
    gCallbackQueue.push_back(cqn);
    loom_mutex_unlock(gCallbackLock);
}
Beispiel #10
0
    // add's a breakpoint at the given source and line, checks for duplicates
    // and avoids them
    static void addBreakpoint(const char *source, int line)
    {
        Breakpoint *bp;

        for (UTsize i = 0; i < breakpoints.size(); i++)
        {
            bp = breakpoints.at(i);
            if ((bp->source == source) && (bp->line == line))
            {
                return;
            }
        }

        bp         = new Breakpoint;
        bp->source = source;
        bp->line   = line;

        breakpoints.push_back(bp);

        regenerateSourceBreakpoints();
    }
Beispiel #11
0
static void postResampleEvent(const char *path, float progress)
{
    if (gEventQueueMutex == NULL)
    {
        gEventQueueMutex = loom_mutex_create();
    }

    loom_mutex_lock(gEventQueueMutex);

    RescaleEventStatus res;
    res.path     = path;
    res.progress = progress;
    gEventQueue.push_back(res);

    loom_mutex_unlock(gEventQueueMutex);
}
Beispiel #12
0
void Assembly::getLoadedAssemblies(LSLuaState *vm, utList<Assembly *>& oassemblies)
{
    utHashTable<utHashedString, Assembly *> *lookup = NULL;

    UTsize idx = assemblies.find(vm);

    if (idx != UT_NPOS)
    {
        lookup = assemblies.at(idx);
    }
    else
    {
        return;
    }

    for (UTsize i = 0; i < lookup->size(); i++)
    {
        oassemblies.push_back(lookup->at(i));
    }
}
Beispiel #13
0
    // Main lua VM debug hook
    static void debugHook(lua_State *L, lua_Debug *ar)
    {
        int top = lua_gettop(L);

        // line event
        if ((ar->event == LUA_HOOKLINE) && lineEventDelegate.getCount() && !assertion)
        {
            // If we're finishing an method we are not interested
            // in line events until we have returned from the method
            if (finishMethod)
            {
                return;
            }

            // if we're not stepping, have no breakpoints, and haven't hit a Debug.debug()
            // we are not interested in the line event
            if (!stepping && !breakpoints.size() && !debugBreak)
            {
                return;
            }

            // get the call stack at this line
            getCallStack(L, LINE_EVENT);

            // if we don't have a valid stack, return
            if (lua_isnil(L, -1))
            {
                lua_pop(L, 1);
                return;
            }

            // call the native delegate
            lineEventDelegate.incArgCount();
            lineEventDelegate.invoke();
        }

        // return hook
        if ((ar->event == LUA_HOOKRET) && returnEventDelegate.getCount() && !assertion)
        {
            // if we don't have a method we're finishing, we
            // don't care
            if (!finishMethod)
            {
                return;
            }

            // get the call stack
            getCallStack(L, RETURN_EVENT);

            // invalid stack?  No problem, bail
            if (lua_isnil(L, -1))
            {
                lua_pop(L, 1);
                return;
            }

            // call the debugger's native delegate
            returnEventDelegate.incArgCount();
            returnEventDelegate.invoke();
        }

        // call hook
        if ((ar->event == LUA_HOOKCALL) && callEventDelegate.getCount() && !assertion)
        {
            // we on;y care about call events when stepping over
            if (!blocking || !stepping || !stepOver)
            {
                return;
            }

            // get the call stack for this event
            getCallStack(L, CALL_EVENT);

            // invalid? If so, bail
            if (lua_isnil(L, -1))
            {
                lua_pop(L, 1);
                return;
            }

            // call the debugger's event delegate
            callEventDelegate.incArgCount();
            callEventDelegate.invoke();
        }


        lua_settop(L, top);
    }
Beispiel #14
0
namespace GFX
{
/**
 * This is the implementation of the background-threaded image rescaling API.
 * Someday it should live elsewhere than in this file. For the meanwhile, it
 * is a cozy home!
 */
struct RescaleEventStatus
{
    utString path;
    float    progress;
};

struct RescaleNote
{
    utString outPath;
    utString inPath;
    int      outWidth;
    int      outHeight;
    bool     preserveAspect;
};

static MutexHandle                gEventQueueMutex = NULL;
static utList<RescaleEventStatus> gEventQueue;
static LS::NativeDelegate         gImageScaleProgressDelegate;

static void pollScaling()
{
    // Check the event queue.
    if (gEventQueueMutex == NULL)
    {
        return;
    }

    loom_mutex_lock(gEventQueueMutex);

    while (gEventQueue.size() > 0)
    {
        RescaleEventStatus curItem = gEventQueue.front();

        gImageScaleProgressDelegate.pushArgument(curItem.path.c_str());
        gImageScaleProgressDelegate.pushArgument(curItem.progress);
        gImageScaleProgressDelegate.invoke();

        // Flush the asset (only works on main thread atm)
        if (curItem.progress == 1.0f)
        {
            loom_asset_flush(curItem.path.c_str());
        }

        gEventQueue.pop_front();
    }

    loom_mutex_unlock(gEventQueueMutex);
}


static void postResampleEvent(const char *path, float progress)
{
    if (gEventQueueMutex == NULL)
    {
        gEventQueueMutex = loom_mutex_create();
    }

    loom_mutex_lock(gEventQueueMutex);

    RescaleEventStatus res;
    res.path     = path;
    res.progress = progress;
    gEventQueue.push_back(res);

    loom_mutex_unlock(gEventQueueMutex);
}


static int __stdcall scaleImageOnDisk_body(void *param)
{
    // Grab our arguments.
    RescaleNote *rn            = (RescaleNote *)param;
    const char  *outPath       = rn->outPath.c_str();
    const char  *inPath        = rn->inPath.c_str();
    int         outWidth       = rn->outWidth;
    int         outHeight      = rn->outHeight;
    bool        preserveAspect = rn->preserveAspect;

    // Load the image. We always work in 4 components (rgba).
    int t0 = platform_getMilliseconds();

    loom_asset_image *lai = NULL;

    // Load async since we're in a background thread.
    while ((lai = (loom_asset_image *)loom_asset_lock(inPath, LATImage, 0)) == NULL)
    {
        loom_thread_yield();
    }

    int     imageX     = lai->width;
    int     imageY     = lai->height;
    stbi_uc *imageBits = (stbi_uc *)lai->bits;

    lmLog(gGFXTextureLogGroup, "Image setup took %dms", t0 - platform_getMilliseconds());

    int t1 = platform_getMilliseconds();

    // Resize to fit within the specified size preserving aspect ratio, if flag is set.
    if (preserveAspect)
    {
        float scaleX = float(outWidth) / float(imageX);
        float scaleY = float(outHeight) / float(imageY);

        float actualScale = (scaleX < scaleY) ? scaleX : scaleY;

        outWidth  = (int)(imageX * actualScale);
        outHeight = (int)(imageY * actualScale);
        lmLog(gGFXTextureLogGroup, "Scale to %d %d due to scale %f %f actual=%f", outWidth, outHeight, scaleX, scaleY, actualScale);
    }

    // Build a buffer for byte->float conversions...
    Resampler::Sample *buffRed   = (Resampler::Sample *)malloc(sizeof(Resampler::Sample) * imageX);
    Resampler::Sample *buffGreen = (Resampler::Sample *)malloc(sizeof(Resampler::Sample) * imageX);
    Resampler::Sample *buffBlue  = (Resampler::Sample *)malloc(sizeof(Resampler::Sample) * imageX);

    // And the downsampled image. Give a slight margin because the scaling routine above can give
    // up to outWidth inclusive as an output value.
    stbi_uc *outBuffer = (stbi_uc *)malloc(sizeof(stbi_uc) * 3 * (outWidth + 1) * (outHeight + 1));

    // Set up the resamplers, reusing filter constants.
    const char *pFilter     = "blackman";
    float      filter_scale = 1.0;
    Resampler  resizeR(imageX, imageY, outWidth, outHeight, Resampler::BOUNDARY_CLAMP, 0.0f, 1.0f, pFilter, NULL, NULL, filter_scale, filter_scale);
    Resampler  resizeG(imageX, imageY, outWidth, outHeight, Resampler::BOUNDARY_CLAMP, 0.0f, 1.0f, pFilter, resizeR.get_clist_x(), resizeR.get_clist_y(), filter_scale, filter_scale);
    Resampler  resizeB(imageX, imageY, outWidth, outHeight, Resampler::BOUNDARY_CLAMP, 0.0f, 1.0f, pFilter, resizeR.get_clist_x(), resizeR.get_clist_y(), filter_scale, filter_scale);

    int resultY = 0;

    lmLog(gGFXTextureLogGroup, "Resample setup took %dms", t1 - platform_getMilliseconds());

    int t2 = platform_getMilliseconds();

    // Process each row of the image.
    for (int y = 0; y < imageY; y++)
    {
        // Deinterleave each row.
        for (int x = 0; x < imageX; x++)
        {
            buffRed[x]   = Resampler::Sample(imageBits[(y * imageX * 4) + (x * 4) + 0]) / Resampler::Sample(255.f);
            buffGreen[x] = Resampler::Sample(imageBits[(y * imageX * 4) + (x * 4) + 1]) / Resampler::Sample(255.f);
            buffBlue[x]  = Resampler::Sample(imageBits[(y * imageX * 4) + (x * 4) + 2]) / Resampler::Sample(255.f);
        }

        // Submit to resampler.
        lmAssert(resizeR.put_line(buffRed), "bad red");
        lmAssert(resizeG.put_line(buffGreen), "bad green");
        lmAssert(resizeB.put_line(buffBlue), "bad blue");

        // If there are results, reinterleave and consume them.
        while (resizeR.check_line() && resizeG.check_line() && resizeB.check_line() && resultY < outHeight)
        {
            const Resampler::Sample *outRowR = resizeR.get_line();
            const Resampler::Sample *outRowG = resizeG.get_line();
            const Resampler::Sample *outRowB = resizeB.get_line();

            if (outRowR || outRowG || outRowB)
            {
                lmAssert(outRowR && outRowG && outRowB, "Somehow got one line without others!");
            }
            else
            {
                break;
            }

            // Find the row for output.
            stbi_uc *imageOutBits = outBuffer + (resultY * outWidth * 3);
            resultY++;

            for (int i = 0; i < outWidth; i++)
            {
                imageOutBits[i * 3 + 0] = int(outRowR[i] * Resampler::Sample(255.f));
                imageOutBits[i * 3 + 1] = int(outRowG[i] * Resampler::Sample(255.f));
                imageOutBits[i * 3 + 2] = int(outRowB[i] * Resampler::Sample(255.f));
            }

            // Every hundred lines post an update.
            if (resultY % 100 == 0)
            {
                postResampleEvent(outPath, (float)resultY / (float)outHeight);
            }
        }
    }

    lmLog(gGFXTextureLogGroup, "Resample took %dms", t2 - platform_getMilliseconds());

    // Write it back out.
    int t3 = platform_getMilliseconds();
    jpge::compress_image_to_jpeg_file(outPath, outWidth, outHeight, 3, outBuffer);
    lmLog(gGFXTextureLogGroup, "JPEG output took %dms", t3 - platform_getMilliseconds());

    // Post completion event.
    postResampleEvent(outPath, 1.0);

    // Free everything!
    loom_asset_unlock(inPath);
    free(buffRed);
    free(buffGreen);
    free(buffBlue);
    free(outBuffer);
    delete rn;

    return 0;
}


static void scaleImageOnDisk(const char *outPath, const char *inPath, int outWidth, int outHeight, bool preserveAspect)
{
    RescaleNote *rn = new RescaleNote();

    rn->outPath   = outPath;
    rn->inPath    = inPath;
    rn->outWidth  = outWidth;
    rn->outHeight = outHeight;

    loom_thread_start(scaleImageOnDisk_body, rn);
}


static const NativeDelegate *getImageScaleProgressDelegate()
{
    return &gImageScaleProgressDelegate;
}


static int registerLoomGraphics(lua_State *L)
{
    beginPackage(L, "loom.graphics")

       .beginClass<Texture> ("Texture2D")
       .addStaticMethod("initFromAsset", &Texture::initFromAssetManager)
       .addStaticMethod("dispose", &Texture::dispose)
       .addStaticMethod("scaleImageOnDisk", &scaleImageOnDisk)
       .addStaticMethod("pollScaling", &pollScaling)
       .addStaticProperty("imageScaleProgress", &getImageScaleProgressDelegate)
       .endClass()

       .beginClass<Graphics> ("Graphics")
       .addStaticMethod("handleContextLoss", &Graphics::handleContextLoss)
       .addStaticMethod("screenshot", &Graphics::screenshot)
       .addStaticMethod("setDebug", &Graphics::setDebug)
       .addStaticMethod("setFillColor", &Graphics::setFillColor)
       .endClass()

       .beginClass<TextureInfo> ("TextureInfo")
       .addVar("width", &TextureInfo::width)
       .addVar("height", &TextureInfo::height)
       .addVar("id", &TextureInfo::id)
       .addVarAccessor("update", &TextureInfo::getUpdateDelegate)
       .endClass()


       .endPackage();

    return 0;
}
}