| /* libs/pixelflinger/t32cb16blend.S |
| ** |
| ** Copyright 2010, The Android Open Source Project |
| ** |
| ** Licensed under the Apache License, Version 2.0 (the "License"); |
| ** you may not use this file except in compliance with the License. |
| ** You may obtain a copy of the License at |
| ** |
| ** http://www.apache.org/licenses/LICENSE-2.0 |
| ** |
| ** Unless required by applicable law or agreed to in writing, software |
| ** distributed under the License is distributed on an "AS IS" BASIS, |
| ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| ** See the License for the specific language governing permissions and |
| ** limitations under the License. |
| */ |
| |
| #ifdef DEBUG |
| #define DBG |
| #else |
| #define DBG # |
| #endif |
| |
| /* |
| * blend one of 2 16bpp RGB pixels held in dreg selected by shift |
| * with the 32bpp ABGR pixel held in src and store the result in fb |
| * |
| * Assumes that the dreg data is little endian and that |
| * the the second pixel (shift==16) will be merged into |
| * the fb result |
| * |
| * Uses $t0,$t6,$t7,$t8 |
| */ |
| |
| #if __mips==32 && __mips_isa_rev>=2 |
| .macro pixel dreg src fb shift |
| /* |
| * sA = s >> 24 |
| * f = 0x100 - (sA + (sA>>7)) |
| */ |
| DBG .set noat |
| DBG rdhwr $at,$2 |
| DBG .set at |
| |
| srl $t7,\src,24 |
| srl $t6,$t7,7 |
| addu $t7,$t6 |
| li $t6,0x100 |
| subu $t7,$t6,$t7 |
| |
| /* red */ |
| ext $t8,\dreg,\shift+6+5,5 # dst[\shift:15..11] |
| mul $t6,$t8,$t7 |
| ext $t0,\dreg,\shift+5,6 # start green extraction dst[\shift:10..5] |
| ext $t8,\src,3,5 # src[7..3] |
| srl $t6,8 |
| addu $t8,$t6 |
| .if \shift!=0 |
| sll $t8,\shift+11 |
| or \fb,$t8 |
| .else |
| sll \fb,$t8,11 |
| .endif |
| |
| /* green */ |
| mul $t8,$t0,$t7 |
| ext $t0,\dreg,\shift,5 # start blue extraction dst[\shift:4..0] |
| ext $t6,\src,2+8,6 # src[15..10] |
| srl $t8,8 |
| addu $t8,$t6 |
| |
| /* blue */ |
| mul $t0,$t0,$t7 |
| sll $t8, $t8, \shift+5 |
| or \fb, \fb, $t8 |
| ext $t6,\src,(3+8+8),5 |
| srl $t8,$t0,8 |
| addu $t8,$t6 |
| sll $t8, $t8, \shift |
| or \fb, \fb, $t8 |
| |
| DBG .set noat |
| DBG rdhwr $t8,$2 |
| DBG subu $t8,$at |
| DBG sltu $at,$t8,$v0 |
| DBG movn $v0,$t8,$at |
| DBG sgtu $at,$t8,$v1 |
| DBG movn $v1,$t8,$at |
| DBG .set at |
| .endm |
| |
| #else |
| |
| .macro pixel dreg src fb shift |
| /* |
| * sA = s >> 24 |
| * f = 0x100 - (sA + (sA>>7)) |
| */ |
| DBG .set push |
| DBG .set noat |
| DBG .set mips32r2 |
| DBG rdhwr $at,$2 |
| DBG .set pop |
| |
| srl $t7,\src,24 |
| srl $t6,$t7,7 |
| addu $t7,$t6 |
| li $t6,0x100 |
| subu $t7,$t6,$t7 |
| |
| /* |
| * red |
| * dR = (d >> (6 + 5)) & 0x1f; |
| * dR = (f*dR)>>8 |
| * sR = (s >> ( 3)) & 0x1f; |
| * sR += dR |
| * fb |= sR << 11 |
| */ |
| srl $t8,\dreg,\shift+6+5 |
| .if \shift==0 |
| and $t8,0x1f |
| .endif |
| mul $t8,$t8,$t7 |
| srl $t6,\src,3 |
| and $t6,0x1f |
| srl $t8,8 |
| addu $t8,$t6 |
| .if \shift!=0 |
| sll $t8,\shift+11 |
| or \fb,$t8 |
| .else |
| sll \fb,$t8,11 |
| .endif |
| |
| /* |
| * green |
| * dG = (d >> 5) & 0x3f |
| * dG = (f*dG) >> 8 |
| * sG = (s >> ( 8+2))&0x3F; |
| */ |
| srl $t8,\dreg,\shift+5 |
| and $t8,0x3f |
| mul $t8,$t8,$t7 |
| srl $t6,\src,8+2 |
| and $t6,0x3f |
| srl $t8,8 |
| addu $t8,$t6 |
| sll $t8,\shift + 5 |
| or \fb,$t8 |
| |
| /* blue */ |
| .if \shift!=0 |
| srl $t8,\dreg,\shift |
| and $t8,0x1f |
| .else |
| and $t8,\dreg,0x1f |
| .endif |
| mul $t8,$t8,$t7 |
| srl $t6,\src,(8+8+3) |
| and $t6,0x1f |
| srl $t8,8 |
| addu $t8,$t6 |
| .if \shift!=0 |
| sll $t8,\shift |
| .endif |
| or \fb,$t8 |
| DBG .set push |
| DBG .set noat |
| DBG .set mips32r2 |
| DBG rdhwr $t8,$2 |
| DBG subu $t8,$at |
| DBG sltu $at,$t8,$v0 |
| DBG movn $v0,$t8,$at |
| DBG sgtu $at,$t8,$v1 |
| DBG movn $v1,$t8,$at |
| DBG .set pop |
| .endm |
| #endif |
| |
| .text |
| .align |
| |
| .global scanline_t32cb16blend_mips |
| .ent scanline_t32cb16blend_mips |
| scanline_t32cb16blend_mips: |
| DBG li $v0,0xffffffff |
| DBG li $v1,0 |
| /* Align the destination if necessary */ |
| and $t0,$a0,3 |
| beqz $t0,aligned |
| |
| /* as long as there is at least one pixel */ |
| beqz $a2,done |
| |
| lw $t4,($a1) |
| addu $a0,2 |
| addu $a1,4 |
| beqz $t4,1f |
| lhu $t3,-2($a0) |
| pixel $t3,$t4,$t1,0 |
| sh $t1,-2($a0) |
| 1: subu $a2,1 |
| |
| aligned: |
| /* Check to see if its worth unrolling the loop */ |
| subu $a2,4 |
| bltz $a2,tail |
| |
| /* Process 4 pixels at a time */ |
| fourpixels: |
| /* 1st pair of pixels */ |
| lw $t4,0($a1) |
| lw $t5,4($a1) |
| addu $a0,8 |
| addu $a1,16 |
| |
| /* both are zero, skip this pair */ |
| or $t3,$t4,$t5 |
| beqz $t3,1f |
| |
| /* load the destination */ |
| lw $t3,-8($a0) |
| |
| pixel $t3,$t4,$t1,0 |
| andi $t1, 0xFFFF |
| pixel $t3,$t5,$t1,16 |
| sw $t1,-8($a0) |
| |
| 1: |
| /* 2nd pair of pixels */ |
| lw $t4,-8($a1) |
| lw $t5,-4($a1) |
| |
| /* both are zero, skip this pair */ |
| or $t3,$t4,$t5 |
| beqz $t3,1f |
| |
| /* load the destination */ |
| lw $t3,-4($a0) |
| |
| pixel $t3,$t4,$t1,0 |
| andi $t1, 0xFFFF |
| pixel $t3,$t5,$t1,16 |
| sw $t1,-4($a0) |
| |
| 1: subu $a2,4 |
| bgtz $a2,fourpixels |
| |
| tail: |
| /* the pixel count underran, restore it now */ |
| addu $a2,4 |
| |
| /* handle the last 0..3 pixels */ |
| beqz $a2,done |
| onepixel: |
| lw $t4,($a1) |
| addu $a0,2 |
| addu $a1,4 |
| beqz $t4,1f |
| lhu $t3,-2($a0) |
| pixel $t3,$t4,$t1,0 |
| sh $t1,-2($a0) |
| 1: subu $a2,1 |
| bnez $a2,onepixel |
| done: |
| DBG .set push |
| DBG .set mips32r2 |
| DBG rdhwr $a0,$3 |
| DBG mul $v0,$a0 |
| DBG mul $v1,$a0 |
| DBG .set pop |
| j $ra |
| .end scanline_t32cb16blend_mips |