forked from KolibriOS/kolibrios
112 lines
3.0 KiB
NASM
112 lines
3.0 KiB
NASM
|
|
||
|
align 4
|
||
|
proc calc_buf uses ebx ecx, buf:dword, shininess:dword
|
||
|
locals
|
||
|
val dd ? ;float
|
||
|
f_inc dd ? ;float
|
||
|
endl
|
||
|
mov dword[val],0.0f
|
||
|
mov dword[f_inc],SPECULAR_BUFFER_SIZE
|
||
|
fld1
|
||
|
fidiv dword[f_inc]
|
||
|
fstp dword[f_inc] ;f_inc = 1.0f/SPECULAR_BUFFER_SIZE
|
||
|
xor ecx,ecx
|
||
|
align 4
|
||
|
.cycle_0: ;for (i = 0; i <= SPECULAR_BUFFER_SIZE; i++)
|
||
|
cmp ecx,SPECULAR_BUFFER_SIZE
|
||
|
jg @f
|
||
|
;Вычисляем x^y
|
||
|
fld dword[shininess]
|
||
|
fld dword[val]
|
||
|
fyl2x ;Стек FPU теперь содержит: st0=z=y*log2(x):
|
||
|
;Теперь считаем 2**z:
|
||
|
fld st0 ;Создаем еще одну копию z
|
||
|
frndint ;Округляем
|
||
|
fsubr st0,st1 ;st1=z, st0=z-trunc(z)
|
||
|
f2xm1 ;st1=z, st0=2**(z-trunc(z))-1
|
||
|
fld1
|
||
|
faddp ;st1=z, st0=2**(z-trunc(z))
|
||
|
fscale ;st1=z, st0=(2**trunc(z))*(2**(z-trunc(z)))=2**t
|
||
|
fxch st1
|
||
|
fstp st ;Результат остается на вершине стека st0
|
||
|
|
||
|
mov ebx,ecx
|
||
|
shl ebx,2
|
||
|
add ebx,offs_spec_buf
|
||
|
add ebx,[buf]
|
||
|
fstp dword[ebx] ;buf.buf[i] = pow(val, shininess)
|
||
|
|
||
|
fld dword[val]
|
||
|
fadd dword[f_inc]
|
||
|
fstp dword[val] ;val += f_inc
|
||
|
inc ecx
|
||
|
jmp .cycle_0
|
||
|
@@:
|
||
|
ret
|
||
|
endp
|
||
|
|
||
|
align 4
|
||
|
proc specbuf_get_buffer uses ebx ecx edx, context:dword, shininess_i:dword, shininess:dword
|
||
|
locals
|
||
|
found dd ? ;GLSpecBuf *
|
||
|
oldest dd ? ;GLSpecBuf *
|
||
|
endl
|
||
|
mov edx,[context]
|
||
|
mov eax,[edx+offs_cont_specbuf_first]
|
||
|
mov [found],eax
|
||
|
mov [oldest],eax
|
||
|
mov ebx,[shininess_i]
|
||
|
.cycle_0:
|
||
|
or eax,eax ;while (found)
|
||
|
jz @f
|
||
|
cmp [eax+offs_spec_shininess_i],ebx ;while (found.shininess_i != shininess_i)
|
||
|
je @f
|
||
|
mov ecx,[oldest]
|
||
|
mov ecx,[ecx+offs_spec_last_used]
|
||
|
cmp [eax+offs_spec_last_used],ecx ;if (found.last_used < oldest.last_used)
|
||
|
jge .end_0
|
||
|
mov [oldest],eax ;oldest = found
|
||
|
.end_0:
|
||
|
mov eax,[eax+offs_spec_next] ;found = found.next
|
||
|
jmp .cycle_0
|
||
|
@@:
|
||
|
cmp dword[found],0 ;if (found) /* hey, found one! */
|
||
|
je @f
|
||
|
mov eax,[found]
|
||
|
mov ecx,[edx+offs_cont_specbuf_used_counter]
|
||
|
mov [eax+offs_spec_last_used],ecx ;found.last_used = context.specbuf_used_counter
|
||
|
inc dword[edx+offs_cont_specbuf_used_counter]
|
||
|
jmp .end_f ;return found
|
||
|
@@:
|
||
|
cmp dword[oldest],0 ;if (oldest == NULL || context.specbuf_num_buffers < MAX_SPECULAR_BUFFERS)
|
||
|
je @f
|
||
|
cmp dword[edx+offs_cont_specbuf_num_buffers],MAX_SPECULAR_BUFFERS
|
||
|
jl @f
|
||
|
jmp .end_1
|
||
|
@@:
|
||
|
; create new buffer
|
||
|
stdcall gl_malloc, sizeof.GLSpecBuf
|
||
|
;if (!eax) gl_fatal_error("could not allocate specular buffer")
|
||
|
inc dword[edx+offs_cont_specbuf_num_buffers]
|
||
|
mov ecx,[edx+offs_cont_specbuf_first]
|
||
|
mov [eax+offs_spec_next],ecx
|
||
|
mov [edx+offs_cont_specbuf_first],eax
|
||
|
mov ecx,[edx+offs_cont_specbuf_used_counter]
|
||
|
mov [eax+offs_spec_last_used],ecx
|
||
|
inc dword[edx+offs_cont_specbuf_used_counter]
|
||
|
mov [eax+offs_spec_shininess_i],ebx
|
||
|
stdcall calc_buf, eax,dword[shininess]
|
||
|
jmp .end_f
|
||
|
.end_1:
|
||
|
; overwrite the lru buffer
|
||
|
;tgl_trace("overwriting spec buffer :(\n");
|
||
|
mov eax,[oldest]
|
||
|
mov [eax+offs_spec_shininess_i],ebx
|
||
|
mov ecx,[edx+offs_cont_specbuf_used_counter]
|
||
|
mov [eax+offs_spec_last_used],ecx
|
||
|
inc dword[edx+offs_cont_specbuf_used_counter]
|
||
|
stdcall calc_buf, eax,dword[shininess]
|
||
|
.end_f:
|
||
|
ret
|
||
|
endp
|