From 70bf298e8b880ff0bbb987bf757252c04b72203b Mon Sep 17 00:00:00 2001 From: gamax92 Date: Mon, 21 Dec 2015 13:02:07 -0700 Subject: [PATCH] Speed up some screen operations Use rectangles and texure coloring instead of redrawing the entire texture, cuts down things by half. Error if a component doesn't load on boot Also fix various usage of the ffi api, so that luajit wouldn't complain. Correct a typo on keyboard --- src/apis/component.lua | 5 ++- src/component/keyboard_sdl2.lua | 14 ++++---- src/component/screen_sdl2.lua | 62 +++++++++++++++++++++------------ 3 files changed, 51 insertions(+), 30 deletions(-) diff --git a/src/apis/component.lua b/src/apis/component.lua index 2461762..236f091 100644 --- a/src/apis/component.lua +++ b/src/apis/component.lua @@ -114,7 +114,10 @@ end local components = settings.components for k,v in pairs(components) do v[2] = v[2] or k - component.connect(v) + local ok, err=component.connect(v) + if not ok then + error(err,0) + end end env.component = {list = component.list} diff --git a/src/component/keyboard_sdl2.lua b/src/component/keyboard_sdl2.lua index c2fb7b1..951bf35 100644 --- a/src/component/keyboard_sdl2.lua +++ b/src/component/keyboard_sdl2.lua @@ -15,17 +15,17 @@ local function setLatest(char) end function elsa.textinput(event) - local textevent = ffi.cast("SDL_TextInputEvent", event) + local textevent = ffi.cast("SDL_TextInputEvent*", event) local text = ffi.string(textevent.text) cprint("textinput",text) setLatest(lua_utf8.byte(text)) end function elsa.keydown(event) - local keyevent = ffi.cast("SDL_KeyboardEvent", event) - local key = keyevent.keysym.scancode + local keyevent = ffi.cast("SDL_KeyboardEvent*", event) + local key = tonumber(keyevent.keysym.scancode) local lwjgl = keys[key] - cprint("keydown",keyevent.keysym.scancode,lwjgl) + cprint("keydown",key,lwjgl) -- TODO: Lovely SDL Hacks if lwjgl ~= 1 then -- Escape table.insert(kbdcodes,{type="key_down",addr=address,code=lwjgl or 0}) @@ -41,10 +41,10 @@ function elsa.keydown(event) end function elsa.keyup(event) - local keyevent = ffi.cast("SDL_KeyboardEvent", event) - local key = keyevent.keysym.scancode + local keyevent = ffi.cast("SDL_KeyboardEvent*", event) + local key = tonumber(keyevent.keysym.scancode) local lwjgl = keys[key] - cprint("keydown",keyevent.keysym.scancode,lwjgl) + cprint("keyup",key,lwjgl) if key ~= 41 then -- Escape table.insert(kbdcodes,{type="key_up",addr=address,code=lwjgl or 0,char=code2char[lwjgl]}) end diff --git a/src/component/screen_sdl2.lua b/src/component/screen_sdl2.lua index bdec8dd..01a76f4 100644 --- a/src/component/screen_sdl2.lua +++ b/src/component/screen_sdl2.lua @@ -58,7 +58,7 @@ end local buttons = {[SDL.BUTTON_LEFT] = 0, [SDL.BUTTON_RIGHT] = 1} local moved, bttndown, lx, ly = false function elsa.mousebuttondown(event) - local mbevent = ffi.cast("SDL_MouseButtonEvent", event) + local mbevent = ffi.cast("SDL_MouseButtonEvent*", event) if buttons[mbevent.button] then if not bttndown then lx, ly = math.floor(mbevent.x/8)+1,math.floor(mbevent.y/16)+1 @@ -69,7 +69,7 @@ function elsa.mousebuttondown(event) end function elsa.mousebuttonup(event) - local mbevent = ffi.cast("SDL_MouseButtonEvent", event) + local mbevent = ffi.cast("SDL_MouseButtonEvent*", event) if bttndown and buttons[mbevent.button] then if moved then moved = false @@ -80,7 +80,7 @@ function elsa.mousebuttonup(event) end function elsa.mousemotion(event) - local mmevent = ffi.cast("SDL_MouseMotionEvent", event) + local mmevent = ffi.cast("SDL_MouseMotionEvent*", event) if bttndown then local nx, ny = math.floor(mmevent.x/8)+1,math.floor(mmevent.y/16)+1 if nx ~= lx or ny ~= ly then @@ -92,7 +92,7 @@ function elsa.mousemotion(event) end function elsa.mousewheel(event) - local mwevent = ffi.cast("SDL_MouseWheelEvent", event) + local mwevent = ffi.cast("SDL_MouseWheelEvent*", event) local x,y = ffi.new("int[1]"),ffi.new("int[1]") SDL.getMouseState(ffi.cast("int*",x), ffi.cast("int*",y)) table.insert(machine.signals,{"scroll",address,math.floor(x[0]/8)+1,math.floor(y[0]/16)+1,mwevent.y}) @@ -116,6 +116,7 @@ local function createWindow() if renderer == ffi.C.NULL then error(ffi.string(SDL.getError())) end + SDL.setRenderDrawBlendMode(renderer, SDL.BLENDMODE_BLEND) texture = SDL.createTexture(renderer, SDL.PIXELFORMAT_ARGB8888, SDL.TEXTUREACCESS_TARGET, width*8, height*16); if texture == ffi.C.NULL then error(ffi.string(SDL.getError())) @@ -128,11 +129,10 @@ local function createWindow() -- Initialize all the textures to black SDL.setRenderDrawColor(renderer, 0, 0, 0, 255) SDL.renderFillRect(renderer, ffi.C.NULL) - SDL.setRenderTarget(renderer, texture); - SDL.renderFillRect(renderer, ffi.C.NULL) SDL.setRenderTarget(renderer, copytexture); SDL.renderFillRect(renderer, ffi.C.NULL) - SDL.setRenderTarget(renderer, ffi.C.NULL); + SDL.setRenderTarget(renderer, texture); + SDL.renderFillRect(renderer, ffi.C.NULL) end local function cleanUpWindow(wind) @@ -153,17 +153,23 @@ elsa.cleanup[#elsa.cleanup+1] = function() end function elsa.draw() + SDL.setRenderTarget(renderer, ffi.C.NULL); SDL.renderCopy(renderer, texture, ffi.C.NULL, ffi.C.NULL) SDL.renderPresent(renderer) + SDL.setRenderTarget(renderer, texture); end +local function extract(value) + return bit.rshift(bit.band(value,0xFF0000),16), + bit.rshift(bit.band(value,0xFF00),8), + bit.band(value,0xFF) +end + +local charCache={} local char8 = ffi.new("uint32_t[?]", 8*16) local char16 = ffi.new("uint32_t[?]", 16*16) -local function renderChar(char,x,y,fg,bg) - if unifont[char] == nil then - char = 63 - end - char = unifont[char] +local function _renderChar(ochar) + char = unifont[ochar] local size,pchar = #char/16 if size == 2 then pchar = char8 @@ -176,13 +182,32 @@ local function renderChar(char,x,y,fg,bg) local cx = 0 for j = size*4-1,0,-1 do local bit = math.floor(line/2^j)%2 - local color = bit == 0 and bg or fg - pchar[cy*size*4+cx] = color + 0xFF000000 + pchar[cy*size*4+cx] = (bit == 0 and 0 or 0xFFFFFFFF) cx = cx + 1 end cy = cy + 1 end - SDL.updateTexture(texture, ffi.new("SDL_Rect",{x=x,y=y,w=size*4,h=16}), pchar, (size*4) * ffi.sizeof("uint32_t")) + local texture = SDL.createTexture(renderer, SDL.PIXELFORMAT_ARGB8888, SDL.TEXTUREACCESS_STATIC, size*4, 16); + SDL.setTextureBlendMode(texture, SDL.BLENDMODE_BLEND) + SDL.updateTexture(texture, ffi.C.NULL, pchar, (size*4) * ffi.sizeof("uint32_t")) + charCache[ochar] = texture +end + +local function renderChar(char,x,y,fg,bg) + if unifont[char] == nil then + char = 63 + end + if not charCache[char] then + _renderChar(char) + end + local br, bg, bb = extract(bg) + SDL.setRenderDrawColor(renderer, br, bg, bb, 255) + local dest = ffi.new("SDL_Rect",{x=x,y=y,w=#unifont[char]/4,h=16}) + SDL.renderFillRect(renderer, dest) + if char~=32 then + SDL.setTextureColorMod(charCache[char], extract(fg)) + SDL.renderCopy(renderer, charCache[char], ffi.C.NULL, dest) + end end local function screenSet(x,y,c) @@ -215,12 +240,6 @@ local function setPos(x,y,c,fg,bg) end end -local function extract(value) - return bit.rshift(bit.band(value,0xFF0000),16), - bit.rshift(bit.band(value,0xFF00),8), - bit.band(value,0xFF) -end - local function compare(value1, value2) local r1,g1,b1 = extract(value1) local r2,g2,b2 = extract(value2) @@ -577,7 +596,6 @@ function cec.copy(x1, y1, w, h, tx, ty) -- Copies a portion of the screen from t SDL.setRenderTarget(renderer, copytexture); SDL.renderCopy(renderer, texture, ffi.C.NULL, ffi.C.NULL) SDL.renderCopy(renderer, texture, ffi.new("SDL_Rect",{x=(x1-1)*8,y=(y1-1)*16,w=w*8,h=h*16}), ffi.new("SDL_Rect",{x=(x1+tx-1)*8,y=(y1+ty-1)*16,w=w*8,h=h*16})) - SDL.setRenderTarget(renderer, ffi.C.NULL); texture,copytexture=copytexture,texture end